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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { n as asyncStreamRegistry } from "./stream-BcC146Ud.mjs";
|
|
1
2
|
//#region src/args.ts
|
|
2
3
|
/**
|
|
3
4
|
* Convert a camelCase string to kebab-case.
|
|
@@ -8,17 +9,37 @@ function camelToKebab(str) {
|
|
|
8
9
|
return str.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`);
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Returns the stdin field name from the config.
|
|
12
13
|
*/
|
|
13
14
|
function parseStdinConfig(stdin) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
return stdin;
|
|
16
|
+
}
|
|
17
|
+
/** Options passed to `jsonSchema.input()` to handle unrepresentable types like `z.custom()`. */
|
|
18
|
+
const JSON_SCHEMA_OPTS = {
|
|
19
|
+
target: "draft-2020-12",
|
|
20
|
+
libraryOptions: { unrepresentable: "any" }
|
|
21
|
+
};
|
|
22
|
+
function getFieldJsonSchema(schema, field) {
|
|
23
|
+
if (!schema) return void 0;
|
|
24
|
+
try {
|
|
25
|
+
const jsonSchema = schema["~standard"].jsonSchema.input(JSON_SCHEMA_OPTS);
|
|
26
|
+
if (jsonSchema.type === "object" && jsonSchema.properties) return jsonSchema.properties[field];
|
|
27
|
+
} catch {}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Checks if a field in the schema is an array type (e.g. `z.string().array()`).
|
|
31
|
+
*/
|
|
32
|
+
function isArrayField(schema, field) {
|
|
33
|
+
return getFieldJsonSchema(schema, field)?.type === "array";
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Checks if a field is an async stream (marked with `asyncStream()` metadata).
|
|
37
|
+
* Returns the item schema if provided, or `true` if it's a plain string stream.
|
|
38
|
+
*/
|
|
39
|
+
function isAsyncStreamField(schema, field) {
|
|
40
|
+
const asyncStreamId = getFieldJsonSchema(schema, field)?.asyncStream;
|
|
41
|
+
if (asyncStreamId && asyncStreamRegistry.has(asyncStreamId)) return { itemSchema: asyncStreamRegistry.get(asyncStreamId)?.itemSchema };
|
|
42
|
+
return false;
|
|
22
43
|
}
|
|
23
44
|
/**
|
|
24
45
|
* Parse positional configuration to extract names and variadic info.
|
|
@@ -50,7 +71,7 @@ function extractSchemaMetadata(schema, meta, autoAlias) {
|
|
|
50
71
|
if (value.alias) addEntries(aliases, key, value.alias, (item) => item.length > 1);
|
|
51
72
|
}
|
|
52
73
|
try {
|
|
53
|
-
const jsonSchema = schema["~standard"].jsonSchema.input(
|
|
74
|
+
const jsonSchema = schema["~standard"].jsonSchema.input(JSON_SCHEMA_OPTS);
|
|
54
75
|
if (jsonSchema.type === "object" && jsonSchema.properties) for (const [propertyName, propertySchema] of Object.entries(jsonSchema.properties)) {
|
|
55
76
|
if (!propertySchema) continue;
|
|
56
77
|
const propFlags = propertySchema.flags;
|
|
@@ -113,7 +134,7 @@ function preprocessArgs(data, ctx) {
|
|
|
113
134
|
function coerceArgs(data, schema) {
|
|
114
135
|
let properties;
|
|
115
136
|
try {
|
|
116
|
-
const jsonSchema = schema["~standard"].jsonSchema.input(
|
|
137
|
+
const jsonSchema = schema["~standard"].jsonSchema.input(JSON_SCHEMA_OPTS);
|
|
117
138
|
if (jsonSchema.type !== "object" || !jsonSchema.properties) return data;
|
|
118
139
|
properties = jsonSchema.properties;
|
|
119
140
|
} catch {
|
|
@@ -131,25 +152,29 @@ function coerceArgs(data, schema) {
|
|
|
131
152
|
}
|
|
132
153
|
} else if (targetType === "boolean") {
|
|
133
154
|
if (typeof value === "string") {
|
|
134
|
-
|
|
135
|
-
|
|
155
|
+
const lower = value.toLowerCase();
|
|
156
|
+
if (lower === "true" || lower === "1" || lower === "yes" || lower === "on") result[key] = true;
|
|
157
|
+
else if (lower === "false" || lower === "0" || lower === "no" || lower === "off") result[key] = false;
|
|
136
158
|
}
|
|
137
|
-
} else if (targetType === "array"
|
|
159
|
+
} else if (targetType === "array") {
|
|
160
|
+
const arr = Array.isArray(value) ? value : [value];
|
|
138
161
|
const itemType = prop.items?.type;
|
|
139
|
-
if (itemType === "number" || itemType === "integer") result[key] =
|
|
162
|
+
if (itemType === "number" || itemType === "integer") result[key] = arr.map((v) => {
|
|
140
163
|
if (typeof v === "string") {
|
|
141
164
|
const num = Number(v);
|
|
142
165
|
return Number.isNaN(num) ? v : num;
|
|
143
166
|
}
|
|
144
167
|
return v;
|
|
145
168
|
});
|
|
146
|
-
else if (itemType === "boolean") result[key] =
|
|
169
|
+
else if (itemType === "boolean") result[key] = arr.map((v) => {
|
|
147
170
|
if (typeof v === "string") {
|
|
148
|
-
|
|
149
|
-
if (
|
|
171
|
+
const lower = v.toLowerCase();
|
|
172
|
+
if (lower === "true" || lower === "1" || lower === "yes" || lower === "on") return true;
|
|
173
|
+
if (lower === "false" || lower === "0" || lower === "no" || lower === "off") return false;
|
|
150
174
|
}
|
|
151
175
|
return v;
|
|
152
176
|
});
|
|
177
|
+
else if (!Array.isArray(value)) result[key] = arr;
|
|
153
178
|
}
|
|
154
179
|
}
|
|
155
180
|
return result;
|
|
@@ -165,7 +190,7 @@ function detectUnknownArgs(data, schema, flags, aliases, suggestFn) {
|
|
|
165
190
|
let properties;
|
|
166
191
|
let isLoose = false;
|
|
167
192
|
try {
|
|
168
|
-
const jsonSchema = schema["~standard"].jsonSchema.input(
|
|
193
|
+
const jsonSchema = schema["~standard"].jsonSchema.input(JSON_SCHEMA_OPTS);
|
|
169
194
|
if (jsonSchema.type !== "object" || !jsonSchema.properties) return [];
|
|
170
195
|
properties = jsonSchema.properties;
|
|
171
196
|
if (jsonSchema.additionalProperties !== void 0 && jsonSchema.additionalProperties !== false) isLoose = true;
|
|
@@ -192,6 +217,6 @@ function detectUnknownArgs(data, schema, flags, aliases, suggestFn) {
|
|
|
192
217
|
return unknowns;
|
|
193
218
|
}
|
|
194
219
|
//#endregion
|
|
195
|
-
export {
|
|
220
|
+
export { extractSchemaMetadata as a, parsePositionalConfig as c, detectUnknownArgs as i, parseStdinConfig as l, camelToKebab as n, isArrayField as o, coerceArgs as r, isAsyncStreamField as s, JSON_SCHEMA_OPTS as t, preprocessArgs as u };
|
|
196
221
|
|
|
197
|
-
//# sourceMappingURL=args-
|
|
222
|
+
//# sourceMappingURL=args-D5PNDyNu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args-D5PNDyNu.mjs","names":[],"sources":["../src/args.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec';\nimport { asyncStreamRegistry } from './stream.ts';\n\ntype Letter =\n | 'a'\n | 'b'\n | 'c'\n | 'd'\n | 'e'\n | 'f'\n | 'g'\n | 'h'\n | 'i'\n | 'j'\n | 'k'\n | 'l'\n | 'm'\n | 'n'\n | 'o'\n | 'p'\n | 'q'\n | 'r'\n | 's'\n | 't'\n | 'u'\n | 'v'\n | 'w'\n | 'x'\n | 'y'\n | 'z';\n\n/** A single letter character, valid as a short CLI flag (e.g. `'v'`, `'n'`, `'V'`). */\nexport type SingleChar = Letter | Uppercase<Letter>;\n\nexport interface PadroneFieldMeta {\n description?: string;\n /** Single-character short flags (stackable: `-abc` = `-a -b -c`). Used with single dash. */\n flags?: readonly SingleChar[] | SingleChar;\n /** Multi-character alternative long names. Used with double dash (e.g. `--dry-run` for `--dryRun`). */\n alias?: readonly string[] | string;\n deprecated?: boolean | string;\n hidden?: boolean;\n examples?: readonly unknown[];\n /** Group name for organizing this option under a labeled section in help output. */\n group?: string;\n}\n\ntype PositionalArgs<TObj> =\n TObj extends Record<string, any>\n ? {\n [K in keyof TObj]: NonNullable<TObj[K]> extends Array<any> ? `...${K & string}` | (K & string) : K & string;\n }[keyof TObj]\n : string;\n\n/**\n * Meta configuration for arguments, including positional arguments.\n * The `positional` array defines which arguments are positional and their order.\n * Use '...name' prefix to indicate variadic (rest) arguments, matching JS/TS rest syntax.\n *\n * @example\n * ```ts\n * .arguments(schema, {\n * positional: ['source', '...files', 'dest'], // '...files' is variadic\n * })\n * ```\n */\n/**\n * Configuration for reading from stdin and mapping it to an argument field.\n * Simply specify the field name — the read mode is inferred from the schema:\n * - `string` field → reads all stdin as text\n * - `string[]` field → reads stdin line-by-line\n */\nexport type StdinConfig<TObj = Record<string, any>> = keyof TObj & string;\n\nexport interface PadroneArgsSchemaMeta<TObj = Record<string, any>> {\n /**\n * Array of argument names that should be treated as positional arguments.\n * Order in array determines position. Use '...name' prefix for variadic args.\n * @example ['source', '...files', 'dest'] - 'files' captures multiple values\n */\n positional?: readonly PositionalArgs<TObj>[];\n /**\n * Per-argument metadata.\n */\n fields?: { [K in keyof TObj]?: PadroneFieldMeta };\n /**\n * Automatically generate kebab-case aliases for camelCase option names.\n * For example, `dryRun` automatically gets `--dry-run` as an alias.\n * Defaults to `true`. Set to `false` to disable.\n *\n * @default true\n * @example\n * ```ts\n * // Auto-aliases enabled (default): --dry-run → dryRun\n * .arguments(z.object({ dryRun: z.boolean() }))\n *\n * // Disable auto-aliases\n * .arguments(z.object({ dryRun: z.boolean() }), { autoAlias: false })\n * ```\n */\n autoAlias?: boolean;\n /**\n * Read from stdin and inject the data into the specified argument field.\n * Only reads when stdin is piped (not a TTY) and the field wasn't already provided via CLI flags.\n *\n * The read mode is inferred from the schema type of the target field:\n * - `string` field → reads all stdin as a single string\n * - `string[]` field → reads stdin line-by-line into an array\n *\n * Precedence: CLI flags > stdin > env vars > config file > schema defaults.\n *\n * @example\n * ```ts\n * // Read all stdin as text into 'data' field\n * .arguments(z.object({ data: z.string() }), { stdin: 'data' })\n *\n * // Read stdin lines into 'lines' field (inferred from array schema)\n * .arguments(z.object({ lines: z.string().array() }), { stdin: 'lines' })\n * ```\n */\n stdin?: StdinConfig<TObj>;\n /**\n * Fields to interactively prompt for when their values are missing after CLI/env/config resolution.\n * - `true`: prompt for all required fields that are missing.\n * - `string[]`: prompt for these specific fields if missing.\n *\n * Interactive prompting only occurs in `cli()` when the runtime has `interactive: true`.\n * Setting this makes `parse()` and `cli()` return Promises.\n *\n * @example\n * ```ts\n * .arguments(schema, {\n * interactive: true, // prompt all missing required fields\n * interactive: ['name', 'template'], // prompt only these fields\n * })\n * ```\n */\n interactive?: true | readonly (keyof TObj & string)[];\n /**\n * Optional fields offered after required interactive prompts.\n * Users are shown a multi-select to choose which of these fields to configure.\n * - `true`: offer all optional fields that are missing.\n * - `string[]`: offer these specific fields.\n *\n * @example\n * ```ts\n * .arguments(schema, {\n * interactive: ['name'],\n * optionalInteractive: ['typescript', 'eslint', 'prettier'],\n * })\n * ```\n */\n optionalInteractive?: true | readonly (keyof TObj & string)[];\n}\n\n/**\n * Convert a camelCase string to kebab-case.\n * Returns null if the string has no uppercase letters (no conversion needed).\n */\nexport function camelToKebab(str: string): string | null {\n if (!/[A-Z]/.test(str)) return null;\n return str.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`);\n}\n\n/**\n * Returns the stdin field name from the config.\n */\nexport function parseStdinConfig(stdin: StdinConfig): string {\n return stdin;\n}\n\n/** Options passed to `jsonSchema.input()` to handle unrepresentable types like `z.custom()`. */\nexport const JSON_SCHEMA_OPTS = { target: 'draft-2020-12', libraryOptions: { unrepresentable: 'any' } } as const;\n\nfunction getFieldJsonSchema(schema: StandardJSONSchemaV1 | undefined, field: string): Record<string, any> | undefined {\n if (!schema) return undefined;\n try {\n const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;\n if (jsonSchema.type === 'object' && jsonSchema.properties) return jsonSchema.properties[field];\n } catch {}\n return undefined;\n}\n\n/**\n * Checks if a field in the schema is an array type (e.g. `z.string().array()`).\n */\nexport function isArrayField(schema: StandardJSONSchemaV1 | undefined, field: string): boolean {\n return getFieldJsonSchema(schema, field)?.type === 'array';\n}\n\n/**\n * Checks if a field is an async stream (marked with `asyncStream()` metadata).\n * Returns the item schema if provided, or `true` if it's a plain string stream.\n */\nexport function isAsyncStreamField(schema: StandardJSONSchemaV1 | undefined, field: string): { itemSchema?: StandardSchemaV1 } | false {\n const prop = getFieldJsonSchema(schema, field);\n const asyncStreamId = prop?.asyncStream;\n if (asyncStreamId && asyncStreamRegistry.has(asyncStreamId)) {\n const meta = asyncStreamRegistry.get(asyncStreamId);\n return { itemSchema: meta?.itemSchema };\n }\n\n return false;\n}\n\n/**\n * Parse positional configuration to extract names and variadic info.\n */\nexport function parsePositionalConfig(positional: readonly string[]): { name: string; variadic: boolean }[] {\n return positional.map((p) => {\n const isVariadic = p.startsWith('...');\n const name = isVariadic ? p.slice(3) : p;\n return { name, variadic: isVariadic };\n });\n}\n\n/**\n * Result type for extractSchemaMetadata function.\n */\ninterface SchemaMetadataResult {\n /** Single-char flags: maps flag char → full arg name (e.g. `{ v: 'verbose' }`) */\n flags: Record<string, string>;\n /** Multi-char aliases: maps alias → full arg name (e.g. `{ 'dry-run': 'dryRun' }`) */\n aliases: Record<string, string>;\n}\n\nfunction addEntries(target: Record<string, string>, key: string, items: string | readonly string[], filter?: (item: string) => boolean) {\n const list = typeof items === 'string' ? [items] : items;\n for (const item of list) {\n if (typeof item === 'string' && item && item !== key && !(item in target) && (!filter || filter(item))) {\n target[item] = key;\n }\n }\n}\n\n/**\n * Extract all arg metadata from schema and meta in a single pass.\n * Returns flags (single-char, stackable) and aliases (multi-char, long names) separately.\n * When `autoAlias` is true (default), camelCase property names automatically get kebab-case aliases.\n */\nexport function extractSchemaMetadata(\n schema: StandardJSONSchemaV1,\n meta?: Record<string, PadroneFieldMeta | undefined>,\n autoAlias?: boolean,\n): SchemaMetadataResult {\n const flags: Record<string, string> = {};\n const aliases: Record<string, string> = {};\n\n // Extract from meta object\n if (meta) {\n for (const [key, value] of Object.entries(meta)) {\n if (!value) continue;\n\n if (value.flags) {\n addEntries(flags, key, value.flags, (item) => item.length === 1);\n }\n if (value.alias) {\n addEntries(aliases, key, value.alias, (item) => item.length > 1);\n }\n }\n }\n\n // Extract from JSON schema properties\n try {\n const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;\n if (jsonSchema.type === 'object' && jsonSchema.properties) {\n for (const [propertyName, propertySchema] of Object.entries(jsonSchema.properties as Record<string, any>)) {\n if (!propertySchema) continue;\n\n // Extract flags from schema `.meta({ flags: ... })`\n const propFlags = propertySchema.flags;\n if (propFlags) {\n addEntries(flags, propertyName, propFlags, (item) => item.length === 1);\n }\n\n // Extract aliases from schema `.meta({ alias: ... })`\n const propAlias = propertySchema.alias;\n if (propAlias) {\n const list = typeof propAlias === 'string' ? [propAlias] : propAlias;\n if (Array.isArray(list)) {\n addEntries(aliases, propertyName, list, (item) => item.length > 1);\n }\n }\n\n // Auto-generate kebab-case alias for camelCase property names\n if (autoAlias !== false) {\n const kebab = camelToKebab(propertyName);\n if (kebab && !(kebab in aliases)) {\n aliases[kebab] = propertyName;\n }\n }\n }\n }\n } catch {\n // Ignore errors from JSON schema generation\n }\n\n return { flags, aliases };\n}\n\nfunction preprocessMappings(data: Record<string, unknown>, mappings: Record<string, string>): Record<string, unknown> {\n const result = { ...data };\n\n for (const [mappedKey, fullArgName] of Object.entries(mappings)) {\n if (mappedKey in data && mappedKey !== fullArgName) {\n const mappedValue = data[mappedKey];\n // Prefer full arg name if it exists\n if (!(fullArgName in result)) result[fullArgName] = mappedValue;\n delete result[mappedKey];\n }\n }\n\n return result;\n}\n\ninterface ParseArgsContext {\n flags?: Record<string, string>;\n aliases?: Record<string, string>;\n stdinData?: Record<string, unknown>;\n envData?: Record<string, unknown>;\n configData?: Record<string, unknown>;\n}\n\n/**\n * Apply values directly to arguments.\n * CLI values take precedence over the provided values.\n */\nfunction applyValues(data: Record<string, unknown>, values: Record<string, unknown>): Record<string, unknown> {\n const result = { ...data };\n\n for (const [key, value] of Object.entries(values)) {\n // Only apply value if arg wasn't already set\n if (key in result && result[key] !== undefined) continue;\n if (value !== undefined) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Combined preprocessing of arguments with all features.\n * Precedence order (highest to lowest): CLI args > stdin > env vars > config file\n */\nexport function preprocessArgs(data: Record<string, unknown>, ctx: ParseArgsContext): Record<string, unknown> {\n let result = { ...data };\n\n // 1. Apply flags and aliases first\n if (ctx.flags && Object.keys(ctx.flags).length > 0) {\n result = preprocessMappings(result, ctx.flags);\n }\n if (ctx.aliases && Object.keys(ctx.aliases).length > 0) {\n result = preprocessMappings(result, ctx.aliases);\n }\n\n // 2. Apply stdin data (higher precedence than env)\n // Only applies if CLI didn't set the arg\n if (ctx.stdinData) {\n result = applyValues(result, ctx.stdinData);\n }\n\n // 3. Apply environment variables (higher precedence than config)\n // These only apply if CLI/stdin didn't set the arg\n if (ctx.envData) {\n result = applyValues(result, ctx.envData);\n }\n\n // 4. Apply config file values (lowest precedence)\n // These only apply if neither CLI, stdin, nor env set the arg\n if (ctx.configData) {\n result = applyValues(result, ctx.configData);\n }\n\n return result;\n}\n\n/**\n * Auto-coerce CLI string values to match the expected schema types.\n * Handles: string → number, string → boolean for primitive schema fields.\n * Arrays of primitives are also coerced element-wise.\n */\nexport function coerceArgs(data: Record<string, unknown>, schema: StandardJSONSchemaV1): Record<string, unknown> {\n let properties: Record<string, any>;\n try {\n const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;\n if (jsonSchema.type !== 'object' || !jsonSchema.properties) return data;\n properties = jsonSchema.properties;\n } catch {\n return data;\n }\n\n const result = { ...data };\n\n for (const [key, value] of Object.entries(result)) {\n const prop = properties[key];\n if (!prop) continue;\n\n const targetType = prop.type as string | undefined;\n\n if (targetType === 'number' || targetType === 'integer') {\n if (typeof value === 'string') {\n const num = Number(value);\n if (!Number.isNaN(num)) result[key] = num;\n }\n } else if (targetType === 'boolean') {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 'on') result[key] = true;\n else if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'off') result[key] = false;\n }\n } else if (targetType === 'array') {\n // Coerce single items to array\n const arr = Array.isArray(value) ? value : [value];\n const itemType = prop.items?.type as string | undefined;\n if (itemType === 'number' || itemType === 'integer') {\n result[key] = arr.map((v) => {\n if (typeof v === 'string') {\n const num = Number(v);\n return Number.isNaN(num) ? v : num;\n }\n return v;\n });\n } else if (itemType === 'boolean') {\n result[key] = arr.map((v) => {\n if (typeof v === 'string') {\n const lower = v.toLowerCase();\n if (lower === 'true' || lower === '1' || lower === 'yes' || lower === 'on') return true;\n if (lower === 'false' || lower === '0' || lower === 'no' || lower === 'off') return false;\n }\n return v;\n });\n } else if (!Array.isArray(value)) {\n result[key] = arr;\n }\n }\n }\n\n return result;\n}\n\n/** Keys consumed by the CLI framework that are not user-defined args. */\nconst frameworkReservedKeys = new Set(['config', 'c']);\n\n/**\n * Detect unknown keys in the args that don't match any schema property.\n * Returns an array of { key, suggestion? } for each unknown key.\n * Framework-reserved keys (--config, -c) are always allowed.\n */\nexport function detectUnknownArgs(\n data: Record<string, unknown>,\n schema: StandardJSONSchemaV1,\n flags: Record<string, string>,\n aliases: Record<string, string>,\n suggestFn: (input: string, candidates: string[]) => string,\n): { key: string; suggestion: string }[] {\n let properties: Record<string, any>;\n let isLoose = false;\n try {\n const jsonSchema = schema['~standard'].jsonSchema.input(JSON_SCHEMA_OPTS) as Record<string, any>;\n if (jsonSchema.type !== 'object' || !jsonSchema.properties) return [];\n properties = jsonSchema.properties;\n // If additionalProperties is set (true, {}, or a schema), the schema allows extra keys\n if (jsonSchema.additionalProperties !== undefined && jsonSchema.additionalProperties !== false) isLoose = true;\n } catch {\n return [];\n }\n\n if (isLoose) return [];\n\n const knownKeys = new Set<string>([\n ...Object.keys(properties),\n ...Object.keys(flags),\n ...Object.values(flags),\n ...Object.keys(aliases),\n ...Object.values(aliases),\n ]);\n const propertyNames = Object.keys(properties);\n const unknowns: { key: string; suggestion: string }[] = [];\n\n for (const key of Object.keys(data)) {\n if (!knownKeys.has(key) && !frameworkReservedKeys.has(key)) {\n const suggestion = suggestFn(key, propertyNames);\n unknowns.push({ key, suggestion });\n }\n }\n\n return unknowns;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __exportAll = (all, no_symbols) => {
|
|
5
|
+
let target = {};
|
|
6
|
+
for (var name in all) __defProp(target, name, {
|
|
7
|
+
get: all[name],
|
|
8
|
+
enumerable: true
|
|
9
|
+
});
|
|
10
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
14
|
+
//#endregion
|
|
15
|
+
export { __require as n, __exportAll as t };
|
package/dist/codegen/index.d.mts
CHANGED
|
@@ -149,11 +149,15 @@ type TemplateFunction = (text: string) => (data: Record<string, unknown>) => str
|
|
|
149
149
|
declare function createCodeBuilder(): CodeBuilder;
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region src/codegen/discovery.d.ts
|
|
152
|
-
type DiscoverySource = 'help' | 'fish' | 'zsh';
|
|
152
|
+
type DiscoverySource = 'help' | 'completion' | 'bash' | 'fish' | 'zsh';
|
|
153
153
|
interface DiscoveryOptions {
|
|
154
154
|
/** The command to discover (e.g. 'gh', 'docker', 'kubectl'). */
|
|
155
155
|
command: string;
|
|
156
|
-
/**
|
|
156
|
+
/**
|
|
157
|
+
* Which parsing sources to use. Default: ['help'].
|
|
158
|
+
* Use `'completion'` to auto-detect the best shell completion source
|
|
159
|
+
* by probing `<cmd> completion <shell>` (bash → fish → zsh).
|
|
160
|
+
*/
|
|
157
161
|
sources?: DiscoverySource[];
|
|
158
162
|
/** Max subcommand depth. 0 = root only, undefined = unlimited. */
|
|
159
163
|
depth?: number;
|
|
@@ -177,6 +181,12 @@ interface DiscoveryResult {
|
|
|
177
181
|
* parsing shell completion scripts.
|
|
178
182
|
*/
|
|
179
183
|
declare function discoverCli(options: DiscoveryOptions): Promise<DiscoveryResult>;
|
|
184
|
+
/**
|
|
185
|
+
* Detect the best shell for completion parsing by probing the command.
|
|
186
|
+
* Tries `<cmd> completion <shell>` for bash, fish, zsh (in that order).
|
|
187
|
+
* Returns the shell name if successful, or null if no completion command exists.
|
|
188
|
+
*/
|
|
189
|
+
declare function detectCompletionShell(command: string, timeout?: number): Promise<'bash' | 'fish' | 'zsh' | null>;
|
|
180
190
|
//#endregion
|
|
181
191
|
//#region src/codegen/file-emitter.d.ts
|
|
182
192
|
/**
|
|
@@ -224,6 +234,21 @@ interface CommandTreeOptions {
|
|
|
224
234
|
*/
|
|
225
235
|
declare function generateCommandTree(root: CommandMeta, ctx: GeneratorContext, options?: CommandTreeOptions): void;
|
|
226
236
|
//#endregion
|
|
237
|
+
//#region src/codegen/parsers/bash.d.ts
|
|
238
|
+
/**
|
|
239
|
+
* Parse bash completion scripts into CommandMeta.
|
|
240
|
+
*
|
|
241
|
+
* Bash completions typically use `complete -F <func> <command>` and define
|
|
242
|
+
* a function that sets COMPREPLY. Common patterns:
|
|
243
|
+
*
|
|
244
|
+
* local commands="init build deploy"
|
|
245
|
+
* local args="--verbose --output --format"
|
|
246
|
+
* case "$prev" in --format) COMPREPLY=($(compgen -W "json yaml toml" ...)) ;;
|
|
247
|
+
* COMPREPLY=($(compgen -W "$commands" ...))
|
|
248
|
+
* COMPREPLY=($(compgen -W "$args" ...))
|
|
249
|
+
*/
|
|
250
|
+
declare function parseBashCompletions(text: string): CommandMeta;
|
|
251
|
+
//#endregion
|
|
227
252
|
//#region src/codegen/parsers/fish.d.ts
|
|
228
253
|
/**
|
|
229
254
|
* Parse fish shell completion scripts into CommandMeta.
|
|
@@ -301,5 +326,5 @@ type TemplateRenderer = (data: Record<string, unknown>, partials?: Record<string
|
|
|
301
326
|
*/
|
|
302
327
|
declare function template(text: string): TemplateRenderer;
|
|
303
328
|
//#endregion
|
|
304
|
-
export { type CodeBuildResult, type CodeBuilder, type CommandFileOptions, type CommandMeta, type CommandTreeOptions, type DiscoveryOptions, type DiscoveryResult, type DiscoverySource, type EmitResult, type FieldMeta, type FileEmitter, type FileEmitterOptions, type GeneratorContext, type GeneratorLogger, type TemplateFunction, createCodeBuilder, createFileEmitter, discoverCli, fieldMetaToCode, generateBarrelFile, generateCommandFile, generateCommandTree, mergeCommandMeta, parseFishCompletions, parseHelpOutput, parseZshCompletions, schemaToCode, template };
|
|
329
|
+
export { type CodeBuildResult, type CodeBuilder, type CommandFileOptions, type CommandMeta, type CommandTreeOptions, type DiscoveryOptions, type DiscoveryResult, type DiscoverySource, type EmitResult, type FieldMeta, type FileEmitter, type FileEmitterOptions, type GeneratorContext, type GeneratorLogger, type TemplateFunction, createCodeBuilder, createFileEmitter, detectCompletionShell, discoverCli, fieldMetaToCode, generateBarrelFile, generateCommandFile, generateCommandTree, mergeCommandMeta, parseBashCompletions, parseFishCompletions, parseHelpOutput, parseZshCompletions, schemaToCode, template };
|
|
305
330
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/codegen/types.ts","../../src/codegen/code-builder.ts","../../src/codegen/discovery.ts","../../src/codegen/file-emitter.ts","../../src/codegen/generators/barrel-file.ts","../../src/codegen/generators/command-file.ts","../../src/codegen/generators/command-tree.ts","../../src/codegen/parsers/fish.ts","../../src/codegen/parsers/help.ts","../../src/codegen/parsers/merge.ts","../../src/codegen/parsers/zsh.ts","../../src/codegen/schema-to-code.ts","../../src/codegen/template.ts"],"mappings":";;;;;;UAGiB,SAAA;EACf,IAAA;EACA,IAAA;EAFwB;EAIxB,KAAA;EAFA;EAIA,UAAA;EACA,WAAA;EACA,OAAA;EACA,QAAA;EACA,OAAA;EACA,UAAA;EAAA;EAEA,SAAA;AAAA;;AAOF;;;UAAiB,WAAA;EACf,IAAA;EACA,WAAA;EACA,OAAA;EAMyB;EAJzB,SAAA,GAAY,SAAA;EAHZ;EAKA,WAAA,GAAc,SAAA;EAFd;EAIA,WAAA,GAAc,WAAA;EACd,QAAA;EACA,UAAA;AAAA;;;;UAMe,eAAA;EACf,IAAA,CAAK,OAAA;EACL,IAAA,CAAK,OAAA;EACL,KAAA,CAAM,OAAA;EACN,OAAA,CAAQ,OAAA;AAAA;;;;UAMO,gBAAA;EAPf;EASA,MAAA;EARA;EAUA,iBAAA,QAAyB,WAAA;EAVF;EAYvB,OAAA,EAAS,WAAA;EANM;EAQf,QAAA,EAAU,gBAAA;;EAEV,GAAA,EAAK,eAAA;AAAA;;;;UAMU,eAAA;EAdf;EAgBA,IAAA;EAdyB;EAgBzB,OAAA,EAAS,GAAA;IAAc,UAAA,EAAY,GAAA;IAAa,QAAA;EAAA;AAAA;;;;UAMjC,WAAA;EAVe;EAY9B,MAAA,CAAO,SAAA,qBAA8B,MAAA,WAAiB,WAAA;EAR1C;EAUZ,aAAA,CAAc,IAAA,UAAc,MAAA,WAAiB,WAAA;EAV7C;EAYA,UAAA,CAAW,SAAA,qBAA8B,MAAA,WAAiB,WAAA;EAZnC;EAcvB,IAAA,CAAK,IAAA,YAAgB,WAAA;EAd2B;EAgBhD,KAAA,CAAM,OAAA,GAAU,CAAA,EAAG,WAAA,KAAgB,WAAA,GAAc,WAAA;EAhBO;EAkBxD,KAAA,CAAM,IAAA,UAAc,OAAA,GAAU,CAAA,EAAG,WAAA,KAAgB,WAAA,EAAa,KAAA,YAAiB,WAAA;EAZrD;EAc1B,KAAA,CAAM,IAAA,UAAc,KAAA,UAAe,OAAA,GAAU,CAAA,EAAG,WAAA,KAAgB,WAAA,GAAc,WAAA;EAZxB;EActD,OAAA,CAAQ,IAAA,WAAe,WAAA;EAVmC;EAY1D,UAAA,CAAW,IAAA,WAAe,WAAA;EARP;EAUnB,WAAA,CAAY,IAAA,WAAe,WAAA;EAVsB;EAYjD,GAAA,CAAI,IAAA,WAAe,WAAA;EAV8B;EAYjD,KAAA,IAAS,eAAA;AAAA;;;;UAMM,UAAA;EAVY;EAY3B,OAAA;EARS;EAUT,OAAA;EAVwB;EAYxB,MAAA;IAAU,IAAA;IAAc,KAAA,EAAO,KAAA;EAAA;AAAA;;;;UAMhB,kBAAA;EApCJ;EAsCX,MAAA;EAtC0D;EAwC1D,MAAA;EAtCK;EAwCL,SAAA;EAtCA;EAwCA,MAAA;AAAA;;;;UAMe,WAAA;EA5CT;EA8CN,OAAA,CAAQ,IAAA,UAAc,OAAA,WAAkB,eAAA;EA9CV;EAgD9B,IAAA,IAAQ,OAAA,CAAQ,UAAA;AAAA;;;;KAMN,gBAAA,IAAoB,IAAA,cAAkB,IAAA,EAAM,MAAA;;;;;AA3IxD;iBC4NgB,iBAAA,CAAA,GAAqB,WAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/codegen/types.ts","../../src/codegen/code-builder.ts","../../src/codegen/discovery.ts","../../src/codegen/file-emitter.ts","../../src/codegen/generators/barrel-file.ts","../../src/codegen/generators/command-file.ts","../../src/codegen/generators/command-tree.ts","../../src/codegen/parsers/bash.ts","../../src/codegen/parsers/fish.ts","../../src/codegen/parsers/help.ts","../../src/codegen/parsers/merge.ts","../../src/codegen/parsers/zsh.ts","../../src/codegen/schema-to-code.ts","../../src/codegen/template.ts"],"mappings":"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"}
|
package/dist/codegen/index.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { t as JSON_SCHEMA_OPTS } from "../args-D5PNDyNu.mjs";
|
|
1
2
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { execFile } from "node:child_process";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
3
6
|
//#region src/codegen/code-builder.ts
|
|
4
7
|
var CodeBuilderImpl = class CodeBuilderImpl {
|
|
5
8
|
imports = /* @__PURE__ */ new Map();
|
|
@@ -182,6 +185,115 @@ function createCodeBuilder() {
|
|
|
182
185
|
return new CodeBuilderImpl();
|
|
183
186
|
}
|
|
184
187
|
//#endregion
|
|
188
|
+
//#region src/codegen/parsers/bash.ts
|
|
189
|
+
/**
|
|
190
|
+
* Parse bash completion scripts into CommandMeta.
|
|
191
|
+
*
|
|
192
|
+
* Bash completions typically use `complete -F <func> <command>` and define
|
|
193
|
+
* a function that sets COMPREPLY. Common patterns:
|
|
194
|
+
*
|
|
195
|
+
* local commands="init build deploy"
|
|
196
|
+
* local args="--verbose --output --format"
|
|
197
|
+
* case "$prev" in --format) COMPREPLY=($(compgen -W "json yaml toml" ...)) ;;
|
|
198
|
+
* COMPREPLY=($(compgen -W "$commands" ...))
|
|
199
|
+
* COMPREPLY=($(compgen -W "$args" ...))
|
|
200
|
+
*/
|
|
201
|
+
function parseBashCompletions(text) {
|
|
202
|
+
const result = {
|
|
203
|
+
name: "",
|
|
204
|
+
arguments: [],
|
|
205
|
+
subcommands: []
|
|
206
|
+
};
|
|
207
|
+
const completeMatch = text.match(/complete\s+(?:[^-]|-[^F])*-F\s+\S+\s+(\S+)/);
|
|
208
|
+
if (completeMatch) result.name = completeMatch[1];
|
|
209
|
+
if (!result.name) {
|
|
210
|
+
const markerMatch = text.match(/###-begin-(\S+)-completion-###/);
|
|
211
|
+
if (markerMatch) result.name = markerMatch[1];
|
|
212
|
+
}
|
|
213
|
+
const joined = text.replace(/\\\n\s*/g, " ");
|
|
214
|
+
const variables = extractVariables(joined);
|
|
215
|
+
const commandWords = variables.get("commands") ?? variables.get("cmds") ?? variables.get("subcommands");
|
|
216
|
+
if (commandWords) for (const name of splitWords(commandWords)) result.subcommands.push({ name });
|
|
217
|
+
const argWords = variables.get("args") ?? variables.get("opts") ?? variables.get("options") ?? variables.get("flags");
|
|
218
|
+
const optionNames = /* @__PURE__ */ new Set();
|
|
219
|
+
if (argWords) {
|
|
220
|
+
for (const word of splitWords(argWords)) if (word.startsWith("-")) optionNames.add(word);
|
|
221
|
+
}
|
|
222
|
+
const compgenRegex = /compgen\s+-W\s+["']([^"']+)["']/g;
|
|
223
|
+
let compgenMatch;
|
|
224
|
+
while ((compgenMatch = compgenRegex.exec(joined)) !== null) {
|
|
225
|
+
if (compgenMatch[1].startsWith("$")) continue;
|
|
226
|
+
for (const word of splitWords(compgenMatch[1])) if (word.startsWith("-")) optionNames.add(word);
|
|
227
|
+
}
|
|
228
|
+
const enumMap = parseCaseStatement(joined);
|
|
229
|
+
const seenArgs = /* @__PURE__ */ new Set();
|
|
230
|
+
for (const rawName of optionNames) {
|
|
231
|
+
if (rawName === "--help" || rawName === "-h" || rawName === "--version" || rawName === "-V") continue;
|
|
232
|
+
const name = rawName.replace(/^-+/, "").replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
233
|
+
if (!name || seenArgs.has(name)) continue;
|
|
234
|
+
seenArgs.add(name);
|
|
235
|
+
const enumValues = enumMap.get(rawName);
|
|
236
|
+
const isShort = rawName.startsWith("-") && !rawName.startsWith("--") && rawName.length === 2;
|
|
237
|
+
const field = {
|
|
238
|
+
name,
|
|
239
|
+
type: enumValues ? "enum" : "string",
|
|
240
|
+
enumValues,
|
|
241
|
+
ambiguous: !enumValues
|
|
242
|
+
};
|
|
243
|
+
if (isShort) field.aliases = [rawName];
|
|
244
|
+
result.arguments.push(field);
|
|
245
|
+
}
|
|
246
|
+
if (result.arguments.length === 0) delete result.arguments;
|
|
247
|
+
if (result.subcommands.length === 0) delete result.subcommands;
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Extract variable assignments: `local VAR="value"`, `VAR="value"`, `local VAR='value'`
|
|
252
|
+
*/
|
|
253
|
+
function extractVariables(text) {
|
|
254
|
+
const vars = /* @__PURE__ */ new Map();
|
|
255
|
+
const regex = /(?:local\s+)?(\w+)=["']([^"']+)["']/g;
|
|
256
|
+
let match;
|
|
257
|
+
while ((match = regex.exec(text)) !== null) vars.set(match[1], match[2]);
|
|
258
|
+
return vars;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Parse case statements to find option → enum value mappings.
|
|
262
|
+
*
|
|
263
|
+
* Matches patterns like:
|
|
264
|
+
* case "$prev" in
|
|
265
|
+
* --format) COMPREPLY=($(compgen -W "json yaml toml" ...)) ;;
|
|
266
|
+
* --env|--environment) COMPREPLY=($(compgen -W "dev staging prod" ...)) ;;
|
|
267
|
+
*/
|
|
268
|
+
function parseCaseStatement(text) {
|
|
269
|
+
const result = /* @__PURE__ */ new Map();
|
|
270
|
+
const caseRegex = /case\s+[^i]*\bin\b\s*([\s\S]*?)esac/g;
|
|
271
|
+
let caseMatch;
|
|
272
|
+
while ((caseMatch = caseRegex.exec(text)) !== null) {
|
|
273
|
+
const branches = caseMatch[1].split(";;");
|
|
274
|
+
for (const branch of branches) {
|
|
275
|
+
const patternMatch = branch.match(/^\s*([-\w|]+)\)/);
|
|
276
|
+
if (!patternMatch) continue;
|
|
277
|
+
const compgenMatch = branch.match(/compgen\s+-W\s+["']([^"']+)["']/);
|
|
278
|
+
if (!compgenMatch) continue;
|
|
279
|
+
const values = compgenMatch[1];
|
|
280
|
+
const words = splitWords(values).filter((w) => !w.startsWith("$"));
|
|
281
|
+
if (words.length === 0) continue;
|
|
282
|
+
for (const pattern of patternMatch[1].split("|")) {
|
|
283
|
+
const trimmed = pattern.trim();
|
|
284
|
+
if (trimmed.startsWith("-")) result.set(trimmed, words);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Split a space-separated word list, filtering empty strings.
|
|
292
|
+
*/
|
|
293
|
+
function splitWords(text) {
|
|
294
|
+
return text.split(/\s+/).filter(Boolean);
|
|
295
|
+
}
|
|
296
|
+
//#endregion
|
|
185
297
|
//#region src/codegen/parsers/fish.ts
|
|
186
298
|
/**
|
|
187
299
|
* Parse fish shell completion scripts into CommandMeta.
|
|
@@ -792,7 +904,8 @@ function findSubcommands(text) {
|
|
|
792
904
|
* parsing shell completion scripts.
|
|
793
905
|
*/
|
|
794
906
|
async function discoverCli(options) {
|
|
795
|
-
const { command, sources = ["help"], depth, delay = 50, log, timeout = 1e4 } = options;
|
|
907
|
+
const { command, sources: rawSources = ["help"], depth, delay = 50, log, timeout = 1e4 } = options;
|
|
908
|
+
const sources = await resolveSources(rawSources, command, timeout, log);
|
|
796
909
|
const warnings = [];
|
|
797
910
|
let invocations = 0;
|
|
798
911
|
const results = [];
|
|
@@ -812,6 +925,12 @@ async function discoverCli(options) {
|
|
|
812
925
|
});
|
|
813
926
|
results.push(helpResult);
|
|
814
927
|
}
|
|
928
|
+
if (sources.includes("bash")) {
|
|
929
|
+
log?.info(`Parsing bash completions for ${command}...`);
|
|
930
|
+
const bashText = await getCompletionScript(command, "bash", timeout);
|
|
931
|
+
if (bashText) results.push(parseBashCompletions(bashText));
|
|
932
|
+
else warnings.push("Could not obtain bash completion script");
|
|
933
|
+
}
|
|
815
934
|
if (sources.includes("fish")) {
|
|
816
935
|
log?.info(`Parsing fish completions for ${command}...`);
|
|
817
936
|
const fishText = await getCompletionScript(command, "fish", timeout);
|
|
@@ -875,20 +994,17 @@ async function runHelp(command, args, timeout) {
|
|
|
875
994
|
*/
|
|
876
995
|
async function runCommand(command, args, timeout) {
|
|
877
996
|
try {
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
997
|
+
const { stdout, stderr } = await new Promise((resolve) => {
|
|
998
|
+
execFile(command, args, {
|
|
999
|
+
timeout,
|
|
1000
|
+
maxBuffer: 10 * 1024 * 1024
|
|
1001
|
+
}, (_error, stdout, stderr) => {
|
|
1002
|
+
resolve({
|
|
1003
|
+
stdout: (stdout ?? "").trim(),
|
|
1004
|
+
stderr: (stderr ?? "").trim()
|
|
1005
|
+
});
|
|
1006
|
+
});
|
|
882
1007
|
});
|
|
883
|
-
const timer = setTimeout(() => proc.kill(), timeout);
|
|
884
|
-
const [_exitCode, stdoutBuf, stderrBuf] = await Promise.all([
|
|
885
|
-
proc.exited,
|
|
886
|
-
new Response(proc.stdout).arrayBuffer(),
|
|
887
|
-
new Response(proc.stderr).arrayBuffer()
|
|
888
|
-
]);
|
|
889
|
-
clearTimeout(timer);
|
|
890
|
-
const stdout = new TextDecoder().decode(stdoutBuf).trim();
|
|
891
|
-
const stderr = new TextDecoder().decode(stderrBuf).trim();
|
|
892
1008
|
const combined = stdout || stderr;
|
|
893
1009
|
if (!combined) return null;
|
|
894
1010
|
if (combined.length < 10) return null;
|
|
@@ -906,13 +1022,47 @@ async function getCompletionScript(command, shell, timeout) {
|
|
|
906
1022
|
if (result) return result;
|
|
907
1023
|
result = await runCommand(command, ["completions", shell], timeout);
|
|
908
1024
|
if (result) return result;
|
|
909
|
-
const paths = shell === "fish" ? [`/usr/share/fish/vendor_completions.d/${command}.fish`, `/usr/local/share/fish/vendor_completions.d/${command}.fish`] : [
|
|
1025
|
+
const paths = shell === "fish" ? [`/usr/share/fish/vendor_completions.d/${command}.fish`, `/usr/local/share/fish/vendor_completions.d/${command}.fish`] : shell === "bash" ? [
|
|
1026
|
+
`/usr/share/bash-completion/completions/${command}`,
|
|
1027
|
+
`/usr/local/share/bash-completion/completions/${command}`,
|
|
1028
|
+
`/etc/bash_completion.d/${command}`
|
|
1029
|
+
] : [`/usr/share/zsh/site-functions/_${command}`, `/usr/local/share/zsh/site-functions/_${command}`];
|
|
910
1030
|
for (const path of paths) try {
|
|
911
|
-
|
|
912
|
-
if (await file.exists()) return await file.text();
|
|
1031
|
+
return await readFile(path, "utf-8");
|
|
913
1032
|
} catch {}
|
|
914
1033
|
return null;
|
|
915
1034
|
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Detect the best shell for completion parsing by probing the command.
|
|
1037
|
+
* Tries `<cmd> completion <shell>` for bash, fish, zsh (in that order).
|
|
1038
|
+
* Returns the shell name if successful, or null if no completion command exists.
|
|
1039
|
+
*/
|
|
1040
|
+
async function detectCompletionShell(command, timeout = 5e3) {
|
|
1041
|
+
for (const shell of [
|
|
1042
|
+
"bash",
|
|
1043
|
+
"fish",
|
|
1044
|
+
"zsh"
|
|
1045
|
+
]) if (await getCompletionScript(command, shell, timeout)) return shell;
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Resolve 'completion' entries in the sources array by probing for the best available shell.
|
|
1050
|
+
* Other sources are passed through unchanged.
|
|
1051
|
+
*/
|
|
1052
|
+
async function resolveSources(sources, command, timeout, log) {
|
|
1053
|
+
if (!sources.includes("completion")) return sources;
|
|
1054
|
+
log?.info(`Probing ${command} for completion command...`);
|
|
1055
|
+
const shell = await detectCompletionShell(command, timeout);
|
|
1056
|
+
return sources.flatMap((s) => {
|
|
1057
|
+
if (s !== "completion") return s;
|
|
1058
|
+
if (shell) {
|
|
1059
|
+
log?.info(` Found ${shell} completion support`);
|
|
1060
|
+
return shell;
|
|
1061
|
+
}
|
|
1062
|
+
log?.info(" No completion command found, skipping");
|
|
1063
|
+
return [];
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
916
1066
|
function sleep(ms) {
|
|
917
1067
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
918
1068
|
}
|
|
@@ -1011,7 +1161,7 @@ function jsonSchemaPropertyToZod(prop, required, ambiguous) {
|
|
|
1011
1161
|
*/
|
|
1012
1162
|
function schemaToCode(schema) {
|
|
1013
1163
|
try {
|
|
1014
|
-
return jsonSchemaToCode(schema["~standard"].jsonSchema.input(
|
|
1164
|
+
return jsonSchemaToCode(schema["~standard"].jsonSchema.input(JSON_SCHEMA_OPTS));
|
|
1015
1165
|
} catch {
|
|
1016
1166
|
return {
|
|
1017
1167
|
code: "z.unknown()",
|
|
@@ -1353,6 +1503,6 @@ function render(text, data, partials) {
|
|
|
1353
1503
|
return result;
|
|
1354
1504
|
}
|
|
1355
1505
|
//#endregion
|
|
1356
|
-
export { createCodeBuilder, createFileEmitter, discoverCli, fieldMetaToCode, generateBarrelFile, generateCommandFile, generateCommandTree, mergeCommandMeta, parseFishCompletions, parseHelpOutput, parseZshCompletions, schemaToCode, template };
|
|
1506
|
+
export { createCodeBuilder, createFileEmitter, detectCompletionShell, discoverCli, fieldMetaToCode, generateBarrelFile, generateCommandFile, generateCommandTree, mergeCommandMeta, parseBashCompletions, parseFishCompletions, parseHelpOutput, parseZshCompletions, schemaToCode, template };
|
|
1357
1507
|
|
|
1358
1508
|
//# sourceMappingURL=index.mjs.map
|