@reliverse/rempts 1.7.29 → 1.7.30

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 (128) hide show
  1. package/README.md +92 -29
  2. package/bin/{components/animate/animate.js → libs/animate/animate-mod.js} +1 -4
  3. package/bin/{components → libs}/anykey/anykey-mod.js +2 -2
  4. package/bin/libs/confirm/confirm-alias.d.ts +1 -0
  5. package/bin/libs/confirm/confirm-alias.js +2 -0
  6. package/bin/{components/confirm/confirm-prompt.js → libs/confirm/confirm-mod.js} +1 -1
  7. package/bin/{components → libs}/editor/editor-mod.js +8 -8
  8. package/bin/{components → libs}/figures/figures-mod.d.ts +2 -3
  9. package/bin/{components → libs}/figures/figures-mod.js +1 -2
  10. package/bin/libs/input/input-alias.d.ts +4 -0
  11. package/bin/libs/input/input-alias.js +4 -0
  12. package/bin/{components/input/input-prompt.js → libs/input/input-mod.js} +2 -2
  13. package/bin/libs/intro/intro-alias.d.ts +2 -0
  14. package/bin/libs/intro/intro-alias.js +3 -0
  15. package/bin/{components/intro/intro-start.js → libs/intro/intro-mod.js} +3 -3
  16. package/bin/libs/launcher/launcher-alias.d.ts +2 -0
  17. package/bin/libs/launcher/launcher-alias.js +2 -0
  18. package/bin/{components → libs}/launcher/launcher-mod.d.ts +37 -5
  19. package/bin/{components → libs}/launcher/launcher-mod.js +326 -205
  20. package/bin/{components → libs}/launcher/launcher-types.d.ts +1 -1
  21. package/bin/libs/launcher/trpc-orpc-support/completions.d.ts +4 -0
  22. package/bin/libs/launcher/trpc-orpc-support/completions.js +45 -0
  23. package/bin/libs/launcher/trpc-orpc-support/errors.d.ts +11 -0
  24. package/bin/libs/launcher/trpc-orpc-support/errors.js +10 -0
  25. package/bin/libs/launcher/trpc-orpc-support/index.d.ts +34 -0
  26. package/bin/libs/launcher/trpc-orpc-support/index.js +641 -0
  27. package/bin/libs/launcher/trpc-orpc-support/json-schema.d.ts +17 -0
  28. package/bin/libs/launcher/trpc-orpc-support/json-schema.js +168 -0
  29. package/bin/libs/launcher/trpc-orpc-support/json.d.ts +44 -0
  30. package/bin/libs/launcher/trpc-orpc-support/json.js +41 -0
  31. package/bin/libs/launcher/trpc-orpc-support/logging.d.ts +11 -0
  32. package/bin/libs/launcher/trpc-orpc-support/logging.js +26 -0
  33. package/bin/libs/launcher/trpc-orpc-support/parse-procedure.d.ts +2 -0
  34. package/bin/libs/launcher/trpc-orpc-support/parse-procedure.js +486 -0
  35. package/bin/libs/launcher/trpc-orpc-support/prompts.d.ts +18 -0
  36. package/bin/libs/launcher/trpc-orpc-support/prompts.js +534 -0
  37. package/bin/libs/launcher/trpc-orpc-support/standard-schema/contract.d.ts +53 -0
  38. package/bin/libs/launcher/trpc-orpc-support/standard-schema/contract.js +0 -0
  39. package/bin/libs/launcher/trpc-orpc-support/standard-schema/errors.d.ts +9 -0
  40. package/bin/libs/launcher/trpc-orpc-support/standard-schema/errors.js +47 -0
  41. package/bin/libs/launcher/trpc-orpc-support/standard-schema/utils.d.ts +3 -0
  42. package/bin/libs/launcher/trpc-orpc-support/standard-schema/utils.js +6 -0
  43. package/bin/libs/launcher/trpc-orpc-support/trpc-compat.d.ts +71 -0
  44. package/bin/libs/launcher/trpc-orpc-support/trpc-compat.js +11 -0
  45. package/bin/libs/launcher/trpc-orpc-support/types.d.ts +276 -0
  46. package/bin/libs/launcher/trpc-orpc-support/types.js +0 -0
  47. package/bin/libs/launcher/trpc-orpc-support/util.d.ts +9 -0
  48. package/bin/libs/launcher/trpc-orpc-support/util.js +9 -0
  49. package/bin/{components → libs}/msg-fmt/logger.js +1 -1
  50. package/bin/libs/multiselect/multiselect-alias.d.ts +1 -0
  51. package/bin/libs/multiselect/multiselect-alias.js +2 -0
  52. package/bin/{components/select → libs/multiselect}/multiselect-prompt.js +1 -1
  53. package/bin/{components → libs}/number/number-mod.js +1 -4
  54. package/bin/libs/outro/outro-alias.d.ts +2 -0
  55. package/bin/libs/outro/outro-alias.js +3 -0
  56. package/bin/{components/outro/outro-end.js → libs/outro/outro-mod.js} +2 -2
  57. package/bin/libs/select/aliases-alias.d.ts +1 -0
  58. package/bin/libs/select/aliases-alias.js +2 -0
  59. package/bin/{components → libs}/select/select-prompt.js +2 -2
  60. package/bin/{components → libs}/select/toggle-prompt.js +1 -1
  61. package/bin/libs/spinner/spinner-alias.d.ts +1 -0
  62. package/bin/libs/spinner/spinner-alias.js +2 -0
  63. package/bin/{components → libs}/spinner/spinner-mod.js +3 -1
  64. package/bin/{components → libs}/task/task-spin.js +1 -1
  65. package/bin/{utils → libs/utils}/colorize.d.ts +1 -1
  66. package/bin/{utils → libs/utils}/prevent.d.ts +1 -1
  67. package/bin/{utils → libs/utils}/prevent.js +2 -2
  68. package/bin/{utils → libs/utils}/prompt-end.d.ts +1 -1
  69. package/bin/{utils → libs/utils}/prompt-end.js +2 -2
  70. package/bin/{utils → libs/utils}/stream-text.d.ts +1 -1
  71. package/bin/{utils → libs/utils}/stream-text.js +2 -2
  72. package/bin/mod.d.ts +66 -41
  73. package/bin/mod.js +102 -66
  74. package/package.json +16 -2
  75. package/bin/components/aliases/aliases-mod.d.ts +0 -11
  76. package/bin/components/aliases/aliases-mod.js +0 -16
  77. /package/bin/{components/animate/animate.d.ts → libs/animate/animate-mod.d.ts} +0 -0
  78. /package/bin/{components → libs}/anykey/anykey-mod.d.ts +0 -0
  79. /package/bin/{components → libs}/cancel/cancel.d.ts +0 -0
  80. /package/bin/{components → libs}/cancel/cancel.js +0 -0
  81. /package/bin/{components/confirm/confirm-prompt.d.ts → libs/confirm/confirm-mod.d.ts} +0 -0
  82. /package/bin/{components → libs}/date/date.d.ts +0 -0
  83. /package/bin/{components → libs}/date/date.js +0 -0
  84. /package/bin/{components → libs}/editor/editor-mod.d.ts +0 -0
  85. /package/bin/{components/input/input-prompt.d.ts → libs/input/input-mod.d.ts} +0 -0
  86. /package/bin/{components/intro/intro-start.d.ts → libs/intro/intro-mod.d.ts} +0 -0
  87. /package/bin/{components → libs}/launcher/launcher-types.js +0 -0
  88. /package/bin/{components → libs}/launcher/run-command.d.ts +0 -0
  89. /package/bin/{components → libs}/launcher/run-command.js +0 -0
  90. /package/bin/{components/log/log.d.ts → libs/log/log-alias.d.ts} +0 -0
  91. /package/bin/{components/log/log.js → libs/log/log-alias.js} +0 -0
  92. /package/bin/{components → libs}/msg-fmt/colors.d.ts +0 -0
  93. /package/bin/{components → libs}/msg-fmt/colors.js +0 -0
  94. /package/bin/{components → libs}/msg-fmt/logger.d.ts +0 -0
  95. /package/bin/{components → libs}/msg-fmt/mapping.d.ts +0 -0
  96. /package/bin/{components → libs}/msg-fmt/mapping.js +0 -0
  97. /package/bin/{components → libs}/msg-fmt/messages.d.ts +0 -0
  98. /package/bin/{components → libs}/msg-fmt/messages.js +0 -0
  99. /package/bin/{components → libs}/msg-fmt/terminal.d.ts +0 -0
  100. /package/bin/{components → libs}/msg-fmt/terminal.js +0 -0
  101. /package/bin/{components → libs}/msg-fmt/variants.d.ts +0 -0
  102. /package/bin/{components → libs}/msg-fmt/variants.js +0 -0
  103. /package/bin/{components/select → libs/multiselect}/multiselect-prompt.d.ts +0 -0
  104. /package/bin/{components → libs}/next-steps/next-steps.d.ts +0 -0
  105. /package/bin/{components → libs}/next-steps/next-steps.js +0 -0
  106. /package/bin/{components → libs}/number/number-mod.d.ts +0 -0
  107. /package/bin/{components/outro/outro-end.d.ts → libs/outro/outro-mod.d.ts} +0 -0
  108. /package/bin/{components → libs}/results/results.d.ts +0 -0
  109. /package/bin/{components → libs}/results/results.js +0 -0
  110. /package/bin/{components → libs}/select/nummultiselect-prompt.d.ts +0 -0
  111. /package/bin/{components → libs}/select/nummultiselect-prompt.js +0 -0
  112. /package/bin/{components → libs}/select/numselect-prompt.d.ts +0 -0
  113. /package/bin/{components → libs}/select/numselect-prompt.js +0 -0
  114. /package/bin/{components → libs}/select/select-prompt.d.ts +0 -0
  115. /package/bin/{components → libs}/select/toggle-prompt.d.ts +0 -0
  116. /package/bin/{components → libs}/spinner/spinner-mod.d.ts +0 -0
  117. /package/bin/{components → libs}/task/progress.d.ts +0 -0
  118. /package/bin/{components → libs}/task/progress.js +0 -0
  119. /package/bin/{components → libs}/task/task-spin.d.ts +0 -0
  120. /package/bin/{utils → libs/utils}/colorize.js +0 -0
  121. /package/bin/{utils → libs/utils}/errors.d.ts +0 -0
  122. /package/bin/{utils → libs/utils}/errors.js +0 -0
  123. /package/bin/{utils → libs/utils}/system.d.ts +0 -0
  124. /package/bin/{utils → libs/utils}/system.js +0 -0
  125. /package/bin/{utils → libs/utils}/validate.d.ts +0 -0
  126. /package/bin/{utils → libs/utils}/validate.js +0 -0
  127. /package/bin/{components/ascii-art/ascii-art.d.ts → libs/visual/visual-mod.d.ts} +0 -0
  128. /package/bin/{components/ascii-art/ascii-art.js → libs/visual/visual-mod.js} +0 -0
@@ -0,0 +1,534 @@
1
+ import { Argument, Command, Option } from "commander";
2
+ const parseUpstreamOptionInfo = (value) => {
3
+ if (typeof value !== "string" || !value.startsWith("{")) return null;
4
+ try {
5
+ const info = JSON.parse(value);
6
+ if (info.typeName !== "UpstreamOptionInfo") return null;
7
+ return info;
8
+ } catch {
9
+ return null;
10
+ }
11
+ };
12
+ const parseUpstreamArgumentInfo = (value) => {
13
+ if (typeof value !== "string" || !value.startsWith("{")) return null;
14
+ try {
15
+ const info = JSON.parse(value);
16
+ if (info.typeName !== "UpstreamArgumentInfo") return null;
17
+ return info;
18
+ } catch {
19
+ return null;
20
+ }
21
+ };
22
+ const getDefaultSubcommand = (command) => {
23
+ const defaultChild = /Available subcommands:.* (\S+) \(default\)/.exec(
24
+ command.description()
25
+ )?.[1];
26
+ return defaultChild ? command.commands.find((c) => c.name() === defaultChild) : void 0;
27
+ };
28
+ export const createShadowCommand = (command, onAnalyze) => {
29
+ const shadow = new Command(command.name());
30
+ shadow.exitOverride();
31
+ shadow.configureOutput({
32
+ writeOut: () => {
33
+ },
34
+ writeErr: () => {
35
+ }
36
+ });
37
+ const argumentsMap = /* @__PURE__ */ new Map();
38
+ const optionsMap = /* @__PURE__ */ new Map();
39
+ command.options.forEach((original) => {
40
+ const id = Date.now().toString() + Math.random().toString().slice(1);
41
+ const shadowOption = new Option(
42
+ original.flags.replace("<", "[").replace(">", "]"),
43
+ JSON.stringify([`id=${id}`, original.description])
44
+ );
45
+ const upstreamOptionInfo = {
46
+ typeName: "UpstreamOptionInfo",
47
+ id,
48
+ specified: false
49
+ };
50
+ shadowOption.default(JSON.stringify(upstreamOptionInfo));
51
+ shadowOption.argParser(
52
+ (value) => JSON.stringify({ ...upstreamOptionInfo, specified: true, value })
53
+ );
54
+ shadow.addOption(shadowOption);
55
+ optionsMap.set(id, { shadow: shadowOption, original });
56
+ });
57
+ command.registeredArguments.forEach((original) => {
58
+ const shadowArgument = new Argument(original.name(), original.description);
59
+ const id = Date.now().toString() + Math.random().toString().slice(1);
60
+ shadowArgument.argOptional();
61
+ const upstreamArgumentInfo = {
62
+ typeName: "UpstreamArgumentInfo",
63
+ id,
64
+ specified: false
65
+ };
66
+ shadowArgument.default(JSON.stringify(upstreamArgumentInfo));
67
+ shadowArgument.argParser(
68
+ (value) => JSON.stringify({ ...upstreamArgumentInfo, specified: true, value })
69
+ );
70
+ shadow.addArgument(shadowArgument);
71
+ argumentsMap.set(id, { shadow: shadowArgument, original });
72
+ });
73
+ const analysis = {
74
+ command: { shadow, original: command },
75
+ arguments: [],
76
+ options: []
77
+ };
78
+ shadow.action(async (...args) => {
79
+ const positionalValues = args.slice(0, -2);
80
+ const options = shadow.opts();
81
+ if (args.at(-2) !== options) {
82
+ throw new Error(
83
+ "Unexpected args format, second last arg is not the options object",
84
+ { cause: args }
85
+ );
86
+ }
87
+ if (args.at(-1) !== shadow) {
88
+ throw new Error(
89
+ "Unexpected args format, last arg is not the Command instance",
90
+ { cause: args }
91
+ );
92
+ }
93
+ positionalValues.forEach((value) => {
94
+ const argumentInfo = parseUpstreamArgumentInfo(value);
95
+ if (argumentInfo) {
96
+ analysis.arguments.push({
97
+ ...argumentsMap.get(argumentInfo.id),
98
+ value: argumentInfo.value,
99
+ specified: argumentInfo.specified
100
+ });
101
+ }
102
+ });
103
+ Object.values(options).forEach((value) => {
104
+ const upstreamOptionInfo = parseUpstreamOptionInfo(value);
105
+ if (upstreamOptionInfo) {
106
+ analysis.options.push({
107
+ ...optionsMap.get(upstreamOptionInfo.id),
108
+ value: upstreamOptionInfo.value,
109
+ specified: upstreamOptionInfo.specified
110
+ });
111
+ }
112
+ });
113
+ await onAnalyze(analysis);
114
+ });
115
+ command.commands.forEach((subcommand) => {
116
+ const shadowSubcommand = createShadowCommand(subcommand, onAnalyze);
117
+ shadow.addCommand(shadowSubcommand);
118
+ });
119
+ return shadow;
120
+ };
121
+ const inquirerPrompter = (prompts) => {
122
+ return prompts;
123
+ };
124
+ const clackPrompter = (prompts) => {
125
+ const clack = prompts;
126
+ class ExitPromptError extends Error {
127
+ }
128
+ const throwOnCancel = (value) => {
129
+ if (clack.isCancel(value)) throw new ExitPromptError();
130
+ return value;
131
+ };
132
+ return {
133
+ input: async (params) => {
134
+ return clack.text({
135
+ message: params.message,
136
+ initialValue: params.default,
137
+ defaultValue: params.default,
138
+ placeholder: params.default,
139
+ validate: params.validate ? (input) => {
140
+ const result = params.validate(input);
141
+ if (result === true) return void 0;
142
+ if (result === false) return "Invalid input";
143
+ return result;
144
+ } : void 0
145
+ }).then(throwOnCancel);
146
+ },
147
+ checkbox: async (params) => {
148
+ return clack.multiselect({
149
+ message: params.message,
150
+ options: params.choices.map((c) => ({
151
+ label: c.name,
152
+ value: c.value
153
+ })),
154
+ initialValues: params.choices.flatMap(
155
+ (c) => c.checked ? [c.value] : []
156
+ )
157
+ }).then(throwOnCancel);
158
+ },
159
+ confirm: async (params) => {
160
+ return clack.confirm({
161
+ message: params.message,
162
+ initialValue: params.default
163
+ }).then(throwOnCancel);
164
+ },
165
+ select: async (params) => {
166
+ return clack.select({
167
+ message: params.message,
168
+ options: params.choices.map((sorc) => {
169
+ const c = typeof sorc === "string" ? { name: sorc, value: sorc } : sorc;
170
+ return {
171
+ label: c.name,
172
+ value: c.value,
173
+ hint: c.description
174
+ };
175
+ }),
176
+ initialValue: params.default
177
+ }).then(throwOnCancel);
178
+ }
179
+ };
180
+ };
181
+ const promptsPrompter = (prompts) => {
182
+ const p = prompts;
183
+ function x() {
184
+ return (value) => value.x;
185
+ }
186
+ return {
187
+ input: async (params) => {
188
+ return p({
189
+ name: "x",
190
+ type: "text",
191
+ message: params.message,
192
+ validate: params.validate,
193
+ initial: params.default
194
+ }).then(x());
195
+ },
196
+ confirm: async (params) => {
197
+ return p({
198
+ name: "x",
199
+ type: "confirm",
200
+ message: params.message,
201
+ active: params.default ? "yes" : "no"
202
+ }).then(x());
203
+ },
204
+ select: async (params) => {
205
+ const choicesObjects = params.choices.map(
206
+ (c) => typeof c === "string" ? { name: c, value: c } : c
207
+ );
208
+ return p({
209
+ name: "x",
210
+ type: "select",
211
+ message: params.message,
212
+ active: params.default,
213
+ choices: choicesObjects.map((c) => ({
214
+ title: c.name || c.value,
215
+ value: c.value
216
+ })),
217
+ initial: params.default ? choicesObjects.findIndex((c) => c.value === params.default) : void 0
218
+ }).then(x());
219
+ },
220
+ checkbox: async (params) => {
221
+ const choicesObjects = params.choices.map(
222
+ (c) => typeof c === "string" ? { name: c, value: c } : c
223
+ );
224
+ return p({
225
+ name: "x",
226
+ type: "multiselect",
227
+ message: params.message,
228
+ choices: choicesObjects.map((c) => ({
229
+ title: c.name || c.value,
230
+ value: c.value,
231
+ selected: c.checked
232
+ }))
233
+ }).then(x());
234
+ }
235
+ };
236
+ };
237
+ const enquirerPrompter = (prompts) => {
238
+ const enquirer = prompts;
239
+ function x() {
240
+ return (value) => value.x;
241
+ }
242
+ return {
243
+ input: async (params) => {
244
+ return enquirer.prompt({
245
+ type: "input",
246
+ name: "x",
247
+ message: params.message,
248
+ validate: params.validate,
249
+ initial: params.default
250
+ }).then(x());
251
+ },
252
+ confirm: async (params) => {
253
+ return enquirer.prompt({
254
+ type: "confirm",
255
+ name: "x",
256
+ message: params.message,
257
+ validate: params.validate,
258
+ initial: params.default
259
+ }).then(x());
260
+ },
261
+ select: async (params) => {
262
+ return enquirer.prompt({
263
+ type: "select",
264
+ name: "x",
265
+ message: params.message,
266
+ // @ts-expect-error not sure why this is an error, in the IDE it infers the type correctly
267
+ choices: params.choices.slice(),
268
+ validate: params.validate,
269
+ initial: params.default
270
+ }).then(x());
271
+ },
272
+ checkbox: async (params) => {
273
+ return enquirer.prompt({
274
+ type: "multiselect",
275
+ name: "x",
276
+ message: params.message,
277
+ // @ts-expect-error not sure why this is an error, in the IDE it infers the type correctly
278
+ choices: params.choices.slice().map((c) => ({
279
+ name: c.name,
280
+ value: c.value
281
+ })),
282
+ // validate: params.validate ? v => params.validate!([{value: v}]) : undefined,
283
+ initial: params.choices.flatMap((c, i) => c.checked ? [i] : [])
284
+ }).then(x());
285
+ }
286
+ };
287
+ };
288
+ export const promptify = (program, prompts) => {
289
+ let promptsInput = prompts;
290
+ if (promptsInput?.default) promptsInput = promptsInput.default;
291
+ let prompter;
292
+ if (typeof promptsInput === "function" && typeof promptsInput.inject === "function") {
293
+ prompter = promptsPrompter(promptsInput);
294
+ } else if (promptsInput?.name === "Enquirer") {
295
+ prompter = enquirerPrompter(promptsInput);
296
+ } else if (typeof promptsInput?.rawlist === "function") {
297
+ prompter = inquirerPrompter(promptsInput);
298
+ } else if (typeof promptsInput?.intro === "function") {
299
+ prompter = clackPrompter(promptsInput);
300
+ } else if (typeof promptsInput === "function") {
301
+ prompter = promptsInput(program);
302
+ } else {
303
+ prompter = promptsInput;
304
+ }
305
+ const command = program;
306
+ const analyseThenParse = async (argv, parseOptions) => {
307
+ if (parseOptions?.from === "electron") {
308
+ console.warn(
309
+ `Warning: using prompts in electron mode is untested. The first two args of $0 are not available in electron mode. Assuming that the first two args of ${JSON.stringify(argv)} are electron-related and not intended for the CLI.`
310
+ );
311
+ }
312
+ if (parseOptions?.from !== "user") {
313
+ argv = argv.slice(2);
314
+ parseOptions = { from: "user" };
315
+ }
316
+ const f = { command, args: [...argv] };
317
+ const nextArgv = [...f.args];
318
+ let analysis;
319
+ const maxAttempts = 100;
320
+ for (let i = maxAttempts; i >= 0 && !analysis; i--) {
321
+ analysis = await new Promise((resolve, reject) => {
322
+ const shadow = createShadowCommand(f.command, async (an) => {
323
+ if (an.command.original.commands.length === 0) {
324
+ resolve(an);
325
+ return;
326
+ }
327
+ const defaultSubcommand = getDefaultSubcommand(an.command.original);
328
+ if (defaultSubcommand) {
329
+ resolve(an);
330
+ return;
331
+ }
332
+ const name = await prompter.select(
333
+ {
334
+ message: `Select a ${an.command.original.name() || ""} subcommand`.replace(
335
+ " ",
336
+ " "
337
+ ),
338
+ choices: an.command.original.commands.map((c) => ({
339
+ name: c.name(),
340
+ value: c.name(),
341
+ description: c.description()
342
+ }))
343
+ },
344
+ {}
345
+ );
346
+ nextArgv.push(name);
347
+ resolve(void 0);
348
+ });
349
+ shadow.parseAsync(nextArgv, parseOptions).catch((e) => {
350
+ if (e?.constructor?.name === "CommanderError") {
351
+ resolve({
352
+ command: { shadow: f.command, original: f.command },
353
+ arguments: [],
354
+ options: []
355
+ });
356
+ } else {
357
+ reject(e);
358
+ }
359
+ });
360
+ });
361
+ }
362
+ if (!analysis) {
363
+ const message = `Failed to find a subcommand after ${maxAttempts} attempts - failing to avoid an infinite loop. This is probably a bug in @reliverse/rempts.`;
364
+ throw new Error(message);
365
+ }
366
+ const getMessage = (argOrOpt) => {
367
+ const name = "long" in argOrOpt ? argOrOpt.flags : `[${argOrOpt.name()}]`;
368
+ const parts = [
369
+ name,
370
+ argOrOpt.description,
371
+ argOrOpt.defaultValue && `(default: ${argOrOpt.defaultValue})`,
372
+ !argOrOpt.defaultValue && !argOrOpt.required && "(optional)"
373
+ ];
374
+ return `${parts.filter(Boolean).join(" ").trim()}:`;
375
+ };
376
+ const baseContext = {
377
+ command: analysis.command.original,
378
+ inputs: {
379
+ argv,
380
+ arguments: analysis.arguments.map((a) => ({
381
+ name: a.original.name(),
382
+ specified: a.specified,
383
+ value: a.value
384
+ })),
385
+ options: analysis.options.map((o) => ({
386
+ name: o.original.name(),
387
+ specified: o.specified,
388
+ value: o.value
389
+ }))
390
+ }
391
+ };
392
+ await prompter.setup?.(baseContext);
393
+ const promptConfig = "necessary";
394
+ let shouldPrompt;
395
+ if (promptConfig === "always") {
396
+ shouldPrompt = true;
397
+ } else if (promptConfig === "never") {
398
+ shouldPrompt = false;
399
+ } else {
400
+ promptConfig;
401
+ const someRequiredArgsUnspecified = analysis.arguments.some(
402
+ (a) => a.original.required && !a.specified
403
+ );
404
+ const someRequiredOptionsUnspecified = analysis.options.some(
405
+ (o) => o.original.required && !o.specified
406
+ );
407
+ shouldPrompt = someRequiredArgsUnspecified || someRequiredOptionsUnspecified;
408
+ }
409
+ if (shouldPrompt) {
410
+ for (const arg of analysis.arguments) {
411
+ const ctx = { ...baseContext, argument: arg.original };
412
+ if (!arg.specified) {
413
+ const parseArg = "parseArg" in arg.original && typeof arg.original.parseArg === "function" ? arg.original.parseArg : void 0;
414
+ const promptedValue = await prompter.input(
415
+ {
416
+ message: getMessage(arg.original),
417
+ required: arg.original.required,
418
+ default: arg.value,
419
+ validate: (input) => {
420
+ try {
421
+ parseArg?.(input);
422
+ return true;
423
+ } catch (e) {
424
+ return e?.message || e;
425
+ }
426
+ }
427
+ },
428
+ ctx
429
+ );
430
+ nextArgv.push(promptedValue);
431
+ }
432
+ }
433
+ for (const option of analysis.options) {
434
+ const ctx = { ...baseContext, option: option.original };
435
+ if (!option.specified) {
436
+ const fullFlag = option.original.long || `--${option.original.name()}`;
437
+ const isBoolean = option.original.isBoolean() || option.original.flags.includes("[boolean]");
438
+ if (isBoolean) {
439
+ const promptedValue = await prompter.confirm(
440
+ {
441
+ message: getMessage(option.original),
442
+ default: option.original.defaultValue ?? false
443
+ },
444
+ ctx
445
+ );
446
+ if (promptedValue) nextArgv.push(fullFlag);
447
+ } else if (option.original.variadic && option.original.argChoices) {
448
+ const choices = option.original.argChoices.slice();
449
+ const results = await prompter.checkbox(
450
+ {
451
+ message: getMessage(option.original),
452
+ choices: choices.map((choice) => ({
453
+ value: choice,
454
+ name: choice,
455
+ checked: true
456
+ }))
457
+ },
458
+ ctx
459
+ );
460
+ results.forEach((result) => {
461
+ if (typeof result === "string") nextArgv.push(fullFlag, result);
462
+ });
463
+ } else if (option.original.argChoices) {
464
+ const choices = option.original.argChoices.slice();
465
+ const set = new Set(choices);
466
+ const promptedValue = await prompter.select(
467
+ {
468
+ message: getMessage(option.original),
469
+ choices,
470
+ default: option.original.defaultValue
471
+ // required: option.original.required,
472
+ },
473
+ ctx
474
+ );
475
+ if (set.has(promptedValue)) {
476
+ nextArgv.push(fullFlag, promptedValue);
477
+ }
478
+ } else if (option.original.variadic) {
479
+ const values = [];
480
+ do {
481
+ const promptedValue = await prompter.input(
482
+ {
483
+ message: getMessage(option.original),
484
+ default: option.original.defaultValue?.[values.length]
485
+ },
486
+ ctx
487
+ );
488
+ if (!promptedValue) break;
489
+ values.push(fullFlag, promptedValue);
490
+ } while (values);
491
+ nextArgv.push(...values);
492
+ } else {
493
+ const getParsedValue = (input) => {
494
+ return option.original.parseArg ? option.original.parseArg(
495
+ input,
496
+ void 0
497
+ ) : input;
498
+ };
499
+ const promptedValue = await prompter.input(
500
+ {
501
+ message: getMessage(option.original),
502
+ default: option.value,
503
+ required: option.original.required,
504
+ validate: (input) => {
505
+ const parsed = getParsedValue(input);
506
+ if (parsed == null && input != null) return "Invalid value";
507
+ return true;
508
+ }
509
+ },
510
+ ctx
511
+ );
512
+ if (promptedValue)
513
+ nextArgv.push(
514
+ fullFlag,
515
+ getParsedValue(promptedValue) ?? promptedValue
516
+ );
517
+ }
518
+ }
519
+ }
520
+ }
521
+ await prompter.teardown?.(baseContext);
522
+ return f.command.parseAsync(nextArgv, parseOptions);
523
+ };
524
+ const parseAsync = (args, parseOptions) => analyseThenParse(args, parseOptions).catch((e) => {
525
+ if (e?.constructor?.name === "ExitPromptError") return;
526
+ throw e;
527
+ });
528
+ return new Proxy(program, {
529
+ get(target, prop, receiver) {
530
+ if (prop === "parseAsync") return parseAsync;
531
+ return Reflect.get(target, prop, receiver);
532
+ }
533
+ });
534
+ };
@@ -0,0 +1,53 @@
1
+ /** The Standard Schema interface. */
2
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ /** The Standard Schema properties. */
4
+ readonly "~standard": StandardSchemaV1Props<Input, Output>;
5
+ }
6
+ /** The Standard Schema properties interface. */
7
+ export interface StandardSchemaV1Props<Input = unknown, Output = Input> {
8
+ /** The version number of the standard. */
9
+ readonly version: 1;
10
+ /** The vendor name of the schema library. */
11
+ readonly vendor: string;
12
+ /** Validates unknown input values. */
13
+ readonly validate: (value: unknown) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>;
14
+ /** Inferred types associated with the schema. */
15
+ readonly types?: StandardSchemaV1Types<Input, Output> | undefined;
16
+ }
17
+ /** The result interface of the validate function. */
18
+ export type StandardSchemaV1Result<Output> = StandardSchemaV1SuccessResult<Output> | StandardSchemaV1FailureResult;
19
+ /** The result interface if validation succeeds. */
20
+ export interface StandardSchemaV1SuccessResult<Output> {
21
+ /** The typed output value. */
22
+ readonly value: Output;
23
+ /** The non-existent issues. */
24
+ readonly issues?: undefined;
25
+ }
26
+ /** The result interface if validation fails. */
27
+ export interface StandardSchemaV1FailureResult {
28
+ /** The issues of failed validation. */
29
+ readonly issues: readonly StandardSchemaV1Issue[];
30
+ }
31
+ /** The issue interface of the failure output. */
32
+ export interface StandardSchemaV1Issue {
33
+ /** The error message of the issue. */
34
+ readonly message: string;
35
+ /** The path of the issue, if any. */
36
+ readonly path?: readonly (PropertyKey | StandardSchemaV1PathSegment)[] | undefined;
37
+ }
38
+ /** The path segment interface of the issue. */
39
+ export interface StandardSchemaV1PathSegment {
40
+ /** The key representing a path segment. */
41
+ readonly key: PropertyKey;
42
+ }
43
+ /** The Standard Schema types interface. */
44
+ export interface StandardSchemaV1Types<Input = unknown, Output = Input> {
45
+ /** The input type of the schema. */
46
+ readonly input: Input;
47
+ /** The output type of the schema. */
48
+ readonly output: Output;
49
+ }
50
+ /** Infers the input type of a Standard Schema. */
51
+ export type StandardSchemaV1InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
52
+ /** Infers the output type of a Standard Schema. */
53
+ export type StandardSchemaV1InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
@@ -0,0 +1,9 @@
1
+ import type { StandardSchemaV1FailureResult } from "./contract";
2
+ export declare const prettifyStandardSchemaError: (error: unknown) => string | null;
3
+ export declare function toDotPath(path: (string | number | symbol)[]): string;
4
+ export declare class StandardSchemaV1Error extends Error implements StandardSchemaV1FailureResult {
5
+ issues: StandardSchemaV1FailureResult["issues"];
6
+ constructor(failure: StandardSchemaV1FailureResult, options?: {
7
+ cause?: Error;
8
+ });
9
+ }
@@ -0,0 +1,47 @@
1
+ import { looksLikeStandardSchemaFailure } from "./utils.js";
2
+ export const prettifyStandardSchemaError = (error) => {
3
+ if (!looksLikeStandardSchemaFailure(error)) return null;
4
+ const issues = [...error.issues].map((issue) => {
5
+ const path = issue.path || [];
6
+ const primitivePathSegments = path.map((segment) => {
7
+ if (typeof segment === "string" || typeof segment === "number" || typeof segment === "symbol")
8
+ return segment;
9
+ return segment.key;
10
+ });
11
+ const dotPath = toDotPath(primitivePathSegments);
12
+ return {
13
+ issue,
14
+ path,
15
+ primitivePathSegments,
16
+ dotPath
17
+ };
18
+ }).sort((a, b) => a.path.length - b.path.length);
19
+ const lines = [];
20
+ for (const { issue, dotPath } of issues) {
21
+ let message = `\u2716 ${issue.message}`;
22
+ if (dotPath) message += ` \u2192 at ${dotPath}`;
23
+ lines.push(message);
24
+ }
25
+ return lines.join("\n");
26
+ };
27
+ export function toDotPath(path) {
28
+ const segs = [];
29
+ for (const seg of path) {
30
+ if (typeof seg === "number") segs.push(`[${seg}]`);
31
+ else if (typeof seg === "symbol")
32
+ segs.push(`[${JSON.stringify(String(seg))}]`);
33
+ else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
34
+ else {
35
+ if (segs.length) segs.push(".");
36
+ segs.push(seg);
37
+ }
38
+ }
39
+ return segs.join("");
40
+ }
41
+ export class StandardSchemaV1Error extends Error {
42
+ issues;
43
+ constructor(failure, options) {
44
+ super("Standard Schema error - details in `issues`.", options);
45
+ this.issues = failure.issues;
46
+ }
47
+ }
@@ -0,0 +1,3 @@
1
+ import type { StandardSchemaV1, StandardSchemaV1FailureResult } from "./contract";
2
+ export declare const looksLikeStandardSchemaFailure: (error: unknown) => error is StandardSchemaV1FailureResult;
3
+ export declare const looksLikeStandardSchema: (thing: unknown) => thing is StandardSchemaV1;
@@ -0,0 +1,6 @@
1
+ export const looksLikeStandardSchemaFailure = (error) => {
2
+ return !!error && typeof error === "object" && "issues" in error && Array.isArray(error.issues);
3
+ };
4
+ export const looksLikeStandardSchema = (thing) => {
5
+ return !!thing && typeof thing === "object" && "~standard" in thing && typeof thing["~standard"] === "object";
6
+ };