@sayknow-cli/utils 0.3.11 → 0.3.13

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/src/prompt.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { HelperDelegate, HelperOptions, Template, TemplateDelegate } from "handlebars";
2
- import Handlebars from "handlebars";
3
2
 
4
3
  export type { HelperDelegate, HelperOptions, Template, TemplateDelegate };
5
4
 
@@ -223,107 +222,133 @@ export interface TemplateContext extends Record<string, unknown> {
223
222
  arguments?: string;
224
223
  }
225
224
 
226
- const handlebars = Handlebars.create();
225
+ type HandlebarsRuntime = typeof import("handlebars");
226
+ type HandlebarsInstance = ReturnType<HandlebarsRuntime["create"]>;
227
+
228
+ let handlebars: HandlebarsInstance | undefined;
229
+
230
+ function getHandlebars(): HandlebarsInstance {
231
+ if (handlebars) return handlebars;
232
+ // Lazy bare-literal require: statically traceable, so the bundler always
233
+ // embeds handlebars in the main bundle (compiled binaries included), while
234
+ // the module still loads only on first template render. The previous
235
+ // bunfs extra-entrypoint require crashed v0.9.3–v0.9.6 compiled releases
236
+ // at startup when --minify dropped the entrypoint (#1939).
237
+ const Handlebars = asHandlebarsRuntime(require("handlebars"));
238
+ handlebars = Handlebars.create();
239
+ registerBuiltinHelpers(handlebars);
240
+ return handlebars;
241
+ }
227
242
 
228
- handlebars.registerHelper("arg", function (this: TemplateContext, index: number | string): string {
229
- const args = this.args ?? [];
230
- const parsedIndex = typeof index === "number" ? index : Number.parseInt(index, 10);
231
- if (!Number.isFinite(parsedIndex)) return "";
232
- const zeroBased = parsedIndex - 1;
233
- if (zeroBased < 0) return "";
234
- return args[zeroBased] ?? "";
235
- });
243
+ function asHandlebarsRuntime(value: unknown): HandlebarsRuntime {
244
+ if (isHandlebarsRuntime(value)) return value;
245
+ if (isObjectRecord(value) && isHandlebarsRuntime(value.default)) return value.default;
246
+ throw new Error("Loaded handlebars module does not expose the expected runtime API.");
247
+ }
236
248
 
237
- /**
238
- * {{#list items prefix="- " suffix="" join="\n"}}{{this}}{{/list}}
239
- * Renders an array with customizable prefix, suffix, and join separator.
240
- * Note: Use \n in join for newlines (will be unescaped automatically).
241
- */
242
- handlebars.registerHelper(
243
- "list",
244
- function (this: unknown, context: unknown[], options: Handlebars.HelperOptions): string {
249
+ function isHandlebarsRuntime(value: unknown): value is HandlebarsRuntime {
250
+ return isObjectRecord(value) && typeof value.create === "function";
251
+ }
252
+
253
+ function isObjectRecord(value: unknown): value is Record<string, unknown> {
254
+ return typeof value === "object" && value !== null;
255
+ }
256
+
257
+ function registerBuiltinHelpers(handlebars: HandlebarsInstance): void {
258
+ handlebars.registerHelper("arg", function (this: TemplateContext, index: number | string): string {
259
+ const args = this.args ?? [];
260
+ const parsedIndex = typeof index === "number" ? index : Number.parseInt(index, 10);
261
+ if (!Number.isFinite(parsedIndex)) return "";
262
+ const zeroBased = parsedIndex - 1;
263
+ if (zeroBased < 0) return "";
264
+ return args[zeroBased] ?? "";
265
+ });
266
+
267
+ /**
268
+ * {{#list items prefix="- " suffix="" join="\n"}}{{this}}{{/list}}
269
+ * Renders an array with customizable prefix, suffix, and join separator.
270
+ * Note: Use \n in join for newlines (will be unescaped automatically).
271
+ */
272
+ handlebars.registerHelper("list", function (this: unknown, context: unknown[], options: HelperOptions): string {
245
273
  if (!Array.isArray(context) || context.length === 0) return "";
246
274
  const prefix = (options.hash.prefix as string) ?? "";
247
275
  const suffix = (options.hash.suffix as string) ?? "";
248
276
  const rawSeparator = (options.hash.join as string) ?? "\n";
249
277
  const separator = rawSeparator.replace(/\\n/g, "\n").replace(/\\t/g, "\t");
250
278
  return context.map(item => `${prefix}${options.fn(item)}${suffix}`).join(separator);
251
- },
252
- );
253
-
254
- /**
255
- * {{join array ", "}}
256
- * Joins an array with a separator (default: ", ").
257
- */
258
- handlebars.registerHelper("join", (context: unknown[], separator?: unknown): string => {
259
- if (!Array.isArray(context)) return "";
260
- const sep = typeof separator === "string" ? separator : ", ";
261
- return context.join(sep);
262
- });
263
-
264
- /**
265
- * {{default value "fallback"}}
266
- * Returns the value if truthy, otherwise returns the fallback.
267
- */
268
- handlebars.registerHelper("default", (value: unknown, defaultValue: unknown): unknown => value || defaultValue);
269
-
270
- /**
271
- * {{pluralize count "item" "items"}}
272
- * Returns "1 item" or "5 items" based on count.
273
- */
274
- handlebars.registerHelper(
275
- "pluralize",
276
- (count: number, singular: string, plural: string): string => `${count} ${count === 1 ? singular : plural}`,
277
- );
279
+ });
278
280
 
279
- /**
280
- * {{#when value "==" compare}}...{{else}}...{{/when}}
281
- * Conditional block with comparison operators: ==, ===, !=, !==, >, <, >=, <=
282
- */
283
- handlebars.registerHelper(
284
- "when",
285
- function (this: unknown, lhs: unknown, operator: string, rhs: unknown, options: Handlebars.HelperOptions): string {
286
- const ops: Record<string, (a: unknown, b: unknown) => boolean> = {
287
- "==": (a, b) => a === b,
288
- "===": (a, b) => a === b,
289
- "!=": (a, b) => a !== b,
290
- "!==": (a, b) => a !== b,
291
- ">": (a, b) => (a as number) > (b as number),
292
- "<": (a, b) => (a as number) < (b as number),
293
- ">=": (a, b) => (a as number) >= (b as number),
294
- "<=": (a, b) => (a as number) <= (b as number),
295
- };
296
- const fn = ops[operator];
297
- if (!fn) return options.inverse(this);
298
- return fn(lhs, rhs) ? options.fn(this) : options.inverse(this);
299
- },
300
- );
281
+ /**
282
+ * {{join array ", "}}
283
+ * Joins an array with a separator (default: ", ").
284
+ */
285
+ handlebars.registerHelper("join", (context: unknown[], separator?: unknown): string => {
286
+ if (!Array.isArray(context)) return "";
287
+ const sep = typeof separator === "string" ? separator : ", ";
288
+ return context.join(sep);
289
+ });
301
290
 
302
- /**
303
- * {{#ifAny a b c}}...{{else}}...{{/ifAny}}
304
- * True if any argument is truthy.
305
- */
306
- handlebars.registerHelper("ifAny", function (this: unknown, ...args: unknown[]): string {
307
- const options = args.pop() as Handlebars.HelperOptions;
308
- return args.some(Boolean) ? options.fn(this) : options.inverse(this);
309
- });
291
+ /**
292
+ * {{default value "fallback"}}
293
+ * Returns the value if truthy, otherwise returns the fallback.
294
+ */
295
+ handlebars.registerHelper("default", (value: unknown, defaultValue: unknown): unknown => value || defaultValue);
296
+
297
+ /**
298
+ * {{pluralize count "item" "items"}}
299
+ * Returns "1 item" or "5 items" based on count.
300
+ */
301
+ handlebars.registerHelper(
302
+ "pluralize",
303
+ (count: number, singular: string, plural: string): string => `${count} ${count === 1 ? singular : plural}`,
304
+ );
305
+
306
+ /**
307
+ * {{#when value "==" compare}}...{{else}}...{{/when}}
308
+ * Conditional block with comparison operators: ==, ===, !=, !==, >, <, >=, <=
309
+ */
310
+ handlebars.registerHelper(
311
+ "when",
312
+ function (this: unknown, lhs: unknown, operator: string, rhs: unknown, options: HelperOptions): string {
313
+ const ops: Record<string, (a: unknown, b: unknown) => boolean> = {
314
+ "==": (a, b) => a === b,
315
+ "===": (a, b) => a === b,
316
+ "!=": (a, b) => a !== b,
317
+ "!==": (a, b) => a !== b,
318
+ ">": (a, b) => (a as number) > (b as number),
319
+ "<": (a, b) => (a as number) < (b as number),
320
+ ">=": (a, b) => (a as number) >= (b as number),
321
+ "<=": (a, b) => (a as number) <= (b as number),
322
+ };
323
+ const fn = ops[operator];
324
+ if (!fn) return options.inverse(this);
325
+ return fn(lhs, rhs) ? options.fn(this) : options.inverse(this);
326
+ },
327
+ );
328
+
329
+ /**
330
+ * {{#ifAny a b c}}...{{else}}...{{/ifAny}}
331
+ * True if any argument is truthy.
332
+ */
333
+ handlebars.registerHelper("ifAny", function (this: unknown, ...args: unknown[]): string {
334
+ const options = args.pop() as HelperOptions;
335
+ return args.some(Boolean) ? options.fn(this) : options.inverse(this);
336
+ });
310
337
 
311
- /**
312
- * {{#ifAll a b c}}...{{else}}...{{/ifAll}}
313
- * True if all arguments are truthy.
314
- */
315
- handlebars.registerHelper("ifAll", function (this: unknown, ...args: unknown[]): string {
316
- const options = args.pop() as Handlebars.HelperOptions;
317
- return args.every(Boolean) ? options.fn(this) : options.inverse(this);
318
- });
338
+ /**
339
+ * {{#ifAll a b c}}...{{else}}...{{/ifAll}}
340
+ * True if all arguments are truthy.
341
+ */
342
+ handlebars.registerHelper("ifAll", function (this: unknown, ...args: unknown[]): string {
343
+ const options = args.pop() as HelperOptions;
344
+ return args.every(Boolean) ? options.fn(this) : options.inverse(this);
345
+ });
319
346
 
320
- /**
321
- * {{#table rows headers="Col1|Col2"}}{{col1}}|{{col2}}{{/table}}
322
- * Generates a markdown table from an array of objects.
323
- */
324
- handlebars.registerHelper(
325
- "table",
326
- function (this: unknown, context: unknown[], options: Handlebars.HelperOptions): string {
347
+ /**
348
+ * {{#table rows headers="Col1|Col2"}}{{col1}}|{{col2}}{{/table}}
349
+ * Generates a markdown table from an array of objects.
350
+ */
351
+ handlebars.registerHelper("table", function (this: unknown, context: unknown[], options: HelperOptions): string {
327
352
  if (!Array.isArray(context) || context.length === 0) return "";
328
353
  const headersStr = options.hash.headers as string | undefined;
329
354
  const headers = headersStr?.split("|") ?? [];
@@ -331,108 +356,108 @@ handlebars.registerHelper(
331
356
  const headerRow = headers.length > 0 ? `| ${headers.join(" | ")} |\n| ${separator} |\n` : "";
332
357
  const rows = context.map(item => `| ${options.fn(item).trim()} |`).join("\n");
333
358
  return headerRow + rows;
334
- },
335
- );
336
-
337
- /**
338
- * {{#codeblock lang="diff"}}...{{/codeblock}}
339
- * Wraps content in a fenced code block.
340
- */
341
- handlebars.registerHelper("codeblock", function (this: unknown, options: Handlebars.HelperOptions): string {
342
- const lang = (options.hash.lang as string) ?? "";
343
- const content = options.fn(this).trim();
344
- return `\`\`\`${lang}\n${content}\n\`\`\``;
345
- });
346
-
347
- /**
348
- * {{#xml "tag"}}content{{/xml}}
349
- * Wraps content in XML-style tags. Returns empty string if content is empty.
350
- */
351
- handlebars.registerHelper("xml", function (this: unknown, tag: string, options: Handlebars.HelperOptions): string {
352
- const content = options.fn(this).trim();
353
- if (!content) return "";
354
- return `<${tag}>\n${content}\n</${tag}>`;
355
- });
359
+ });
356
360
 
357
- /**
358
- * {{escapeXml value}}
359
- * Escapes XML special characters: & < > "
360
- */
361
- handlebars.registerHelper("escapeXml", (value: unknown): string => {
362
- if (value == null) return "";
363
- return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
364
- });
361
+ /**
362
+ * {{#codeblock lang="diff"}}...{{/codeblock}}
363
+ * Wraps content in a fenced code block.
364
+ */
365
+ handlebars.registerHelper("codeblock", function (this: unknown, options: HelperOptions): string {
366
+ const lang = (options.hash.lang as string) ?? "";
367
+ const content = options.fn(this).trim();
368
+ return `\`\`\`${lang}\n${content}\n\`\`\``;
369
+ });
365
370
 
366
- /**
367
- * {{len array}}
368
- * Returns the length of an array or string.
369
- */
370
- handlebars.registerHelper("len", (value: unknown): number => {
371
- if (Array.isArray(value)) return value.length;
372
- if (typeof value === "string") return value.length;
373
- return 0;
374
- });
371
+ /**
372
+ * {{#xml "tag"}}content{{/xml}}
373
+ * Wraps content in XML-style tags. Returns empty string if content is empty.
374
+ */
375
+ handlebars.registerHelper("xml", function (this: unknown, tag: string, options: HelperOptions): string {
376
+ const content = options.fn(this).trim();
377
+ if (!content) return "";
378
+ return `<${tag}>\n${content}\n</${tag}>`;
379
+ });
375
380
 
376
- /**
377
- * {{add a b}}
378
- * Adds two numbers.
379
- */
380
- handlebars.registerHelper("add", (a: number, b: number): number => (a ?? 0) + (b ?? 0));
381
+ /**
382
+ * {{escapeXml value}}
383
+ * Escapes XML special characters: & < > "
384
+ */
385
+ handlebars.registerHelper("escapeXml", (value: unknown): string => {
386
+ if (value == null) return "";
387
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
388
+ });
381
389
 
382
- /**
383
- * {{sub a b}}
384
- * Subtracts b from a.
385
- */
386
- handlebars.registerHelper("sub", (a: number, b: number): number => (a ?? 0) - (b ?? 0));
390
+ /**
391
+ * {{len array}}
392
+ * Returns the length of an array or string.
393
+ */
394
+ handlebars.registerHelper("len", (value: unknown): number => {
395
+ if (Array.isArray(value)) return value.length;
396
+ if (typeof value === "string") return value.length;
397
+ return 0;
398
+ });
387
399
 
388
- /**
389
- * {{#has collection item}}...{{else}}...{{/has}}
390
- * Checks if an array includes an item or if a Set/Map has a key.
391
- */
392
- handlebars.registerHelper(
393
- "has",
394
- function (this: unknown, collection: unknown, item: unknown, options: Handlebars.HelperOptions): string {
395
- let found = false;
396
- if (Array.isArray(collection)) {
397
- found = collection.includes(item);
398
- } else if (collection instanceof Set) {
399
- found = collection.has(item);
400
- } else if (collection instanceof Map) {
401
- found = collection.has(item);
402
- } else if (collection && typeof collection === "object") {
403
- if (typeof item === "string" || typeof item === "number" || typeof item === "symbol") {
404
- found = item in collection;
400
+ /**
401
+ * {{add a b}}
402
+ * Adds two numbers.
403
+ */
404
+ handlebars.registerHelper("add", (a: number, b: number): number => (a ?? 0) + (b ?? 0));
405
+
406
+ /**
407
+ * {{sub a b}}
408
+ * Subtracts b from a.
409
+ */
410
+ handlebars.registerHelper("sub", (a: number, b: number): number => (a ?? 0) - (b ?? 0));
411
+
412
+ /**
413
+ * {{#has collection item}}...{{else}}...{{/has}}
414
+ * Checks if an array includes an item or if a Set/Map has a key.
415
+ */
416
+ handlebars.registerHelper(
417
+ "has",
418
+ function (this: unknown, collection: unknown, item: unknown, options: HelperOptions): string {
419
+ let found = false;
420
+ if (Array.isArray(collection)) {
421
+ found = collection.includes(item);
422
+ } else if (collection instanceof Set) {
423
+ found = collection.has(item);
424
+ } else if (collection instanceof Map) {
425
+ found = collection.has(item);
426
+ } else if (collection && typeof collection === "object") {
427
+ if (typeof item === "string" || typeof item === "number" || typeof item === "symbol") {
428
+ found = item in collection;
429
+ }
405
430
  }
406
- }
407
- return found ? options.fn(this) : options.inverse(this);
408
- },
409
- );
431
+ return found ? options.fn(this) : options.inverse(this);
432
+ },
433
+ );
434
+
435
+ /**
436
+ * {{includes array item}}
437
+ * Returns true if array includes item. For use in other helpers.
438
+ */
439
+ handlebars.registerHelper("includes", (collection: unknown, item: unknown): boolean => {
440
+ if (Array.isArray(collection)) return collection.includes(item);
441
+ if (collection instanceof Set) return collection.has(item);
442
+ if (collection instanceof Map) return collection.has(item);
443
+ return false;
444
+ });
410
445
 
411
- /**
412
- * {{includes array item}}
413
- * Returns true if array includes item. For use in other helpers.
414
- */
415
- handlebars.registerHelper("includes", (collection: unknown, item: unknown): boolean => {
416
- if (Array.isArray(collection)) return collection.includes(item);
417
- if (collection instanceof Set) return collection.has(item);
418
- if (collection instanceof Map) return collection.has(item);
419
- return false;
420
- });
446
+ /**
447
+ * {{not value}}
448
+ * Returns logical NOT of value. For use in subexpressions.
449
+ */
450
+ handlebars.registerHelper("not", (value: unknown): boolean => !value);
421
451
 
422
- /**
423
- * {{not value}}
424
- * Returns logical NOT of value. For use in subexpressions.
425
- */
426
- handlebars.registerHelper("not", (value: unknown): boolean => !value);
427
-
428
- handlebars.registerHelper("jsonStringify", (value: unknown): string => JSON.stringify(value));
452
+ handlebars.registerHelper("jsonStringify", (value: unknown): string => JSON.stringify(value));
453
+ }
429
454
 
430
455
  export function registerHelper(name: string, fn: HelperDelegate): void {
431
- handlebars.registerHelper(name, fn);
456
+ getHandlebars().registerHelper(name, fn);
432
457
  }
433
458
 
434
459
  export function registerPartial(name: string, fn: Template): void {
435
- handlebars.registerPartial(name, fn);
460
+ getHandlebars().registerPartial(name, fn);
436
461
  }
437
462
 
438
463
  /**
@@ -457,7 +482,7 @@ export function compile(template: string): (context: TemplateContext) => string
457
482
  const disambiguated = disambiguateClosingBraces(template);
458
483
  const cached = compiledTemplateCache.get(disambiguated);
459
484
  if (cached) return cached;
460
- const compiled = handlebars.compile(disambiguated, { noEscape: true, strict: false }) as (
485
+ const compiled = getHandlebars().compile(disambiguated, { noEscape: true, strict: false }) as (
461
486
  context: TemplateContext,
462
487
  ) => string;
463
488
  compiledTemplateCache.set(disambiguated, compiled);
@@ -1,27 +0,0 @@
1
- export declare class AbortError extends Error {
2
- constructor(signal: AbortSignal);
3
- }
4
- /**
5
- * Creates an abortable stream from a given stream and signal.
6
- *
7
- * @param stream - The stream to make abortable
8
- * @param signal - The signal to abort the stream
9
- * @returns The abortable stream
10
- */
11
- export declare function createAbortableStream<T>(stream: ReadableStream<T>, signal?: AbortSignal): ReadableStream<T>;
12
- /**
13
- * Runs a promise-returning function (`pr`). If the given AbortSignal is aborted before or during
14
- * execution, the promise is rejected with a standard error.
15
- *
16
- * @param signal - Optional AbortSignal to cancel the operation
17
- * @param pr - Function returning a promise to run
18
- * @returns Promise resolving as `pr` would, or rejecting on abort
19
- */
20
- export declare function untilAborted<T>(signal: AbortSignal | undefined | null, pr: Promise<T> | (() => Promise<T>)): Promise<T>;
21
- /**
22
- * Memoizes a function with no arguments, calling it once and caching the result.
23
- *
24
- * @param fn - Function to be called once
25
- * @returns A function that returns the cached result of `fn`
26
- */
27
- export declare function once<T>(fn: () => T): () => T;
@@ -1,6 +0,0 @@
1
- /**
2
- * Wrap a promise with a timeout and optional abort signal.
3
- * Rejects with the given message if the timeout fires first.
4
- * Cleans up all listeners on settlement.
5
- */
6
- export declare function withTimeout<T>(promise: Promise<T>, ms: number, message: string, signal?: AbortSignal): Promise<T>;
@@ -1,126 +0,0 @@
1
- export interface FlagDescriptor<K extends "string" | "boolean" | "integer" = "string" | "boolean" | "integer"> {
2
- kind: K;
3
- description?: string;
4
- char?: string;
5
- default?: unknown;
6
- multiple?: boolean;
7
- options?: readonly string[];
8
- required?: boolean;
9
- }
10
- export interface ArgDescriptor {
11
- kind: "string";
12
- description?: string;
13
- required?: boolean;
14
- multiple?: boolean;
15
- options?: readonly string[];
16
- }
17
- interface FlagInput {
18
- description?: string;
19
- char?: string;
20
- default?: unknown;
21
- multiple?: boolean;
22
- options?: readonly string[];
23
- required?: boolean;
24
- }
25
- interface ArgInput {
26
- description?: string;
27
- required?: boolean;
28
- multiple?: boolean;
29
- options?: readonly string[];
30
- }
31
- /** Builders that match the `Flags.*()` / `Args.*()` API from oclif. */
32
- export declare const Flags: {
33
- string<T extends FlagInput>(opts?: T): FlagDescriptor<"string"> & T;
34
- boolean<T_1 extends FlagInput>(opts?: T_1): FlagDescriptor<"boolean"> & T_1;
35
- integer<T_2 extends FlagInput & {
36
- default?: number;
37
- }>(opts?: T_2): FlagDescriptor<"integer"> & T_2;
38
- };
39
- export declare const Args: {
40
- string<T extends ArgInput>(opts?: T): ArgDescriptor & T;
41
- };
42
- /**
43
- * Thrown when CLI argument/flag parsing or validation fails (unknown flag,
44
- * bad option value, missing required arg, etc.). `run()` catches this to print
45
- * the message and render usage instead of crashing as an uncaught exception.
46
- */
47
- export declare class CliParseError extends Error {
48
- constructor(message: string);
49
- }
50
- type FlagValue<D extends FlagDescriptor> = D["kind"] extends "boolean" ? D extends {
51
- default: boolean;
52
- } ? boolean : boolean | undefined : D["kind"] extends "integer" ? D extends {
53
- default: number;
54
- } ? number : number | undefined : D extends {
55
- multiple: true;
56
- } ? string[] | undefined : string | undefined;
57
- type ArgValue<D extends ArgDescriptor> = D extends {
58
- multiple: true;
59
- } ? string[] | undefined : string | undefined;
60
- type FlagValues<T extends Record<string, FlagDescriptor>> = {
61
- [K in keyof T]: FlagValue<T[K]>;
62
- };
63
- type ArgValues<T extends Record<string, ArgDescriptor>> = {
64
- [K in keyof T]: ArgValue<T[K]>;
65
- };
66
- export interface ParseOutput<F extends Record<string, FlagDescriptor> = Record<string, FlagDescriptor>, A extends Record<string, ArgDescriptor> = Record<string, ArgDescriptor>> {
67
- flags: FlagValues<F>;
68
- args: ArgValues<A>;
69
- argv: string[];
70
- }
71
- export interface CommandCtor {
72
- new (argv: string[], config: CliConfig): Command;
73
- description?: string;
74
- hidden?: boolean;
75
- strict?: boolean;
76
- aliases?: string[];
77
- examples?: string[];
78
- flags?: Record<string, FlagDescriptor>;
79
- args?: Record<string, ArgDescriptor>;
80
- delegateHelp?: boolean;
81
- }
82
- /** Configuration passed to every command instance and help renderers. */
83
- export interface CliConfig {
84
- bin: string;
85
- version: string;
86
- /** All registered commands keyed by their canonical name. */
87
- commands: Map<string, CommandCtor>;
88
- }
89
- /** Minimal Command base matching the oclif surface we use. */
90
- export declare abstract class Command {
91
- argv: string[];
92
- config: CliConfig;
93
- constructor(argv: string[], config: CliConfig);
94
- abstract run(): Promise<void>;
95
- /**
96
- * Parse argv against the static `flags` and `args` declared on the
97
- * concrete command class. Returns a typed `{ flags, args, argv }` object.
98
- */
99
- parse<C extends CommandCtor>(_Cmd: C): Promise<ParseOutput<NonNullable<C["flags"]> extends Record<string, FlagDescriptor> ? NonNullable<C["flags"]> : Record<string, FlagDescriptor>, NonNullable<C["args"]> extends Record<string, ArgDescriptor> ? NonNullable<C["args"]> : Record<string, ArgDescriptor>>>;
100
- }
101
- /** Render full root help: header, default command details, subcommand list. */
102
- export declare function renderRootHelp(config: CliConfig): void;
103
- /** Render help for a single command. */
104
- export declare function renderCommandHelp(bin: string, id: string, Cmd: CommandCtor): void;
105
- /** A lazily-loaded command: canonical name, loader, and optional aliases. */
106
- export interface CommandEntry {
107
- name: string;
108
- load: () => Promise<CommandCtor>;
109
- aliases?: string[];
110
- }
111
- export interface RunOptions {
112
- bin: string;
113
- version: string;
114
- argv: string[];
115
- commands: CommandEntry[];
116
- /** Custom help renderer. Receives fully-populated config. */
117
- help?: (config: CliConfig) => Promise<void> | void;
118
- }
119
- /**
120
- * Main entry point — replaces `run()` from @oclif/core.
121
- *
122
- * Each command is explicitly registered with a lazy loader.
123
- * No filesystem scanning, no plugin system, no package.json reading.
124
- */
125
- export declare function run(opts: RunOptions): Promise<void>;
126
- export {};