cli-forge 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/bin/commands/generate-documentation.js +1 -13
  2. package/dist/bin/commands/generate-documentation.js.map +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/internal-cli.d.ts +33 -2
  6. package/dist/lib/internal-cli.js +90 -4
  7. package/dist/lib/internal-cli.js.map +1 -1
  8. package/dist/lib/prompt-types.d.ts +44 -0
  9. package/dist/lib/prompt-types.js +3 -0
  10. package/dist/lib/prompt-types.js.map +1 -0
  11. package/dist/lib/public-api.d.ts +45 -12
  12. package/dist/lib/public-api.js.map +1 -1
  13. package/dist/lib/resolve-prompts.d.ts +13 -0
  14. package/dist/lib/resolve-prompts.js +121 -0
  15. package/dist/lib/resolve-prompts.js.map +1 -0
  16. package/dist/lib/test-harness.js +1 -1
  17. package/dist/lib/test-harness.js.map +1 -1
  18. package/dist/prompt-providers/clack.d.ts +29 -0
  19. package/dist/prompt-providers/clack.js +136 -0
  20. package/dist/prompt-providers/clack.js.map +1 -0
  21. package/package.json +11 -2
  22. package/src/bin/commands/generate-documentation.ts +1 -13
  23. package/src/index.ts +1 -0
  24. package/src/lib/composable-builder.ts +3 -3
  25. package/src/lib/internal-cli.spec.ts +300 -0
  26. package/src/lib/internal-cli.ts +117 -9
  27. package/src/lib/prompt-types.ts +48 -0
  28. package/src/lib/public-api.ts +31 -19
  29. package/src/lib/resolve-prompts.spec.ts +311 -0
  30. package/src/lib/resolve-prompts.ts +156 -0
  31. package/src/lib/test-harness.ts +1 -1
  32. package/src/prompt-providers/clack.spec.ts +376 -0
  33. package/src/prompt-providers/clack.ts +169 -0
  34. package/tsconfig.lib.json.tsbuildinfo +1 -1
  35. package/typedoc.json +10 -0
  36. package/.eslintrc.json +0 -36
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePrompts = resolvePrompts;
4
+ /**
5
+ * Collects options that need prompting, matches them to providers,
6
+ * executes prompts, and returns the prompted values.
7
+ */
8
+ async function resolvePrompts(opts) {
9
+ const { configuredOptions, configuredImplies, promptConfigs, providers, currentArgs, } = opts;
10
+ // Step 1: Collect promptable options
11
+ const promptableOptions = [];
12
+ for (const [name, config] of Object.entries(configuredOptions)) {
13
+ // Skip internal options
14
+ if (name === 'help' ||
15
+ name === 'version' ||
16
+ name === 'unmatched' ||
17
+ name === '--') {
18
+ continue;
19
+ }
20
+ // Already has a value — skip unless prompt is explicitly true/string
21
+ const hasValue = currentArgs[name] !== undefined;
22
+ const promptSetting = promptConfigs.get(name);
23
+ let resolved;
24
+ if (typeof promptSetting === 'function') {
25
+ resolved = promptSetting(currentArgs);
26
+ // Callback: null/undefined treated as false
27
+ if (resolved === null || resolved === undefined) {
28
+ continue;
29
+ }
30
+ }
31
+ else if (promptSetting !== undefined) {
32
+ // Static value
33
+ resolved = promptSetting;
34
+ }
35
+ else {
36
+ // Not specified: prompt only if required and missing value
37
+ if (hasValue)
38
+ continue;
39
+ const isRequired = config.required === true;
40
+ const isImplied = isOptionImplied(name, configuredImplies, currentArgs);
41
+ if (!isRequired && !isImplied)
42
+ continue;
43
+ if (providers.length === 0)
44
+ continue; // No providers, let validation handle it
45
+ resolved = true; // Will prompt
46
+ }
47
+ if (resolved === false)
48
+ continue;
49
+ if (hasValue && resolved !== true && typeof resolved !== 'string')
50
+ continue;
51
+ promptableOptions.push({
52
+ name,
53
+ config: {
54
+ ...config,
55
+ prompt: resolved === true ? true : resolved ?? undefined,
56
+ },
57
+ });
58
+ }
59
+ if (promptableOptions.length === 0) {
60
+ return {};
61
+ }
62
+ // Step 2: Match options to providers
63
+ const filteredProviders = providers.filter((p) => p.filter);
64
+ const fallbackProviders = providers.filter((p) => !p.filter);
65
+ const providerGroups = new Map();
66
+ const unmatchedOptions = [];
67
+ for (const option of promptableOptions) {
68
+ let matched = false;
69
+ for (const provider of filteredProviders) {
70
+ if (provider.filter(option.name, option.config)) {
71
+ if (!providerGroups.has(provider)) {
72
+ providerGroups.set(provider, []);
73
+ }
74
+ providerGroups.get(provider).push(option);
75
+ matched = true;
76
+ break;
77
+ }
78
+ }
79
+ if (!matched) {
80
+ unmatchedOptions.push(option);
81
+ }
82
+ }
83
+ // Assign unmatched options to first fallback provider
84
+ if (unmatchedOptions.length > 0) {
85
+ if (fallbackProviders.length === 0) {
86
+ const names = unmatchedOptions.map((o) => `'${o.name}'`).join(', ');
87
+ throw new Error(`Option(s) ${names} require prompting but no prompt provider is available`);
88
+ }
89
+ const fallback = fallbackProviders[0];
90
+ if (!providerGroups.has(fallback)) {
91
+ providerGroups.set(fallback, []);
92
+ }
93
+ providerGroups.get(fallback).push(...unmatchedOptions);
94
+ }
95
+ // Step 3: Execute prompts
96
+ const results = {};
97
+ for (const [provider, options] of providerGroups) {
98
+ if (provider.promptBatch) {
99
+ const batchResults = await provider.promptBatch(options);
100
+ Object.assign(results, batchResults);
101
+ }
102
+ else if (provider.prompt) {
103
+ for (const option of options) {
104
+ results[option.name] = await provider.prompt(option);
105
+ }
106
+ }
107
+ }
108
+ return results;
109
+ }
110
+ /**
111
+ * Check if an option is implied by another option that has been set.
112
+ */
113
+ function isOptionImplied(name, configuredImplies, currentArgs) {
114
+ for (const [trigger, implied] of Object.entries(configuredImplies)) {
115
+ if (implied.has(name) && currentArgs[trigger] !== undefined) {
116
+ return true;
117
+ }
118
+ }
119
+ return false;
120
+ }
121
+ //# sourceMappingURL=resolve-prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-prompts.js","sourceRoot":"","sources":["../../src/lib/resolve-prompts.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ const internal_cli_1 = require("./internal-cli");
9
9
  class TestHarness {
10
10
  cli;
11
11
  constructor(cli) {
12
- if (cli instanceof internal_cli_1.InternalCLI) {
12
+ if (internal_cli_1.InternalCLI.isInternalCLI(cli)) {
13
13
  this.cli = cli;
14
14
  mockHandler(cli);
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../../src/lib/test-harness.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AA8B7C;;;GAGG;AACH,MAAa,WAAW;IACd,GAAG,CAAiB;IAE5B,YAAY,GAAW;QACrB,IAAI,GAAG,YAAY,0BAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;YACf,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAc;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,OAAO;YACL,IAAI,EAAE,IAAI;YACV,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;SACpC,CAAC;IACJ,CAAC;CACF;AAtBD,kCAsBC;AAED,SAAS,WAAW,CAAC,GAAgB;IACnC,IAAI,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC;QAC/B,GAAG,CAAC,aAAa,CAAC,OAAO,GAAG,GAAG,EAAE;YAC/B,6BAA6B;QAC/B,CAAC,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC7C,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"test-harness.js","sourceRoot":"","sources":["../../src/lib/test-harness.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AA8B7C;;;GAGG;AACH,MAAa,WAAW;IACd,GAAG,CAAiB;IAE5B,YAAY,GAAW;QACrB,IAAI,0BAAW,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;YACf,WAAW,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAc;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,OAAO;YACL,IAAI,EAAE,IAAI;YACV,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;SACpC,CAAC;IACJ,CAAC;CACF;AAtBD,kCAsBC;AAED,SAAS,WAAW,CAAC,GAAgB;IACnC,IAAI,GAAG,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC;QAC/B,GAAG,CAAC,aAAa,CAAC,OAAO,GAAG,GAAG,EAAE;YAC/B,6BAA6B;QAC/B,CAAC,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC7C,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Readable, Writable } from 'node:stream';
2
+ import type { PromptProvider } from '../lib/prompt-types';
3
+ /**
4
+ * Options for {@link createClackPromptProvider}.
5
+ */
6
+ export interface ClackPromptProviderOptions {
7
+ /**
8
+ * Custom input stream to read from instead of `process.stdin`.
9
+ * Useful for testing — pass a `Readable` with `isTTY = true` and
10
+ * a no-op `setRawMode` to emulate a terminal.
11
+ */
12
+ input?: Readable;
13
+ /**
14
+ * Custom output stream to write to instead of `process.stdout`.
15
+ */
16
+ output?: Writable;
17
+ }
18
+ /**
19
+ * Creates a prompt provider backed by @clack/prompts.
20
+ * Requires `@clack/prompts` as a peer dependency.
21
+ *
22
+ * The provider uses dynamic imports so that `@clack/prompts` is only
23
+ * loaded when prompting actually occurs.
24
+ */
25
+ export declare function createClackPromptProvider(providerOptions?: ClackPromptProviderOptions): PromptProvider;
26
+ /**
27
+ * Default clack prompt provider, uses stdin/stdout
28
+ */
29
+ export declare const ClackPromptProvider: PromptProvider;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClackPromptProvider = void 0;
4
+ exports.createClackPromptProvider = createClackPromptProvider;
5
+ /**
6
+ * Creates a prompt provider backed by @clack/prompts.
7
+ * Requires `@clack/prompts` as a peer dependency.
8
+ *
9
+ * The provider uses dynamic imports so that `@clack/prompts` is only
10
+ * loaded when prompting actually occurs.
11
+ */
12
+ function createClackPromptProvider(providerOptions) {
13
+ // Build the common stream options once; spread into every prompt call.
14
+ const streamOpts = {};
15
+ if (providerOptions?.input)
16
+ streamOpts.input = providerOptions.input;
17
+ if (providerOptions?.output)
18
+ streamOpts.output = providerOptions.output;
19
+ return {
20
+ async promptBatch(options) {
21
+ const clack = await import('@clack/prompts');
22
+ const results = {};
23
+ for (const option of options) {
24
+ const message = getLabel(option);
25
+ const defaultValue = getDefault(option.config);
26
+ let value;
27
+ if (option.config.type === 'boolean') {
28
+ value = await clack.confirm({
29
+ ...streamOpts,
30
+ message,
31
+ initialValue: typeof defaultValue === 'boolean' ? defaultValue : undefined,
32
+ });
33
+ }
34
+ else if (hasChoices(option.config)) {
35
+ const choices = getChoices(option.config);
36
+ if (option.config.type === 'array') {
37
+ value = await clack.multiselect({
38
+ ...streamOpts,
39
+ message,
40
+ options: choices.map((c) => ({ value: c, label: String(c) })),
41
+ });
42
+ }
43
+ else {
44
+ value = await clack.select({
45
+ ...streamOpts,
46
+ message,
47
+ options: choices.map((c) => ({ value: c, label: String(c) })),
48
+ });
49
+ }
50
+ }
51
+ else if (option.config.type === 'number') {
52
+ const raw = await clack.text({
53
+ ...streamOpts,
54
+ message,
55
+ placeholder: defaultValue !== undefined ? String(defaultValue) : undefined,
56
+ defaultValue: defaultValue !== undefined ? String(defaultValue) : undefined,
57
+ validate: (val) => {
58
+ if (val && isNaN(Number(val))) {
59
+ return 'Please enter a valid number';
60
+ }
61
+ return undefined;
62
+ },
63
+ });
64
+ if (clack.isCancel(raw)) {
65
+ clack.cancel('Operation cancelled.');
66
+ throw new Error('Prompt cancelled by user');
67
+ }
68
+ value = raw !== undefined && raw !== '' ? Number(raw) : defaultValue;
69
+ }
70
+ else {
71
+ // string, array without choices
72
+ value = await clack.text({
73
+ ...streamOpts,
74
+ message,
75
+ placeholder: defaultValue !== undefined ? String(defaultValue) : undefined,
76
+ defaultValue: defaultValue !== undefined ? String(defaultValue) : undefined,
77
+ });
78
+ }
79
+ // clack returns a Symbol when the user cancels (Ctrl+C)
80
+ if (clack.isCancel(value)) {
81
+ clack.cancel('Operation cancelled.');
82
+ throw new Error('Prompt cancelled by user');
83
+ }
84
+ results[option.name] = value;
85
+ }
86
+ return results;
87
+ },
88
+ };
89
+ }
90
+ /**
91
+ * Default clack prompt provider, uses stdin/stdout
92
+ */
93
+ exports.ClackPromptProvider = createClackPromptProvider();
94
+ /**
95
+ * Determine the label to show for a prompt option.
96
+ * Priority: prompt string > description > option name.
97
+ */
98
+ function getLabel(option) {
99
+ if (typeof option.config.prompt === 'string') {
100
+ return option.config.prompt;
101
+ }
102
+ return option.config.description ?? option.name;
103
+ }
104
+ /**
105
+ * Extract the default value from an option config.
106
+ * Handles the three forms:
107
+ * - Primitive value directly
108
+ * - `{ value: T; description: string }` object
109
+ * - `{ factory: () => T; description: string }` object
110
+ */
111
+ function getDefault(config) {
112
+ if (config.default === undefined)
113
+ return undefined;
114
+ if (typeof config.default === 'object' && config.default !== null) {
115
+ if ('factory' in config.default) {
116
+ return config.default.factory();
117
+ }
118
+ if ('value' in config.default) {
119
+ return config.default.value;
120
+ }
121
+ }
122
+ return config.default;
123
+ }
124
+ function hasChoices(config) {
125
+ return ('choices' in config &&
126
+ config['choices'] !== undefined);
127
+ }
128
+ function getChoices(config) {
129
+ const cfg = config;
130
+ const choices = cfg['choices'];
131
+ if (typeof choices === 'function') {
132
+ return choices();
133
+ }
134
+ return choices ?? [];
135
+ }
136
+ //# sourceMappingURL=clack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clack.js","sourceRoot":"","sources":["../../src/prompt-providers/clack.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "cli-forge",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.0",
6
- "@cli-forge/parser": "1.2.2"
6
+ "@cli-forge/parser": "1.3.0"
7
7
  },
8
8
  "peerDependencies": {
9
+ "@clack/prompts": "*",
9
10
  "markdown-factory": "^0.2.0",
10
11
  "tsx": "^4.19.0",
11
12
  "zod": "^4.1.13"
12
13
  },
13
14
  "peerDependenciesMeta": {
15
+ "@clack/prompts": {
16
+ "optional": true
17
+ },
14
18
  "markdown-factory": {
15
19
  "optional": true,
16
20
  "dev": true
@@ -53,6 +57,11 @@
53
57
  "require": "./dist/middleware/*.js",
54
58
  "types": "./dist/middleware/*.d.ts"
55
59
  },
60
+ "./prompt-providers/clack": {
61
+ "require": "./dist/prompt-providers/clack.js",
62
+ "types": "./dist/prompt-providers/clack.d.ts",
63
+ "import": "./dist/prompt-providers/clack.js"
64
+ },
56
65
  "./package.json": "./package.json"
57
66
  },
58
67
  "publishConfig": {
@@ -386,19 +386,7 @@ async function importMarkdownFactory(): Promise<mdfactory> {
386
386
  }
387
387
 
388
388
  function isCLI(obj: unknown): obj is InternalCLI {
389
- if (obj instanceof InternalCLI) {
390
- return true;
391
- }
392
- if (typeof obj !== 'object' || !obj) {
393
- return false;
394
- }
395
- if (!('constructor' in obj)) {
396
- return false;
397
- }
398
- if (!('name' in obj.constructor)) {
399
- return false;
400
- }
401
- return obj.constructor.name === InternalCLI.name;
389
+ return InternalCLI.isInternalCLI(obj);
402
390
  }
403
391
 
404
392
  function getExamplesFragment(
package/src/index.ts CHANGED
@@ -9,5 +9,6 @@ export type {
9
9
  ExtractChildren,
10
10
  } from './lib/composable-builder';
11
11
  export type { ArgumentsOf } from './lib/utils';
12
+ export type { PromptConfig, PromptOptionConfig, PromptOption, PromptProvider } from './lib/prompt-types';
12
13
  export { ConfigurationProviders } from './lib/configuration-providers';
13
14
  export type { LocalizationDictionary, LocalizationFunction } from '@cli-forge/parser';
@@ -19,7 +19,7 @@ export type ExtractArgs<T> = T extends CLI<infer A, any, any, any> ? A : never;
19
19
  */
20
20
  export type ComposableBuilder<
21
21
  TArgs2 extends ParsedArgs,
22
- // eslint-disable-next-line @typescript-eslint/ban-types
22
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
23
23
  TAddedChildren = {}
24
24
  > = <TInit extends ParsedArgs, THandlerReturn, TChildren, TParent>(
25
25
  init: CLI<TInit, THandlerReturn, TChildren, TParent>
@@ -39,11 +39,11 @@ export type ComposableBuilder<
39
39
  */
40
40
  export function makeComposableBuilder<
41
41
  TArgs2 extends ParsedArgs,
42
- // eslint-disable-next-line @typescript-eslint/ban-types
42
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
43
43
  TChildren2 = {}
44
44
  >(
45
45
  fn: (
46
- // eslint-disable-next-line @typescript-eslint/ban-types
46
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
47
47
  init: CLI<ParsedArgs, any, {}, any>
48
48
  ) => CLI<TArgs2, any, TChildren2, any>
49
49
  ) {