padrone 1.3.0 → 1.5.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.
- package/CHANGELOG.md +94 -0
- package/README.md +105 -284
- package/dist/{args-DFEI7_G_.mjs → args-D5PNDyNu.mjs} +46 -21
- package/dist/args-D5PNDyNu.mjs.map +1 -0
- package/dist/chunk-CjcI7cDX.mjs +15 -0
- package/dist/codegen/index.d.mts +28 -3
- package/dist/codegen/index.d.mts.map +1 -1
- package/dist/codegen/index.mjs +169 -19
- package/dist/codegen/index.mjs.map +1 -1
- package/dist/command-utils-B1D-HqCd.mjs +1117 -0
- package/dist/command-utils-B1D-HqCd.mjs.map +1 -0
- package/dist/completion.d.mts +1 -1
- package/dist/completion.d.mts.map +1 -1
- package/dist/completion.mjs +77 -29
- package/dist/completion.mjs.map +1 -1
- package/dist/docs/index.d.mts +22 -2
- package/dist/docs/index.d.mts.map +1 -1
- package/dist/docs/index.mjs +94 -7
- package/dist/docs/index.mjs.map +1 -1
- package/dist/errors-BiVrBgi6.mjs +114 -0
- package/dist/errors-BiVrBgi6.mjs.map +1 -0
- package/dist/{formatter-XroimS3Q.d.mts → formatter-DtHzbP22.d.mts} +35 -5
- package/dist/formatter-DtHzbP22.d.mts.map +1 -0
- package/dist/help-bbmu9-qd.mjs +735 -0
- package/dist/help-bbmu9-qd.mjs.map +1 -0
- package/dist/index.d.mts +32 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +495 -267
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-mLWIdUIu.mjs +379 -0
- package/dist/mcp-mLWIdUIu.mjs.map +1 -0
- package/dist/serve-B0u43DK7.mjs +404 -0
- package/dist/serve-B0u43DK7.mjs.map +1 -0
- package/dist/stream-BcC146Ud.mjs +56 -0
- package/dist/stream-BcC146Ud.mjs.map +1 -0
- package/dist/test.d.mts +1 -1
- package/dist/test.mjs +4 -15
- package/dist/test.mjs.map +1 -1
- package/dist/{types-BS7RP5Ls.d.mts → types-Ch8Mk6Qb.d.mts} +311 -63
- package/dist/types-Ch8Mk6Qb.d.mts.map +1 -0
- package/dist/{update-check-EbNDkzyV.mjs → update-check-CFX1FV3v.mjs} +2 -2
- package/dist/{update-check-EbNDkzyV.mjs.map → update-check-CFX1FV3v.mjs.map} +1 -1
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.mts.map +1 -0
- package/dist/zod.mjs +50 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +10 -2
- package/src/args.ts +76 -44
- package/src/cli/docs.ts +1 -7
- package/src/cli/doctor.ts +195 -10
- package/src/cli/index.ts +1 -1
- package/src/cli/init.ts +2 -3
- package/src/cli/link.ts +2 -2
- package/src/codegen/discovery.ts +80 -28
- package/src/codegen/index.ts +2 -1
- package/src/codegen/parsers/bash.ts +179 -0
- package/src/codegen/schema-to-code.ts +2 -1
- package/src/colorizer.ts +126 -13
- package/src/command-utils.ts +401 -23
- package/src/completion.ts +120 -47
- package/src/create.ts +483 -130
- package/src/docs/index.ts +122 -8
- package/src/formatter.ts +173 -125
- package/src/help.ts +46 -12
- package/src/index.ts +29 -1
- package/src/interactive.ts +45 -4
- package/src/mcp.ts +390 -0
- package/src/repl-loop.ts +16 -3
- package/src/runtime.ts +195 -2
- package/src/serve.ts +442 -0
- package/src/stream.ts +75 -0
- package/src/test.ts +7 -16
- package/src/type-utils.ts +28 -4
- package/src/types.ts +212 -30
- package/src/wrap.ts +23 -25
- package/src/zod.ts +50 -0
- package/dist/args-DFEI7_G_.mjs.map +0 -1
- package/dist/chunk-y_GBKt04.mjs +0 -5
- package/dist/formatter-XroimS3Q.d.mts.map +0 -1
- package/dist/help-CgGP7hQU.mjs +0 -1229
- package/dist/help-CgGP7hQU.mjs.map +0 -1
- package/dist/types-BS7RP5Ls.d.mts.map +0 -1
package/src/help.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { StandardJSONSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import { extractSchemaMetadata, type PadroneArgsSchemaMeta, parsePositionalConfig, parseStdinConfig } from './args.ts';
|
|
2
|
+
import { extractSchemaMetadata, JSON_SCHEMA_OPTS, type PadroneArgsSchemaMeta, parsePositionalConfig, parseStdinConfig } from './args.ts';
|
|
3
|
+
import type { ColorConfig, ColorTheme } from './colorizer.ts';
|
|
3
4
|
import { findCommandByName } from './command-utils.ts';
|
|
4
5
|
import {
|
|
5
6
|
createFormatter,
|
|
@@ -16,6 +17,9 @@ import { getRootCommand } from './utils.ts';
|
|
|
16
17
|
export type HelpPreferences = {
|
|
17
18
|
format?: HelpFormat | 'auto';
|
|
18
19
|
detail?: HelpDetail;
|
|
20
|
+
theme?: ColorTheme | ColorConfig;
|
|
21
|
+
/** Show all global commands and flags in full detail */
|
|
22
|
+
all?: boolean;
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
/**
|
|
@@ -35,7 +39,7 @@ function extractPositionalArgsInfo(
|
|
|
35
39
|
const positionalConfig = parsePositionalConfig(meta.positional);
|
|
36
40
|
|
|
37
41
|
try {
|
|
38
|
-
const jsonSchema = schema['~standard'].jsonSchema.input(
|
|
42
|
+
const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;
|
|
39
43
|
|
|
40
44
|
if (jsonSchema.type === 'object' && jsonSchema.properties) {
|
|
41
45
|
const properties = jsonSchema.properties as Record<string, any>;
|
|
@@ -54,6 +58,7 @@ function extractPositionalArgsInfo(
|
|
|
54
58
|
optional: !required.includes(name),
|
|
55
59
|
default: prop.default,
|
|
56
60
|
type: variadic ? `array<${prop.items?.type || 'string'}>` : prop.type,
|
|
61
|
+
enum: (prop.enum ?? prop.items?.enum) as string[] | undefined,
|
|
57
62
|
});
|
|
58
63
|
}
|
|
59
64
|
}
|
|
@@ -74,7 +79,7 @@ function extractArgsInfo(schema: StandardJSONSchemaV1, meta?: PadroneArgsSchemaM
|
|
|
74
79
|
const argsMeta = meta?.fields;
|
|
75
80
|
|
|
76
81
|
try {
|
|
77
|
-
const jsonSchema = schema['~standard'].jsonSchema.input(
|
|
82
|
+
const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;
|
|
78
83
|
|
|
79
84
|
// Handle object: z.object({ key: z.string(), ... })
|
|
80
85
|
if (jsonSchema.type === 'object' && jsonSchema.properties) {
|
|
@@ -133,6 +138,7 @@ function extractArgsInfo(schema: StandardJSONSchemaV1, meta?: PadroneArgsSchemaM
|
|
|
133
138
|
examples: optMeta?.examples ?? prop?.examples,
|
|
134
139
|
variadic: propType === 'array',
|
|
135
140
|
negatable: isNegatable,
|
|
141
|
+
group: optMeta?.group,
|
|
136
142
|
});
|
|
137
143
|
}
|
|
138
144
|
}
|
|
@@ -153,7 +159,7 @@ function extractArgsInfo(schema: StandardJSONSchemaV1, meta?: PadroneArgsSchemaM
|
|
|
153
159
|
* @param cmd - The command to build help info for
|
|
154
160
|
* @param detail - The level of detail ('minimal', 'standard', or 'full')
|
|
155
161
|
*/
|
|
156
|
-
export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['detail'] = 'standard'): HelpInfo {
|
|
162
|
+
export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['detail'] = 'standard', all?: boolean): HelpInfo {
|
|
157
163
|
const rootCmd = getRootCommand(cmd);
|
|
158
164
|
// A command is a "default" command if its name is '' or it has '' as an alias
|
|
159
165
|
const isDefaultCommand = cmd.parent && (!cmd.name || cmd.aliases?.includes(''));
|
|
@@ -175,6 +181,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
175
181
|
name: commandName,
|
|
176
182
|
title: cmd.title,
|
|
177
183
|
description: cmd.description,
|
|
184
|
+
examples: cmd.examples,
|
|
178
185
|
aliases: displayAliases,
|
|
179
186
|
deprecated: cmd.deprecated,
|
|
180
187
|
hidden: cmd.hidden,
|
|
@@ -183,7 +190,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
183
190
|
hasSubcommands: !!(cmd.commands && cmd.commands.length > 0),
|
|
184
191
|
hasPositionals,
|
|
185
192
|
hasArguments: false, // updated below after extracting arguments
|
|
186
|
-
stdinField: cmd.meta?.stdin ? parseStdinConfig(cmd.meta.stdin)
|
|
193
|
+
stdinField: cmd.meta?.stdin ? parseStdinConfig(cmd.meta.stdin) : undefined,
|
|
187
194
|
},
|
|
188
195
|
};
|
|
189
196
|
|
|
@@ -221,6 +228,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
221
228
|
aliases: displayAliases?.length ? displayAliases : undefined,
|
|
222
229
|
deprecated: c.deprecated,
|
|
223
230
|
hidden: c.hidden,
|
|
231
|
+
group: c.group,
|
|
224
232
|
},
|
|
225
233
|
{
|
|
226
234
|
name: displayName,
|
|
@@ -229,6 +237,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
229
237
|
deprecated: c.deprecated,
|
|
230
238
|
hidden: c.hidden,
|
|
231
239
|
hasSubcommands: true,
|
|
240
|
+
group: c.group,
|
|
232
241
|
},
|
|
233
242
|
];
|
|
234
243
|
}
|
|
@@ -242,6 +251,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
242
251
|
deprecated: c.deprecated,
|
|
243
252
|
hidden: c.hidden,
|
|
244
253
|
hasSubcommands,
|
|
254
|
+
group: c.group,
|
|
245
255
|
},
|
|
246
256
|
];
|
|
247
257
|
}),
|
|
@@ -284,40 +294,64 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
284
294
|
}
|
|
285
295
|
}
|
|
286
296
|
|
|
287
|
-
// Add
|
|
288
|
-
if (!cmd.parent) {
|
|
297
|
+
// Add global commands/flags (root command by default, all commands when --all is passed)
|
|
298
|
+
if (!cmd.parent || all) {
|
|
289
299
|
const builtins: HelpInfo['builtins'] = [];
|
|
290
300
|
|
|
291
|
-
if (!findCommandByName('help',
|
|
301
|
+
if (!findCommandByName('help', rootCmd.commands)) {
|
|
292
302
|
builtins.push({
|
|
293
303
|
name: 'help [command], -h, --help',
|
|
294
304
|
description: 'Show help for a command',
|
|
295
305
|
sub: [
|
|
306
|
+
{ name: '--all', description: 'Show all global commands and flags' },
|
|
296
307
|
{ name: '--detail <level>', description: 'Detail level (minimal, standard, full)' },
|
|
297
308
|
{ name: '--format <format>', description: 'Output format (text, ansi, json, markdown, html)' },
|
|
298
309
|
],
|
|
299
310
|
});
|
|
300
311
|
}
|
|
301
312
|
|
|
302
|
-
if (!findCommandByName('version',
|
|
313
|
+
if (!findCommandByName('version', rootCmd.commands)) {
|
|
303
314
|
builtins.push({
|
|
304
315
|
name: 'version, -v, --version',
|
|
305
316
|
description: 'Show version information',
|
|
306
317
|
});
|
|
307
318
|
}
|
|
308
319
|
|
|
309
|
-
if (!findCommandByName('completion',
|
|
320
|
+
if (!findCommandByName('completion', rootCmd.commands)) {
|
|
310
321
|
builtins.push({
|
|
311
322
|
name: 'completion [shell]',
|
|
312
323
|
description: 'Generate shell completions (bash, zsh, fish, powershell)',
|
|
313
324
|
});
|
|
314
325
|
}
|
|
315
326
|
|
|
327
|
+
if (!findCommandByName('man', rootCmd.commands)) {
|
|
328
|
+
builtins.push({
|
|
329
|
+
name: 'man',
|
|
330
|
+
description: 'Show or install man pages (--setup to install, --remove to uninstall) (experimental)',
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
316
334
|
builtins.push({
|
|
317
335
|
name: '[command] --repl',
|
|
318
336
|
description: 'Start interactive REPL scoped to a command',
|
|
319
337
|
});
|
|
320
338
|
|
|
339
|
+
if (!findCommandByName('mcp', rootCmd.commands)) {
|
|
340
|
+
builtins.push({
|
|
341
|
+
name: 'mcp [http|stdio]',
|
|
342
|
+
description: 'Start a Model Context Protocol server to expose commands as AI tools (experimental)',
|
|
343
|
+
sub: [
|
|
344
|
+
{ name: '--port <port>', description: 'HTTP port (default: 3000)' },
|
|
345
|
+
{ name: '--host <host>', description: 'HTTP host (default: 127.0.0.1)' },
|
|
346
|
+
],
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
builtins.push({
|
|
351
|
+
name: '--color [theme], --no-color',
|
|
352
|
+
description: 'Set color theme (default, ocean, warm, monochrome) or disable colors',
|
|
353
|
+
});
|
|
354
|
+
|
|
321
355
|
if (builtins.length > 0) {
|
|
322
356
|
helpInfo.builtins = builtins;
|
|
323
357
|
}
|
|
@@ -331,7 +365,7 @@ export function getHelpInfo(cmd: AnyPadroneCommand, detail: HelpPreferences['det
|
|
|
331
365
|
// ============================================================================
|
|
332
366
|
|
|
333
367
|
export function generateHelp(rootCommand: AnyPadroneCommand, commandObj: AnyPadroneCommand = rootCommand, prefs?: HelpPreferences): string {
|
|
334
|
-
const helpInfo = getHelpInfo(commandObj, prefs?.detail);
|
|
335
|
-
const formatter = createFormatter(prefs?.format ?? 'auto', prefs?.detail);
|
|
368
|
+
const helpInfo = getHelpInfo(commandObj, prefs?.detail, prefs?.all);
|
|
369
|
+
const formatter = createFormatter(prefs?.format ?? 'auto', prefs?.detail, prefs?.theme, prefs?.all);
|
|
336
370
|
return formatter.format(helpInfo);
|
|
337
371
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
export type { AnsiStyle, ColorConfig, ColorTheme } from './colorizer.ts';
|
|
2
|
+
export { colorThemes } from './colorizer.ts';
|
|
1
3
|
export { asyncSchema, buildReplCompleter, createPadrone } from './create.ts';
|
|
2
4
|
export type { PadroneErrorOptions } from './errors.ts';
|
|
3
5
|
export { ActionError, ConfigError, PadroneError, RoutingError, ValidationError } from './errors.ts';
|
|
4
6
|
export type { HelpInfo } from './formatter.ts';
|
|
5
|
-
export type {
|
|
7
|
+
export type { PadroneMcpPreferences } from './mcp.ts';
|
|
8
|
+
export type {
|
|
9
|
+
InteractiveMode,
|
|
10
|
+
InteractivePromptConfig,
|
|
11
|
+
PadroneProgressIndicator,
|
|
12
|
+
PadroneProgressOptions,
|
|
13
|
+
PadroneRuntime,
|
|
14
|
+
PadroneSpinnerConfig,
|
|
15
|
+
PadroneSpinnerPreset,
|
|
16
|
+
} from './runtime.ts';
|
|
6
17
|
export { REPL_SIGINT } from './runtime.ts';
|
|
18
|
+
export type { AsyncStreamMeta } from './stream.ts';
|
|
19
|
+
export { asyncStream } from './stream.ts';
|
|
7
20
|
export type { InferArgsInput, InferArgsOutput, InferCommand } from './type-helpers.ts';
|
|
21
|
+
export type { Drained } from './type-utils.ts';
|
|
8
22
|
export type {
|
|
9
23
|
AnyPadroneBuilder,
|
|
10
24
|
AnyPadroneCommand,
|
|
@@ -14,10 +28,24 @@ export type {
|
|
|
14
28
|
PadroneBuilder,
|
|
15
29
|
PadroneCommand,
|
|
16
30
|
PadroneCommandResult,
|
|
31
|
+
PadroneDrainResult,
|
|
17
32
|
PadroneParseResult,
|
|
18
33
|
PadronePlugin,
|
|
19
34
|
PadroneProgram,
|
|
35
|
+
PadroneProgressMessage,
|
|
36
|
+
PadroneProgressPrefs as PadroneProgressConfig,
|
|
20
37
|
PadroneSchema,
|
|
38
|
+
PluginBaseContext,
|
|
39
|
+
PluginErrorContext,
|
|
40
|
+
PluginErrorResult,
|
|
41
|
+
PluginExecuteContext,
|
|
42
|
+
PluginExecuteResult,
|
|
43
|
+
PluginParseContext,
|
|
44
|
+
PluginParseResult,
|
|
45
|
+
PluginShutdownContext,
|
|
46
|
+
PluginStartContext,
|
|
47
|
+
PluginValidateContext,
|
|
48
|
+
PluginValidateResult,
|
|
21
49
|
} from './types.ts';
|
|
22
50
|
export type { UpdateCheckConfig } from './update-check.ts';
|
|
23
51
|
export type { WrapConfig, WrapResult } from './wrap.ts';
|
package/src/interactive.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JSON_SCHEMA_OPTS } from './args.ts';
|
|
1
2
|
import type { InteractivePromptConfig, ResolvedPadroneRuntime } from './runtime.ts';
|
|
2
3
|
import type { AnyPadroneCommand } from './types.ts';
|
|
3
4
|
|
|
@@ -44,6 +45,46 @@ export function detectPromptConfig(
|
|
|
44
45
|
return { name, message, type: 'input', default: propSchema.default };
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Prompt a single field and validate it against the command's schema.
|
|
50
|
+
* Re-prompts with a warning until the user provides a valid value.
|
|
51
|
+
*/
|
|
52
|
+
async function promptWithValidation(
|
|
53
|
+
field: string,
|
|
54
|
+
config: InteractivePromptConfig,
|
|
55
|
+
currentData: Record<string, unknown>,
|
|
56
|
+
command: AnyPadroneCommand,
|
|
57
|
+
runtime: ResolvedPadroneRuntime,
|
|
58
|
+
): Promise<unknown> {
|
|
59
|
+
let promptConfig = config;
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line no-constant-condition
|
|
62
|
+
while (true) {
|
|
63
|
+
const value = await runtime.prompt!(promptConfig);
|
|
64
|
+
|
|
65
|
+
if (!command.argsSchema) return value;
|
|
66
|
+
|
|
67
|
+
// Validate the full object with the new value to catch field-level issues
|
|
68
|
+
const testData = { ...currentData, [field]: value };
|
|
69
|
+
const validated = await command.argsSchema['~standard'].validate(testData);
|
|
70
|
+
|
|
71
|
+
if (!validated.issues) return value;
|
|
72
|
+
|
|
73
|
+
// Only keep issues whose path starts with this field
|
|
74
|
+
const fieldIssues = validated.issues.filter((issue: { path?: ReadonlyArray<PropertyKey> }) => {
|
|
75
|
+
const rootKey = issue.path?.[0];
|
|
76
|
+
return rootKey !== undefined && String(rootKey) === field;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (fieldIssues.length === 0) return value;
|
|
80
|
+
|
|
81
|
+
// Warn the user and re-prompt with the invalid value as default
|
|
82
|
+
const messages = fieldIssues.map((i: { message: string }) => i.message).join('; ');
|
|
83
|
+
runtime.error(`Invalid value for "${field}": ${messages}`);
|
|
84
|
+
promptConfig = { ...config, default: value };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
47
88
|
/**
|
|
48
89
|
* Prompt for missing interactive fields.
|
|
49
90
|
* Runs after env/config preprocessing and before schema validation.
|
|
@@ -69,7 +110,7 @@ export async function promptInteractiveFields(
|
|
|
69
110
|
let requiredFields: Set<string> = new Set();
|
|
70
111
|
if (command.argsSchema) {
|
|
71
112
|
try {
|
|
72
|
-
const jsonSchema = command.argsSchema['~standard'].jsonSchema.input(
|
|
113
|
+
const jsonSchema = command.argsSchema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;
|
|
73
114
|
if (jsonSchema.type === 'object' && jsonSchema.properties) {
|
|
74
115
|
jsonProperties = jsonSchema.properties;
|
|
75
116
|
}
|
|
@@ -108,14 +149,14 @@ export async function promptInteractiveFields(
|
|
|
108
149
|
}
|
|
109
150
|
}
|
|
110
151
|
|
|
111
|
-
// Prompt each required interactive field
|
|
152
|
+
// Prompt each required interactive field with per-field validation
|
|
112
153
|
for (const field of fieldsToPrompt) {
|
|
113
154
|
const config = detectPromptConfig(field, jsonProperties[field], fieldDescriptions[field]);
|
|
114
155
|
// When forced, use the current value as the default
|
|
115
156
|
if (force && result[field] !== undefined) {
|
|
116
157
|
config.default = result[field];
|
|
117
158
|
}
|
|
118
|
-
result[field] = await
|
|
159
|
+
result[field] = await promptWithValidation(field, config, result, command, runtime);
|
|
119
160
|
}
|
|
120
161
|
|
|
121
162
|
// Determine optional interactive fields
|
|
@@ -160,7 +201,7 @@ export async function promptInteractiveFields(
|
|
|
160
201
|
if (force && result[field] !== undefined) {
|
|
161
202
|
config.default = result[field];
|
|
162
203
|
}
|
|
163
|
-
result[field] = await
|
|
204
|
+
result[field] = await promptWithValidation(field, config, result, command, runtime);
|
|
164
205
|
}
|
|
165
206
|
}
|
|
166
207
|
}
|