@@ -31,6 +31,7 @@ npm install inquirerer
3131- ✅ ** Smart Validation** - Built-in pattern matching, custom validators, and sanitizers
3232- 🔀 ** Conditional Logic** - Show/hide questions based on previous answers
3333- 🎨 ** Interactive UX** - Fuzzy search, keyboard navigation, and visual feedback
34+ - 🔄 ** Dynamic Defaults** - Auto-populate defaults from git config, date/time, or custom resolvers
3435
3536## Table of Contents
3637
@@ -55,6 +56,10 @@ npm install inquirerer
5556 - [ CLI with Commander Integration] ( #cli-with-commander-integration )
5657 - [ Dynamic Dependencies] ( #dynamic-dependencies )
5758 - [ Custom Validation] ( #custom-validation )
59+ - [ Dynamic Defaults with Resolvers] ( #dynamic-defaults-with-resolvers )
60+ - [ Built-in Resolvers] ( #built-in-resolvers )
61+ - [ Custom Resolvers] ( #custom-resolvers )
62+ - [ Resolver Examples] ( #resolver-examples )
5863- [ CLI Helper] ( #cli-helper )
5964- [ Developing] ( #developing )
6065
@@ -100,7 +105,10 @@ import {
100105 ListQuestion ,
101106 AutocompleteQuestion ,
102107 CheckboxQuestion ,
103- InquirererOptions
108+ InquirererOptions ,
109+ DefaultResolverRegistry ,
110+ registerDefaultResolver ,
111+ resolveDefault
104112} from ' inquirerer' ;
105113
106114interface UserConfig {
@@ -124,6 +132,7 @@ interface BaseQuestion {
124132 message? : string ; // Prompt message to display
125133 description? : string ; // Additional context
126134 default? : any ; // Default value
135+ defaultFrom? : string ; // Dynamic default from resolver (e.g., 'git.user.name')
127136 useDefault? : boolean ; // Skip prompt and use default
128137 required? : boolean ; // Validation requirement
129138 validate? : (input : any , answers : any ) => boolean | Validation ;
@@ -153,12 +162,13 @@ const prompter = new Inquirerer({
153162
154163``` typescript
155164interface InquirererOptions {
156- noTty? : boolean ; // Disable interactive mode
157- input? : Readable ; // Input stream (default: process.stdin)
158- output? : Writable ; // Output stream (default: process.stdout)
159- useDefaults? : boolean ; // Skip prompts and use defaults
160- globalMaxLines? : number ; // Max lines for list displays (default: 10)
161- mutateArgs? : boolean ; // Mutate argv object (default: true)
165+ noTty? : boolean ; // Disable interactive mode
166+ input? : Readable ; // Input stream (default: process.stdin)
167+ output? : Writable ; // Output stream (default: process.stdout)
168+ useDefaults? : boolean ; // Skip prompts and use defaults
169+ globalMaxLines? : number ; // Max lines for list displays (default: 10)
170+ mutateArgs? : boolean ; // Mutate argv object (default: true)
171+ resolverRegistry? : DefaultResolverRegistry ; // Custom resolver registry
162172}
163173
164174const prompter = new Inquirerer (options );
@@ -668,6 +678,261 @@ const questions: Question[] = [
668678];
669679```
670680
681+ ## Dynamic Defaults with Resolvers
682+
683+ The ` defaultFrom ` feature allows you to automatically populate question defaults from dynamic sources like git configuration, environment variables, date/time values, or custom resolvers. This eliminates repetitive boilerplate code for common default values.
684+
685+ ### Quick Example
686+
687+ ``` typescript
688+ import { Inquirerer } from ' inquirerer' ;
689+
690+ const questions = [
691+ {
692+ type: ' text' ,
693+ name: ' authorName' ,
694+ message: ' Author name?' ,
695+ defaultFrom: ' git.user.name' // Auto-fills from git config
696+ },
697+ {
698+ type: ' text' ,
699+ name: ' authorEmail' ,
700+ message: ' Author email?' ,
701+ defaultFrom: ' git.user.email' // Auto-fills from git config
702+ },
703+ {
704+ type: ' text' ,
705+ name: ' copyrightYear' ,
706+ message: ' Copyright year?' ,
707+ defaultFrom: ' date.year' // Auto-fills current year
708+ }
709+ ];
710+
711+ const prompter = new Inquirerer ();
712+ const answers = await prompter .prompt ({}, questions );
713+ ```
714+
715+ ### Built-in Resolvers
716+
717+ Inquirerer comes with several built-in resolvers ready to use:
718+
719+ #### Git Configuration
720+
721+ | Resolver | Description | Example Output |
722+ | ----------| -------------| ----------------|
723+ | ` git.user.name ` | Git global user name | ` "John Doe" ` |
724+ | ` git.user.email ` | Git global user email
| ` "[email protected] " ` | 725+
726+ #### Date & Time
727+
728+ | Resolver | Description | Example Output |
729+ | ----------| -------------| ----------------|
730+ | ` date.year ` | Current year | ` "2025" ` |
731+ | ` date.month ` | Current month (zero-padded) | ` "11" ` |
732+ | ` date.day ` | Current day (zero-padded) | ` "23" ` |
733+ | ` date.iso ` | ISO date (YYYY-MM-DD) | ` "2025-11-23" ` |
734+ | ` date.now ` | ISO timestamp | ` "2025-11-23T15:30:45.123Z" ` |
735+ | ` date.timestamp ` | Unix timestamp (ms) | ` "1732375845123" ` |
736+
737+ ### Priority Order
738+
739+ When resolving default values, inquirerer follows this priority:
740+
741+ 1 . ** CLI Arguments** - Values passed via command line (highest priority)
742+ 2 . ** ` defaultFrom ` ** - Dynamically resolved values
743+ 3 . ** ` default ` ** - Static default values
744+ 4 . ** ` undefined ` ** - No default available
745+
746+ ``` typescript
747+ {
748+ type : ' text' ,
749+ name : ' author' ,
750+ defaultFrom : ' git.user.name' , // Try git first
751+ default : ' Anonymous' // Fallback if git not configured
752+ }
753+ ```
754+
755+ ### Custom Resolvers
756+
757+ Register your own custom resolvers for project-specific needs:
758+
759+ ``` typescript
760+ import { registerDefaultResolver } from ' inquirerer' ;
761+
762+ // Register a resolver for current directory name
763+ registerDefaultResolver (' cwd.name' , () => {
764+ return process .cwd ().split (' /' ).pop ();
765+ });
766+
767+ // Register a resolver for environment variable
768+ registerDefaultResolver (' env.user' , () => {
769+ return process .env .USER ;
770+ });
771+
772+ // Use in questions
773+ const questions = [
774+ {
775+ type: ' text' ,
776+ name: ' projectName' ,
777+ message: ' Project name?' ,
778+ defaultFrom: ' cwd.name' ,
779+ default: ' my-project'
780+ },
781+ {
782+ type: ' text' ,
783+ name: ' author' ,
784+ message: ' Author?' ,
785+ defaultFrom: ' env.user'
786+ }
787+ ];
788+ ```
789+
790+ ### Instance-Specific Resolvers
791+
792+ For isolated resolver registries, use a custom resolver registry per Inquirerer instance:
793+
794+ ``` typescript
795+ import { DefaultResolverRegistry , Inquirerer } from ' inquirerer' ;
796+
797+ const customRegistry = new DefaultResolverRegistry ();
798+
799+ // Register resolvers specific to this instance
800+ customRegistry .register (' app.name' , () => ' my-app' );
801+ customRegistry .register (' app.port' , () => 3000 );
802+
803+ const prompter = new Inquirerer ({
804+ resolverRegistry: customRegistry // Use custom registry
805+ });
806+
807+ const questions = [
808+ {
809+ type: ' text' ,
810+ name: ' appName' ,
811+ defaultFrom: ' app.name'
812+ },
813+ {
814+ type: ' number' ,
815+ name: ' port' ,
816+ defaultFrom: ' app.port'
817+ }
818+ ];
819+
820+ const answers = await prompter .prompt ({}, questions );
821+ ```
822+
823+ ### Resolver Examples
824+
825+ #### System Information
826+
827+ ``` typescript
828+ import os from ' os' ;
829+ import { registerDefaultResolver } from ' inquirerer' ;
830+
831+ registerDefaultResolver (' system.hostname' , () => os .hostname ());
832+ registerDefaultResolver (' system.username' , () => os .userInfo ().username );
833+
834+ const questions = [
835+ {
836+ type: ' text' ,
837+ name: ' hostname' ,
838+ message: ' Hostname?' ,
839+ defaultFrom: ' system.hostname'
840+ }
841+ ];
842+ ```
843+
844+ #### Conditional Defaults
845+
846+ ``` typescript
847+ registerDefaultResolver (' app.port' , () => {
848+ return process .env .NODE_ENV === ' production' ? 80 : 3000 ;
849+ });
850+
851+ const questions = [
852+ {
853+ type: ' number' ,
854+ name: ' port' ,
855+ message: ' Port?' ,
856+ defaultFrom: ' app.port'
857+ }
858+ ];
859+ ```
860+
861+ ### Error Handling
862+
863+ Resolvers fail silently by default. If a resolver throws an error or returns ` undefined ` , inquirerer falls back to the static ` default ` value (if provided):
864+
865+ ``` typescript
866+ {
867+ type : ' text' ,
868+ name : ' author' ,
869+ defaultFrom : ' git.user.name' , // May fail if git not configured
870+ default : ' Anonymous' , // Used if resolver fails
871+ required : true
872+ }
873+ ```
874+
875+ For debugging, set ` DEBUG=inquirerer ` to see resolver errors:
876+
877+ ``` bash
878+ DEBUG=inquirerer node your-cli.js
879+ ```
880+
881+ ### Real-World Use Case
882+
883+ ``` typescript
884+ import { Inquirerer , registerDefaultResolver } from ' inquirerer' ;
885+
886+ // Register a resolver for current directory name
887+ registerDefaultResolver (' cwd.name' , () => {
888+ return process .cwd ().split (' /' ).pop ();
889+ });
890+
891+ const questions = [
892+ {
893+ type: ' text' ,
894+ name: ' projectName' ,
895+ message: ' Project name?' ,
896+ defaultFrom: ' cwd.name' ,
897+ required: true
898+ },
899+ {
900+ type: ' text' ,
901+ name: ' author' ,
902+ message: ' Author?' ,
903+ defaultFrom: ' git.user.name' ,
904+ required: true
905+ },
906+ {
907+ type: ' text' ,
908+ name: ' email' ,
909+ message: ' Email?' ,
910+ defaultFrom: ' git.user.email' ,
911+ required: true
912+ },
913+ {
914+ type: ' text' ,
915+ name: ' year' ,
916+ message: ' Copyright year?' ,
917+ defaultFrom: ' date.year'
918+ }
919+ ];
920+
921+ const prompter = new Inquirerer ();
922+ const config = await prompter .prompt ({}, questions );
923+ ```
924+
925+ With git configured, the prompts will show:
926+
927+ ``` bash
928+ Project name? (my-project-dir)
929+ Author? (John Doe)
930+ 931+ Copyright year? (2025)
932+ ```
933+
934+ All defaults automatically populated from git config, directory name, and current date!
935+
671936## CLI Helper
672937
673938The ` CLI ` class provides integration with command-line argument parsing:
0 commit comments