@politty/zod 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +31 -0
  2. package/dist/{arg-registry-Be4GJADw.d.ts → arg-registry-BzQ-y-e0.d.ts} +2 -2
  3. package/dist/augment.d.ts +1 -1
  4. package/dist/augment.js +1 -1
  5. package/dist/cli-main-B4FX3h4J.js +1 -0
  6. package/dist/cli-main-CjYk6tAX.js +2 -0
  7. package/dist/cli-run-DN55A0JZ.js +1 -0
  8. package/dist/cli.js +1 -15
  9. package/dist/command-Mbdt0bmN.js +1 -0
  10. package/dist/compile-cache-VuUbFWIo.js +1 -0
  11. package/dist/compile-cache.js +1 -3
  12. package/dist/completion-D8DMrPqg.js +116 -0
  13. package/dist/completion-DUMcvXkT.js +1 -0
  14. package/dist/completion.d.ts +87 -7
  15. package/dist/completion.js +1 -4
  16. package/dist/docs.d.ts +1 -1
  17. package/dist/docs.js +84 -3063
  18. package/dist/dynamic-CMtee4tD.js +1 -0
  19. package/dist/dynamic-CrnlveHj.js +6 -0
  20. package/dist/field-meta-COGya7xp.js +1 -0
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +1 -27
  23. package/dist/log-collector-DICKib75.js +1 -0
  24. package/dist/logger-CJsyJ8sb.js +1 -0
  25. package/dist/prompt-CqmGq1_N.js +1 -0
  26. package/dist/prompt-clack.d.ts +1 -1
  27. package/dist/prompt-clack.js +1 -32
  28. package/dist/prompt-inquirer.d.ts +1 -1
  29. package/dist/prompt-inquirer.js +1 -47
  30. package/dist/prompt.d.ts +1 -1
  31. package/dist/prompt.js +1 -4
  32. package/dist/register-C1WbbeYH.js +1 -0
  33. package/dist/runner-BIdcntiz.js +29 -0
  34. package/dist/runner-Chaf_5lK.js +1 -0
  35. package/dist/schema-BiUP_KyV.js +1 -0
  36. package/dist/schema-extractor-DU0Vuhbd.js +1 -0
  37. package/dist/skill.d.ts +1 -1
  38. package/dist/skill.js +2 -1837
  39. package/dist/subcommand-router-D8GTMXYL.js +1 -0
  40. package/dist/{index-B4NylQOW.d.ts → with-completion-command-CmVdHFHX.d.ts} +3 -74
  41. package/dist/with-completion-command-DDohm8U6.js +3 -0
  42. package/package.json +3 -3
  43. package/dist/cli-main-CAa5KwCo.js +0 -314
  44. package/dist/cli-main-DIRMduj1.js +0 -3
  45. package/dist/cli-run-B--tZW_I.js +0 -8
  46. package/dist/command-k-4yAz4J.js +0 -42
  47. package/dist/compile-cache-BC65o7MH.js +0 -103
  48. package/dist/completion-Ot2qpNNw.js +0 -5616
  49. package/dist/field-meta-CO38jOvl.js +0 -148
  50. package/dist/log-collector-CoUkLVJB.js +0 -114
  51. package/dist/logger-i_bb-Jhc.js +0 -133
  52. package/dist/prompt-BjIZThsH.js +0 -169
  53. package/dist/register-DdcsbNwM.js +0 -440
  54. package/dist/runner-Bz3arOqh.js +0 -3051
  55. package/dist/runner-Cs-Mz9JN.js +0 -3
  56. package/dist/schema-extractor-CVNDs07l.js +0 -250
  57. package/dist/src-D4QGGgW1.js +0 -6
  58. package/dist/src-DhQVU2hG.js +0 -12
  59. package/dist/subcommand-router-Cskpofdk.js +0 -134
@@ -0,0 +1 @@
1
+ const e=`__politty_lazy__`;function t(t){return typeof t==`object`&&!!t&&e in t&&t[e]===!0}function n(t,n){return{[e]:!0,meta:t,load:n}}function r(e){return t(e)?e.meta:typeof e==`function`?null:e}async function i(e){return t(e)?await e.load():typeof e==`function`?await e():e}async function a(e,t){if(!e.subCommands)return;let n=Object.hasOwn(e.subCommands,t)?e.subCommands[t]:void 0;if(n)return{command:await i(n),aliasFor:void 0};let r=o(e,t);if(r)return{command:await i(e.subCommands[r]),aliasFor:r}}function o(e,t){if(e.subCommands){for(let[n,i]of Object.entries(e.subCommands))if(r(i)?.aliases?.includes(t))return n}}function s(e){let t=new Set;if(!e.subCommands)return t;for(let[n,i]of Object.entries(e.subCommands)){t.add(n);let e=r(i);if(e?.aliases)for(let n of e.aliases)t.add(n)}return t}function c(e){return e.subCommands?Object.keys(e.subCommands):[]}export{a,r as c,o as i,c as n,t as o,i as r,n as s,s as t};
@@ -1,4 +1,4 @@
1
- import { C as Command, Q as UnknownKeysMode, b as ArgsSchema, f as ResolvedExpandCandidate, g as DynamicCompletionResolver, n as ArgMeta, v as AnyCommand } from "./arg-registry-Be4GJADw.js";
1
+ import { Q as UnknownKeysMode, b as ArgsSchema, f as ResolvedExpandCandidate, g as DynamicCompletionResolver, n as ArgMeta, v as AnyCommand } from "./arg-registry-BzQ-y-e0.js";
2
2
  //#region ../core/src/adapter/internal-args.d.ts
3
3
  /** Runtime brand distinguishing internal descriptors from library schemas. */
4
4
  declare const INTERNAL_ARGS_BRAND = "__polittyInternalArgs";
@@ -338,78 +338,7 @@ declare function defaultBundledWorkerOutputPath(shell: ShellType): string;
338
338
  declare function validateBundledWorkerFile(path: string, programName: string, shell: ShellType): void;
339
339
  declare function generateBundledCompletionWorker(options: GenerateBundledCompletionWorkerOptions): Promise<GenerateBundledCompletionWorkerResult>;
340
340
  //#endregion
341
- //#region ../core/src/completion/index.d.ts
342
- /**
343
- * Generate completion script for the specified shell
344
- */
345
- declare function generateCompletion(command: AnyCommand, options: CompletionOptions): CompletionResult;
346
- /**
347
- * Get the list of supported shells
348
- */
349
- declare function getSupportedShells(): ShellType[];
350
- /**
351
- * Detect the current shell from environment
352
- */
353
- declare function detectShell(): ShellType | null;
354
- /**
355
- * Schema for the completion command arguments
356
- */
357
- declare const completionArgsSchema: InternalArgsSchema<{
358
- shell: "bash" | "fish" | "zsh" | undefined;
359
- instructions: boolean;
360
- loader: boolean;
361
- install: boolean;
362
- static: boolean;
363
- dispatcher: boolean;
364
- worker: boolean;
365
- }>;
366
- type CompletionArgs = InferInternalArgs<typeof completionArgsSchema>;
367
- declare const refreshArgsSchema: InternalArgsSchema<{
368
- shell: "bash" | "fish" | "zsh";
369
- target: string | undefined;
370
- static: boolean;
371
- worker: boolean;
372
- }>;
373
- type RefreshArgs = InferInternalArgs<typeof refreshArgsSchema>;
374
- declare const workerPathArgsSchema: InternalArgsSchema<{
375
- shell: "bash" | "fish" | "zsh";
376
- }>;
377
- type WorkerPathArgs = InferInternalArgs<typeof workerPathArgsSchema>;
378
- /**
379
- * Create a completion subcommand for your CLI
380
- *
381
- * This creates a ready-to-use subcommand that generates completion scripts.
382
- *
383
- * @example
384
- * ```typescript
385
- * const mainCommand = defineCommand({
386
- * name: "mycli",
387
- * subCommands: {
388
- * completion: createCompletionCommand(mainCommand)
389
- * }
390
- * });
391
- * ```
392
- */
393
- declare function createCompletionCommand(rootCommand: AnyCommand, programName?: string, globalArgsSchema?: ArgsSchema, extra?: {
394
- cacheDir?: string;
395
- programVersion?: string;
396
- bundledWorker?: BundledWorkerOptions;
397
- }): Command<typeof completionArgsSchema, CompletionArgs, any>;
398
- /**
399
- * Hidden subcommand that the runMain background hook spawns. It does
400
- * the same stat-compare + atomic rewrite as the rc loader, but in a
401
- * detached child process so it's invisible to the user.
402
- */
403
- declare function createRefreshCompletionCommand(rootCommand: AnyCommand, programName: string, extra?: {
404
- cacheDir?: string;
405
- programVersion?: string;
406
- globalArgsSchema?: ArgsSchema;
407
- bundledWorker?: BundledWorkerOptions;
408
- }): Command<typeof refreshArgsSchema, RefreshArgs, any>;
409
- declare function createCompletionWorkerPathCommand(programName: string, extra?: {
410
- binPath?: string;
411
- bundledWorker?: BundledWorkerOptions;
412
- }): Command<typeof workerPathArgsSchema, WorkerPathArgs, any>;
341
+ //#region ../core/src/completion/with-completion-command.d.ts
413
342
  /**
414
343
  * Options for withCompletionCommand
415
344
  */
@@ -452,4 +381,4 @@ interface WithCompletionOptions {
452
381
  */
453
382
  declare function withCompletionCommand<T extends AnyCommand>(command: T, options?: string | WithCompletionOptions): T;
454
383
  //#endregion
455
- export { CompletionResult as C, InternalArgsSchema as D, InferInternalArgs as E, CompletionOptions as S, ValueCompletion as T, CompletablePositional as _, detectShell as a, CompletionGenerator as b, withCompletionCommand as c, bundledWorkerShellExtension as d, defaultBundledWorkerOutputPath as f, CompletableOption as g, BundledWorkerOptions as h, createRefreshCompletionCommand as i, GenerateBundledCompletionWorkerOptions as l, validateBundledWorkerFile as m, createCompletionCommand as n, generateCompletion as o, generateBundledCompletionWorker as p, createCompletionWorkerPathCommand as r, getSupportedShells as s, WithCompletionOptions as t, GenerateBundledCompletionWorkerResult as u, CompletableSubcommand as v, ShellType as w, CompletionMode as x, CompletionData as y };
384
+ export { CompletionResult as _, bundledWorkerShellExtension as a, InferInternalArgs as b, validateBundledWorkerFile as c, CompletablePositional as d, CompletableSubcommand as f, CompletionOptions as g, CompletionMode as h, GenerateBundledCompletionWorkerResult as i, BundledWorkerOptions as l, CompletionGenerator as m, withCompletionCommand as n, defaultBundledWorkerOutputPath as o, CompletionData as p, GenerateBundledCompletionWorkerOptions as r, generateBundledCompletionWorker as s, WithCompletionOptions as t, CompletableOption as u, ShellType as v, InternalArgsSchema as x, ValueCompletion as y };
@@ -0,0 +1,3 @@
1
+ import{a as e,i as t}from"./schema-extractor-DU0Vuhbd.js";import{n}from"./command-Mbdt0bmN.js";import{s as r}from"./subcommand-router-D8GTMXYL.js";import{t as i}from"./schema-BiUP_KyV.js";import{existsSync as a,readFileSync as o}from"node:fs";import{join as s}from"node:path";import{spawn as c}from"node:child_process";function l(){let e=(process.env.SHELL||``).split(`/`).pop()?.toLowerCase()||``;return e.includes(`bash`)?`bash`:e.includes(`zsh`)?`zsh`:e.includes(`fish`)?`fish`:null}function u(e){return`${process.env.XDG_CACHE_HOME??`${process.env.HOME??``}/.cache`}/${e}`}function d(e,t,n){if(t===`fish`){let t=process.env.XDG_CONFIG_HOME??`${process.env.HOME??``}/.config`;return s(t,`fish`,`completions`,`${e}.fish`)}let r=n??u(e);return s(r,`completion.${t}`)}function f(e){try{if(!a(e))return null;let t=o(e,`utf8`).split(`
2
+ `,6).join(`
3
+ `).match(/^# politty-bin-sig: (\S+)/m);return t?t[1]:null}catch{return null}}function p(e,t){return f(d(e.programName,t,e.cacheDir))!==null}function m(e,t){try{c(process.execPath,[e,`__refresh-completion`,t],{detached:!0,stdio:`ignore`}).unref()}catch{}}const h=t({shell:e.optionalEnum([`bash`,`zsh`,`fish`],{positional:!0,description:`Shell type (bash, zsh, or fish)`,placeholder:`SHELL`}),instructions:e.boolean({alias:`i`,description:`Show installation instructions`}),loader:e.boolean({description:`Print just the rc loader snippet (bash/zsh). Add it to ~/.bashrc or ~/.zshrc; it auto-regenerates the cache when the binary changes.`}),install:e.boolean({description:`Write the completion script to its on-disk cache (bash/zsh) or autoload location (fish) instead of printing it.`}),static:e.boolean({description:`Generate the legacy static completion script with command metadata baked in.`}),dispatcher:e.boolean({description:`Generate the runtime dispatcher completion script. This is the default.`}),worker:e.boolean({description:`Generate an internal static worker artifact for dispatcher mode.`})}),g=t({shell:e.enum([`bash`,`zsh`,`fish`],{positional:!0,description:`Shell to refresh`,placeholder:`SHELL`}),target:e.optionalString({positional:!0,description:`Existing politty-generated completion file to refresh`,placeholder:`TARGET`}),static:e.boolean({description:`Refresh using the legacy static completion script mode.`}),worker:e.boolean({description:`Refresh an internal static worker completion script.`})}),_=t({shell:e.enum([`bash`,`zsh`,`fish`],{positional:!0,description:`Shell worker to locate`,placeholder:`SHELL`})});function v(e,t){let{programName:a,globalArgsSchema:o,cacheDir:s,programVersion:c,bundledWorker:l}=typeof t==`string`?{programName:t}:t??{},u=a??e.name,d={...s!==void 0&&{cacheDir:s},...c!==void 0&&{programVersion:c},...o!==void 0&&{globalArgsSchema:o},...l!==void 0&&{bundledWorker:l}},f={...e};return f.subCommands={...e.subCommands,completion:r(n({name:`completion`,description:`Generate shell completion script`,args:h,run(){}}),()=>import(`./completion-DUMcvXkT.js`).then(e=>e.createCompletionCommand(f,a,o,d))),__complete:r(n({name:`__complete`,args:i,run(){}}),()=>import(`./dynamic-CMtee4tD.js`).then(e=>e.createDynamicCompleteCommand(f,a,o))),"__refresh-completion":r(n({name:`__refresh-completion`,description:`(internal) Refresh the on-disk completion cache if stale.`,args:g,run(){}}),()=>import(`./completion-DUMcvXkT.js`).then(e=>e.createRefreshCompletionCommand(f,u,d))),"__completion-worker-path":r(n({name:`__completion-worker-path`,description:`(internal) Print the bundled completion worker path when available.`,args:_,run(){}}),()=>import(`./completion-DUMcvXkT.js`).then(e=>e.createCompletionWorkerPathCommand(u,d)))},f.runMainHook=e=>{y(e,{programName:u,...s!==void 0&&{cacheDir:s}})},f}function y(e,t){if(process.env.POLITTY_NO_COMPLETION_REFRESH)return;let n=e.find(e=>!e.startsWith(`-`));if(n===`__complete`||n===`__refresh-completion`||n===`__completion-worker-path`||n===`completion`)return;let r=l();if(!r)return;let i=process.argv[1];i&&p(t,r)&&m(i,r)}export{d as a,_ as i,h as n,f as o,g as r,l as s,v as t};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@politty/zod",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "A lightweight CLI framework inspired by citty with zod v4 registry integration for type-safe metadata management",
5
5
  "keywords": [
6
6
  "argument-parser",
@@ -74,12 +74,12 @@
74
74
  "yaml": "^2.9.0"
75
75
  },
76
76
  "devDependencies": {
77
+ "@politty/core": "0.1.0",
77
78
  "@types/node": "25.9.5",
78
79
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
79
80
  "tsdown": "0.22.14",
80
81
  "typescript": "7.0.2",
81
- "zod": "4.4.3",
82
- "@politty/core": "0.1.0"
82
+ "zod": "4.4.3"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "@clack/prompts": "^0.10.0 || ^0.11.0 || ^1.0.0",
@@ -1,314 +0,0 @@
1
- import { a as internalField, i as internalArgs } from "./schema-extractor-CVNDs07l.js";
2
- import { n as defineCommand } from "./command-k-4yAz4J.js";
3
- import { n as runMain } from "./runner-Bz3arOqh.js";
4
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
- import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
-
8
- //#region ../core/src/compile-cache-shim.ts
9
- /**
10
- * Generator for compile-cache bin shims.
11
- *
12
- * Emits the minimal entry file described in docs/recipes.md ("Faster
13
- * Startup"): a shim that enables the Node.js on-disk compile cache and then
14
- * loads the real CLI with a dynamic import. Meant to be wired into a
15
- * `postbuild` or `prepack` script via `politty generate-shim` so the shim
16
- * never has to live in source.
17
- *
18
- * Each politty package binds its own generator with
19
- * {@link createCompileCacheShimGenerator}, so the shim imports the cache
20
- * helper from the package that generated it.
21
- */
22
- /**
23
- * Marker identifying files this generator wrote (overwrite guard). Must be
24
- * shim-specific: other politty artifacts (e.g. completion scripts) also say
25
- * "Generated by politty", and those must never be treated as overwritable.
26
- */
27
- const SHIM_MARKER = "Generated by politty: compile-cache bin shim";
28
- /** Entry candidates tried, in order, when `entry` is omitted. */
29
- const DEFAULT_ENTRY_CANDIDATES = [
30
- "./cli.js",
31
- "./cli.mjs",
32
- "./index.js",
33
- "./index.mjs"
34
- ];
35
- /**
36
- * Read the nearest `package.json`, walking up from `startDir` to the
37
- * filesystem root. A malformed file is a real error and propagates.
38
- */
39
- function readNearestPackageJson(startDir) {
40
- let dir = resolve(startDir);
41
- for (;;) {
42
- const candidate = join(dir, "package.json");
43
- if (existsSync(candidate)) return {
44
- pkg: JSON.parse(readFileSync(candidate, "utf8")),
45
- dir
46
- };
47
- const parent = dirname(dir);
48
- if (parent === dir) return void 0;
49
- dir = parent;
50
- }
51
- }
52
- /**
53
- * `bin` entries as `[name, path]` pairs: the object form's entries in
54
- * declaration order, or the string form as a single pair named after the
55
- * package (npm's own convention for `"bin": "path"`).
56
- */
57
- function binEntries(pkg) {
58
- if (!pkg) return [];
59
- if (typeof pkg.bin === "string" && pkg.bin) {
60
- const name = defaultProgramName(pkg);
61
- return name ? [[name, pkg.bin]] : [];
62
- }
63
- if (typeof pkg.bin === "object" && pkg.bin !== null) return Object.entries(pkg.bin).filter((pair) => typeof pair[1] === "string" && pair[1] !== "");
64
- return [];
65
- }
66
- /**
67
- * Derive the fallback program name from a package.json: the first `bin`
68
- * command name when present (that is the name users type in their shell),
69
- * else the package name without its scope.
70
- */
71
- function defaultProgramName(pkg) {
72
- if (!pkg) return void 0;
73
- if (typeof pkg.bin === "object" && pkg.bin !== null) {
74
- const [first] = Object.keys(pkg.bin);
75
- if (first) return first;
76
- }
77
- if (typeof pkg.name === "string" && pkg.name) {
78
- const name = pkg.name;
79
- return name.startsWith("@") ? name.split("/")[1] ?? name : name;
80
- }
81
- }
82
- /**
83
- * Pick the default entry: the first {@link DEFAULT_ENTRY_CANDIDATES} that
84
- * exists next to the shim (never the shim itself).
85
- */
86
- function defaultEntry(outputPath) {
87
- const dir = dirname(outputPath);
88
- const self = basename(outputPath);
89
- for (const candidate of DEFAULT_ENTRY_CANDIDATES) {
90
- if (basename(candidate) === self) continue;
91
- if (existsSync(join(dir, candidate))) return candidate;
92
- }
93
- }
94
- function shimContent(program, entry, compileCacheSpecifier) {
95
- return [
96
- "#!/usr/bin/env node",
97
- "",
98
- `// ${SHIM_MARKER}.`,
99
- "// Enables the Node.js on-disk compile cache (V8 code cache) before the",
100
- "// CLI module graph is compiled, so warm starts skip recompilation",
101
- "// (Node >= 22.8.0; silent no-op otherwise).",
102
- "try {",
103
- ` const { enableCompileCache } = await import(${JSON.stringify(compileCacheSpecifier)});`,
104
- ` enableCompileCache(${JSON.stringify(program)});`,
105
- "} catch {",
106
- ` // ${compileCacheSpecifier} is not resolvable from here (e.g. a fully`,
107
- " // bundled CLI) — start without the compile cache rather than failing",
108
- " // the CLI.",
109
- "}",
110
- `await import(${JSON.stringify(entry)});`,
111
- ""
112
- ].join("\n");
113
- }
114
- function toArray(value) {
115
- if (value === void 0) return [];
116
- return Array.isArray(value) ? value : [value];
117
- }
118
- /**
119
- * Build the shim generator for one politty package.
120
- *
121
- * `ownerPackage` is the npm name of the package the generator is exported
122
- * from (`@politty/zod`, `@politty/valibot`, `politty`), and the shim imports
123
- * `enableCompileCache` from its `compile-cache` subpath. Taking the name from
124
- * the owner rather than guessing it is what makes the specifier reliable:
125
- * reaching this generator at all — through that package's bin or through an
126
- * import of it — means the package is installed in the host, so the specifier
127
- * resolves from the shim that lands there. The alternative, reading the host's
128
- * `package.json`, could only guess which of the three politty packages was
129
- * meant.
130
- *
131
- * The returned function generates executable shims. With no explicit paths,
132
- * one is generated per `bin` entry of the nearest `package.json`, each
133
- * importing a conventional built module next to it — so a bare
134
- * `politty generate-shim` in a `postbuild` script is usually enough. Explicit
135
- * `entry` values are paired in order with the `bin` entries (or with explicit
136
- * `out` values of the same count).
137
- *
138
- * The generated files are ESM (they use top-level `await import`), so `.js`
139
- * output requires `"type": "module"` in the package; use a `.mjs` extension
140
- * otherwise. Refuses to overwrite an existing file it did not generate, so
141
- * a `bin` path still pointing at the real CLI entry fails loudly instead of
142
- * clobbering the build output.
143
- */
144
- function createCompileCacheShimGenerator(ownerPackage) {
145
- return (options = {}) => generateShims(`${ownerPackage}/compile-cache`, options);
146
- }
147
- function generateShims(defaultCompileCacheSpecifier, options) {
148
- const cwd = options.cwd ?? process.cwd();
149
- const found = readNearestPackageJson(cwd);
150
- const pkg = found?.pkg;
151
- const entries = toArray(options.entry);
152
- const outs = toArray(options.out);
153
- const bins = binEntries(pkg);
154
- let outputPaths;
155
- if (outs.length > 0) {
156
- if (entries.length > 0 && entries.length !== outs.length) throw new Error(`--entry count (${entries.length}) does not match --out count (${outs.length}); pass one --out per --entry or omit --out entirely.`);
157
- outputPaths = outs.map((out) => isAbsolute(out) ? out : resolve(cwd, out));
158
- } else {
159
- if (bins.length === 0 || found === void 0) throw new Error("Cannot derive the output path: no bin entry in package.json. Pass --out explicitly.");
160
- if (entries.length > 0 && entries.length !== bins.length) throw new Error(`--entry count (${entries.length}) does not match the package's bin entries (${bins.length}); pass one --entry per bin (in declaration order) or matching --out paths.`);
161
- outputPaths = bins.map(([, path]) => resolve(found.dir, path));
162
- }
163
- if (new Set(outputPaths).size !== outputPaths.length) throw new Error("Duplicate output paths; each shim needs a distinct output file. Check the --out values (or the bin paths in package.json when --out is omitted).");
164
- const binNameByPath = /* @__PURE__ */ new Map();
165
- if (found) for (const [name, path] of bins) binNameByPath.set(resolve(found.dir, path), name);
166
- const warnings = [];
167
- const compileCacheSpecifier = options.compileCacheSpecifier ?? defaultCompileCacheSpecifier;
168
- if (/[\r\n\u2028\u2029]/.test(compileCacheSpecifier)) throw new Error(`Invalid compile-cache specifier ${JSON.stringify(compileCacheSpecifier)}: a module specifier cannot contain a line terminator.`);
169
- const plans = outputPaths.map((outputPath, index) => {
170
- const matchedBinName = binNameByPath.get(outputPath);
171
- const program = options.program ?? matchedBinName ?? defaultProgramName(pkg);
172
- if (!program) throw new Error("Cannot derive a program name: no bin or name in package.json. Pass --program explicitly.");
173
- if (options.program === void 0 && matchedBinName === void 0 && outs.length > 0) warnings.push(`Warning: ${formatShimPath(outputPath, cwd)} does not match any bin path in package.json, so its cache directory uses the program name ${JSON.stringify(program)}. Pass --program to override.`);
174
- if (outputPath.endsWith(".cjs")) throw new Error("The generated shim is an ES module and cannot be written to a .cjs file. Use a .mjs (or .js in a \"type\": \"module\" package) output path.");
175
- if (extname(outputPath) === "") throw new Error("The generated shim is an ES module and cannot be written to an extensionless file (it would not load on every supported Node.js version). Use a .mjs (or .js in a \"type\": \"module\" package) output path.");
176
- if (outputPath.endsWith(".js") && pkg?.type !== "module") throw new Error(pkg === void 0 ? "The generated shim is an ES module, and no package.json was found to confirm .js files are treated as ESM. Write it to a .mjs file instead (e.g. --out dist/bin.mjs)." : "The generated shim is an ES module, but the package is not \"type\": \"module\". Write it to a .mjs file instead (e.g. --out dist/bin.mjs).");
177
- const entry = entries[index] ?? defaultEntry(outputPath);
178
- if (entry === void 0) throw new Error(`Cannot derive an entry: none of ${DEFAULT_ENTRY_CANDIDATES.join(", ")} exist next to ${outputPath}. Pass --entry explicitly.`);
179
- if (!entry.startsWith("./") && !entry.startsWith("../") && !entry.startsWith("file:")) throw new Error(`Invalid entry ${entry}: pass a specifier relative to the shim file ("./..." or "../...") or a file: URL.`);
180
- let entryPath;
181
- if (entry.startsWith("file:")) try {
182
- entryPath = fileURLToPath(entry);
183
- } catch {
184
- entryPath = void 0;
185
- }
186
- else entryPath = resolve(dirname(outputPath), entry);
187
- if (entryPath === outputPath) throw new Error(`The shim at ${outputPath} would import itself (entry ${entry}). Point bin at a separate shim path (e.g. dist/bin.js) or pass a different --entry.`);
188
- if (existsSync(outputPath) && !readFileSync(outputPath, "utf8").includes(SHIM_MARKER)) throw new Error(`Refusing to overwrite ${outputPath}: it exists and was not generated by politty. If bin currently points at your real CLI entry, point it at a separate shim path (e.g. dist/bin.js) or pass --out explicitly.`);
189
- return {
190
- outputPath,
191
- program,
192
- entry,
193
- compileCacheSpecifier
194
- };
195
- });
196
- for (const warning of warnings) console.warn(warning);
197
- for (const { outputPath, program, entry } of plans) {
198
- mkdirSync(dirname(outputPath), { recursive: true });
199
- writeFileSync(outputPath, shimContent(program, entry, compileCacheSpecifier));
200
- chmodSync(outputPath, 493);
201
- }
202
- return plans;
203
- }
204
- /**
205
- * Format a generated path for CLI output: relative to `cwd` when inside it.
206
- */
207
- function formatShimPath(outputPath, cwd) {
208
- const rel = relative(cwd, outputPath);
209
- return rel && !rel.startsWith("..") ? rel : outputPath;
210
- }
211
-
212
- //#endregion
213
- //#region ../core/src/cli-main.ts
214
- const generateWorkerArgsSchema = internalArgs({
215
- bin: internalField.string({
216
- description: "CLI binary or built JS entry file to invoke",
217
- placeholder: "PATH"
218
- }),
219
- program: internalField.string({
220
- description: "Program name embedded in worker metadata",
221
- placeholder: "NAME"
222
- }),
223
- shell: internalField.enum([
224
- "bash",
225
- "zsh",
226
- "fish"
227
- ], {
228
- description: "Shell worker to generate",
229
- placeholder: "SHELL"
230
- }),
231
- out: internalField.optionalString({
232
- description: "Output worker path (defaults to dist/completion/<shell>-worker.<ext>)",
233
- placeholder: "PATH"
234
- }),
235
- verify: internalField.boolean({ description: "Verify __completion-worker-path resolves to the generated worker" })
236
- });
237
- const generateWorkerCommand = defineCommand({
238
- name: "generate-worker",
239
- description: "Generate and verify a bundled shell completion worker",
240
- args: generateWorkerArgsSchema,
241
- async run(args) {
242
- const { generateBundledCompletionWorker } = await import("./src-DhQVU2hG.js");
243
- await generateBundledCompletionWorker({
244
- bin: args.bin,
245
- programName: args.program,
246
- shell: args.shell,
247
- ...args.out !== void 0 && { outputPath: args.out },
248
- verify: args.verify
249
- });
250
- }
251
- });
252
- const generateShimArgsSchema = internalArgs({
253
- entry: internalField.optionalStringArray({
254
- description: "Module specifier the shim imports, relative to the shim file; repeatable, one per bin/--out (defaults to ./cli.js, ./cli.mjs, ./index.js, or ./index.mjs next to each shim)",
255
- placeholder: "SPECIFIER"
256
- }),
257
- out: internalField.optionalStringArray({
258
- description: "Output path for the generated shim; repeatable, one per --entry (defaults to the bin paths in package.json)",
259
- placeholder: "PATH"
260
- }),
261
- program: internalField.optionalString({
262
- description: "Program name for the cache directory, applied to all shims (defaults per shim to its bin name)",
263
- placeholder: "NAME"
264
- }),
265
- compileCacheSpecifier: internalField.optionalString({
266
- description: "Module specifier the shim imports enableCompileCache from (defaults to the compile-cache subpath of the politty package running this command)",
267
- placeholder: "SPECIFIER"
268
- })
269
- });
270
- /**
271
- * Run politty's own development CLI (`generate-shim`, `generate-worker`).
272
- *
273
- * `ownerPackage` is the npm name of the politty package providing the `politty`
274
- * bin that invoked this — `@politty/zod`, `@politty/valibot`, or `politty`. It
275
- * is threaded through to {@link createCompileCacheShimGenerator} so a generated
276
- * shim imports the cache helper from the package the user actually installed,
277
- * which is the one guaranteed to resolve from their own package.
278
- *
279
- * Never returns: it exits the process, like `runMain`.
280
- */
281
- function runPolittyCli(ownerPackage) {
282
- const generateCompileCacheShim = createCompileCacheShimGenerator(ownerPackage);
283
- const generateShimCommand = defineCommand({
284
- name: "generate-shim",
285
- description: "Generate a compile-cache bin shim that loads the real CLI via dynamic import",
286
- args: generateShimArgsSchema,
287
- run(args) {
288
- const cwd = process.cwd();
289
- const results = generateCompileCacheShim({
290
- ...args.entry !== void 0 && { entry: args.entry },
291
- ...args.out !== void 0 && { out: args.out },
292
- ...args.program !== void 0 && { program: args.program },
293
- ...args.compileCacheSpecifier !== void 0 && { compileCacheSpecifier: args.compileCacheSpecifier },
294
- cwd
295
- });
296
- for (const result of results) console.log(`Generated compile-cache shim: ${formatShimPath(result.outputPath, cwd)} (program: ${result.program}, entry: ${result.entry}, compile-cache: ${result.compileCacheSpecifier})`);
297
- }
298
- });
299
- const cli = defineCommand({
300
- name: "politty",
301
- description: "politty development utilities",
302
- subCommands: {
303
- "generate-shim": generateShimCommand,
304
- "generate-worker": generateWorkerCommand
305
- }
306
- });
307
- return runMain(cli).catch((error) => {
308
- console.error(error instanceof Error ? error.message : String(error));
309
- process.exit(1);
310
- });
311
- }
312
-
313
- //#endregion
314
- export { createCompileCacheShimGenerator as n, runPolittyCli as t };
@@ -1,3 +0,0 @@
1
- import { t as runPolittyCli } from "./cli-main-CAa5KwCo.js";
2
-
3
- export { runPolittyCli };
@@ -1,8 +0,0 @@
1
- import "./register-DdcsbNwM.js";
2
-
3
- //#region src/cli-run.ts
4
- const { runPolittyCli } = await import("./cli-main-DIRMduj1.js");
5
- await runPolittyCli("@politty/zod");
6
-
7
- //#endregion
8
- export { };
@@ -1,42 +0,0 @@
1
- //#region ../core/src/core/command.ts
2
- function defineCommand(config) {
3
- return {
4
- name: config.name,
5
- description: config.description,
6
- aliases: config.aliases,
7
- args: config.args,
8
- subCommands: config.subCommands,
9
- setup: config.setup,
10
- run: config.run,
11
- cleanup: config.cleanup,
12
- notes: config.notes,
13
- examples: config.examples
14
- };
15
- }
16
- /**
17
- * Create a typed defineCommand factory with pre-bound global args type.
18
- * This is the recommended pattern for type-safe global options.
19
- *
20
- * @example
21
- * ```ts
22
- * // global-args.ts
23
- * type GlobalArgsType = { verbose: boolean; config?: string };
24
- * export const defineAppCommand = createDefineCommand<GlobalArgsType>();
25
- *
26
- * // commands/build.ts
27
- * export const buildCommand = defineAppCommand({
28
- * name: "build",
29
- * args: z.object({ output: arg(z.string().default("dist")) }),
30
- * run: (args) => {
31
- * args.verbose; // typed via GlobalArgsType
32
- * args.output; // typed via local args
33
- * },
34
- * });
35
- * ```
36
- */
37
- function createDefineCommand() {
38
- return defineCommand;
39
- }
40
-
41
- //#endregion
42
- export { defineCommand as n, createDefineCommand as t };
@@ -1,103 +0,0 @@
1
- import * as nodeModule from "node:module";
2
- import { join } from "node:path";
3
- import { homedir } from "node:os";
4
-
5
- //#region ../core/src/compile-cache.ts
6
- /**
7
- * Node.js on-disk compile cache (V8 code cache) helpers.
8
- *
9
- * `node:module`'s `enableCompileCache` (Node.js >= 22.8.0) persists compiled
10
- * bytecode to disk so warm starts skip recompilation. Because ESM static
11
- * import graphs are compiled during the link phase — before any user code
12
- * runs — enabling the cache inside `runMain` only covers modules imported
13
- * *after* the call (e.g. `lazy()` subcommands). To cover the whole CLI,
14
- * enable it from a minimal bin shim that dynamically imports the real entry:
15
- *
16
- * ```ts
17
- * #!/usr/bin/env node
18
- * // Import from the `compile-cache` subpath of the politty package your CLI
19
- * // depends on — `politty generate-shim` writes that specifier for you,
20
- * // naming whichever package's bin generated the shim.
21
- * import { enableCompileCache } from "<your-politty-package>/compile-cache";
22
- *
23
- * enableCompileCache("my-cli");
24
- * await import("./cli.js");
25
- * ```
26
- *
27
- * This module must stay dependency-free (node builtins only) so the shim's
28
- * static graph — the part that can never be cached — stays tiny.
29
- */
30
- /**
31
- * Reduce a program name to a single safe path segment. Path separators and
32
- * a leading scope marker are collapsed (`@scope/cli` → `scope-cli`) so the
33
- * name cannot escape the cache root; names that reduce to nothing (or to
34
- * `.`/`..`) yield `undefined`. Realistic command names pass through
35
- * unchanged.
36
- */
37
- function sanitizeProgramName(programName) {
38
- const safe = programName.replace(/^@/, "").replace(/[/\\]+/g, "-").trim();
39
- if (!safe || /^[.-]+$/.test(safe)) return void 0;
40
- return safe;
41
- }
42
- /**
43
- * Compute the cache directory for a program following the same XDG
44
- * convention as the shell-completion dispatcher scripts
45
- * (`src/completion/dispatcher.ts`), so direct CLI runs and completion
46
- * workers share one warm cache:
47
- * `${XDG_CACHE_HOME:-$HOME/.cache}/<sanitized programName>/node-compile-cache`.
48
- * The program name is first reduced to a single safe path segment by
49
- * {@link sanitizeProgramName} (e.g. `@scope/cli` → `scope-cli`). The
50
- * dispatcher scripts use the raw name, but a completion program name is a
51
- * single shell word resolved on PATH and can never contain separators, so
52
- * for every name that can actually reach both sides the two paths coincide.
53
- *
54
- * Returns `undefined` when no home directory can be resolved or the program
55
- * name does not reduce to a safe path segment; callers fall back to Node's
56
- * default location (`NODE_COMPILE_CACHE` or the OS tmpdir).
57
- */
58
- function compileCacheDir(programName) {
59
- const safeName = sanitizeProgramName(programName);
60
- if (safeName === void 0) return void 0;
61
- const xdg = process.env.XDG_CACHE_HOME;
62
- if (xdg) return join(xdg, safeName, "node-compile-cache");
63
- try {
64
- const home = homedir();
65
- if (!home) return void 0;
66
- return join(home, ".cache", safeName, "node-compile-cache");
67
- } catch {
68
- return;
69
- }
70
- }
71
- /**
72
- * Enable the Node.js on-disk compile cache for this process.
73
- *
74
- * - No-ops (returns `{ enabled: false }`) on runtimes without
75
- * `module.enableCompileCache` (Node.js < 22.8.0) and never throws.
76
- * - When the `NODE_COMPILE_CACHE` environment variable is set it always
77
- * wins, keeping runs spawned by completion scripts (which set the same
78
- * variable) consistent with direct runs.
79
- * - Repeat calls are harmless: Node keeps the directory from the first
80
- * successful call.
81
- *
82
- * @param options - Program name (string shorthand) or {@link CompileCacheOptions}.
83
- */
84
- function enableCompileCache(options) {
85
- const opts = typeof options === "string" ? { programName: options } : options ?? {};
86
- try {
87
- const enable = nodeModule.enableCompileCache;
88
- if (typeof enable !== "function") return { enabled: false };
89
- let dir;
90
- if (!process.env.NODE_COMPILE_CACHE) dir = opts.cacheDir ?? (opts.programName !== void 0 ? compileCacheDir(opts.programName) : void 0);
91
- const result = dir === void 0 ? enable() : enable(dir);
92
- const status = nodeModule.constants?.compileCacheStatus;
93
- return {
94
- enabled: status !== void 0 ? result.status === status.ENABLED || result.status === status.ALREADY_ENABLED : result.status === 0 || result.status === 1,
95
- ...result.directory !== void 0 && { directory: result.directory }
96
- };
97
- } catch {
98
- return { enabled: false };
99
- }
100
- }
101
-
102
- //#endregion
103
- export { enableCompileCache as n, compileCacheDir as t };