@politty/zod 0.1.1 → 0.2.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/README.md +31 -0
- package/dist/{arg-registry-B8QvBM_Q.d.ts → arg-registry-Be4GJADw.d.ts} +15 -1
- package/dist/augment.d.ts +1 -1
- package/dist/augment.js +1 -1
- package/dist/cli-main-C8D_mKfv.js +2 -0
- package/dist/cli-main-ClQaGXB3.js +1 -0
- package/dist/cli-run-BFXIag27.js +1 -0
- package/dist/cli.js +1 -15
- package/dist/command-Mbdt0bmN.js +1 -0
- package/dist/compile-cache-VuUbFWIo.js +1 -0
- package/dist/compile-cache.js +1 -3
- package/dist/completion-D8DMrPqg.js +116 -0
- package/dist/completion-DUMcvXkT.js +1 -0
- package/dist/completion.d.ts +87 -7
- package/dist/completion.js +1 -4
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +84 -3045
- package/dist/dynamic-CMtee4tD.js +1 -0
- package/dist/dynamic-CrnlveHj.js +6 -0
- package/dist/field-meta-COGya7xp.js +1 -0
- package/dist/index.d.ts +20 -16
- package/dist/index.js +1 -27
- package/dist/log-collector-hiFa3sNm.js +1 -0
- package/dist/logger-CJsyJ8sb.js +1 -0
- package/dist/prompt-CqmGq1_N.js +1 -0
- package/dist/prompt-clack.d.ts +1 -1
- package/dist/prompt-clack.js +1 -32
- package/dist/prompt-inquirer.d.ts +1 -1
- package/dist/prompt-inquirer.js +1 -47
- package/dist/prompt.d.ts +1 -1
- package/dist/prompt.js +1 -4
- package/dist/register-C1WbbeYH.js +1 -0
- package/dist/runner-C_wCXh6X.js +1 -0
- package/dist/runner-uPmkI9Gb.js +29 -0
- package/dist/schema-BiUP_KyV.js +1 -0
- package/dist/schema-extractor-DU0Vuhbd.js +1 -0
- package/dist/skill.d.ts +1 -1
- package/dist/skill.js +2 -1835
- package/dist/subcommand-router-D8GTMXYL.js +1 -0
- package/dist/with-completion-command-DDohm8U6.js +3 -0
- package/dist/{index-CMb2xLiJ.d.ts → with-completion-command-xaVZtAga.d.ts} +3 -74
- package/package.json +3 -3
- package/dist/cli-main-BQfutJEX.js +0 -3
- package/dist/cli-main-D4kkrRfX.js +0 -314
- package/dist/cli-run-wxd6kPPf.js +0 -8
- package/dist/command-k-4yAz4J.js +0 -42
- package/dist/compile-cache-BC65o7MH.js +0 -103
- package/dist/completion-DW5qVc3l.js +0 -5613
- package/dist/field-meta-DMy5BcRr.js +0 -146
- package/dist/log-collector-CoUkLVJB.js +0 -114
- package/dist/logger-i_bb-Jhc.js +0 -133
- package/dist/prompt-BjIZThsH.js +0 -169
- package/dist/register-DlGnMLIY.js +0 -440
- package/dist/runner-DAGvxV2P.js +0 -2980
- package/dist/runner-MMjpKeEa.js +0 -3
- package/dist/schema-extractor-DMSozq40.js +0 -250
- package/dist/src-CLogLsbS.js +0 -12
- package/dist/src-bYH2XCQ4.js +0 -6
- package/dist/subcommand-router-Cskpofdk.js +0 -134
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
//#region ../core/src/adapter/registry.ts
|
|
2
|
-
let registered;
|
|
3
|
-
/**
|
|
4
|
-
* Register the validator adapter core should use for user schemas.
|
|
5
|
-
* Registration unconditionally replaces the current adapter, so every
|
|
6
|
-
* adapter entry module may call this safely — repeated registration of
|
|
7
|
-
* the same adapter has no observable effect.
|
|
8
|
-
*
|
|
9
|
-
* Single-adapter assumption: the registry holds one adapter per process
|
|
10
|
-
* (last registration wins) — a CLI is built against exactly one schema
|
|
11
|
-
* library. If mixing adapters in one process ever becomes a supported
|
|
12
|
-
* scenario, this needs per-schema vendor dispatch instead.
|
|
13
|
-
*/
|
|
14
|
-
function registerValidatorAdapter(adapter) {
|
|
15
|
-
registered = adapter;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Resolve the registered validator adapter.
|
|
19
|
-
*
|
|
20
|
-
* @throws if no adapter has been registered — i.e. core was imported
|
|
21
|
-
* directly instead of through an adapter package entry.
|
|
22
|
-
*/
|
|
23
|
-
function getValidatorAdapter() {
|
|
24
|
-
if (!registered) throw new Error("No validator adapter registered. Import politty through an adapter package (e.g. `import { defineCommand } from \"@politty/zod\"` or `from \"politty\"`) so the schema library integration is set up.");
|
|
25
|
-
return registered;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region ../core/src/adapter/field-meta.ts
|
|
30
|
-
/**
|
|
31
|
-
* Long flag names reserved for built-in handling (parseArgs / scanForSubcommand
|
|
32
|
-
* intercept these before option parsing), so custom negation names must avoid them.
|
|
33
|
-
*/
|
|
34
|
-
const RESERVED_NEGATION_NAMES = /* @__PURE__ */ new Set([
|
|
35
|
-
"help",
|
|
36
|
-
"help-all",
|
|
37
|
-
"version"
|
|
38
|
-
]);
|
|
39
|
-
/**
|
|
40
|
-
* Convert camelCase to kebab-case
|
|
41
|
-
* @example toKebabCase("dryRun") => "dry-run"
|
|
42
|
-
* @example toKebabCase("outputDir") => "output-dir"
|
|
43
|
-
* @example toKebabCase("XMLParser") => "xml-parser"
|
|
44
|
-
*/
|
|
45
|
-
function toKebabCase(str) {
|
|
46
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Convert hyphen-separated sequences to camelCase.
|
|
50
|
-
*
|
|
51
|
-
* Replaces `-x` (hyphen followed by a lowercase letter) with the uppercase
|
|
52
|
-
* variant. Non-hyphenated input (e.g., already camelCase) is returned as-is.
|
|
53
|
-
*
|
|
54
|
-
* @param str - A string that may contain hyphens
|
|
55
|
-
* @example toCamelCase("dry-run") => "dryRun"
|
|
56
|
-
* @example toCamelCase("output-dir") => "outputDir"
|
|
57
|
-
* @example toCamelCase("dryRun") => "dryRun"
|
|
58
|
-
*/
|
|
59
|
-
function toCamelCase(str) {
|
|
60
|
-
return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Get the combined list of visible + hidden aliases for a field.
|
|
64
|
-
* Used by the parser and validators which treat both equally,
|
|
65
|
-
* while help/docs/completion rely on `field.alias` only.
|
|
66
|
-
*/
|
|
67
|
-
function getAllAliases(field) {
|
|
68
|
-
if (!field.alias && !field.hiddenAlias) return [];
|
|
69
|
-
return [...field.alias ?? [], ...field.hiddenAlias ?? []];
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Assemble a {@link ResolvedFieldMeta} from adapter-provided introspection.
|
|
73
|
-
* Single source of truth for alias/negation normalization and validation.
|
|
74
|
-
*/
|
|
75
|
-
function resolveFieldMeta(name, intro) {
|
|
76
|
-
const argMeta = intro.argMeta;
|
|
77
|
-
const description = argMeta?.description ?? intro.description;
|
|
78
|
-
const cliName = toKebabCase(name);
|
|
79
|
-
const aliasPattern = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
80
|
-
const normalizeAliasList = (input, metaKey) => {
|
|
81
|
-
if (input == null) return void 0;
|
|
82
|
-
const normalized = (Array.isArray(input) ? input : [input]).map((a) => {
|
|
83
|
-
if (typeof a !== "string") throw new Error(`Invalid ${metaKey} for field "${name}": expected string or string[], received ${typeof a}.`);
|
|
84
|
-
const candidate = a.trim().replace(/^-+/, "");
|
|
85
|
-
if (candidate.length === 0 || !aliasPattern.test(candidate)) throw new Error(`Invalid ${metaKey} "${a}" for field "${name}": aliases must match ${aliasPattern}.`);
|
|
86
|
-
return candidate;
|
|
87
|
-
});
|
|
88
|
-
const result = Array.from(new Set(normalized));
|
|
89
|
-
return result.length > 0 ? result : void 0;
|
|
90
|
-
};
|
|
91
|
-
const alias = normalizeAliasList(argMeta?.alias, "alias");
|
|
92
|
-
const visibleSet = new Set(alias ?? []);
|
|
93
|
-
const hiddenAlias = normalizeAliasList(argMeta?.hiddenAlias, "hiddenAlias")?.filter((a) => !visibleSet.has(a));
|
|
94
|
-
const hiddenAliasFinal = hiddenAlias && hiddenAlias.length > 0 ? hiddenAlias : void 0;
|
|
95
|
-
const fieldType = intro.type;
|
|
96
|
-
const rawNegation = argMeta?.negation;
|
|
97
|
-
let negation;
|
|
98
|
-
if (rawNegation !== void 0 && rawNegation !== null) if (typeof rawNegation === "boolean") {
|
|
99
|
-
if (fieldType !== "boolean") throw new Error(`Invalid negation for field "${name}": negation can only be used on boolean fields.`);
|
|
100
|
-
negation = rawNegation;
|
|
101
|
-
} else {
|
|
102
|
-
if (typeof rawNegation !== "string") throw new Error(`Invalid negation for field "${name}": expected string or boolean, received ${typeof rawNegation}.`);
|
|
103
|
-
const candidate = rawNegation.trim().replace(/^-+/, "");
|
|
104
|
-
if (candidate.length === 0 || !aliasPattern.test(candidate)) throw new Error(`Invalid negation "${rawNegation}" for field "${name}": negation names must match ${aliasPattern}.`);
|
|
105
|
-
if (RESERVED_NEGATION_NAMES.has(candidate)) throw new Error(`Invalid negation "${rawNegation}" for field "${name}": negation cannot use reserved built-in flag names (${[...RESERVED_NEGATION_NAMES].map((n) => `--${n}`).join(", ")}).`);
|
|
106
|
-
if (fieldType !== "boolean") throw new Error(`Invalid negation for field "${name}": negation can only be used on boolean fields.`);
|
|
107
|
-
negation = candidate;
|
|
108
|
-
}
|
|
109
|
-
const rawNegationDescription = argMeta?.negationDescription;
|
|
110
|
-
let negationDescription;
|
|
111
|
-
if (rawNegationDescription !== void 0 && rawNegationDescription !== null) {
|
|
112
|
-
if (typeof rawNegationDescription !== "string") throw new Error(`Invalid negationDescription for field "${name}": expected string, received ${typeof rawNegationDescription}.`);
|
|
113
|
-
if (negation === false) throw new Error(`Invalid negationDescription for field "${name}": negationDescription cannot be used when negation is false.`);
|
|
114
|
-
if (negation === void 0) throw new Error(`Invalid negationDescription for field "${name}": negationDescription requires \`negation\` to be set (string or true).`);
|
|
115
|
-
const trimmed = rawNegationDescription.trim();
|
|
116
|
-
if (trimmed.length === 0) throw new Error(`Invalid negationDescription for field "${name}": negationDescription must be a non-empty string.`);
|
|
117
|
-
negationDescription = trimmed;
|
|
118
|
-
}
|
|
119
|
-
const negationDisplay = typeof negation === "string" ? negation : negation === true ? `no-${cliName}` : void 0;
|
|
120
|
-
const meta = {
|
|
121
|
-
name,
|
|
122
|
-
cliName,
|
|
123
|
-
alias,
|
|
124
|
-
hiddenAlias: hiddenAliasFinal,
|
|
125
|
-
description,
|
|
126
|
-
positional: argMeta?.positional ?? false,
|
|
127
|
-
placeholder: argMeta?.placeholder,
|
|
128
|
-
env: argMeta?.env,
|
|
129
|
-
required: intro.required,
|
|
130
|
-
defaultValue: intro.defaultValue,
|
|
131
|
-
type: fieldType,
|
|
132
|
-
schema: intro.schema,
|
|
133
|
-
enumValues: intro.enumValues,
|
|
134
|
-
completion: argMeta?.completion,
|
|
135
|
-
prompt: argMeta?.prompt,
|
|
136
|
-
negation,
|
|
137
|
-
negationDisplay,
|
|
138
|
-
negationDescription,
|
|
139
|
-
effect: argMeta?.effect
|
|
140
|
-
};
|
|
141
|
-
if (argMeta && "overrideBuiltinAlias" in argMeta && argMeta.overrideBuiltinAlias === true) meta.overrideBuiltinAlias = true;
|
|
142
|
-
return meta;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
//#endregion
|
|
146
|
-
export { getValidatorAdapter as a, toKebabCase as i, resolveFieldMeta as n, registerValidatorAdapter as o, toCamelCase as r, getAllAliases as t };
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
//#region ../core/src/executor/log-collector.ts
|
|
2
|
-
/**
|
|
3
|
-
* Mapping from log level to output stream
|
|
4
|
-
*/
|
|
5
|
-
const LOG_STREAM_MAP = {
|
|
6
|
-
log: "stdout",
|
|
7
|
-
info: "stdout",
|
|
8
|
-
debug: "stdout",
|
|
9
|
-
warn: "stderr",
|
|
10
|
-
error: "stderr"
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* All log levels
|
|
14
|
-
*/
|
|
15
|
-
const ALL_LOG_LEVELS = [
|
|
16
|
-
"log",
|
|
17
|
-
"info",
|
|
18
|
-
"debug",
|
|
19
|
-
"warn",
|
|
20
|
-
"error"
|
|
21
|
-
];
|
|
22
|
-
/**
|
|
23
|
-
* Format console arguments to string
|
|
24
|
-
*/
|
|
25
|
-
function formatArgs(args) {
|
|
26
|
-
return args.map((arg) => {
|
|
27
|
-
if (arg instanceof Error) return arg.message;
|
|
28
|
-
if (typeof arg === "object" && arg !== null) try {
|
|
29
|
-
return JSON.stringify(arg);
|
|
30
|
-
} catch {
|
|
31
|
-
return String(arg);
|
|
32
|
-
}
|
|
33
|
-
return String(arg);
|
|
34
|
-
}).join(" ");
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Create a log collector that intercepts console methods
|
|
38
|
-
*
|
|
39
|
-
* @param options - Options for the log collector
|
|
40
|
-
* @returns A log collector instance
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* const collector = createLogCollector();
|
|
45
|
-
* collector.start();
|
|
46
|
-
*
|
|
47
|
-
* console.log("Info message");
|
|
48
|
-
* console.error("Something went wrong");
|
|
49
|
-
* console.warn("This is a warning");
|
|
50
|
-
*
|
|
51
|
-
* collector.stop();
|
|
52
|
-
* const logs = collector.getLogs();
|
|
53
|
-
* // {
|
|
54
|
-
* // entries: [
|
|
55
|
-
* // { message: "Info message", level: "log", stream: "stdout", timestamp: ... },
|
|
56
|
-
* // { message: "Something went wrong", level: "error", stream: "stderr", timestamp: ... },
|
|
57
|
-
* // { message: "This is a warning", level: "warn", stream: "stderr", timestamp: ... }
|
|
58
|
-
* // ]
|
|
59
|
-
* // }
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
function createLogCollector(options = {}) {
|
|
63
|
-
const entries = [];
|
|
64
|
-
const levels = options.levels ?? ALL_LOG_LEVELS;
|
|
65
|
-
const passthrough = options.passthrough ?? true;
|
|
66
|
-
let originals = null;
|
|
67
|
-
const createInterceptor = (level, original) => {
|
|
68
|
-
return (...args) => {
|
|
69
|
-
entries.push({
|
|
70
|
-
message: formatArgs(args),
|
|
71
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
72
|
-
level,
|
|
73
|
-
stream: LOG_STREAM_MAP[level]
|
|
74
|
-
});
|
|
75
|
-
if (passthrough) original.apply(console, args);
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
return {
|
|
79
|
-
getLogs() {
|
|
80
|
-
return { entries: [...entries] };
|
|
81
|
-
},
|
|
82
|
-
start() {
|
|
83
|
-
if (originals !== null) return;
|
|
84
|
-
originals = {
|
|
85
|
-
log: console.log,
|
|
86
|
-
info: console.info,
|
|
87
|
-
debug: console.debug,
|
|
88
|
-
warn: console.warn,
|
|
89
|
-
error: console.error
|
|
90
|
-
};
|
|
91
|
-
for (const level of levels) console[level] = createInterceptor(level, originals[level]);
|
|
92
|
-
},
|
|
93
|
-
stop() {
|
|
94
|
-
if (originals === null) return;
|
|
95
|
-
for (const level of levels) console[level] = originals[level];
|
|
96
|
-
originals = null;
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Merge multiple CollectedLogs into one (sorted by timestamp)
|
|
102
|
-
*/
|
|
103
|
-
function mergeLogs(...logsArray) {
|
|
104
|
-
return { entries: logsArray.flatMap((l) => l.entries).sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime()) };
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Create an empty CollectedLogs object
|
|
108
|
-
*/
|
|
109
|
-
function emptyLogs() {
|
|
110
|
-
return { entries: [] };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
//#endregion
|
|
114
|
-
export { emptyLogs as n, mergeLogs as r, createLogCollector as t };
|
package/dist/logger-i_bb-Jhc.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { styleText } from "node:util";
|
|
2
|
-
|
|
3
|
-
//#region ../core/src/output/logger.ts
|
|
4
|
-
/**
|
|
5
|
-
* Check if color output should be disabled
|
|
6
|
-
*/
|
|
7
|
-
function shouldDisableColor() {
|
|
8
|
-
if (process.env.NO_COLOR !== void 0) return true;
|
|
9
|
-
if (process.env.FORCE_COLOR === "0") return true;
|
|
10
|
-
if (process.env.FORCE_COLOR) return false;
|
|
11
|
-
if (process.env.CI) return true;
|
|
12
|
-
if (!process.stdout.isTTY) return true;
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Global flag to control color output
|
|
17
|
-
*/
|
|
18
|
-
let colorDisabled = shouldDisableColor();
|
|
19
|
-
/**
|
|
20
|
-
* Enable or disable color output programmatically
|
|
21
|
-
*/
|
|
22
|
-
function setColorEnabled(enabled) {
|
|
23
|
-
colorDisabled = !enabled;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Check if color output is currently enabled
|
|
27
|
-
*/
|
|
28
|
-
function isColorEnabled() {
|
|
29
|
-
return !colorDisabled;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Create a style function that applies the given styles
|
|
33
|
-
*/
|
|
34
|
-
function createStyleFn(...styleArgs) {
|
|
35
|
-
return (text) => {
|
|
36
|
-
if (colorDisabled) return text;
|
|
37
|
-
let result = text;
|
|
38
|
-
for (const style of styleArgs) result = styleText(style, result);
|
|
39
|
-
return result;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Semantic style functions for inline text styling
|
|
44
|
-
*/
|
|
45
|
-
const styles = {
|
|
46
|
-
success: createStyleFn("green"),
|
|
47
|
-
error: createStyleFn("red"),
|
|
48
|
-
warning: createStyleFn("yellow"),
|
|
49
|
-
info: createStyleFn("cyan"),
|
|
50
|
-
bold: createStyleFn("bold"),
|
|
51
|
-
dim: createStyleFn("dim"),
|
|
52
|
-
italic: createStyleFn("italic"),
|
|
53
|
-
underline: createStyleFn("underline"),
|
|
54
|
-
red: createStyleFn("red"),
|
|
55
|
-
green: createStyleFn("green"),
|
|
56
|
-
yellow: createStyleFn("yellow"),
|
|
57
|
-
blue: createStyleFn("blue"),
|
|
58
|
-
magenta: createStyleFn("magenta"),
|
|
59
|
-
cyan: createStyleFn("cyan"),
|
|
60
|
-
white: createStyleFn("white"),
|
|
61
|
-
gray: createStyleFn("gray"),
|
|
62
|
-
command: createStyleFn("bold"),
|
|
63
|
-
commandName: createStyleFn("bold", "underline", "cyan"),
|
|
64
|
-
option: createStyleFn("cyan"),
|
|
65
|
-
optionName: createStyleFn("bold"),
|
|
66
|
-
placeholder: createStyleFn("dim"),
|
|
67
|
-
defaultValue: createStyleFn("dim"),
|
|
68
|
-
required: createStyleFn("yellow"),
|
|
69
|
-
description: (text) => text,
|
|
70
|
-
sectionHeader: createStyleFn("bold", "underline"),
|
|
71
|
-
version: createStyleFn("dim")
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* Standardized symbols for CLI output
|
|
75
|
-
*/
|
|
76
|
-
const symbols = {
|
|
77
|
-
success: styles.green("✓"),
|
|
78
|
-
error: styles.red("✖"),
|
|
79
|
-
warning: styles.yellow("⚠"),
|
|
80
|
-
info: styles.cyan("ℹ"),
|
|
81
|
-
bullet: styles.gray("•"),
|
|
82
|
-
arrow: styles.gray("→")
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Logger for CLI output
|
|
86
|
-
*/
|
|
87
|
-
const logger = {
|
|
88
|
-
/**
|
|
89
|
-
* Log informational message
|
|
90
|
-
*/
|
|
91
|
-
info(message) {
|
|
92
|
-
console.log(message);
|
|
93
|
-
},
|
|
94
|
-
/**
|
|
95
|
-
* Log success message
|
|
96
|
-
*/
|
|
97
|
-
success(message) {
|
|
98
|
-
console.log(`${symbols.success} ${styles.success(message)}`);
|
|
99
|
-
},
|
|
100
|
-
/**
|
|
101
|
-
* Log warning message
|
|
102
|
-
*/
|
|
103
|
-
warn(message) {
|
|
104
|
-
console.warn(`${symbols.warning} ${styles.warning(message)}`);
|
|
105
|
-
},
|
|
106
|
-
/**
|
|
107
|
-
* Log error message
|
|
108
|
-
*/
|
|
109
|
-
error(message) {
|
|
110
|
-
console.error(`${symbols.error} ${styles.error(message)}`);
|
|
111
|
-
},
|
|
112
|
-
/**
|
|
113
|
-
* Log raw message without prefix
|
|
114
|
-
*/
|
|
115
|
-
log(message) {
|
|
116
|
-
console.log(message);
|
|
117
|
-
},
|
|
118
|
-
/**
|
|
119
|
-
* Log empty line
|
|
120
|
-
*/
|
|
121
|
-
newline() {
|
|
122
|
-
console.log("");
|
|
123
|
-
},
|
|
124
|
-
/**
|
|
125
|
-
* Log debug message with dim color
|
|
126
|
-
*/
|
|
127
|
-
debug(message) {
|
|
128
|
-
console.log(styles.dim(message));
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
//#endregion
|
|
133
|
-
export { symbols as a, styles as i, logger as n, setColorEnabled as r, isColorEnabled as t };
|
package/dist/prompt-BjIZThsH.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
//#region ../core/src/prompt/prompt-resolver.ts
|
|
2
|
-
/**
|
|
3
|
-
* Resolve prompt configuration for a field.
|
|
4
|
-
*
|
|
5
|
-
* Priority for prompt type:
|
|
6
|
-
* 1. Explicit type from prompt.type
|
|
7
|
-
* 2. Explicit choices from prompt.choices (forces "select")
|
|
8
|
-
* 3. Inherited from completion metadata (file/directory -> "text")
|
|
9
|
-
* 4. Auto-detected from the extracted field type (adapter-provided):
|
|
10
|
-
* - enum (has enumValues) -> "select"
|
|
11
|
-
* - boolean -> "confirm"
|
|
12
|
-
* - string/number/unknown -> "text"
|
|
13
|
-
*
|
|
14
|
-
* Returns null if the field has no prompt metadata or prompting is disabled.
|
|
15
|
-
*/
|
|
16
|
-
function resolvePromptConfig(field) {
|
|
17
|
-
const promptMeta = field.prompt;
|
|
18
|
-
if (!promptMeta || promptMeta.enabled === false) return null;
|
|
19
|
-
const message = promptMeta.message ?? field.description ?? field.name;
|
|
20
|
-
const rawType = resolvePromptType(field, promptMeta);
|
|
21
|
-
const choices = resolveChoices(field, promptMeta, rawType);
|
|
22
|
-
return {
|
|
23
|
-
field,
|
|
24
|
-
type: rawType === "select" && !choices ? "text" : rawType,
|
|
25
|
-
message,
|
|
26
|
-
...choices && { choices }
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
function hasChoices(list) {
|
|
30
|
-
return list !== void 0 && list.length > 0;
|
|
31
|
-
}
|
|
32
|
-
function resolvePromptType(field, promptMeta) {
|
|
33
|
-
if (promptMeta.type) return promptMeta.type === "file" || promptMeta.type === "directory" ? "text" : promptMeta.type;
|
|
34
|
-
if (hasChoices(promptMeta.choices)) return "select";
|
|
35
|
-
if (field.completion?.type === "file" || field.completion?.type === "directory") return "text";
|
|
36
|
-
if (hasChoices(field.enumValues)) return "select";
|
|
37
|
-
if (field.type === "boolean") return "confirm";
|
|
38
|
-
return "text";
|
|
39
|
-
}
|
|
40
|
-
function resolveChoices(field, promptMeta, type) {
|
|
41
|
-
if (hasChoices(promptMeta.choices)) return promptMeta.choices.map((c) => typeof c === "string" ? {
|
|
42
|
-
label: c,
|
|
43
|
-
value: c
|
|
44
|
-
} : c);
|
|
45
|
-
if (type === "select" && hasChoices(field.enumValues)) return field.enumValues.map((v) => ({
|
|
46
|
-
label: v,
|
|
47
|
-
value: v
|
|
48
|
-
}));
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Filter fields that need prompting (missing value + prompt configured).
|
|
52
|
-
*
|
|
53
|
-
* For discriminatedUnion schemas, variant-aware narrowing is handled by the
|
|
54
|
-
* caller (promptMissingArgs) which prompts the discriminator first and then
|
|
55
|
-
* passes only the active variant's fields. For plain union schemas, this
|
|
56
|
-
* iterates all fields across every variant without narrowing.
|
|
57
|
-
*
|
|
58
|
-
* Fields with Zod defaults that also have prompt metadata will be prompted
|
|
59
|
-
* when the raw value is undefined. This is intentional: `prompt: {}` is an
|
|
60
|
-
* explicit opt-in to interactive input. Omit prompt metadata to let the
|
|
61
|
-
* default apply silently.
|
|
62
|
-
*/
|
|
63
|
-
function getFieldsToPrompt(fields, rawArgs) {
|
|
64
|
-
const configs = [];
|
|
65
|
-
for (const field of fields) {
|
|
66
|
-
if (rawArgs[field.name] !== void 0) continue;
|
|
67
|
-
if (field.type === "array") continue;
|
|
68
|
-
const config = resolvePromptConfig(field);
|
|
69
|
-
if (config) configs.push(config);
|
|
70
|
-
}
|
|
71
|
-
return configs;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
//#endregion
|
|
75
|
-
//#region ../core/src/prompt/tty-detector.ts
|
|
76
|
-
/**
|
|
77
|
-
* Detect whether the current environment supports interactive prompts.
|
|
78
|
-
* Returns false in CI, piped input, or non-TTY environments.
|
|
79
|
-
*/
|
|
80
|
-
function isInteractive() {
|
|
81
|
-
if (!process.stdin.isTTY) return false;
|
|
82
|
-
if (!process.stdout.isTTY) return false;
|
|
83
|
-
if (process.env.CI) return false;
|
|
84
|
-
if (process.env.POLITTY_NO_PROMPT) return false;
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region ../core/src/prompt/index.ts
|
|
90
|
-
/**
|
|
91
|
-
* Prompt for missing argument values interactively.
|
|
92
|
-
*
|
|
93
|
-
* Only prompts for fields that have `prompt` metadata set via `arg()` and
|
|
94
|
-
* whose values are still undefined after CLI and env resolution.
|
|
95
|
-
* Returns rawArgs unchanged in non-interactive environments.
|
|
96
|
-
*/
|
|
97
|
-
async function promptMissingArgs(rawArgs, extracted, options) {
|
|
98
|
-
if (!(options.interactive ?? isInteractive())) return rawArgs;
|
|
99
|
-
const adapter = options.adapter;
|
|
100
|
-
const result = { ...rawArgs };
|
|
101
|
-
if (extracted.schemaType === "discriminatedUnion" && extracted.discriminator && extracted.variants) await promptDiscriminatedUnion(adapter, result, extracted);
|
|
102
|
-
else if (extracted.schemaType === "union" || extracted.schemaType === "xor") {} else await promptAllFields(adapter, result, extracted.fields);
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
async function promptDiscriminatedUnion(adapter, result, extracted) {
|
|
106
|
-
const { discriminator, variants } = extracted;
|
|
107
|
-
if (!discriminator || !variants) return;
|
|
108
|
-
if (result[discriminator] === void 0) {
|
|
109
|
-
const discField = findDiscriminatorField(extracted.fields, variants, discriminator);
|
|
110
|
-
const discConfig = discField ? resolvePromptConfig(discField) : null;
|
|
111
|
-
if (discConfig) {
|
|
112
|
-
const allValues = variants.map((v) => v.discriminatorValue).filter(Boolean);
|
|
113
|
-
if (allValues.length > 0) {
|
|
114
|
-
discConfig.type = "select";
|
|
115
|
-
discConfig.choices = allValues.map((v) => ({
|
|
116
|
-
label: v,
|
|
117
|
-
value: v
|
|
118
|
-
}));
|
|
119
|
-
}
|
|
120
|
-
await promptAndCollect(adapter, result, discConfig);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
const discValue = String(result[discriminator] ?? "");
|
|
124
|
-
const activeVariant = variants.find((v) => v.discriminatorValue === discValue);
|
|
125
|
-
if (activeVariant) await promptAllFields(adapter, result, activeVariant.fields.filter((f) => f.name !== discriminator));
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Find the discriminator field with prompt metadata, checking the
|
|
129
|
-
* deduplicated top-level fields first, then scanning per-variant fields.
|
|
130
|
-
*/
|
|
131
|
-
function findDiscriminatorField(fields, variants, discriminator) {
|
|
132
|
-
const topLevel = fields.find((f) => f.name === discriminator);
|
|
133
|
-
if (topLevel?.prompt) return topLevel;
|
|
134
|
-
for (const variant of variants) {
|
|
135
|
-
const field = variant.fields.find((f) => f.name === discriminator);
|
|
136
|
-
if (field?.prompt) return field;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async function promptAllFields(adapter, result, fields) {
|
|
140
|
-
const fieldsToPrompt = getFieldsToPrompt(fields, result);
|
|
141
|
-
for (const config of fieldsToPrompt) await promptAndCollect(adapter, result, config);
|
|
142
|
-
}
|
|
143
|
-
async function promptAndCollect(adapter, result, config) {
|
|
144
|
-
const { message } = config;
|
|
145
|
-
let value;
|
|
146
|
-
switch (config.type) {
|
|
147
|
-
case "text":
|
|
148
|
-
value = await adapter.text({
|
|
149
|
-
message,
|
|
150
|
-
placeholder: config.field.placeholder
|
|
151
|
-
});
|
|
152
|
-
break;
|
|
153
|
-
case "password":
|
|
154
|
-
value = await adapter.password({ message });
|
|
155
|
-
break;
|
|
156
|
-
case "confirm":
|
|
157
|
-
value = await adapter.confirm({ message });
|
|
158
|
-
break;
|
|
159
|
-
case "select": value = await adapter.select({
|
|
160
|
-
message,
|
|
161
|
-
options: config.choices ?? []
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
if (adapter.isCancelled(value)) throw new Error("Prompt cancelled by user");
|
|
165
|
-
result[config.field.name] = value;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
//#endregion
|
|
169
|
-
export { resolvePromptConfig as i, isInteractive as n, getFieldsToPrompt as r, promptMissingArgs as t };
|