@zveltio/cli 1.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.
Files changed (3) hide show
  1. package/README.md +117 -0
  2. package/dist/index.js +3619 -0
  3. package/package.json +24 -0
package/dist/index.js ADDED
@@ -0,0 +1,3619 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
13
+ var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
21
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
22
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ if (canCache)
30
+ cache.set(mod, to);
31
+ return to;
32
+ };
33
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __require = import.meta.require;
35
+
36
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/error.js
37
+ var require_error = __commonJS((exports) => {
38
+ class CommanderError extends Error {
39
+ constructor(exitCode, code, message) {
40
+ super(message);
41
+ Error.captureStackTrace(this, this.constructor);
42
+ this.name = this.constructor.name;
43
+ this.code = code;
44
+ this.exitCode = exitCode;
45
+ this.nestedError = undefined;
46
+ }
47
+ }
48
+
49
+ class InvalidArgumentError extends CommanderError {
50
+ constructor(message) {
51
+ super(1, "commander.invalidArgument", message);
52
+ Error.captureStackTrace(this, this.constructor);
53
+ this.name = this.constructor.name;
54
+ }
55
+ }
56
+ exports.CommanderError = CommanderError;
57
+ exports.InvalidArgumentError = InvalidArgumentError;
58
+ });
59
+
60
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/argument.js
61
+ var require_argument = __commonJS((exports) => {
62
+ var { InvalidArgumentError } = require_error();
63
+
64
+ class Argument {
65
+ constructor(name, description) {
66
+ this.description = description || "";
67
+ this.variadic = false;
68
+ this.parseArg = undefined;
69
+ this.defaultValue = undefined;
70
+ this.defaultValueDescription = undefined;
71
+ this.argChoices = undefined;
72
+ switch (name[0]) {
73
+ case "<":
74
+ this.required = true;
75
+ this._name = name.slice(1, -1);
76
+ break;
77
+ case "[":
78
+ this.required = false;
79
+ this._name = name.slice(1, -1);
80
+ break;
81
+ default:
82
+ this.required = true;
83
+ this._name = name;
84
+ break;
85
+ }
86
+ if (this._name.length > 3 && this._name.slice(-3) === "...") {
87
+ this.variadic = true;
88
+ this._name = this._name.slice(0, -3);
89
+ }
90
+ }
91
+ name() {
92
+ return this._name;
93
+ }
94
+ _concatValue(value, previous) {
95
+ if (previous === this.defaultValue || !Array.isArray(previous)) {
96
+ return [value];
97
+ }
98
+ return previous.concat(value);
99
+ }
100
+ default(value, description) {
101
+ this.defaultValue = value;
102
+ this.defaultValueDescription = description;
103
+ return this;
104
+ }
105
+ argParser(fn) {
106
+ this.parseArg = fn;
107
+ return this;
108
+ }
109
+ choices(values) {
110
+ this.argChoices = values.slice();
111
+ this.parseArg = (arg, previous) => {
112
+ if (!this.argChoices.includes(arg)) {
113
+ throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
114
+ }
115
+ if (this.variadic) {
116
+ return this._concatValue(arg, previous);
117
+ }
118
+ return arg;
119
+ };
120
+ return this;
121
+ }
122
+ argRequired() {
123
+ this.required = true;
124
+ return this;
125
+ }
126
+ argOptional() {
127
+ this.required = false;
128
+ return this;
129
+ }
130
+ }
131
+ function humanReadableArgName(arg) {
132
+ const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
133
+ return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
134
+ }
135
+ exports.Argument = Argument;
136
+ exports.humanReadableArgName = humanReadableArgName;
137
+ });
138
+
139
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/help.js
140
+ var require_help = __commonJS((exports) => {
141
+ var { humanReadableArgName } = require_argument();
142
+
143
+ class Help {
144
+ constructor() {
145
+ this.helpWidth = undefined;
146
+ this.sortSubcommands = false;
147
+ this.sortOptions = false;
148
+ this.showGlobalOptions = false;
149
+ }
150
+ visibleCommands(cmd) {
151
+ const visibleCommands = cmd.commands.filter((cmd2) => !cmd2._hidden);
152
+ const helpCommand = cmd._getHelpCommand();
153
+ if (helpCommand && !helpCommand._hidden) {
154
+ visibleCommands.push(helpCommand);
155
+ }
156
+ if (this.sortSubcommands) {
157
+ visibleCommands.sort((a, b) => {
158
+ return a.name().localeCompare(b.name());
159
+ });
160
+ }
161
+ return visibleCommands;
162
+ }
163
+ compareOptions(a, b) {
164
+ const getSortKey = (option) => {
165
+ return option.short ? option.short.replace(/^-/, "") : option.long.replace(/^--/, "");
166
+ };
167
+ return getSortKey(a).localeCompare(getSortKey(b));
168
+ }
169
+ visibleOptions(cmd) {
170
+ const visibleOptions = cmd.options.filter((option) => !option.hidden);
171
+ const helpOption = cmd._getHelpOption();
172
+ if (helpOption && !helpOption.hidden) {
173
+ const removeShort = helpOption.short && cmd._findOption(helpOption.short);
174
+ const removeLong = helpOption.long && cmd._findOption(helpOption.long);
175
+ if (!removeShort && !removeLong) {
176
+ visibleOptions.push(helpOption);
177
+ } else if (helpOption.long && !removeLong) {
178
+ visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
179
+ } else if (helpOption.short && !removeShort) {
180
+ visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
181
+ }
182
+ }
183
+ if (this.sortOptions) {
184
+ visibleOptions.sort(this.compareOptions);
185
+ }
186
+ return visibleOptions;
187
+ }
188
+ visibleGlobalOptions(cmd) {
189
+ if (!this.showGlobalOptions)
190
+ return [];
191
+ const globalOptions = [];
192
+ for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
193
+ const visibleOptions = ancestorCmd.options.filter((option) => !option.hidden);
194
+ globalOptions.push(...visibleOptions);
195
+ }
196
+ if (this.sortOptions) {
197
+ globalOptions.sort(this.compareOptions);
198
+ }
199
+ return globalOptions;
200
+ }
201
+ visibleArguments(cmd) {
202
+ if (cmd._argsDescription) {
203
+ cmd.registeredArguments.forEach((argument) => {
204
+ argument.description = argument.description || cmd._argsDescription[argument.name()] || "";
205
+ });
206
+ }
207
+ if (cmd.registeredArguments.find((argument) => argument.description)) {
208
+ return cmd.registeredArguments;
209
+ }
210
+ return [];
211
+ }
212
+ subcommandTerm(cmd) {
213
+ const args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
214
+ return cmd._name + (cmd._aliases[0] ? "|" + cmd._aliases[0] : "") + (cmd.options.length ? " [options]" : "") + (args ? " " + args : "");
215
+ }
216
+ optionTerm(option) {
217
+ return option.flags;
218
+ }
219
+ argumentTerm(argument) {
220
+ return argument.name();
221
+ }
222
+ longestSubcommandTermLength(cmd, helper) {
223
+ return helper.visibleCommands(cmd).reduce((max, command) => {
224
+ return Math.max(max, helper.subcommandTerm(command).length);
225
+ }, 0);
226
+ }
227
+ longestOptionTermLength(cmd, helper) {
228
+ return helper.visibleOptions(cmd).reduce((max, option) => {
229
+ return Math.max(max, helper.optionTerm(option).length);
230
+ }, 0);
231
+ }
232
+ longestGlobalOptionTermLength(cmd, helper) {
233
+ return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
234
+ return Math.max(max, helper.optionTerm(option).length);
235
+ }, 0);
236
+ }
237
+ longestArgumentTermLength(cmd, helper) {
238
+ return helper.visibleArguments(cmd).reduce((max, argument) => {
239
+ return Math.max(max, helper.argumentTerm(argument).length);
240
+ }, 0);
241
+ }
242
+ commandUsage(cmd) {
243
+ let cmdName = cmd._name;
244
+ if (cmd._aliases[0]) {
245
+ cmdName = cmdName + "|" + cmd._aliases[0];
246
+ }
247
+ let ancestorCmdNames = "";
248
+ for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
249
+ ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
250
+ }
251
+ return ancestorCmdNames + cmdName + " " + cmd.usage();
252
+ }
253
+ commandDescription(cmd) {
254
+ return cmd.description();
255
+ }
256
+ subcommandDescription(cmd) {
257
+ return cmd.summary() || cmd.description();
258
+ }
259
+ optionDescription(option) {
260
+ const extraInfo = [];
261
+ if (option.argChoices) {
262
+ extraInfo.push(`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
263
+ }
264
+ if (option.defaultValue !== undefined) {
265
+ const showDefault = option.required || option.optional || option.isBoolean() && typeof option.defaultValue === "boolean";
266
+ if (showDefault) {
267
+ extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
268
+ }
269
+ }
270
+ if (option.presetArg !== undefined && option.optional) {
271
+ extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
272
+ }
273
+ if (option.envVar !== undefined) {
274
+ extraInfo.push(`env: ${option.envVar}`);
275
+ }
276
+ if (extraInfo.length > 0) {
277
+ return `${option.description} (${extraInfo.join(", ")})`;
278
+ }
279
+ return option.description;
280
+ }
281
+ argumentDescription(argument) {
282
+ const extraInfo = [];
283
+ if (argument.argChoices) {
284
+ extraInfo.push(`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
285
+ }
286
+ if (argument.defaultValue !== undefined) {
287
+ extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
288
+ }
289
+ if (extraInfo.length > 0) {
290
+ const extraDescripton = `(${extraInfo.join(", ")})`;
291
+ if (argument.description) {
292
+ return `${argument.description} ${extraDescripton}`;
293
+ }
294
+ return extraDescripton;
295
+ }
296
+ return argument.description;
297
+ }
298
+ formatHelp(cmd, helper) {
299
+ const termWidth = helper.padWidth(cmd, helper);
300
+ const helpWidth = helper.helpWidth || 80;
301
+ const itemIndentWidth = 2;
302
+ const itemSeparatorWidth = 2;
303
+ function formatItem(term, description) {
304
+ if (description) {
305
+ const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
306
+ return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth);
307
+ }
308
+ return term;
309
+ }
310
+ function formatList(textArray) {
311
+ return textArray.join(`
312
+ `).replace(/^/gm, " ".repeat(itemIndentWidth));
313
+ }
314
+ let output = [`Usage: ${helper.commandUsage(cmd)}`, ""];
315
+ const commandDescription = helper.commandDescription(cmd);
316
+ if (commandDescription.length > 0) {
317
+ output = output.concat([
318
+ helper.wrap(commandDescription, helpWidth, 0),
319
+ ""
320
+ ]);
321
+ }
322
+ const argumentList = helper.visibleArguments(cmd).map((argument) => {
323
+ return formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument));
324
+ });
325
+ if (argumentList.length > 0) {
326
+ output = output.concat(["Arguments:", formatList(argumentList), ""]);
327
+ }
328
+ const optionList = helper.visibleOptions(cmd).map((option) => {
329
+ return formatItem(helper.optionTerm(option), helper.optionDescription(option));
330
+ });
331
+ if (optionList.length > 0) {
332
+ output = output.concat(["Options:", formatList(optionList), ""]);
333
+ }
334
+ if (this.showGlobalOptions) {
335
+ const globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => {
336
+ return formatItem(helper.optionTerm(option), helper.optionDescription(option));
337
+ });
338
+ if (globalOptionList.length > 0) {
339
+ output = output.concat([
340
+ "Global Options:",
341
+ formatList(globalOptionList),
342
+ ""
343
+ ]);
344
+ }
345
+ }
346
+ const commandList = helper.visibleCommands(cmd).map((cmd2) => {
347
+ return formatItem(helper.subcommandTerm(cmd2), helper.subcommandDescription(cmd2));
348
+ });
349
+ if (commandList.length > 0) {
350
+ output = output.concat(["Commands:", formatList(commandList), ""]);
351
+ }
352
+ return output.join(`
353
+ `);
354
+ }
355
+ padWidth(cmd, helper) {
356
+ return Math.max(helper.longestOptionTermLength(cmd, helper), helper.longestGlobalOptionTermLength(cmd, helper), helper.longestSubcommandTermLength(cmd, helper), helper.longestArgumentTermLength(cmd, helper));
357
+ }
358
+ wrap(str, width, indent, minColumnWidth = 40) {
359
+ const indents = " \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF";
360
+ const manualIndent = new RegExp(`[\\n][${indents}]+`);
361
+ if (str.match(manualIndent))
362
+ return str;
363
+ const columnWidth = width - indent;
364
+ if (columnWidth < minColumnWidth)
365
+ return str;
366
+ const leadingStr = str.slice(0, indent);
367
+ const columnText = str.slice(indent).replace(`\r
368
+ `, `
369
+ `);
370
+ const indentString = " ".repeat(indent);
371
+ const zeroWidthSpace = "\u200B";
372
+ const breaks = `\\s${zeroWidthSpace}`;
373
+ const regex = new RegExp(`
374
+ |.{1,${columnWidth - 1}}([${breaks}]|$)|[^${breaks}]+?([${breaks}]|$)`, "g");
375
+ const lines = columnText.match(regex) || [];
376
+ return leadingStr + lines.map((line, i) => {
377
+ if (line === `
378
+ `)
379
+ return "";
380
+ return (i > 0 ? indentString : "") + line.trimEnd();
381
+ }).join(`
382
+ `);
383
+ }
384
+ }
385
+ exports.Help = Help;
386
+ });
387
+
388
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/option.js
389
+ var require_option = __commonJS((exports) => {
390
+ var { InvalidArgumentError } = require_error();
391
+
392
+ class Option {
393
+ constructor(flags, description) {
394
+ this.flags = flags;
395
+ this.description = description || "";
396
+ this.required = flags.includes("<");
397
+ this.optional = flags.includes("[");
398
+ this.variadic = /\w\.\.\.[>\]]$/.test(flags);
399
+ this.mandatory = false;
400
+ const optionFlags = splitOptionFlags(flags);
401
+ this.short = optionFlags.shortFlag;
402
+ this.long = optionFlags.longFlag;
403
+ this.negate = false;
404
+ if (this.long) {
405
+ this.negate = this.long.startsWith("--no-");
406
+ }
407
+ this.defaultValue = undefined;
408
+ this.defaultValueDescription = undefined;
409
+ this.presetArg = undefined;
410
+ this.envVar = undefined;
411
+ this.parseArg = undefined;
412
+ this.hidden = false;
413
+ this.argChoices = undefined;
414
+ this.conflictsWith = [];
415
+ this.implied = undefined;
416
+ }
417
+ default(value, description) {
418
+ this.defaultValue = value;
419
+ this.defaultValueDescription = description;
420
+ return this;
421
+ }
422
+ preset(arg) {
423
+ this.presetArg = arg;
424
+ return this;
425
+ }
426
+ conflicts(names) {
427
+ this.conflictsWith = this.conflictsWith.concat(names);
428
+ return this;
429
+ }
430
+ implies(impliedOptionValues) {
431
+ let newImplied = impliedOptionValues;
432
+ if (typeof impliedOptionValues === "string") {
433
+ newImplied = { [impliedOptionValues]: true };
434
+ }
435
+ this.implied = Object.assign(this.implied || {}, newImplied);
436
+ return this;
437
+ }
438
+ env(name) {
439
+ this.envVar = name;
440
+ return this;
441
+ }
442
+ argParser(fn) {
443
+ this.parseArg = fn;
444
+ return this;
445
+ }
446
+ makeOptionMandatory(mandatory = true) {
447
+ this.mandatory = !!mandatory;
448
+ return this;
449
+ }
450
+ hideHelp(hide = true) {
451
+ this.hidden = !!hide;
452
+ return this;
453
+ }
454
+ _concatValue(value, previous) {
455
+ if (previous === this.defaultValue || !Array.isArray(previous)) {
456
+ return [value];
457
+ }
458
+ return previous.concat(value);
459
+ }
460
+ choices(values) {
461
+ this.argChoices = values.slice();
462
+ this.parseArg = (arg, previous) => {
463
+ if (!this.argChoices.includes(arg)) {
464
+ throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
465
+ }
466
+ if (this.variadic) {
467
+ return this._concatValue(arg, previous);
468
+ }
469
+ return arg;
470
+ };
471
+ return this;
472
+ }
473
+ name() {
474
+ if (this.long) {
475
+ return this.long.replace(/^--/, "");
476
+ }
477
+ return this.short.replace(/^-/, "");
478
+ }
479
+ attributeName() {
480
+ return camelcase(this.name().replace(/^no-/, ""));
481
+ }
482
+ is(arg) {
483
+ return this.short === arg || this.long === arg;
484
+ }
485
+ isBoolean() {
486
+ return !this.required && !this.optional && !this.negate;
487
+ }
488
+ }
489
+
490
+ class DualOptions {
491
+ constructor(options) {
492
+ this.positiveOptions = new Map;
493
+ this.negativeOptions = new Map;
494
+ this.dualOptions = new Set;
495
+ options.forEach((option) => {
496
+ if (option.negate) {
497
+ this.negativeOptions.set(option.attributeName(), option);
498
+ } else {
499
+ this.positiveOptions.set(option.attributeName(), option);
500
+ }
501
+ });
502
+ this.negativeOptions.forEach((value, key) => {
503
+ if (this.positiveOptions.has(key)) {
504
+ this.dualOptions.add(key);
505
+ }
506
+ });
507
+ }
508
+ valueFromOption(value, option) {
509
+ const optionKey = option.attributeName();
510
+ if (!this.dualOptions.has(optionKey))
511
+ return true;
512
+ const preset = this.negativeOptions.get(optionKey).presetArg;
513
+ const negativeValue = preset !== undefined ? preset : false;
514
+ return option.negate === (negativeValue === value);
515
+ }
516
+ }
517
+ function camelcase(str) {
518
+ return str.split("-").reduce((str2, word) => {
519
+ return str2 + word[0].toUpperCase() + word.slice(1);
520
+ });
521
+ }
522
+ function splitOptionFlags(flags) {
523
+ let shortFlag;
524
+ let longFlag;
525
+ const flagParts = flags.split(/[ |,]+/);
526
+ if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1]))
527
+ shortFlag = flagParts.shift();
528
+ longFlag = flagParts.shift();
529
+ if (!shortFlag && /^-[^-]$/.test(longFlag)) {
530
+ shortFlag = longFlag;
531
+ longFlag = undefined;
532
+ }
533
+ return { shortFlag, longFlag };
534
+ }
535
+ exports.Option = Option;
536
+ exports.DualOptions = DualOptions;
537
+ });
538
+
539
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/suggestSimilar.js
540
+ var require_suggestSimilar = __commonJS((exports) => {
541
+ var maxDistance = 3;
542
+ function editDistance(a, b) {
543
+ if (Math.abs(a.length - b.length) > maxDistance)
544
+ return Math.max(a.length, b.length);
545
+ const d = [];
546
+ for (let i = 0;i <= a.length; i++) {
547
+ d[i] = [i];
548
+ }
549
+ for (let j = 0;j <= b.length; j++) {
550
+ d[0][j] = j;
551
+ }
552
+ for (let j = 1;j <= b.length; j++) {
553
+ for (let i = 1;i <= a.length; i++) {
554
+ let cost = 1;
555
+ if (a[i - 1] === b[j - 1]) {
556
+ cost = 0;
557
+ } else {
558
+ cost = 1;
559
+ }
560
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
561
+ if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
562
+ d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
563
+ }
564
+ }
565
+ }
566
+ return d[a.length][b.length];
567
+ }
568
+ function suggestSimilar(word, candidates) {
569
+ if (!candidates || candidates.length === 0)
570
+ return "";
571
+ candidates = Array.from(new Set(candidates));
572
+ const searchingOptions = word.startsWith("--");
573
+ if (searchingOptions) {
574
+ word = word.slice(2);
575
+ candidates = candidates.map((candidate) => candidate.slice(2));
576
+ }
577
+ let similar = [];
578
+ let bestDistance = maxDistance;
579
+ const minSimilarity = 0.4;
580
+ candidates.forEach((candidate) => {
581
+ if (candidate.length <= 1)
582
+ return;
583
+ const distance = editDistance(word, candidate);
584
+ const length = Math.max(word.length, candidate.length);
585
+ const similarity = (length - distance) / length;
586
+ if (similarity > minSimilarity) {
587
+ if (distance < bestDistance) {
588
+ bestDistance = distance;
589
+ similar = [candidate];
590
+ } else if (distance === bestDistance) {
591
+ similar.push(candidate);
592
+ }
593
+ }
594
+ });
595
+ similar.sort((a, b) => a.localeCompare(b));
596
+ if (searchingOptions) {
597
+ similar = similar.map((candidate) => `--${candidate}`);
598
+ }
599
+ if (similar.length > 1) {
600
+ return `
601
+ (Did you mean one of ${similar.join(", ")}?)`;
602
+ }
603
+ if (similar.length === 1) {
604
+ return `
605
+ (Did you mean ${similar[0]}?)`;
606
+ }
607
+ return "";
608
+ }
609
+ exports.suggestSimilar = suggestSimilar;
610
+ });
611
+
612
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/lib/command.js
613
+ var require_command = __commonJS((exports) => {
614
+ var EventEmitter = __require("events").EventEmitter;
615
+ var childProcess = __require("child_process");
616
+ var path = __require("path");
617
+ var fs = __require("fs");
618
+ var process2 = __require("process");
619
+ var { Argument, humanReadableArgName } = require_argument();
620
+ var { CommanderError } = require_error();
621
+ var { Help } = require_help();
622
+ var { Option, DualOptions } = require_option();
623
+ var { suggestSimilar } = require_suggestSimilar();
624
+
625
+ class Command extends EventEmitter {
626
+ constructor(name) {
627
+ super();
628
+ this.commands = [];
629
+ this.options = [];
630
+ this.parent = null;
631
+ this._allowUnknownOption = false;
632
+ this._allowExcessArguments = true;
633
+ this.registeredArguments = [];
634
+ this._args = this.registeredArguments;
635
+ this.args = [];
636
+ this.rawArgs = [];
637
+ this.processedArgs = [];
638
+ this._scriptPath = null;
639
+ this._name = name || "";
640
+ this._optionValues = {};
641
+ this._optionValueSources = {};
642
+ this._storeOptionsAsProperties = false;
643
+ this._actionHandler = null;
644
+ this._executableHandler = false;
645
+ this._executableFile = null;
646
+ this._executableDir = null;
647
+ this._defaultCommandName = null;
648
+ this._exitCallback = null;
649
+ this._aliases = [];
650
+ this._combineFlagAndOptionalValue = true;
651
+ this._description = "";
652
+ this._summary = "";
653
+ this._argsDescription = undefined;
654
+ this._enablePositionalOptions = false;
655
+ this._passThroughOptions = false;
656
+ this._lifeCycleHooks = {};
657
+ this._showHelpAfterError = false;
658
+ this._showSuggestionAfterError = true;
659
+ this._outputConfiguration = {
660
+ writeOut: (str) => process2.stdout.write(str),
661
+ writeErr: (str) => process2.stderr.write(str),
662
+ getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : undefined,
663
+ getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : undefined,
664
+ outputError: (str, write) => write(str)
665
+ };
666
+ this._hidden = false;
667
+ this._helpOption = undefined;
668
+ this._addImplicitHelpCommand = undefined;
669
+ this._helpCommand = undefined;
670
+ this._helpConfiguration = {};
671
+ }
672
+ copyInheritedSettings(sourceCommand) {
673
+ this._outputConfiguration = sourceCommand._outputConfiguration;
674
+ this._helpOption = sourceCommand._helpOption;
675
+ this._helpCommand = sourceCommand._helpCommand;
676
+ this._helpConfiguration = sourceCommand._helpConfiguration;
677
+ this._exitCallback = sourceCommand._exitCallback;
678
+ this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;
679
+ this._combineFlagAndOptionalValue = sourceCommand._combineFlagAndOptionalValue;
680
+ this._allowExcessArguments = sourceCommand._allowExcessArguments;
681
+ this._enablePositionalOptions = sourceCommand._enablePositionalOptions;
682
+ this._showHelpAfterError = sourceCommand._showHelpAfterError;
683
+ this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;
684
+ return this;
685
+ }
686
+ _getCommandAndAncestors() {
687
+ const result = [];
688
+ for (let command = this;command; command = command.parent) {
689
+ result.push(command);
690
+ }
691
+ return result;
692
+ }
693
+ command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
694
+ let desc = actionOptsOrExecDesc;
695
+ let opts = execOpts;
696
+ if (typeof desc === "object" && desc !== null) {
697
+ opts = desc;
698
+ desc = null;
699
+ }
700
+ opts = opts || {};
701
+ const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);
702
+ const cmd = this.createCommand(name);
703
+ if (desc) {
704
+ cmd.description(desc);
705
+ cmd._executableHandler = true;
706
+ }
707
+ if (opts.isDefault)
708
+ this._defaultCommandName = cmd._name;
709
+ cmd._hidden = !!(opts.noHelp || opts.hidden);
710
+ cmd._executableFile = opts.executableFile || null;
711
+ if (args)
712
+ cmd.arguments(args);
713
+ this._registerCommand(cmd);
714
+ cmd.parent = this;
715
+ cmd.copyInheritedSettings(this);
716
+ if (desc)
717
+ return this;
718
+ return cmd;
719
+ }
720
+ createCommand(name) {
721
+ return new Command(name);
722
+ }
723
+ createHelp() {
724
+ return Object.assign(new Help, this.configureHelp());
725
+ }
726
+ configureHelp(configuration) {
727
+ if (configuration === undefined)
728
+ return this._helpConfiguration;
729
+ this._helpConfiguration = configuration;
730
+ return this;
731
+ }
732
+ configureOutput(configuration) {
733
+ if (configuration === undefined)
734
+ return this._outputConfiguration;
735
+ Object.assign(this._outputConfiguration, configuration);
736
+ return this;
737
+ }
738
+ showHelpAfterError(displayHelp = true) {
739
+ if (typeof displayHelp !== "string")
740
+ displayHelp = !!displayHelp;
741
+ this._showHelpAfterError = displayHelp;
742
+ return this;
743
+ }
744
+ showSuggestionAfterError(displaySuggestion = true) {
745
+ this._showSuggestionAfterError = !!displaySuggestion;
746
+ return this;
747
+ }
748
+ addCommand(cmd, opts) {
749
+ if (!cmd._name) {
750
+ throw new Error(`Command passed to .addCommand() must have a name
751
+ - specify the name in Command constructor or using .name()`);
752
+ }
753
+ opts = opts || {};
754
+ if (opts.isDefault)
755
+ this._defaultCommandName = cmd._name;
756
+ if (opts.noHelp || opts.hidden)
757
+ cmd._hidden = true;
758
+ this._registerCommand(cmd);
759
+ cmd.parent = this;
760
+ cmd._checkForBrokenPassThrough();
761
+ return this;
762
+ }
763
+ createArgument(name, description) {
764
+ return new Argument(name, description);
765
+ }
766
+ argument(name, description, fn, defaultValue) {
767
+ const argument = this.createArgument(name, description);
768
+ if (typeof fn === "function") {
769
+ argument.default(defaultValue).argParser(fn);
770
+ } else {
771
+ argument.default(fn);
772
+ }
773
+ this.addArgument(argument);
774
+ return this;
775
+ }
776
+ arguments(names) {
777
+ names.trim().split(/ +/).forEach((detail) => {
778
+ this.argument(detail);
779
+ });
780
+ return this;
781
+ }
782
+ addArgument(argument) {
783
+ const previousArgument = this.registeredArguments.slice(-1)[0];
784
+ if (previousArgument && previousArgument.variadic) {
785
+ throw new Error(`only the last argument can be variadic '${previousArgument.name()}'`);
786
+ }
787
+ if (argument.required && argument.defaultValue !== undefined && argument.parseArg === undefined) {
788
+ throw new Error(`a default value for a required argument is never used: '${argument.name()}'`);
789
+ }
790
+ this.registeredArguments.push(argument);
791
+ return this;
792
+ }
793
+ helpCommand(enableOrNameAndArgs, description) {
794
+ if (typeof enableOrNameAndArgs === "boolean") {
795
+ this._addImplicitHelpCommand = enableOrNameAndArgs;
796
+ return this;
797
+ }
798
+ enableOrNameAndArgs = enableOrNameAndArgs ?? "help [command]";
799
+ const [, helpName, helpArgs] = enableOrNameAndArgs.match(/([^ ]+) *(.*)/);
800
+ const helpDescription = description ?? "display help for command";
801
+ const helpCommand = this.createCommand(helpName);
802
+ helpCommand.helpOption(false);
803
+ if (helpArgs)
804
+ helpCommand.arguments(helpArgs);
805
+ if (helpDescription)
806
+ helpCommand.description(helpDescription);
807
+ this._addImplicitHelpCommand = true;
808
+ this._helpCommand = helpCommand;
809
+ return this;
810
+ }
811
+ addHelpCommand(helpCommand, deprecatedDescription) {
812
+ if (typeof helpCommand !== "object") {
813
+ this.helpCommand(helpCommand, deprecatedDescription);
814
+ return this;
815
+ }
816
+ this._addImplicitHelpCommand = true;
817
+ this._helpCommand = helpCommand;
818
+ return this;
819
+ }
820
+ _getHelpCommand() {
821
+ const hasImplicitHelpCommand = this._addImplicitHelpCommand ?? (this.commands.length && !this._actionHandler && !this._findCommand("help"));
822
+ if (hasImplicitHelpCommand) {
823
+ if (this._helpCommand === undefined) {
824
+ this.helpCommand(undefined, undefined);
825
+ }
826
+ return this._helpCommand;
827
+ }
828
+ return null;
829
+ }
830
+ hook(event, listener) {
831
+ const allowedValues = ["preSubcommand", "preAction", "postAction"];
832
+ if (!allowedValues.includes(event)) {
833
+ throw new Error(`Unexpected value for event passed to hook : '${event}'.
834
+ Expecting one of '${allowedValues.join("', '")}'`);
835
+ }
836
+ if (this._lifeCycleHooks[event]) {
837
+ this._lifeCycleHooks[event].push(listener);
838
+ } else {
839
+ this._lifeCycleHooks[event] = [listener];
840
+ }
841
+ return this;
842
+ }
843
+ exitOverride(fn) {
844
+ if (fn) {
845
+ this._exitCallback = fn;
846
+ } else {
847
+ this._exitCallback = (err) => {
848
+ if (err.code !== "commander.executeSubCommandAsync") {
849
+ throw err;
850
+ } else {}
851
+ };
852
+ }
853
+ return this;
854
+ }
855
+ _exit(exitCode, code, message) {
856
+ if (this._exitCallback) {
857
+ this._exitCallback(new CommanderError(exitCode, code, message));
858
+ }
859
+ process2.exit(exitCode);
860
+ }
861
+ action(fn) {
862
+ const listener = (args) => {
863
+ const expectedArgsCount = this.registeredArguments.length;
864
+ const actionArgs = args.slice(0, expectedArgsCount);
865
+ if (this._storeOptionsAsProperties) {
866
+ actionArgs[expectedArgsCount] = this;
867
+ } else {
868
+ actionArgs[expectedArgsCount] = this.opts();
869
+ }
870
+ actionArgs.push(this);
871
+ return fn.apply(this, actionArgs);
872
+ };
873
+ this._actionHandler = listener;
874
+ return this;
875
+ }
876
+ createOption(flags, description) {
877
+ return new Option(flags, description);
878
+ }
879
+ _callParseArg(target, value, previous, invalidArgumentMessage) {
880
+ try {
881
+ return target.parseArg(value, previous);
882
+ } catch (err) {
883
+ if (err.code === "commander.invalidArgument") {
884
+ const message = `${invalidArgumentMessage} ${err.message}`;
885
+ this.error(message, { exitCode: err.exitCode, code: err.code });
886
+ }
887
+ throw err;
888
+ }
889
+ }
890
+ _registerOption(option) {
891
+ const matchingOption = option.short && this._findOption(option.short) || option.long && this._findOption(option.long);
892
+ if (matchingOption) {
893
+ const matchingFlag = option.long && this._findOption(option.long) ? option.long : option.short;
894
+ throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
895
+ - already used by option '${matchingOption.flags}'`);
896
+ }
897
+ this.options.push(option);
898
+ }
899
+ _registerCommand(command) {
900
+ const knownBy = (cmd) => {
901
+ return [cmd.name()].concat(cmd.aliases());
902
+ };
903
+ const alreadyUsed = knownBy(command).find((name) => this._findCommand(name));
904
+ if (alreadyUsed) {
905
+ const existingCmd = knownBy(this._findCommand(alreadyUsed)).join("|");
906
+ const newCmd = knownBy(command).join("|");
907
+ throw new Error(`cannot add command '${newCmd}' as already have command '${existingCmd}'`);
908
+ }
909
+ this.commands.push(command);
910
+ }
911
+ addOption(option) {
912
+ this._registerOption(option);
913
+ const oname = option.name();
914
+ const name = option.attributeName();
915
+ if (option.negate) {
916
+ const positiveLongFlag = option.long.replace(/^--no-/, "--");
917
+ if (!this._findOption(positiveLongFlag)) {
918
+ this.setOptionValueWithSource(name, option.defaultValue === undefined ? true : option.defaultValue, "default");
919
+ }
920
+ } else if (option.defaultValue !== undefined) {
921
+ this.setOptionValueWithSource(name, option.defaultValue, "default");
922
+ }
923
+ const handleOptionValue = (val, invalidValueMessage, valueSource) => {
924
+ if (val == null && option.presetArg !== undefined) {
925
+ val = option.presetArg;
926
+ }
927
+ const oldValue = this.getOptionValue(name);
928
+ if (val !== null && option.parseArg) {
929
+ val = this._callParseArg(option, val, oldValue, invalidValueMessage);
930
+ } else if (val !== null && option.variadic) {
931
+ val = option._concatValue(val, oldValue);
932
+ }
933
+ if (val == null) {
934
+ if (option.negate) {
935
+ val = false;
936
+ } else if (option.isBoolean() || option.optional) {
937
+ val = true;
938
+ } else {
939
+ val = "";
940
+ }
941
+ }
942
+ this.setOptionValueWithSource(name, val, valueSource);
943
+ };
944
+ this.on("option:" + oname, (val) => {
945
+ const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
946
+ handleOptionValue(val, invalidValueMessage, "cli");
947
+ });
948
+ if (option.envVar) {
949
+ this.on("optionEnv:" + oname, (val) => {
950
+ const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
951
+ handleOptionValue(val, invalidValueMessage, "env");
952
+ });
953
+ }
954
+ return this;
955
+ }
956
+ _optionEx(config, flags, description, fn, defaultValue) {
957
+ if (typeof flags === "object" && flags instanceof Option) {
958
+ throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");
959
+ }
960
+ const option = this.createOption(flags, description);
961
+ option.makeOptionMandatory(!!config.mandatory);
962
+ if (typeof fn === "function") {
963
+ option.default(defaultValue).argParser(fn);
964
+ } else if (fn instanceof RegExp) {
965
+ const regex = fn;
966
+ fn = (val, def) => {
967
+ const m = regex.exec(val);
968
+ return m ? m[0] : def;
969
+ };
970
+ option.default(defaultValue).argParser(fn);
971
+ } else {
972
+ option.default(fn);
973
+ }
974
+ return this.addOption(option);
975
+ }
976
+ option(flags, description, parseArg, defaultValue) {
977
+ return this._optionEx({}, flags, description, parseArg, defaultValue);
978
+ }
979
+ requiredOption(flags, description, parseArg, defaultValue) {
980
+ return this._optionEx({ mandatory: true }, flags, description, parseArg, defaultValue);
981
+ }
982
+ combineFlagAndOptionalValue(combine = true) {
983
+ this._combineFlagAndOptionalValue = !!combine;
984
+ return this;
985
+ }
986
+ allowUnknownOption(allowUnknown = true) {
987
+ this._allowUnknownOption = !!allowUnknown;
988
+ return this;
989
+ }
990
+ allowExcessArguments(allowExcess = true) {
991
+ this._allowExcessArguments = !!allowExcess;
992
+ return this;
993
+ }
994
+ enablePositionalOptions(positional = true) {
995
+ this._enablePositionalOptions = !!positional;
996
+ return this;
997
+ }
998
+ passThroughOptions(passThrough = true) {
999
+ this._passThroughOptions = !!passThrough;
1000
+ this._checkForBrokenPassThrough();
1001
+ return this;
1002
+ }
1003
+ _checkForBrokenPassThrough() {
1004
+ if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions) {
1005
+ throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`);
1006
+ }
1007
+ }
1008
+ storeOptionsAsProperties(storeAsProperties = true) {
1009
+ if (this.options.length) {
1010
+ throw new Error("call .storeOptionsAsProperties() before adding options");
1011
+ }
1012
+ if (Object.keys(this._optionValues).length) {
1013
+ throw new Error("call .storeOptionsAsProperties() before setting option values");
1014
+ }
1015
+ this._storeOptionsAsProperties = !!storeAsProperties;
1016
+ return this;
1017
+ }
1018
+ getOptionValue(key) {
1019
+ if (this._storeOptionsAsProperties) {
1020
+ return this[key];
1021
+ }
1022
+ return this._optionValues[key];
1023
+ }
1024
+ setOptionValue(key, value) {
1025
+ return this.setOptionValueWithSource(key, value, undefined);
1026
+ }
1027
+ setOptionValueWithSource(key, value, source) {
1028
+ if (this._storeOptionsAsProperties) {
1029
+ this[key] = value;
1030
+ } else {
1031
+ this._optionValues[key] = value;
1032
+ }
1033
+ this._optionValueSources[key] = source;
1034
+ return this;
1035
+ }
1036
+ getOptionValueSource(key) {
1037
+ return this._optionValueSources[key];
1038
+ }
1039
+ getOptionValueSourceWithGlobals(key) {
1040
+ let source;
1041
+ this._getCommandAndAncestors().forEach((cmd) => {
1042
+ if (cmd.getOptionValueSource(key) !== undefined) {
1043
+ source = cmd.getOptionValueSource(key);
1044
+ }
1045
+ });
1046
+ return source;
1047
+ }
1048
+ _prepareUserArgs(argv, parseOptions) {
1049
+ if (argv !== undefined && !Array.isArray(argv)) {
1050
+ throw new Error("first parameter to parse must be array or undefined");
1051
+ }
1052
+ parseOptions = parseOptions || {};
1053
+ if (argv === undefined && parseOptions.from === undefined) {
1054
+ if (process2.versions?.electron) {
1055
+ parseOptions.from = "electron";
1056
+ }
1057
+ const execArgv = process2.execArgv ?? [];
1058
+ if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
1059
+ parseOptions.from = "eval";
1060
+ }
1061
+ }
1062
+ if (argv === undefined) {
1063
+ argv = process2.argv;
1064
+ }
1065
+ this.rawArgs = argv.slice();
1066
+ let userArgs;
1067
+ switch (parseOptions.from) {
1068
+ case undefined:
1069
+ case "node":
1070
+ this._scriptPath = argv[1];
1071
+ userArgs = argv.slice(2);
1072
+ break;
1073
+ case "electron":
1074
+ if (process2.defaultApp) {
1075
+ this._scriptPath = argv[1];
1076
+ userArgs = argv.slice(2);
1077
+ } else {
1078
+ userArgs = argv.slice(1);
1079
+ }
1080
+ break;
1081
+ case "user":
1082
+ userArgs = argv.slice(0);
1083
+ break;
1084
+ case "eval":
1085
+ userArgs = argv.slice(1);
1086
+ break;
1087
+ default:
1088
+ throw new Error(`unexpected parse option { from: '${parseOptions.from}' }`);
1089
+ }
1090
+ if (!this._name && this._scriptPath)
1091
+ this.nameFromFilename(this._scriptPath);
1092
+ this._name = this._name || "program";
1093
+ return userArgs;
1094
+ }
1095
+ parse(argv, parseOptions) {
1096
+ const userArgs = this._prepareUserArgs(argv, parseOptions);
1097
+ this._parseCommand([], userArgs);
1098
+ return this;
1099
+ }
1100
+ async parseAsync(argv, parseOptions) {
1101
+ const userArgs = this._prepareUserArgs(argv, parseOptions);
1102
+ await this._parseCommand([], userArgs);
1103
+ return this;
1104
+ }
1105
+ _executeSubCommand(subcommand, args) {
1106
+ args = args.slice();
1107
+ let launchWithNode = false;
1108
+ const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1109
+ function findFile(baseDir, baseName) {
1110
+ const localBin = path.resolve(baseDir, baseName);
1111
+ if (fs.existsSync(localBin))
1112
+ return localBin;
1113
+ if (sourceExt.includes(path.extname(baseName)))
1114
+ return;
1115
+ const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
1116
+ if (foundExt)
1117
+ return `${localBin}${foundExt}`;
1118
+ return;
1119
+ }
1120
+ this._checkForMissingMandatoryOptions();
1121
+ this._checkForConflictingOptions();
1122
+ let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`;
1123
+ let executableDir = this._executableDir || "";
1124
+ if (this._scriptPath) {
1125
+ let resolvedScriptPath;
1126
+ try {
1127
+ resolvedScriptPath = fs.realpathSync(this._scriptPath);
1128
+ } catch (err) {
1129
+ resolvedScriptPath = this._scriptPath;
1130
+ }
1131
+ executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
1132
+ }
1133
+ if (executableDir) {
1134
+ let localFile = findFile(executableDir, executableFile);
1135
+ if (!localFile && !subcommand._executableFile && this._scriptPath) {
1136
+ const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
1137
+ if (legacyName !== this._name) {
1138
+ localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
1139
+ }
1140
+ }
1141
+ executableFile = localFile || executableFile;
1142
+ }
1143
+ launchWithNode = sourceExt.includes(path.extname(executableFile));
1144
+ let proc;
1145
+ if (process2.platform !== "win32") {
1146
+ if (launchWithNode) {
1147
+ args.unshift(executableFile);
1148
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1149
+ proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" });
1150
+ } else {
1151
+ proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
1152
+ }
1153
+ } else {
1154
+ args.unshift(executableFile);
1155
+ args = incrementNodeInspectorPort(process2.execArgv).concat(args);
1156
+ proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" });
1157
+ }
1158
+ if (!proc.killed) {
1159
+ const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
1160
+ signals.forEach((signal) => {
1161
+ process2.on(signal, () => {
1162
+ if (proc.killed === false && proc.exitCode === null) {
1163
+ proc.kill(signal);
1164
+ }
1165
+ });
1166
+ });
1167
+ }
1168
+ const exitCallback = this._exitCallback;
1169
+ proc.on("close", (code) => {
1170
+ code = code ?? 1;
1171
+ if (!exitCallback) {
1172
+ process2.exit(code);
1173
+ } else {
1174
+ exitCallback(new CommanderError(code, "commander.executeSubCommandAsync", "(close)"));
1175
+ }
1176
+ });
1177
+ proc.on("error", (err) => {
1178
+ if (err.code === "ENOENT") {
1179
+ const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
1180
+ const executableMissing = `'${executableFile}' does not exist
1181
+ - if '${subcommand._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
1182
+ - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
1183
+ - ${executableDirMessage}`;
1184
+ throw new Error(executableMissing);
1185
+ } else if (err.code === "EACCES") {
1186
+ throw new Error(`'${executableFile}' not executable`);
1187
+ }
1188
+ if (!exitCallback) {
1189
+ process2.exit(1);
1190
+ } else {
1191
+ const wrappedError = new CommanderError(1, "commander.executeSubCommandAsync", "(error)");
1192
+ wrappedError.nestedError = err;
1193
+ exitCallback(wrappedError);
1194
+ }
1195
+ });
1196
+ this.runningCommand = proc;
1197
+ }
1198
+ _dispatchSubcommand(commandName, operands, unknown) {
1199
+ const subCommand = this._findCommand(commandName);
1200
+ if (!subCommand)
1201
+ this.help({ error: true });
1202
+ let promiseChain;
1203
+ promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, "preSubcommand");
1204
+ promiseChain = this._chainOrCall(promiseChain, () => {
1205
+ if (subCommand._executableHandler) {
1206
+ this._executeSubCommand(subCommand, operands.concat(unknown));
1207
+ } else {
1208
+ return subCommand._parseCommand(operands, unknown);
1209
+ }
1210
+ });
1211
+ return promiseChain;
1212
+ }
1213
+ _dispatchHelpCommand(subcommandName) {
1214
+ if (!subcommandName) {
1215
+ this.help();
1216
+ }
1217
+ const subCommand = this._findCommand(subcommandName);
1218
+ if (subCommand && !subCommand._executableHandler) {
1219
+ subCommand.help();
1220
+ }
1221
+ return this._dispatchSubcommand(subcommandName, [], [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"]);
1222
+ }
1223
+ _checkNumberOfArguments() {
1224
+ this.registeredArguments.forEach((arg, i) => {
1225
+ if (arg.required && this.args[i] == null) {
1226
+ this.missingArgument(arg.name());
1227
+ }
1228
+ });
1229
+ if (this.registeredArguments.length > 0 && this.registeredArguments[this.registeredArguments.length - 1].variadic) {
1230
+ return;
1231
+ }
1232
+ if (this.args.length > this.registeredArguments.length) {
1233
+ this._excessArguments(this.args);
1234
+ }
1235
+ }
1236
+ _processArguments() {
1237
+ const myParseArg = (argument, value, previous) => {
1238
+ let parsedValue = value;
1239
+ if (value !== null && argument.parseArg) {
1240
+ const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
1241
+ parsedValue = this._callParseArg(argument, value, previous, invalidValueMessage);
1242
+ }
1243
+ return parsedValue;
1244
+ };
1245
+ this._checkNumberOfArguments();
1246
+ const processedArgs = [];
1247
+ this.registeredArguments.forEach((declaredArg, index) => {
1248
+ let value = declaredArg.defaultValue;
1249
+ if (declaredArg.variadic) {
1250
+ if (index < this.args.length) {
1251
+ value = this.args.slice(index);
1252
+ if (declaredArg.parseArg) {
1253
+ value = value.reduce((processed, v) => {
1254
+ return myParseArg(declaredArg, v, processed);
1255
+ }, declaredArg.defaultValue);
1256
+ }
1257
+ } else if (value === undefined) {
1258
+ value = [];
1259
+ }
1260
+ } else if (index < this.args.length) {
1261
+ value = this.args[index];
1262
+ if (declaredArg.parseArg) {
1263
+ value = myParseArg(declaredArg, value, declaredArg.defaultValue);
1264
+ }
1265
+ }
1266
+ processedArgs[index] = value;
1267
+ });
1268
+ this.processedArgs = processedArgs;
1269
+ }
1270
+ _chainOrCall(promise, fn) {
1271
+ if (promise && promise.then && typeof promise.then === "function") {
1272
+ return promise.then(() => fn());
1273
+ }
1274
+ return fn();
1275
+ }
1276
+ _chainOrCallHooks(promise, event) {
1277
+ let result = promise;
1278
+ const hooks = [];
1279
+ this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event] !== undefined).forEach((hookedCommand) => {
1280
+ hookedCommand._lifeCycleHooks[event].forEach((callback) => {
1281
+ hooks.push({ hookedCommand, callback });
1282
+ });
1283
+ });
1284
+ if (event === "postAction") {
1285
+ hooks.reverse();
1286
+ }
1287
+ hooks.forEach((hookDetail) => {
1288
+ result = this._chainOrCall(result, () => {
1289
+ return hookDetail.callback(hookDetail.hookedCommand, this);
1290
+ });
1291
+ });
1292
+ return result;
1293
+ }
1294
+ _chainOrCallSubCommandHook(promise, subCommand, event) {
1295
+ let result = promise;
1296
+ if (this._lifeCycleHooks[event] !== undefined) {
1297
+ this._lifeCycleHooks[event].forEach((hook) => {
1298
+ result = this._chainOrCall(result, () => {
1299
+ return hook(this, subCommand);
1300
+ });
1301
+ });
1302
+ }
1303
+ return result;
1304
+ }
1305
+ _parseCommand(operands, unknown) {
1306
+ const parsed = this.parseOptions(unknown);
1307
+ this._parseOptionsEnv();
1308
+ this._parseOptionsImplied();
1309
+ operands = operands.concat(parsed.operands);
1310
+ unknown = parsed.unknown;
1311
+ this.args = operands.concat(unknown);
1312
+ if (operands && this._findCommand(operands[0])) {
1313
+ return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);
1314
+ }
1315
+ if (this._getHelpCommand() && operands[0] === this._getHelpCommand().name()) {
1316
+ return this._dispatchHelpCommand(operands[1]);
1317
+ }
1318
+ if (this._defaultCommandName) {
1319
+ this._outputHelpIfRequested(unknown);
1320
+ return this._dispatchSubcommand(this._defaultCommandName, operands, unknown);
1321
+ }
1322
+ if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
1323
+ this.help({ error: true });
1324
+ }
1325
+ this._outputHelpIfRequested(parsed.unknown);
1326
+ this._checkForMissingMandatoryOptions();
1327
+ this._checkForConflictingOptions();
1328
+ const checkForUnknownOptions = () => {
1329
+ if (parsed.unknown.length > 0) {
1330
+ this.unknownOption(parsed.unknown[0]);
1331
+ }
1332
+ };
1333
+ const commandEvent = `command:${this.name()}`;
1334
+ if (this._actionHandler) {
1335
+ checkForUnknownOptions();
1336
+ this._processArguments();
1337
+ let promiseChain;
1338
+ promiseChain = this._chainOrCallHooks(promiseChain, "preAction");
1339
+ promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
1340
+ if (this.parent) {
1341
+ promiseChain = this._chainOrCall(promiseChain, () => {
1342
+ this.parent.emit(commandEvent, operands, unknown);
1343
+ });
1344
+ }
1345
+ promiseChain = this._chainOrCallHooks(promiseChain, "postAction");
1346
+ return promiseChain;
1347
+ }
1348
+ if (this.parent && this.parent.listenerCount(commandEvent)) {
1349
+ checkForUnknownOptions();
1350
+ this._processArguments();
1351
+ this.parent.emit(commandEvent, operands, unknown);
1352
+ } else if (operands.length) {
1353
+ if (this._findCommand("*")) {
1354
+ return this._dispatchSubcommand("*", operands, unknown);
1355
+ }
1356
+ if (this.listenerCount("command:*")) {
1357
+ this.emit("command:*", operands, unknown);
1358
+ } else if (this.commands.length) {
1359
+ this.unknownCommand();
1360
+ } else {
1361
+ checkForUnknownOptions();
1362
+ this._processArguments();
1363
+ }
1364
+ } else if (this.commands.length) {
1365
+ checkForUnknownOptions();
1366
+ this.help({ error: true });
1367
+ } else {
1368
+ checkForUnknownOptions();
1369
+ this._processArguments();
1370
+ }
1371
+ }
1372
+ _findCommand(name) {
1373
+ if (!name)
1374
+ return;
1375
+ return this.commands.find((cmd) => cmd._name === name || cmd._aliases.includes(name));
1376
+ }
1377
+ _findOption(arg) {
1378
+ return this.options.find((option) => option.is(arg));
1379
+ }
1380
+ _checkForMissingMandatoryOptions() {
1381
+ this._getCommandAndAncestors().forEach((cmd) => {
1382
+ cmd.options.forEach((anOption) => {
1383
+ if (anOption.mandatory && cmd.getOptionValue(anOption.attributeName()) === undefined) {
1384
+ cmd.missingMandatoryOptionValue(anOption);
1385
+ }
1386
+ });
1387
+ });
1388
+ }
1389
+ _checkForConflictingLocalOptions() {
1390
+ const definedNonDefaultOptions = this.options.filter((option) => {
1391
+ const optionKey = option.attributeName();
1392
+ if (this.getOptionValue(optionKey) === undefined) {
1393
+ return false;
1394
+ }
1395
+ return this.getOptionValueSource(optionKey) !== "default";
1396
+ });
1397
+ const optionsWithConflicting = definedNonDefaultOptions.filter((option) => option.conflictsWith.length > 0);
1398
+ optionsWithConflicting.forEach((option) => {
1399
+ const conflictingAndDefined = definedNonDefaultOptions.find((defined) => option.conflictsWith.includes(defined.attributeName()));
1400
+ if (conflictingAndDefined) {
1401
+ this._conflictingOption(option, conflictingAndDefined);
1402
+ }
1403
+ });
1404
+ }
1405
+ _checkForConflictingOptions() {
1406
+ this._getCommandAndAncestors().forEach((cmd) => {
1407
+ cmd._checkForConflictingLocalOptions();
1408
+ });
1409
+ }
1410
+ parseOptions(argv) {
1411
+ const operands = [];
1412
+ const unknown = [];
1413
+ let dest = operands;
1414
+ const args = argv.slice();
1415
+ function maybeOption(arg) {
1416
+ return arg.length > 1 && arg[0] === "-";
1417
+ }
1418
+ let activeVariadicOption = null;
1419
+ while (args.length) {
1420
+ const arg = args.shift();
1421
+ if (arg === "--") {
1422
+ if (dest === unknown)
1423
+ dest.push(arg);
1424
+ dest.push(...args);
1425
+ break;
1426
+ }
1427
+ if (activeVariadicOption && !maybeOption(arg)) {
1428
+ this.emit(`option:${activeVariadicOption.name()}`, arg);
1429
+ continue;
1430
+ }
1431
+ activeVariadicOption = null;
1432
+ if (maybeOption(arg)) {
1433
+ const option = this._findOption(arg);
1434
+ if (option) {
1435
+ if (option.required) {
1436
+ const value = args.shift();
1437
+ if (value === undefined)
1438
+ this.optionMissingArgument(option);
1439
+ this.emit(`option:${option.name()}`, value);
1440
+ } else if (option.optional) {
1441
+ let value = null;
1442
+ if (args.length > 0 && !maybeOption(args[0])) {
1443
+ value = args.shift();
1444
+ }
1445
+ this.emit(`option:${option.name()}`, value);
1446
+ } else {
1447
+ this.emit(`option:${option.name()}`);
1448
+ }
1449
+ activeVariadicOption = option.variadic ? option : null;
1450
+ continue;
1451
+ }
1452
+ }
1453
+ if (arg.length > 2 && arg[0] === "-" && arg[1] !== "-") {
1454
+ const option = this._findOption(`-${arg[1]}`);
1455
+ if (option) {
1456
+ if (option.required || option.optional && this._combineFlagAndOptionalValue) {
1457
+ this.emit(`option:${option.name()}`, arg.slice(2));
1458
+ } else {
1459
+ this.emit(`option:${option.name()}`);
1460
+ args.unshift(`-${arg.slice(2)}`);
1461
+ }
1462
+ continue;
1463
+ }
1464
+ }
1465
+ if (/^--[^=]+=/.test(arg)) {
1466
+ const index = arg.indexOf("=");
1467
+ const option = this._findOption(arg.slice(0, index));
1468
+ if (option && (option.required || option.optional)) {
1469
+ this.emit(`option:${option.name()}`, arg.slice(index + 1));
1470
+ continue;
1471
+ }
1472
+ }
1473
+ if (maybeOption(arg)) {
1474
+ dest = unknown;
1475
+ }
1476
+ if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown.length === 0) {
1477
+ if (this._findCommand(arg)) {
1478
+ operands.push(arg);
1479
+ if (args.length > 0)
1480
+ unknown.push(...args);
1481
+ break;
1482
+ } else if (this._getHelpCommand() && arg === this._getHelpCommand().name()) {
1483
+ operands.push(arg);
1484
+ if (args.length > 0)
1485
+ operands.push(...args);
1486
+ break;
1487
+ } else if (this._defaultCommandName) {
1488
+ unknown.push(arg);
1489
+ if (args.length > 0)
1490
+ unknown.push(...args);
1491
+ break;
1492
+ }
1493
+ }
1494
+ if (this._passThroughOptions) {
1495
+ dest.push(arg);
1496
+ if (args.length > 0)
1497
+ dest.push(...args);
1498
+ break;
1499
+ }
1500
+ dest.push(arg);
1501
+ }
1502
+ return { operands, unknown };
1503
+ }
1504
+ opts() {
1505
+ if (this._storeOptionsAsProperties) {
1506
+ const result = {};
1507
+ const len = this.options.length;
1508
+ for (let i = 0;i < len; i++) {
1509
+ const key = this.options[i].attributeName();
1510
+ result[key] = key === this._versionOptionName ? this._version : this[key];
1511
+ }
1512
+ return result;
1513
+ }
1514
+ return this._optionValues;
1515
+ }
1516
+ optsWithGlobals() {
1517
+ return this._getCommandAndAncestors().reduce((combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()), {});
1518
+ }
1519
+ error(message, errorOptions) {
1520
+ this._outputConfiguration.outputError(`${message}
1521
+ `, this._outputConfiguration.writeErr);
1522
+ if (typeof this._showHelpAfterError === "string") {
1523
+ this._outputConfiguration.writeErr(`${this._showHelpAfterError}
1524
+ `);
1525
+ } else if (this._showHelpAfterError) {
1526
+ this._outputConfiguration.writeErr(`
1527
+ `);
1528
+ this.outputHelp({ error: true });
1529
+ }
1530
+ const config = errorOptions || {};
1531
+ const exitCode = config.exitCode || 1;
1532
+ const code = config.code || "commander.error";
1533
+ this._exit(exitCode, code, message);
1534
+ }
1535
+ _parseOptionsEnv() {
1536
+ this.options.forEach((option) => {
1537
+ if (option.envVar && option.envVar in process2.env) {
1538
+ const optionKey = option.attributeName();
1539
+ if (this.getOptionValue(optionKey) === undefined || ["default", "config", "env"].includes(this.getOptionValueSource(optionKey))) {
1540
+ if (option.required || option.optional) {
1541
+ this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]);
1542
+ } else {
1543
+ this.emit(`optionEnv:${option.name()}`);
1544
+ }
1545
+ }
1546
+ }
1547
+ });
1548
+ }
1549
+ _parseOptionsImplied() {
1550
+ const dualHelper = new DualOptions(this.options);
1551
+ const hasCustomOptionValue = (optionKey) => {
1552
+ return this.getOptionValue(optionKey) !== undefined && !["default", "implied"].includes(this.getOptionValueSource(optionKey));
1553
+ };
1554
+ this.options.filter((option) => option.implied !== undefined && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(this.getOptionValue(option.attributeName()), option)).forEach((option) => {
1555
+ Object.keys(option.implied).filter((impliedKey) => !hasCustomOptionValue(impliedKey)).forEach((impliedKey) => {
1556
+ this.setOptionValueWithSource(impliedKey, option.implied[impliedKey], "implied");
1557
+ });
1558
+ });
1559
+ }
1560
+ missingArgument(name) {
1561
+ const message = `error: missing required argument '${name}'`;
1562
+ this.error(message, { code: "commander.missingArgument" });
1563
+ }
1564
+ optionMissingArgument(option) {
1565
+ const message = `error: option '${option.flags}' argument missing`;
1566
+ this.error(message, { code: "commander.optionMissingArgument" });
1567
+ }
1568
+ missingMandatoryOptionValue(option) {
1569
+ const message = `error: required option '${option.flags}' not specified`;
1570
+ this.error(message, { code: "commander.missingMandatoryOptionValue" });
1571
+ }
1572
+ _conflictingOption(option, conflictingOption) {
1573
+ const findBestOptionFromValue = (option2) => {
1574
+ const optionKey = option2.attributeName();
1575
+ const optionValue = this.getOptionValue(optionKey);
1576
+ const negativeOption = this.options.find((target) => target.negate && optionKey === target.attributeName());
1577
+ const positiveOption = this.options.find((target) => !target.negate && optionKey === target.attributeName());
1578
+ if (negativeOption && (negativeOption.presetArg === undefined && optionValue === false || negativeOption.presetArg !== undefined && optionValue === negativeOption.presetArg)) {
1579
+ return negativeOption;
1580
+ }
1581
+ return positiveOption || option2;
1582
+ };
1583
+ const getErrorMessage = (option2) => {
1584
+ const bestOption = findBestOptionFromValue(option2);
1585
+ const optionKey = bestOption.attributeName();
1586
+ const source = this.getOptionValueSource(optionKey);
1587
+ if (source === "env") {
1588
+ return `environment variable '${bestOption.envVar}'`;
1589
+ }
1590
+ return `option '${bestOption.flags}'`;
1591
+ };
1592
+ const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;
1593
+ this.error(message, { code: "commander.conflictingOption" });
1594
+ }
1595
+ unknownOption(flag) {
1596
+ if (this._allowUnknownOption)
1597
+ return;
1598
+ let suggestion = "";
1599
+ if (flag.startsWith("--") && this._showSuggestionAfterError) {
1600
+ let candidateFlags = [];
1601
+ let command = this;
1602
+ do {
1603
+ const moreFlags = command.createHelp().visibleOptions(command).filter((option) => option.long).map((option) => option.long);
1604
+ candidateFlags = candidateFlags.concat(moreFlags);
1605
+ command = command.parent;
1606
+ } while (command && !command._enablePositionalOptions);
1607
+ suggestion = suggestSimilar(flag, candidateFlags);
1608
+ }
1609
+ const message = `error: unknown option '${flag}'${suggestion}`;
1610
+ this.error(message, { code: "commander.unknownOption" });
1611
+ }
1612
+ _excessArguments(receivedArgs) {
1613
+ if (this._allowExcessArguments)
1614
+ return;
1615
+ const expected = this.registeredArguments.length;
1616
+ const s = expected === 1 ? "" : "s";
1617
+ const forSubcommand = this.parent ? ` for '${this.name()}'` : "";
1618
+ const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;
1619
+ this.error(message, { code: "commander.excessArguments" });
1620
+ }
1621
+ unknownCommand() {
1622
+ const unknownName = this.args[0];
1623
+ let suggestion = "";
1624
+ if (this._showSuggestionAfterError) {
1625
+ const candidateNames = [];
1626
+ this.createHelp().visibleCommands(this).forEach((command) => {
1627
+ candidateNames.push(command.name());
1628
+ if (command.alias())
1629
+ candidateNames.push(command.alias());
1630
+ });
1631
+ suggestion = suggestSimilar(unknownName, candidateNames);
1632
+ }
1633
+ const message = `error: unknown command '${unknownName}'${suggestion}`;
1634
+ this.error(message, { code: "commander.unknownCommand" });
1635
+ }
1636
+ version(str, flags, description) {
1637
+ if (str === undefined)
1638
+ return this._version;
1639
+ this._version = str;
1640
+ flags = flags || "-V, --version";
1641
+ description = description || "output the version number";
1642
+ const versionOption = this.createOption(flags, description);
1643
+ this._versionOptionName = versionOption.attributeName();
1644
+ this._registerOption(versionOption);
1645
+ this.on("option:" + versionOption.name(), () => {
1646
+ this._outputConfiguration.writeOut(`${str}
1647
+ `);
1648
+ this._exit(0, "commander.version", str);
1649
+ });
1650
+ return this;
1651
+ }
1652
+ description(str, argsDescription) {
1653
+ if (str === undefined && argsDescription === undefined)
1654
+ return this._description;
1655
+ this._description = str;
1656
+ if (argsDescription) {
1657
+ this._argsDescription = argsDescription;
1658
+ }
1659
+ return this;
1660
+ }
1661
+ summary(str) {
1662
+ if (str === undefined)
1663
+ return this._summary;
1664
+ this._summary = str;
1665
+ return this;
1666
+ }
1667
+ alias(alias) {
1668
+ if (alias === undefined)
1669
+ return this._aliases[0];
1670
+ let command = this;
1671
+ if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler) {
1672
+ command = this.commands[this.commands.length - 1];
1673
+ }
1674
+ if (alias === command._name)
1675
+ throw new Error("Command alias can't be the same as its name");
1676
+ const matchingCommand = this.parent?._findCommand(alias);
1677
+ if (matchingCommand) {
1678
+ const existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join("|");
1679
+ throw new Error(`cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`);
1680
+ }
1681
+ command._aliases.push(alias);
1682
+ return this;
1683
+ }
1684
+ aliases(aliases) {
1685
+ if (aliases === undefined)
1686
+ return this._aliases;
1687
+ aliases.forEach((alias) => this.alias(alias));
1688
+ return this;
1689
+ }
1690
+ usage(str) {
1691
+ if (str === undefined) {
1692
+ if (this._usage)
1693
+ return this._usage;
1694
+ const args = this.registeredArguments.map((arg) => {
1695
+ return humanReadableArgName(arg);
1696
+ });
1697
+ return [].concat(this.options.length || this._helpOption !== null ? "[options]" : [], this.commands.length ? "[command]" : [], this.registeredArguments.length ? args : []).join(" ");
1698
+ }
1699
+ this._usage = str;
1700
+ return this;
1701
+ }
1702
+ name(str) {
1703
+ if (str === undefined)
1704
+ return this._name;
1705
+ this._name = str;
1706
+ return this;
1707
+ }
1708
+ nameFromFilename(filename) {
1709
+ this._name = path.basename(filename, path.extname(filename));
1710
+ return this;
1711
+ }
1712
+ executableDir(path2) {
1713
+ if (path2 === undefined)
1714
+ return this._executableDir;
1715
+ this._executableDir = path2;
1716
+ return this;
1717
+ }
1718
+ helpInformation(contextOptions) {
1719
+ const helper = this.createHelp();
1720
+ if (helper.helpWidth === undefined) {
1721
+ helper.helpWidth = contextOptions && contextOptions.error ? this._outputConfiguration.getErrHelpWidth() : this._outputConfiguration.getOutHelpWidth();
1722
+ }
1723
+ return helper.formatHelp(this, helper);
1724
+ }
1725
+ _getHelpContext(contextOptions) {
1726
+ contextOptions = contextOptions || {};
1727
+ const context = { error: !!contextOptions.error };
1728
+ let write;
1729
+ if (context.error) {
1730
+ write = (arg) => this._outputConfiguration.writeErr(arg);
1731
+ } else {
1732
+ write = (arg) => this._outputConfiguration.writeOut(arg);
1733
+ }
1734
+ context.write = contextOptions.write || write;
1735
+ context.command = this;
1736
+ return context;
1737
+ }
1738
+ outputHelp(contextOptions) {
1739
+ let deprecatedCallback;
1740
+ if (typeof contextOptions === "function") {
1741
+ deprecatedCallback = contextOptions;
1742
+ contextOptions = undefined;
1743
+ }
1744
+ const context = this._getHelpContext(contextOptions);
1745
+ this._getCommandAndAncestors().reverse().forEach((command) => command.emit("beforeAllHelp", context));
1746
+ this.emit("beforeHelp", context);
1747
+ let helpInformation = this.helpInformation(context);
1748
+ if (deprecatedCallback) {
1749
+ helpInformation = deprecatedCallback(helpInformation);
1750
+ if (typeof helpInformation !== "string" && !Buffer.isBuffer(helpInformation)) {
1751
+ throw new Error("outputHelp callback must return a string or a Buffer");
1752
+ }
1753
+ }
1754
+ context.write(helpInformation);
1755
+ if (this._getHelpOption()?.long) {
1756
+ this.emit(this._getHelpOption().long);
1757
+ }
1758
+ this.emit("afterHelp", context);
1759
+ this._getCommandAndAncestors().forEach((command) => command.emit("afterAllHelp", context));
1760
+ }
1761
+ helpOption(flags, description) {
1762
+ if (typeof flags === "boolean") {
1763
+ if (flags) {
1764
+ this._helpOption = this._helpOption ?? undefined;
1765
+ } else {
1766
+ this._helpOption = null;
1767
+ }
1768
+ return this;
1769
+ }
1770
+ flags = flags ?? "-h, --help";
1771
+ description = description ?? "display help for command";
1772
+ this._helpOption = this.createOption(flags, description);
1773
+ return this;
1774
+ }
1775
+ _getHelpOption() {
1776
+ if (this._helpOption === undefined) {
1777
+ this.helpOption(undefined, undefined);
1778
+ }
1779
+ return this._helpOption;
1780
+ }
1781
+ addHelpOption(option) {
1782
+ this._helpOption = option;
1783
+ return this;
1784
+ }
1785
+ help(contextOptions) {
1786
+ this.outputHelp(contextOptions);
1787
+ let exitCode = process2.exitCode || 0;
1788
+ if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
1789
+ exitCode = 1;
1790
+ }
1791
+ this._exit(exitCode, "commander.help", "(outputHelp)");
1792
+ }
1793
+ addHelpText(position, text) {
1794
+ const allowedValues = ["beforeAll", "before", "after", "afterAll"];
1795
+ if (!allowedValues.includes(position)) {
1796
+ throw new Error(`Unexpected value for position to addHelpText.
1797
+ Expecting one of '${allowedValues.join("', '")}'`);
1798
+ }
1799
+ const helpEvent = `${position}Help`;
1800
+ this.on(helpEvent, (context) => {
1801
+ let helpStr;
1802
+ if (typeof text === "function") {
1803
+ helpStr = text({ error: context.error, command: context.command });
1804
+ } else {
1805
+ helpStr = text;
1806
+ }
1807
+ if (helpStr) {
1808
+ context.write(`${helpStr}
1809
+ `);
1810
+ }
1811
+ });
1812
+ return this;
1813
+ }
1814
+ _outputHelpIfRequested(args) {
1815
+ const helpOption = this._getHelpOption();
1816
+ const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));
1817
+ if (helpRequested) {
1818
+ this.outputHelp();
1819
+ this._exit(0, "commander.helpDisplayed", "(outputHelp)");
1820
+ }
1821
+ }
1822
+ }
1823
+ function incrementNodeInspectorPort(args) {
1824
+ return args.map((arg) => {
1825
+ if (!arg.startsWith("--inspect")) {
1826
+ return arg;
1827
+ }
1828
+ let debugOption;
1829
+ let debugHost = "127.0.0.1";
1830
+ let debugPort = "9229";
1831
+ let match;
1832
+ if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {
1833
+ debugOption = match[1];
1834
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null) {
1835
+ debugOption = match[1];
1836
+ if (/^\d+$/.test(match[3])) {
1837
+ debugPort = match[3];
1838
+ } else {
1839
+ debugHost = match[3];
1840
+ }
1841
+ } else if ((match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null) {
1842
+ debugOption = match[1];
1843
+ debugHost = match[3];
1844
+ debugPort = match[4];
1845
+ }
1846
+ if (debugOption && debugPort !== "0") {
1847
+ return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;
1848
+ }
1849
+ return arg;
1850
+ });
1851
+ }
1852
+ exports.Command = Command;
1853
+ });
1854
+
1855
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/index.js
1856
+ var require_commander = __commonJS((exports) => {
1857
+ var { Argument } = require_argument();
1858
+ var { Command } = require_command();
1859
+ var { CommanderError, InvalidArgumentError } = require_error();
1860
+ var { Help } = require_help();
1861
+ var { Option } = require_option();
1862
+ exports.program = new Command;
1863
+ exports.createCommand = (name) => new Command(name);
1864
+ exports.createOption = (flags, description) => new Option(flags, description);
1865
+ exports.createArgument = (name, description) => new Argument(name, description);
1866
+ exports.Command = Command;
1867
+ exports.Option = Option;
1868
+ exports.Argument = Argument;
1869
+ exports.Help = Help;
1870
+ exports.CommanderError = CommanderError;
1871
+ exports.InvalidArgumentError = InvalidArgumentError;
1872
+ exports.InvalidOptionArgumentError = InvalidArgumentError;
1873
+ });
1874
+
1875
+ // ../../node_modules/.bun/commander@12.1.0/node_modules/commander/esm.mjs
1876
+ var import__ = __toESM(require_commander(), 1);
1877
+ var {
1878
+ program,
1879
+ createCommand,
1880
+ createArgument,
1881
+ createOption,
1882
+ CommanderError,
1883
+ InvalidArgumentError,
1884
+ InvalidOptionArgumentError,
1885
+ Command,
1886
+ Argument,
1887
+ Option,
1888
+ Help
1889
+ } = import__.default;
1890
+
1891
+ // src/commands/init.ts
1892
+ import { existsSync, mkdirSync } from "fs";
1893
+ import { join } from "path";
1894
+ import { createInterface } from "readline";
1895
+ var c = {
1896
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
1897
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
1898
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
1899
+ dim: (s) => `\x1B[2m${s}\x1B[0m`,
1900
+ red: (s) => `\x1B[31m${s}\x1B[0m`,
1901
+ yellow: (s) => `\x1B[33m${s}\x1B[0m`
1902
+ };
1903
+ function rl() {
1904
+ return createInterface({ input: process.stdin, output: process.stdout });
1905
+ }
1906
+ async function ask(iface, question) {
1907
+ return new Promise((resolve) => iface.question(question, resolve));
1908
+ }
1909
+ async function askWithDefault(iface, question, defaultValue) {
1910
+ const answer = await ask(iface, question);
1911
+ return answer.trim() || defaultValue;
1912
+ }
1913
+ async function askYesNo(iface, question, defaultYes = true) {
1914
+ const hint = defaultYes ? "Y/n" : "y/N";
1915
+ const answer = await ask(iface, `${question} ${c.dim(`[${hint}]`)}: `);
1916
+ const trimmed = answer.trim().toLowerCase();
1917
+ if (!trimmed)
1918
+ return defaultYes;
1919
+ return trimmed === "y" || trimmed === "yes";
1920
+ }
1921
+ async function fetchOfficialExtensions() {
1922
+ try {
1923
+ const res = await fetch("https://registry.zveltio.com/api/extensions/list?official=true", {
1924
+ signal: AbortSignal.timeout(5000)
1925
+ });
1926
+ if (!res.ok)
1927
+ return [];
1928
+ const data = await res.json();
1929
+ return data.extensions ?? [];
1930
+ } catch {
1931
+ return [];
1932
+ }
1933
+ }
1934
+ async function pickExtensions(iface, extensions) {
1935
+ if (extensions.length === 0)
1936
+ return [];
1937
+ const groups = new Map;
1938
+ for (const ext of extensions) {
1939
+ const cat = ext.name.split("/")[0] ?? "general";
1940
+ if (!groups.has(cat))
1941
+ groups.set(cat, []);
1942
+ groups.get(cat).push(ext);
1943
+ }
1944
+ console.log(`
1945
+ ${c.bold("Available extensions:")}`);
1946
+ console.log(c.dim(` Press enter to skip, or enter numbers separated by spaces.
1947
+ `));
1948
+ let idx = 1;
1949
+ const indexed = [];
1950
+ for (const [cat, exts] of groups) {
1951
+ console.log(` ${c.cyan(c.bold(cat))}`);
1952
+ for (const ext of exts) {
1953
+ const shortDesc = ext.description ? ` ${c.dim("\u2014 " + ext.description.slice(0, 55) + (ext.description.length > 55 ? "\u2026" : ""))}` : "";
1954
+ console.log(` ${c.dim(String(idx).padStart(2, " ") + ".")} ${ext.name.split("/").pop()}${shortDesc}`);
1955
+ indexed.push({ num: idx, name: ext.name });
1956
+ idx++;
1957
+ }
1958
+ console.log("");
1959
+ }
1960
+ const answer = await ask(iface, `Extensions to enable ${c.dim("[space-separated numbers, or enter for none]")}: `);
1961
+ if (!answer.trim())
1962
+ return [];
1963
+ const chosen = new Set;
1964
+ for (const token of answer.trim().split(/\s+/)) {
1965
+ const n = parseInt(token, 10);
1966
+ const found = indexed.find((e) => e.num === n);
1967
+ if (found)
1968
+ chosen.add(found.name);
1969
+ }
1970
+ return [...chosen];
1971
+ }
1972
+ async function initCommand(name = ".", _opts = {}) {
1973
+ console.log(`
1974
+ ${c.bold(c.cyan("Zveltio Init"))}
1975
+ `);
1976
+ const extensionsPromise = fetchOfficialExtensions();
1977
+ const iface = rl();
1978
+ const defaultProjectName = name !== "." ? name.split(/[/\\]/).pop() || "zveltio-app" : process.cwd().split(/[/\\]/).pop() || "zveltio-app";
1979
+ const projectName = await askWithDefault(iface, `Project name ${c.dim(`[${defaultProjectName}]`)}: `, defaultProjectName);
1980
+ const dbPassword = crypto.randomUUID().replace(/-/g, "").slice(0, 24);
1981
+ const defaultDbUrl = `postgresql://zveltio:${dbPassword}@localhost:5432/${projectName}`;
1982
+ const databaseUrl = await askWithDefault(iface, `Database URL ${c.dim(`[${defaultDbUrl}]`)}: `, defaultDbUrl);
1983
+ const portStr = await askWithDefault(iface, `Port ${c.dim("[3000]")}: `, "3000");
1984
+ const port = parseInt(portStr, 10) || 3000;
1985
+ const enableStudio = await askYesNo(iface, "Enable Studio (admin UI)?", true);
1986
+ const officialExtensions = await extensionsPromise;
1987
+ let selectedExtensions = [];
1988
+ if (officialExtensions.length > 0) {
1989
+ selectedExtensions = await pickExtensions(iface, officialExtensions);
1990
+ } else {
1991
+ console.log(c.dim(`
1992
+ (Could not reach registry \u2014 extensions can be configured later in .env)
1993
+ `));
1994
+ }
1995
+ iface.close();
1996
+ const dir = name === "." ? process.cwd() : join(process.cwd(), name);
1997
+ if (name !== "." && existsSync(dir)) {
1998
+ console.error(c.red(`
1999
+ Directory "${name}" already exists`));
2000
+ process.exit(1);
2001
+ }
2002
+ mkdirSync(dir, { recursive: true });
2003
+ const s3AccessKey = crypto.randomUUID().replace(/-/g, "").slice(0, 16);
2004
+ const s3SecretKey = crypto.randomUUID().replace(/-/g, "");
2005
+ const authSecret = crypto.randomUUID().replace(/-/g, "");
2006
+ const extensionsValue = selectedExtensions.join(",");
2007
+ await Bun.write(join(dir, ".env"), [
2008
+ "# WARNING: NEVER commit this file to git \u2014 it contains secrets.",
2009
+ "# For production, replace ALL values with strong credentials.",
2010
+ `DATABASE_URL=${databaseUrl}`,
2011
+ `PORT=${port}`,
2012
+ `BETTER_AUTH_SECRET=${authSecret}`,
2013
+ "VALKEY_URL=redis://localhost:6379",
2014
+ "S3_ENDPOINT=http://localhost:8333",
2015
+ "S3_BUCKET=zveltio",
2016
+ `S3_ACCESS_KEY=${s3AccessKey}`,
2017
+ `S3_SECRET_KEY=${s3SecretKey}`,
2018
+ `ENABLE_STUDIO=${enableStudio ? "true" : "false"}`,
2019
+ `ZVELTIO_EXTENSIONS=${extensionsValue}`,
2020
+ ""
2021
+ ].join(`
2022
+ `));
2023
+ await Bun.write(join(dir, ".env.example"), [
2024
+ "# Copy to .env and fill in real values. Never commit .env to git.",
2025
+ "DATABASE_URL=postgresql://zveltio:CHANGE_ME@localhost:5432/dbname",
2026
+ "PORT=3000",
2027
+ "BETTER_AUTH_SECRET=CHANGE_ME_use_random_32+_chars",
2028
+ "VALKEY_URL=redis://localhost:6379",
2029
+ "S3_ENDPOINT=http://localhost:8333",
2030
+ "S3_BUCKET=zveltio",
2031
+ "S3_ACCESS_KEY=CHANGE_ME",
2032
+ "S3_SECRET_KEY=CHANGE_ME",
2033
+ "ENABLE_STUDIO=true",
2034
+ `ZVELTIO_EXTENSIONS=${extensionsValue}`,
2035
+ ""
2036
+ ].join(`
2037
+ `));
2038
+ await Bun.write(join(dir, "package.json"), JSON.stringify({
2039
+ name: projectName,
2040
+ private: true,
2041
+ scripts: {
2042
+ dev: "zveltio dev",
2043
+ start: "zveltio start",
2044
+ migrate: "zveltio migrate"
2045
+ },
2046
+ dependencies: {
2047
+ "@zveltio/engine": "latest"
2048
+ }
2049
+ }, null, 2));
2050
+ const composeDbPassword = dbPassword;
2051
+ const composeDbName = projectName.replace(/[^a-zA-Z0-9_]/g, "_");
2052
+ await Bun.write(join(dir, "docker-compose.yml"), `version: '3.8'
2053
+ services:
2054
+ db:
2055
+ image: postgis/postgis:16-3.4-alpine
2056
+ environment:
2057
+ POSTGRES_DB: ${composeDbName}
2058
+ POSTGRES_USER: zveltio
2059
+ POSTGRES_PASSWORD: ${composeDbPassword}
2060
+ ports:
2061
+ - "5432:5432"
2062
+ volumes:
2063
+ - pgdata:/var/lib/postgresql/data
2064
+ healthcheck:
2065
+ test: ["CMD-SHELL", "pg_isready -U zveltio -d ${composeDbName}"]
2066
+ interval: 10s
2067
+ timeout: 5s
2068
+ retries: 5
2069
+
2070
+ valkey:
2071
+ image: valkey/valkey:7-alpine
2072
+ ports:
2073
+ - "6379:6379"
2074
+ healthcheck:
2075
+ test: ["CMD", "valkey-cli", "ping"]
2076
+ interval: 10s
2077
+ timeout: 5s
2078
+ retries: 5
2079
+
2080
+ volumes:
2081
+ pgdata:
2082
+ `);
2083
+ await Bun.write(join(dir, ".gitignore"), [
2084
+ ".env",
2085
+ "node_modules/",
2086
+ "dist/",
2087
+ ".DS_Store",
2088
+ "*.local",
2089
+ "types/",
2090
+ ""
2091
+ ].join(`
2092
+ `));
2093
+ const extSummary = selectedExtensions.length > 0 ? `
2094
+ ${c.green("\u2714")} Extensions: ${selectedExtensions.map((e) => e.split("/").pop()).join(", ")}` : "";
2095
+ console.log(`
2096
+ ${c.green(`\u2714 Project "${projectName}" initialized`)} at ${dir}${extSummary}`);
2097
+ console.log(`
2098
+ ${c.bold("Next steps:")}
2099
+ ${name !== "." ? `cd ${name}
2100
+ ` : ""}docker compose up -d ${c.dim("# start PostgreSQL + Valkey")}
2101
+ bun install ${c.dim("# install dependencies")}
2102
+ zveltio migrate ${c.dim("# apply database migrations")}
2103
+ zveltio dev ${c.dim("# start development server")}
2104
+
2105
+ ${c.cyan(`Open http://localhost:${port}${enableStudio ? "/admin" : "/api"}`)}
2106
+ `);
2107
+ }
2108
+
2109
+ // src/commands/dev.ts
2110
+ import { existsSync as existsSync2 } from "fs";
2111
+ import { join as join2 } from "path";
2112
+ var c2 = {
2113
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
2114
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
2115
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2116
+ dim: (s) => `\x1B[2m${s}\x1B[0m`,
2117
+ red: (s) => `\x1B[31m${s}\x1B[0m`
2118
+ };
2119
+ async function devCommand(opts) {
2120
+ console.log(`
2121
+ ${c2.bold(c2.cyan("Zveltio Dev Mode"))}
2122
+ `);
2123
+ const port = opts.port || process.env.PORT || "3000";
2124
+ const engineEntry = findEngineEntry();
2125
+ if (!engineEntry) {
2126
+ console.error(c2.red("Could not find engine entry point. Make sure you are in a Zveltio project directory."));
2127
+ console.error(c2.dim(" Expected: packages/engine/src/index.ts, src/index.ts, or index.ts"));
2128
+ process.exit(1);
2129
+ }
2130
+ console.log(` Engine: ${c2.cyan(`http://localhost:${port}/api`)}`);
2131
+ if (opts.studio !== false) {
2132
+ console.log(` Studio: ${c2.cyan(`http://localhost:${port}/admin`)}`);
2133
+ }
2134
+ console.log(` Entry: ${c2.dim(engineEntry)}`);
2135
+ console.log(`
2136
+ ${c2.dim(" Press Ctrl+C to stop")}
2137
+ `);
2138
+ const proc = Bun.spawn(["bun", "run", "--watch", engineEntry], {
2139
+ env: {
2140
+ ...process.env,
2141
+ PORT: port,
2142
+ NODE_ENV: "development",
2143
+ ...opts.studio === false ? { ENABLE_STUDIO: "false" } : {}
2144
+ },
2145
+ stdio: ["inherit", "inherit", "inherit"]
2146
+ });
2147
+ process.on("SIGINT", () => {
2148
+ proc.kill();
2149
+ process.exit(0);
2150
+ });
2151
+ process.on("SIGTERM", () => {
2152
+ proc.kill();
2153
+ process.exit(0);
2154
+ });
2155
+ const exitCode = await proc.exited;
2156
+ process.exit(exitCode);
2157
+ }
2158
+ function findEngineEntry() {
2159
+ const candidates = [
2160
+ "packages/engine/src/index.ts",
2161
+ "src/index.ts",
2162
+ "index.ts"
2163
+ ];
2164
+ for (const candidate of candidates) {
2165
+ if (existsSync2(join2(process.cwd(), candidate))) {
2166
+ return candidate;
2167
+ }
2168
+ }
2169
+ return null;
2170
+ }
2171
+
2172
+ // src/commands/start.ts
2173
+ import { existsSync as existsSync3 } from "fs";
2174
+ import { join as join3 } from "path";
2175
+ var c3 = {
2176
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
2177
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2178
+ dim: (s) => `\x1B[2m${s}\x1B[0m`,
2179
+ red: (s) => `\x1B[31m${s}\x1B[0m`
2180
+ };
2181
+ async function startCommand(opts) {
2182
+ const port = opts.port || process.env.PORT || "3000";
2183
+ const binaryPath = opts.binary || findBinary();
2184
+ if (binaryPath) {
2185
+ console.log(`
2186
+ ${c3.bold("Zveltio")} starting production binary: ${c3.dim(binaryPath)}
2187
+ `);
2188
+ console.log(` API: ${c3.cyan(`http://localhost:${port}/api`)}`);
2189
+ console.log(` Admin: ${c3.cyan(`http://localhost:${port}/admin`)}
2190
+ `);
2191
+ console.log(c3.dim(` Press Ctrl+C to stop
2192
+ `));
2193
+ const proc2 = Bun.spawn([binaryPath], {
2194
+ env: { ...process.env, PORT: port },
2195
+ stdio: ["inherit", "inherit", "inherit"]
2196
+ });
2197
+ process.on("SIGINT", () => {
2198
+ proc2.kill();
2199
+ process.exit(0);
2200
+ });
2201
+ process.on("SIGTERM", () => {
2202
+ proc2.kill();
2203
+ process.exit(0);
2204
+ });
2205
+ const exitCode2 = await proc2.exited;
2206
+ process.exit(exitCode2);
2207
+ return;
2208
+ }
2209
+ const engineEntry = findEngineEntry2();
2210
+ if (!engineEntry) {
2211
+ console.error(c3.red('Could not find a compiled binary or engine source. Did you run "bun build"?'));
2212
+ process.exit(1);
2213
+ }
2214
+ console.log(`
2215
+ ${c3.bold("Zveltio")} starting in production mode...
2216
+ `);
2217
+ console.log(` API: ${c3.cyan(`http://localhost:${port}/api`)}`);
2218
+ console.log(` Admin: ${c3.cyan(`http://localhost:${port}/admin`)}
2219
+ `);
2220
+ console.log(c3.dim(` Press Ctrl+C to stop
2221
+ `));
2222
+ const proc = Bun.spawn(["bun", "run", engineEntry], {
2223
+ env: { ...process.env, PORT: port, NODE_ENV: "production" },
2224
+ stdio: ["inherit", "inherit", "inherit"]
2225
+ });
2226
+ process.on("SIGINT", () => {
2227
+ proc.kill();
2228
+ process.exit(0);
2229
+ });
2230
+ process.on("SIGTERM", () => {
2231
+ proc.kill();
2232
+ process.exit(0);
2233
+ });
2234
+ const exitCode = await proc.exited;
2235
+ process.exit(exitCode);
2236
+ }
2237
+ function findBinary() {
2238
+ const candidates = [
2239
+ "dist/zveltio",
2240
+ "dist/zveltio.exe",
2241
+ "packages/engine/dist/zveltio",
2242
+ "packages/engine/dist/zveltio.exe"
2243
+ ];
2244
+ for (const c4 of candidates) {
2245
+ const full = join3(process.cwd(), c4);
2246
+ if (existsSync3(full))
2247
+ return full;
2248
+ }
2249
+ return null;
2250
+ }
2251
+ function findEngineEntry2() {
2252
+ const candidates = [
2253
+ "packages/engine/src/index.ts",
2254
+ "src/index.ts",
2255
+ "index.ts"
2256
+ ];
2257
+ for (const candidate of candidates) {
2258
+ const full = join3(process.cwd(), candidate);
2259
+ if (existsSync3(full))
2260
+ return candidate;
2261
+ }
2262
+ return null;
2263
+ }
2264
+
2265
+ // src/commands/deploy.ts
2266
+ import { existsSync as existsSync4 } from "fs";
2267
+ import { join as join4 } from "path";
2268
+ var c4 = {
2269
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
2270
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
2271
+ red: (s) => `\x1B[31m${s}\x1B[0m`,
2272
+ yellow: (s) => `\x1B[33m${s}\x1B[0m`,
2273
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2274
+ dim: (s) => `\x1B[2m${s}\x1B[0m`
2275
+ };
2276
+ async function runCommand(cmd, opts) {
2277
+ const proc = Bun.spawn(cmd, {
2278
+ stdout: "inherit",
2279
+ stderr: "inherit",
2280
+ stdin: "inherit",
2281
+ cwd: opts?.cwd,
2282
+ env: opts?.env ? { ...process.env, ...opts.env } : undefined
2283
+ });
2284
+ const code = await proc.exited;
2285
+ if (code !== 0) {
2286
+ throw new Error(`Command failed with exit code ${code}: ${cmd.join(" ")}`);
2287
+ }
2288
+ }
2289
+ async function deployCommand(opts) {
2290
+ console.log(`
2291
+ ${c4.bold(c4.cyan("Zveltio Deploy"))}
2292
+ `);
2293
+ const cwd = process.cwd();
2294
+ let projectName = "zveltio-app";
2295
+ const pkgPath = join4(cwd, "package.json");
2296
+ if (existsSync4(pkgPath)) {
2297
+ const pkg = JSON.parse(await Bun.file(pkgPath).text());
2298
+ projectName = (pkg.name || "zveltio-app").replace(/[@/]/g, "").replace(/\s+/g, "-").toLowerCase();
2299
+ }
2300
+ const registry = opts.registry || process.env.DOCKER_REGISTRY || "";
2301
+ const tag = opts.tag || process.env.DEPLOY_TAG || "latest";
2302
+ const imageName = registry ? `${registry.replace(/\/$/, "")}/${projectName}:${tag}` : `${projectName}:${tag}`;
2303
+ const platform = opts.platform || "linux/amd64";
2304
+ const dockerfile = opts.dockerfile || findDockerfile(cwd);
2305
+ const context = opts.context || ".";
2306
+ console.log(` Image: ${c4.cyan(imageName)}`);
2307
+ console.log(` Platform: ${c4.dim(platform)}`);
2308
+ console.log(` Dockerfile: ${c4.dim(dockerfile || "Dockerfile (auto-detected)")}`);
2309
+ console.log("");
2310
+ {
2311
+ const check = Bun.spawn(["docker", "version", "--format", "{{.Server.Version}}"], {
2312
+ stdout: "pipe",
2313
+ stderr: "pipe"
2314
+ });
2315
+ const code = await check.exited;
2316
+ if (code !== 0) {
2317
+ console.error(c4.red("Docker is not installed or not running."));
2318
+ console.error(c4.dim(" Install Docker: https://docs.docker.com/get-docker/"));
2319
+ process.exit(1);
2320
+ }
2321
+ const version = (await new Response(check.stdout).text()).trim();
2322
+ console.log(` Docker: ${c4.dim(`v${version}`)}`);
2323
+ console.log("");
2324
+ }
2325
+ if (!opts.noBuild) {
2326
+ console.log(`${c4.bold("Building Docker image...")}`);
2327
+ if (!dockerfile) {
2328
+ console.log(c4.yellow(" No Dockerfile found \u2014 generating a minimal one..."));
2329
+ await generateDockerfile(cwd, projectName);
2330
+ console.log(c4.dim(" Created: Dockerfile"));
2331
+ }
2332
+ const buildArgs = [
2333
+ "docker",
2334
+ "build",
2335
+ "--platform",
2336
+ platform,
2337
+ "-t",
2338
+ imageName
2339
+ ];
2340
+ if (dockerfile) {
2341
+ buildArgs.push("-f", dockerfile);
2342
+ }
2343
+ if (opts.env && existsSync4(opts.env)) {
2344
+ const envContent = await Bun.file(opts.env).text();
2345
+ for (const line of envContent.split(`
2346
+ `)) {
2347
+ const trimmed = line.trim();
2348
+ if (!trimmed || trimmed.startsWith("#"))
2349
+ continue;
2350
+ const eqIdx = trimmed.indexOf("=");
2351
+ if (eqIdx === -1)
2352
+ continue;
2353
+ const key = trimmed.slice(0, eqIdx).trim();
2354
+ if (["PORT", "NODE_ENV", "ENABLE_STUDIO"].includes(key)) {
2355
+ buildArgs.push("--build-arg", `${key}=${trimmed.slice(eqIdx + 1).trim()}`);
2356
+ }
2357
+ }
2358
+ }
2359
+ buildArgs.push(context);
2360
+ try {
2361
+ await runCommand(buildArgs);
2362
+ console.log(c4.green(`
2363
+ Image built: ${imageName}
2364
+ `));
2365
+ } catch (err) {
2366
+ console.error(c4.red(`
2367
+ Build failed: ${err.message}`));
2368
+ process.exit(1);
2369
+ }
2370
+ } else {
2371
+ console.log(c4.dim(" Skipping build (--no-build)"));
2372
+ }
2373
+ const shouldPush = opts.push ?? (!opts.noPush && !!registry);
2374
+ if (shouldPush) {
2375
+ if (!registry) {
2376
+ console.error(c4.red("Cannot push: no registry specified."));
2377
+ console.error(c4.dim(" Use --registry <registry> or set DOCKER_REGISTRY env var."));
2378
+ process.exit(1);
2379
+ }
2380
+ console.log(`${c4.bold("Pushing image to registry...")}`);
2381
+ try {
2382
+ await runCommand(["docker", "push", imageName]);
2383
+ console.log(c4.green(`
2384
+ Image pushed: ${imageName}
2385
+ `));
2386
+ } catch (err) {
2387
+ console.error(c4.red(`
2388
+ Push failed: ${err.message}`));
2389
+ console.error(c4.dim(" Ensure you are logged in: docker login"));
2390
+ process.exit(1);
2391
+ }
2392
+ } else if (!registry) {
2393
+ console.log(c4.dim(" Skipping push (no registry configured)"));
2394
+ console.log(c4.dim(" Use --registry <registry> to push to a container registry."));
2395
+ }
2396
+ console.log(`
2397
+ ${c4.green("Deploy complete!")}`);
2398
+ console.log(`
2399
+ Image: ${c4.cyan(imageName)}`);
2400
+ if (shouldPush) {
2401
+ console.log(`
2402
+ ${c4.bold("Run with:")}`);
2403
+ console.log(` docker run -d --env-file .env -p 3000:3000 ${imageName}`);
2404
+ console.log(`
2405
+ ${c4.bold("Or with docker compose:")}`);
2406
+ console.log(` docker compose up -d`);
2407
+ } else {
2408
+ console.log(`
2409
+ ${c4.bold("Run locally:")}`);
2410
+ console.log(` docker run -d --env-file .env -p 3000:3000 ${imageName}`);
2411
+ console.log(`
2412
+ ${c4.bold("Push to registry:")}`);
2413
+ console.log(` zveltio deploy --registry <registry>`);
2414
+ }
2415
+ console.log("");
2416
+ }
2417
+ function findDockerfile(cwd) {
2418
+ const candidates = ["Dockerfile", "docker/Dockerfile", "packages/engine/Dockerfile"];
2419
+ for (const f of candidates) {
2420
+ if (existsSync4(join4(cwd, f)))
2421
+ return f;
2422
+ }
2423
+ return null;
2424
+ }
2425
+ async function generateDockerfile(cwd, projectName) {
2426
+ let entryPoint = "packages/engine/src/index.ts";
2427
+ if (!existsSync4(join4(cwd, entryPoint))) {
2428
+ entryPoint = existsSync4(join4(cwd, "src/index.ts")) ? "src/index.ts" : "index.ts";
2429
+ }
2430
+ await Bun.write(join4(cwd, "Dockerfile"), `# Auto-generated by zveltio deploy
2431
+ # Edit this file to customise your production image.
2432
+ FROM oven/bun:1-alpine AS base
2433
+ WORKDIR /app
2434
+
2435
+ FROM base AS deps
2436
+ COPY package.json bun.lockb* ./
2437
+ RUN bun install --frozen-lockfile --production
2438
+
2439
+ FROM base AS build
2440
+ COPY . .
2441
+ COPY --from=deps /app/node_modules ./node_modules
2442
+ RUN bun build ${entryPoint} \\
2443
+ --compile \\
2444
+ --outfile dist/${projectName} \\
2445
+ --target bun
2446
+
2447
+ FROM base AS runner
2448
+ WORKDIR /app
2449
+ # Run as non-root for security
2450
+ RUN addgroup --system --gid 1001 zveltio && \\
2451
+ adduser --system --uid 1001 zveltio
2452
+ COPY --from=build /app/dist/${projectName} ./dist/${projectName}
2453
+ # Copy migrations and static assets
2454
+ COPY --from=build /app/packages/engine/src/db/migrations ./packages/engine/src/db/migrations
2455
+ USER zveltio
2456
+ EXPOSE 3000
2457
+ ENV NODE_ENV=production
2458
+ CMD ["./dist/${projectName}"]
2459
+ `);
2460
+ }
2461
+
2462
+ // src/commands/migrate.ts
2463
+ var migrateCommand = new Command("migrate").description("Run pending database migrations").option("--url <url>", "Engine URL", "http://localhost:3000").option("--database-url <url>", "Direct database URL (skip engine)").option("--dry-run", "Show pending migrations without applying").action(async (opts) => {
2464
+ console.log(`
2465
+ \uD83D\uDDC4\uFE0F Database Migrations
2466
+ `);
2467
+ const databaseUrl = opts.databaseUrl || process.env.DATABASE_URL;
2468
+ if (databaseUrl) {
2469
+ await runMigrationsDirectly(opts, databaseUrl);
2470
+ } else {
2471
+ await runMigrationsViaAPI(opts);
2472
+ }
2473
+ });
2474
+ async function runMigrationsDirectly(opts, databaseUrl) {
2475
+ try {
2476
+ process.env.DATABASE_URL = databaseUrl;
2477
+ const dbPath = new URL("../../../engine/src/db/index.js", import.meta.url).href;
2478
+ const migrationsPath = new URL("../../../engine/src/db/migrations/index.js", import.meta.url).href;
2479
+ const { initDatabase } = await import(dbPath);
2480
+ const { runMigrations, getAppliedMigrations, getLastAppliedMigration } = await import(migrationsPath);
2481
+ const db = await initDatabase();
2482
+ if (opts.dryRun) {
2483
+ const applied = await getAppliedMigrations(db);
2484
+ const lastVersion = await getLastAppliedMigration(db);
2485
+ console.log(` Applied migrations: ${applied.length}`);
2486
+ console.log(` Last applied version: ${lastVersion}`);
2487
+ console.log(`
2488
+ (dry run \u2014 no changes made)
2489
+ `);
2490
+ await db.destroy?.();
2491
+ return;
2492
+ }
2493
+ await runMigrations(db);
2494
+ console.log(`
2495
+ \u2705 All migrations applied.
2496
+ `);
2497
+ await db.destroy?.();
2498
+ } catch (err) {
2499
+ console.error(`
2500
+ \u274C Migration failed: ${err.message}
2501
+ `);
2502
+ process.exit(1);
2503
+ }
2504
+ }
2505
+ async function runMigrationsViaAPI(opts) {
2506
+ try {
2507
+ const res = await fetch(`${opts.url}/api/admin/migrate`, {
2508
+ method: "POST",
2509
+ headers: { "Content-Type": "application/json" }
2510
+ });
2511
+ if (!res.ok) {
2512
+ const body = await res.json().catch(() => ({}));
2513
+ throw new Error(body.error ?? `Engine returned ${res.status}`);
2514
+ }
2515
+ const data = await res.json();
2516
+ console.log(`\u2705 ${data.applied} migration(s) applied. Schema version: ${data.schema_version}
2517
+ `);
2518
+ } catch (err) {
2519
+ console.error(`
2520
+ \u274C ${err.message}`);
2521
+ console.log(` Tip: Start the engine first, or use --database-url for direct migration
2522
+ `);
2523
+ process.exit(1);
2524
+ }
2525
+ }
2526
+
2527
+ // src/commands/extension.ts
2528
+ import { existsSync as existsSync5 } from "fs";
2529
+ import { mkdir, readFile, writeFile } from "fs/promises";
2530
+ import { join as join5 } from "path";
2531
+ async function extensionCommand(action, name, opts) {
2532
+ switch (action) {
2533
+ case "create":
2534
+ await createExtension(name, opts.category || "custom");
2535
+ break;
2536
+ case "build":
2537
+ await buildExtension();
2538
+ break;
2539
+ case "dev":
2540
+ await devExtension();
2541
+ break;
2542
+ case "publish":
2543
+ await publishExtension(opts.token);
2544
+ break;
2545
+ }
2546
+ }
2547
+ async function createExtension(name, category) {
2548
+ const safeName = name.toLowerCase().replace(/[^a-z0-9-]/g, "-");
2549
+ const targetDir = join5(process.cwd(), "extensions", category, safeName);
2550
+ if (existsSync5(targetDir)) {
2551
+ console.error(`Extension already exists: ${targetDir}`);
2552
+ process.exit(1);
2553
+ }
2554
+ console.log(`
2555
+ Creating extension: ${category}/${safeName}
2556
+ `);
2557
+ await mkdir(join5(targetDir, "engine"), { recursive: true });
2558
+ await mkdir(join5(targetDir, "studio", "src", "pages"), { recursive: true });
2559
+ await mkdir(join5(targetDir, "engine", "migrations"), { recursive: true });
2560
+ await writeFile(join5(targetDir, "manifest.json"), JSON.stringify({
2561
+ name: safeName,
2562
+ package: `@zveltio/ext-${safeName}`,
2563
+ category,
2564
+ displayName: name,
2565
+ description: `${name} extension for Zveltio`,
2566
+ version: "1.0.0",
2567
+ zveltioMinVersion: "2.0.0",
2568
+ zveltioMaxVersion: "3.0.0",
2569
+ permissions: ["database"],
2570
+ contributes: { engine: true, studio: true, fieldTypes: [] }
2571
+ }, null, 2));
2572
+ await writeFile(join5(targetDir, "engine", "index.ts"), `import type { ZveltioExtension } from '@zveltio/sdk/extension';
2573
+ import { join } from 'path';
2574
+
2575
+ const extension: ZveltioExtension = {
2576
+ name: '${category}/${safeName}',
2577
+ category: '${category}',
2578
+
2579
+ getMigrations() {
2580
+ return [
2581
+ join(import.meta.dir, 'migrations/001_init.sql'),
2582
+ ];
2583
+ },
2584
+
2585
+ async register(app, ctx) {
2586
+ // Register your API routes here
2587
+ app.get('/api/${safeName}/ping', (c) => c.json({ pong: true }));
2588
+ },
2589
+ };
2590
+
2591
+ export default extension;
2592
+ `);
2593
+ await writeFile(join5(targetDir, "engine", "migrations", "001_init.sql"), `-- ${name} extension initial schema
2594
+ -- Add your tables here
2595
+
2596
+ -- Example:
2597
+ -- CREATE TABLE IF NOT EXISTS zv_${safeName.replace(/-/g, "_")} (
2598
+ -- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
2599
+ -- name TEXT NOT NULL,
2600
+ -- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2601
+ -- );
2602
+ `);
2603
+ await writeFile(join5(targetDir, "studio", "src", "index.ts"), `import MainPage from './pages/MainPage.svelte';
2604
+
2605
+ export default function register() {
2606
+ const zveltio = (window as any).__zveltio;
2607
+ if (!zveltio) {
2608
+ console.error('Zveltio Studio API not available');
2609
+ return;
2610
+ }
2611
+
2612
+ zveltio.registerRoute({
2613
+ path: '${safeName}',
2614
+ component: MainPage,
2615
+ label: '${name}',
2616
+ icon: 'Puzzle',
2617
+ category: '${category}',
2618
+ });
2619
+ }
2620
+ `);
2621
+ await writeFile(join5(targetDir, "studio", "src", "pages", "MainPage.svelte"), `<script lang="ts">
2622
+ const engineUrl = (window as any).__ZVELTIO_ENGINE_URL__;
2623
+ </script>
2624
+
2625
+ <div class="space-y-6">
2626
+ <h1 class="text-2xl font-bold">${name}</h1>
2627
+ <p class="text-base-content/60">Welcome to the ${name} extension.</p>
2628
+ </div>
2629
+ `);
2630
+ await writeFile(join5(targetDir, "studio", "vite.config.ts"), `import { svelte } from '@sveltejs/vite-plugin-svelte';
2631
+ import { defineConfig } from 'vite';
2632
+
2633
+ export default defineConfig({
2634
+ plugins: [svelte()],
2635
+ build: {
2636
+ lib: {
2637
+ entry: 'src/index.ts',
2638
+ formats: ['iife'],
2639
+ fileName: () => 'bundle.js',
2640
+ },
2641
+ rollupOptions: {
2642
+ external: ['svelte', 'svelte/internal', 'svelte/store'],
2643
+ output: {
2644
+ globals: {
2645
+ 'svelte': 'window.__SvelteRuntime?.svelte',
2646
+ 'svelte/internal': 'window.__SvelteRuntime?.internal',
2647
+ 'svelte/store': 'window.__SvelteRuntime?.store',
2648
+ },
2649
+ },
2650
+ },
2651
+ },
2652
+ });
2653
+ `);
2654
+ await writeFile(join5(targetDir, "studio", "package.json"), JSON.stringify({
2655
+ name: `@zveltio/ext-${safeName}-studio`,
2656
+ version: "1.0.0",
2657
+ type: "module",
2658
+ scripts: {
2659
+ build: "vite build",
2660
+ dev: "vite build --watch"
2661
+ },
2662
+ dependencies: { svelte: "^5.0.0" },
2663
+ devDependencies: {
2664
+ "@sveltejs/vite-plugin-svelte": "^4.0.0",
2665
+ vite: "^6.0.0"
2666
+ }
2667
+ }, null, 2));
2668
+ console.log(`Extension scaffolded at extensions/${category}/${safeName}/
2669
+
2670
+ Structure:
2671
+ engine/
2672
+ index.ts <- API routes
2673
+ migrations/ <- SQL migrations
2674
+ studio/
2675
+ src/
2676
+ index.ts <- Studio registration
2677
+ pages/ <- Svelte UI components
2678
+ vite.config.ts
2679
+ manifest.json
2680
+
2681
+ Next steps:
2682
+ 1. Add your business logic in engine/index.ts
2683
+ 2. Create your UI in studio/src/pages/
2684
+ 3. Enable the extension: ZVELTIO_EXTENSIONS=${category}/${safeName}
2685
+ `);
2686
+ }
2687
+ async function buildExtension() {
2688
+ console.log(`
2689
+ Building extension...
2690
+ `);
2691
+ if (!existsSync5("manifest.json")) {
2692
+ console.error("No manifest.json found. Run this command from an extension directory.");
2693
+ process.exit(1);
2694
+ }
2695
+ const manifest = JSON.parse(await readFile("manifest.json", "utf-8"));
2696
+ if (existsSync5("studio")) {
2697
+ const studioProc = Bun.spawn(["bun", "run", "build"], {
2698
+ cwd: "studio",
2699
+ stdout: "inherit",
2700
+ stderr: "inherit"
2701
+ });
2702
+ const code = await studioProc.exited;
2703
+ if (code !== 0)
2704
+ throw new Error(`Studio build failed with exit code ${code}`);
2705
+ console.log(" Studio bundle built");
2706
+ }
2707
+ const engineProc = Bun.spawn(["bun", "build", "engine/index.ts", "--outdir", "engine/dist", "--target", "bun"], { stdout: "inherit", stderr: "inherit" });
2708
+ const engineCode = await engineProc.exited;
2709
+ if (engineCode !== 0)
2710
+ throw new Error(`Engine build failed with exit code ${engineCode}`);
2711
+ console.log(" Engine built");
2712
+ console.log(`
2713
+ Extension built: ${manifest.name} v${manifest.version}`);
2714
+ }
2715
+ async function devExtension() {
2716
+ console.log(`
2717
+ Starting extension dev mode...
2718
+ `);
2719
+ const studioProc = Bun.spawn(["bun", "run", "dev"], {
2720
+ cwd: "studio",
2721
+ stdout: "inherit",
2722
+ stderr: "inherit"
2723
+ });
2724
+ console.log(" Studio: watching for changes...");
2725
+ process.on("SIGINT", () => {
2726
+ studioProc.kill();
2727
+ process.exit(0);
2728
+ });
2729
+ await studioProc.exited;
2730
+ }
2731
+ async function publishExtension(token) {
2732
+ if (!token) {
2733
+ console.error("Marketplace token required. Use --token <token>");
2734
+ process.exit(1);
2735
+ }
2736
+ console.log(`
2737
+ Publishing to Zveltio marketplace...`);
2738
+ console.log(" (Marketplace coming soon!)");
2739
+ }
2740
+
2741
+ // src/commands/generate-types.ts
2742
+ import { mkdirSync as mkdirSync2 } from "fs";
2743
+ import { dirname } from "path";
2744
+ var c5 = {
2745
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
2746
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
2747
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
2748
+ dim: (s) => `\x1B[2m${s}\x1B[0m`,
2749
+ red: (s) => `\x1B[31m${s}\x1B[0m`
2750
+ };
2751
+ async function generateTypesCommand(collection, opts) {
2752
+ const engineUrl = opts.url || process.env.ZVELTIO_URL || "http://localhost:3000";
2753
+ const outputPath = opts.output || "./types/zveltio.d.ts";
2754
+ console.log(`
2755
+ ${c5.bold("Generate Types")}
2756
+ `);
2757
+ console.log(` Engine: ${c5.dim(engineUrl)}`);
2758
+ console.log(` Output: ${c5.dim(outputPath)}`);
2759
+ if (collection) {
2760
+ console.log(` Collection: ${c5.dim(collection)}`);
2761
+ }
2762
+ console.log("");
2763
+ try {
2764
+ const path = collection ? `/api/admin/types/${encodeURIComponent(collection)}` : `/api/admin/types`;
2765
+ const res = await fetch(`${engineUrl}${path}`, {
2766
+ headers: {
2767
+ Authorization: `Bearer ${process.env.ZVELTIO_API_KEY || ""}`
2768
+ }
2769
+ });
2770
+ if (!res.ok) {
2771
+ console.error(c5.red(`Failed to fetch types: ${res.status} ${res.statusText}`));
2772
+ if (res.status === 401) {
2773
+ console.error(c5.dim(" Set ZVELTIO_API_KEY env var or use an authenticated session."));
2774
+ } else if (res.status === 404) {
2775
+ console.error(c5.dim(" Ensure the engine is running and the /api/admin/types endpoint is available."));
2776
+ }
2777
+ process.exit(1);
2778
+ }
2779
+ const types = await res.text();
2780
+ const dir = dirname(outputPath);
2781
+ if (dir && dir !== ".") {
2782
+ mkdirSync2(dir, { recursive: true });
2783
+ }
2784
+ await Bun.write(outputPath, types);
2785
+ console.log(`${c5.green("Types generated:")} ${outputPath}`);
2786
+ if (!collection) {
2787
+ const typeCount = (types.match(/^export (interface|type) /gm) || []).length;
2788
+ if (typeCount > 0) {
2789
+ console.log(c5.dim(` ${typeCount} type declaration(s) written`));
2790
+ }
2791
+ }
2792
+ console.log("");
2793
+ } catch (err) {
2794
+ console.error(c5.red(`Failed to generate types: ${err.message}`));
2795
+ process.exit(1);
2796
+ }
2797
+ }
2798
+
2799
+ // src/commands/install.ts
2800
+ import { existsSync as existsSync6 } from "fs";
2801
+ import { readFile as readFile2, mkdir as mkdir2, cp } from "fs/promises";
2802
+ import { join as join6 } from "path";
2803
+ async function installCommand(name, opts) {
2804
+ const engineUrl = opts.url || process.env.ENGINE_URL || "http://localhost:3000";
2805
+ console.log(`
2806
+ \uD83D\uDCE6 Installing extension: ${name}
2807
+ `);
2808
+ if (opts.path) {
2809
+ await installFromPath(name, opts.path, engineUrl, opts.force ?? false);
2810
+ return;
2811
+ }
2812
+ await installFromCatalog(name, engineUrl);
2813
+ }
2814
+ async function installFromPath(name, sourcePath, engineUrl, force) {
2815
+ if (!existsSync6(join6(sourcePath, "manifest.json"))) {
2816
+ console.error("\u274C No manifest.json found at", sourcePath);
2817
+ process.exit(1);
2818
+ }
2819
+ let manifest;
2820
+ try {
2821
+ manifest = JSON.parse(await readFile2(join6(sourcePath, "manifest.json"), "utf-8"));
2822
+ } catch {
2823
+ console.error("\u274C Failed to read manifest.json");
2824
+ process.exit(1);
2825
+ }
2826
+ if (!manifest.name) {
2827
+ console.error("\u274C manifest.json is missing required field: name");
2828
+ process.exit(1);
2829
+ }
2830
+ const SAFE_SEGMENT_RE = /^[a-z0-9][a-z0-9_-]*$/;
2831
+ const category = manifest.category || "custom";
2832
+ if (!SAFE_SEGMENT_RE.test(category)) {
2833
+ console.error(`\u274C manifest.json "category" contains invalid characters: "${category}"`);
2834
+ console.error(" Only lowercase letters, digits, hyphens, and underscores are allowed.");
2835
+ process.exit(1);
2836
+ }
2837
+ if (!SAFE_SEGMENT_RE.test(manifest.name)) {
2838
+ console.error(`\u274C manifest.json "name" contains invalid characters: "${manifest.name}"`);
2839
+ console.error(" Only lowercase letters, digits, hyphens, and underscores are allowed.");
2840
+ process.exit(1);
2841
+ }
2842
+ console.log(` Name: ${manifest.displayName || manifest.name}`);
2843
+ console.log(` Version: ${manifest.version || "?"}`);
2844
+ console.log(` Category: ${category}`);
2845
+ const enginePkgPath = join6(process.cwd(), "packages/engine/package.json");
2846
+ if (existsSync6(enginePkgPath)) {
2847
+ const enginePkg = JSON.parse(await readFile2(enginePkgPath, "utf-8"));
2848
+ const engineVersion = enginePkg.version || "2.0.0";
2849
+ if (manifest.zveltioMinVersion) {
2850
+ console.log(` Engine required: >= ${manifest.zveltioMinVersion} (current: ${engineVersion})`);
2851
+ }
2852
+ if (manifest.zveltioMaxVersion) {
2853
+ console.log(` Engine max: <= ${manifest.zveltioMaxVersion}`);
2854
+ }
2855
+ }
2856
+ const extName = manifest.name;
2857
+ const targetDir = join6(process.cwd(), "extensions", category, extName);
2858
+ if (existsSync6(targetDir) && !force) {
2859
+ console.error(`\u274C Extension already exists at ${targetDir}`);
2860
+ console.error(` Use --force to overwrite.`);
2861
+ process.exit(1);
2862
+ }
2863
+ await mkdir2(targetDir, { recursive: true });
2864
+ await cp(sourcePath, targetDir, { recursive: true });
2865
+ console.log(` \u2713 Copied to ${targetDir}`);
2866
+ await activateViaApi(extName, category, engineUrl);
2867
+ console.log(`
2868
+ \u2705 Extension "${manifest.displayName || manifest.name}" installed!`);
2869
+ console.log(`
2870
+ Add to your .env:`);
2871
+ console.log(` ZVELTIO_EXTENSIONS=...,${category}/${extName}
2872
+ `);
2873
+ }
2874
+ async function installFromCatalog(name, engineUrl) {
2875
+ console.log(` Checking engine catalog at ${engineUrl}...`);
2876
+ let catalogRes;
2877
+ try {
2878
+ catalogRes = await fetch(`${engineUrl}/api/marketplace`);
2879
+ } catch {
2880
+ console.error(`\u274C Cannot reach engine at ${engineUrl}`);
2881
+ console.error(` Is the engine running? Use --path for offline install.`);
2882
+ process.exit(1);
2883
+ }
2884
+ if (catalogRes.status === 401) {
2885
+ console.error("\u274C Admin authentication required. Engine marketplace requires admin session.");
2886
+ console.error(" Tip: use --path <local-path> for unauthenticated install.");
2887
+ process.exit(1);
2888
+ }
2889
+ if (!catalogRes.ok) {
2890
+ console.error(`\u274C Marketplace error: ${catalogRes.status} ${catalogRes.statusText}`);
2891
+ process.exit(1);
2892
+ }
2893
+ const { extensions } = await catalogRes.json();
2894
+ const entry = extensions.find((e) => e.name === name || e.package === name || e.name === name.replace("@zveltio/ext-", "") || e.displayName?.toLowerCase() === name.toLowerCase());
2895
+ if (!entry) {
2896
+ console.error(`\u274C Extension "${name}" not found in catalog.`);
2897
+ console.log(`
2898
+ Available extensions:`);
2899
+ const byCategory = {};
2900
+ for (const e of extensions) {
2901
+ if (!byCategory[e.category])
2902
+ byCategory[e.category] = [];
2903
+ byCategory[e.category].push(e);
2904
+ }
2905
+ for (const [cat, exts] of Object.entries(byCategory).sort()) {
2906
+ console.log(`
2907
+ ${cat.toUpperCase()}`);
2908
+ for (const e of exts) {
2909
+ const status = e.is_running ? "\u2705" : e.is_installed ? "\uD83D\uDCE5" : "\u2B1C";
2910
+ console.log(` ${status} ${e.name.padEnd(35)} ${e.description || ""}`);
2911
+ }
2912
+ }
2913
+ console.log("");
2914
+ process.exit(1);
2915
+ }
2916
+ console.log(` Name: ${entry.displayName || entry.name}`);
2917
+ console.log(` Version: ${entry.version || "?"}`);
2918
+ console.log(` Category: ${entry.category || "custom"}`);
2919
+ console.log(` Description: ${entry.description || ""}`);
2920
+ if (entry.is_running) {
2921
+ console.log(`
2922
+ \u2705 Extension "${entry.displayName || entry.name}" is already active.`);
2923
+ return;
2924
+ }
2925
+ if (entry.is_installed) {
2926
+ console.log(` Already installed. Enabling...`);
2927
+ } else {
2928
+ const installRes = await fetch(`${engineUrl}/api/marketplace/${entry.name}/install`, { method: "POST" }).catch(() => null);
2929
+ if (!installRes?.ok) {
2930
+ const err = await installRes?.json().catch(() => ({}));
2931
+ if (installRes?.status === 501) {
2932
+ console.log(` \u2139\uFE0F Bundled extension \u2014 skipping install step, enabling directly...`);
2933
+ } else {
2934
+ console.error(`\u274C Install failed: ${err?.error || `HTTP ${installRes?.status}`}`);
2935
+ process.exit(1);
2936
+ }
2937
+ } else {
2938
+ console.log(` \u2713 Marked as installed`);
2939
+ }
2940
+ }
2941
+ const enableRes = await fetch(`${engineUrl}/api/marketplace/${entry.name}/enable`, { method: "POST" }).catch(() => null);
2942
+ if (!enableRes?.ok) {
2943
+ const err = await enableRes?.json().catch(() => ({}));
2944
+ console.error(`\u274C Enable failed: ${err?.error || `HTTP ${enableRes?.status}`}`);
2945
+ process.exit(1);
2946
+ }
2947
+ const result = await enableRes.json();
2948
+ if (result.hot_loaded) {
2949
+ console.log(`
2950
+ \u2705 Extension "${entry.displayName || entry.name}" is now active (hot-loaded).`);
2951
+ } else {
2952
+ console.log(`
2953
+ \u2705 Extension "${entry.displayName || entry.name}" installed.`);
2954
+ console.log(`
2955
+ Restart engine to activate:`);
2956
+ console.log(` bun run dev
2957
+ `);
2958
+ console.log(` Or add to your .env:`);
2959
+ console.log(` ZVELTIO_EXTENSIONS=...,${entry.name}
2960
+ `);
2961
+ }
2962
+ }
2963
+ async function activateViaApi(name, category, engineUrl) {
2964
+ try {
2965
+ const res = await fetch(`${engineUrl}/api/marketplace/${category}/${name}/enable`, {
2966
+ method: "POST"
2967
+ });
2968
+ if (res.ok) {
2969
+ const result = await res.json();
2970
+ console.log(` \u2713 ${result.hot_loaded ? "Hot-loaded into running engine" : "Registered (restart engine to activate)"}`);
2971
+ } else {
2972
+ console.log(` \u26A0\uFE0F Engine responded with ${res.status} \u2014 enable manually or restart`);
2973
+ }
2974
+ } catch {
2975
+ console.log(` \u26A0\uFE0F Engine not reachable at ${engineUrl} \u2014 enable manually or restart`);
2976
+ }
2977
+ }
2978
+
2979
+ // src/commands/create-god.ts
2980
+ import { createInterface as createInterface2 } from "readline";
2981
+ async function prompt(rl2, question) {
2982
+ return new Promise((resolve) => {
2983
+ rl2.question(question, resolve);
2984
+ });
2985
+ }
2986
+ async function promptHidden(question) {
2987
+ return new Promise((resolve) => {
2988
+ process.stdout.write(question);
2989
+ const stdin = process.stdin;
2990
+ const wasPaused = stdin.isPaused();
2991
+ if (wasPaused)
2992
+ stdin.resume();
2993
+ let value = "";
2994
+ stdin.setRawMode?.(true);
2995
+ stdin.setEncoding("utf8");
2996
+ const handler = (char) => {
2997
+ if (char === `
2998
+ ` || char === "\r" || char === "\x03") {
2999
+ if (char === "\x03")
3000
+ process.exit(1);
3001
+ stdin.setRawMode?.(false);
3002
+ stdin.pause();
3003
+ stdin.off("data", handler);
3004
+ process.stdout.write(`
3005
+ `);
3006
+ resolve(value);
3007
+ } else if (char === "\x7F") {
3008
+ if (value.length > 0)
3009
+ value = value.slice(0, -1);
3010
+ } else {
3011
+ value += char;
3012
+ process.stdout.write("*");
3013
+ }
3014
+ };
3015
+ stdin.on("data", handler);
3016
+ });
3017
+ }
3018
+ async function createGodCommand(opts) {
3019
+ const engineUrl = opts.url || process.env.ENGINE_URL || "http://localhost:3000";
3020
+ console.log(`
3021
+ \u26A0\uFE0F SYSTEM RECOVERY OVERRIDE ACCOUNT`);
3022
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
3023
+ console.log("This account bypasses ALL Casbin permissions.");
3024
+ console.log("EXCLUSIVE USE: disaster recovery when policies");
3025
+ console.log("Casbin are corrupted or admin access is blocked.");
3026
+ console.log("");
3027
+ console.log("Security recommendations:");
3028
+ console.log(" \u2022 Store credentials OFFLINE (not in cloud password manager)");
3029
+ console.log(" \u2022 Do not use this account for daily operations");
3030
+ console.log(" \u2022 Enable 2FA immediately after creation");
3031
+ console.log(" \u2022 Audit logins for this account separately");
3032
+ console.log(`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
3033
+ `);
3034
+ const rlConfirm = createInterface2({
3035
+ input: process.stdin,
3036
+ output: process.stdout
3037
+ });
3038
+ const confirmed = await prompt(rlConfirm, "I understand the risks. Create Recovery Override account? (yes/no): ");
3039
+ rlConfirm.close();
3040
+ if (confirmed.trim().toLowerCase() !== "yes") {
3041
+ console.log("Operation cancelled.");
3042
+ process.exit(0);
3043
+ }
3044
+ console.log(`
3045
+ Creating God (super-admin) user at ${engineUrl}
3046
+ `);
3047
+ const rl2 = createInterface2({ input: process.stdin, output: process.stdout });
3048
+ try {
3049
+ const email = opts.email || await prompt(rl2, "Email: ");
3050
+ const name = opts.name || await prompt(rl2, "Name: ");
3051
+ rl2.close();
3052
+ const password = await promptHidden("Password: ");
3053
+ const confirmPassword = await promptHidden("Confirm password: ");
3054
+ if (password !== confirmPassword) {
3055
+ console.error(`
3056
+ \u274C Passwords do not match`);
3057
+ process.exit(1);
3058
+ }
3059
+ const pwErrors = [];
3060
+ if (password.length < 16)
3061
+ pwErrors.push("at least 16 characters");
3062
+ if (!/[A-Z]/.test(password))
3063
+ pwErrors.push("at least one uppercase letter");
3064
+ if (!/[a-z]/.test(password))
3065
+ pwErrors.push("at least one lowercase letter");
3066
+ if (!/[0-9]/.test(password))
3067
+ pwErrors.push("at least one digit");
3068
+ if (!/[^A-Za-z0-9]/.test(password))
3069
+ pwErrors.push("at least one special character");
3070
+ if (pwErrors.length > 0) {
3071
+ console.error(`
3072
+ \u274C God account password is too weak. Required:`);
3073
+ for (const e of pwErrors)
3074
+ console.error(` \u2022 ${e}`);
3075
+ process.exit(1);
3076
+ }
3077
+ if (!email.includes("@")) {
3078
+ console.error(`
3079
+ \u274C Invalid email address`);
3080
+ process.exit(1);
3081
+ }
3082
+ console.log(`
3083
+ \uD83D\uDD04 Creating god user...`);
3084
+ const res = await fetch(`${engineUrl}/api/auth/sign-up/email`, {
3085
+ method: "POST",
3086
+ headers: { "Content-Type": "application/json" },
3087
+ body: JSON.stringify({
3088
+ email: email.trim(),
3089
+ password,
3090
+ name: name.trim()
3091
+ })
3092
+ });
3093
+ if (!res.ok) {
3094
+ const err = await res.json().catch(() => ({ message: res.statusText }));
3095
+ throw new Error(err.message || `HTTP ${res.status}`);
3096
+ }
3097
+ const { user } = await res.json();
3098
+ console.log("\uD83D\uDD11 Granting god permissions...");
3099
+ const loginRes = await fetch(`${engineUrl}/api/auth/sign-in/email`, {
3100
+ method: "POST",
3101
+ headers: { "Content-Type": "application/json" },
3102
+ body: JSON.stringify({ email: email.trim(), password })
3103
+ });
3104
+ if (!loginRes.ok) {
3105
+ console.warn("\u26A0\uFE0F Could not auto-grant admin role \u2014 grant manually via permissions API");
3106
+ console.log(`
3107
+ \u2705 User created: ${email}
3108
+ `);
3109
+ return;
3110
+ }
3111
+ const sessionCookie = loginRes.headers.get("set-cookie") || "";
3112
+ const permRes = await fetch(`${engineUrl}/api/permissions/assign-role`, {
3113
+ method: "POST",
3114
+ headers: {
3115
+ "Content-Type": "application/json",
3116
+ Cookie: sessionCookie
3117
+ },
3118
+ body: JSON.stringify({ userId: user.id, role: "god" })
3119
+ });
3120
+ if (permRes.ok) {
3121
+ console.log(`
3122
+ \u2705 God user created successfully!`);
3123
+ console.log(` Email: ${email.trim()}`);
3124
+ console.log(` Name: ${name.trim()}`);
3125
+ console.log(` Role: god
3126
+ `);
3127
+ console.log(`\uD83D\uDC49 Log in at: ${engineUrl}/admin
3128
+ `);
3129
+ } else {
3130
+ console.log(`
3131
+ \u2705 User created: ${email.trim()}`);
3132
+ console.warn("\u26A0\uFE0F Could not auto-assign god role.");
3133
+ console.warn(` Use the Permissions page in Studio to assign the admin role manually.
3134
+ `);
3135
+ }
3136
+ } catch (err) {
3137
+ rl2.close();
3138
+ console.error(`
3139
+ \u274C Failed to create god user: ${err.message}
3140
+ `);
3141
+ process.exit(1);
3142
+ }
3143
+ }
3144
+
3145
+ // src/commands/extensions-list.ts
3146
+ async function extensionsListCommand(opts) {
3147
+ const engineUrl = opts.url || process.env.ENGINE_URL || "http://localhost:3000";
3148
+ let res;
3149
+ try {
3150
+ res = await fetch(`${engineUrl}/api/marketplace`);
3151
+ } catch {
3152
+ console.error(`\u274C Cannot reach engine at ${engineUrl}`);
3153
+ console.error(` Is the engine running? Try: zveltio dev`);
3154
+ process.exit(1);
3155
+ }
3156
+ if (res.status === 401) {
3157
+ console.error("\u274C Admin authentication required to view marketplace.");
3158
+ console.error(" Set ENGINE_TOKEN env var or use --token option.");
3159
+ process.exit(1);
3160
+ }
3161
+ if (!res.ok) {
3162
+ console.error(`\u274C Marketplace error: ${res.status} ${res.statusText}`);
3163
+ process.exit(1);
3164
+ }
3165
+ const { extensions } = await res.json();
3166
+ if (opts.json) {
3167
+ console.log(JSON.stringify(extensions, null, 2));
3168
+ return;
3169
+ }
3170
+ const filtered = opts.category ? extensions.filter((e) => e.category === opts.category) : extensions;
3171
+ if (!filtered.length) {
3172
+ console.log(`No extensions found${opts.category ? ` in category "${opts.category}"` : ""}.`);
3173
+ return;
3174
+ }
3175
+ const byCategory = {};
3176
+ for (const ext of filtered) {
3177
+ const cat = ext.category || "custom";
3178
+ if (!byCategory[cat])
3179
+ byCategory[cat] = [];
3180
+ byCategory[cat].push(ext);
3181
+ }
3182
+ const total = filtered.length;
3183
+ const active = filtered.filter((e) => e.is_running).length;
3184
+ const installed = filtered.filter((e) => e.is_installed).length;
3185
+ console.log(`
3186
+ \uD83D\uDCE6 Zveltio Extensions (${active} active / ${installed} installed / ${total} available)
3187
+ `);
3188
+ for (const [category, exts] of Object.entries(byCategory).sort()) {
3189
+ console.log(` ${category.toUpperCase()}`);
3190
+ for (const ext of exts) {
3191
+ const status = ext.is_running ? "\u2705" : ext.is_installed && ext.is_enabled ? "\uD83D\uDD04" : ext.is_installed ? "\uD83D\uDCE5" : "\u2B1C";
3192
+ const needsRestart = ext.needs_restart ? " \u26A0\uFE0F restart needed" : "";
3193
+ const name = (ext.displayName || ext.name).padEnd(32);
3194
+ console.log(` ${status} ${name} v${ext.version || "?"} ${ext.description || ""}${needsRestart}`);
3195
+ }
3196
+ console.log("");
3197
+ }
3198
+ console.log("Legend: \u2705 active \uD83D\uDD04 needs restart \uD83D\uDCE5 installed (disabled) \u2B1C not installed");
3199
+ console.log(`
3200
+ Install: zveltio install <extension-name>`);
3201
+ console.log("Enable: zveltio extensions enable <extension-name>");
3202
+ console.log("");
3203
+ }
3204
+
3205
+ // src/commands/rollback.ts
3206
+ var rollbackCommand = new Command("rollback").description("Rollback database migrations to a specific version").option("--to <version>", "Target schema version number").option("--steps <n>", "Number of migrations to rollback", "1").option("--database-url <url>", "Direct database URL").option("--force", "Skip confirmation prompt").action(async (opts) => {
3207
+ console.log(`
3208
+ \u23EA Zveltio Rollback
3209
+ `);
3210
+ const databaseUrl = opts.databaseUrl || process.env.DATABASE_URL;
3211
+ if (!databaseUrl) {
3212
+ console.error("\u274C DATABASE_URL required. Use --database-url or set the env var.");
3213
+ process.exit(1);
3214
+ }
3215
+ process.env.DATABASE_URL = databaseUrl;
3216
+ const dbPath = new URL("../../../engine/src/db/index.js", import.meta.url).href;
3217
+ const migrationsPath = new URL("../../../engine/src/db/migrations/index.js", import.meta.url).href;
3218
+ const { initDatabase } = await import(dbPath);
3219
+ const { getLastAppliedMigration, rollbackMigration } = await import(migrationsPath);
3220
+ let targetVersion;
3221
+ if (opts.to !== undefined) {
3222
+ targetVersion = parseInt(opts.to);
3223
+ if (isNaN(targetVersion)) {
3224
+ console.error("\u274C --to must be a valid integer");
3225
+ process.exit(1);
3226
+ }
3227
+ } else {
3228
+ const steps = parseInt(opts.steps);
3229
+ if (isNaN(steps) || steps < 1) {
3230
+ console.error("\u274C --steps must be a positive integer");
3231
+ process.exit(1);
3232
+ }
3233
+ const db = await initDatabase();
3234
+ const current = await getLastAppliedMigration(db);
3235
+ await db.destroy?.();
3236
+ targetVersion = Math.max(0, current - steps);
3237
+ }
3238
+ console.log(` Rolling back to schema version: ${targetVersion}`);
3239
+ if (!opts.force) {
3240
+ const readline = await import("readline");
3241
+ const rl2 = readline.createInterface({
3242
+ input: process.stdin,
3243
+ output: process.stdout
3244
+ });
3245
+ const answer = await new Promise((resolve) => {
3246
+ rl2.question(`
3247
+ \u26A0\uFE0F This will rollback schema changes. Type "yes" to continue: `, resolve);
3248
+ });
3249
+ rl2.close();
3250
+ if (answer.trim().toLowerCase() !== "yes") {
3251
+ console.log(`
3252
+ Rollback cancelled.
3253
+ `);
3254
+ process.exit(0);
3255
+ }
3256
+ }
3257
+ try {
3258
+ const db = await initDatabase();
3259
+ const result = await rollbackMigration(db, targetVersion);
3260
+ await db.destroy?.();
3261
+ if (!result.success) {
3262
+ console.error(`
3263
+ \u274C Rollback failed: ${result.error}
3264
+ `);
3265
+ process.exit(1);
3266
+ }
3267
+ console.log(`
3268
+ \u2705 Rolled back to schema version ${targetVersion}.
3269
+ `);
3270
+ console.log(" \u26A0\uFE0F Restart engine after rollback:");
3271
+ console.log(` zveltio stop && zveltio start
3272
+ `);
3273
+ } catch (err) {
3274
+ console.error(`
3275
+ \u274C Rollback error: ${err.message}
3276
+ `);
3277
+ process.exit(1);
3278
+ }
3279
+ });
3280
+
3281
+ // src/commands/version-cmd.ts
3282
+ var versionCommand = new Command("version").description("Show version information and check for updates").option("--url <url>", "Engine URL", "http://localhost:3000").option("--json", "Output as JSON").action(async (opts) => {
3283
+ try {
3284
+ const [healthRes, updateRes] = await Promise.allSettled([
3285
+ fetch(`${opts.url}/api/health/version`),
3286
+ fetch(`${opts.url}/api/health/update-check`)
3287
+ ]);
3288
+ const versionData = healthRes.status === "fulfilled" && healthRes.value.ok ? await healthRes.value.json() : null;
3289
+ const updateData = updateRes.status === "fulfilled" && updateRes.value.ok ? await updateRes.value.json() : null;
3290
+ if (opts.json) {
3291
+ console.log(JSON.stringify({ version: versionData, update: updateData }, null, 2));
3292
+ return;
3293
+ }
3294
+ if (!versionData) {
3295
+ console.log(`
3296
+ \u26A0\uFE0F Engine not running. Cannot determine version.
3297
+ `);
3298
+ return;
3299
+ }
3300
+ console.log(`
3301
+ \uD83D\uDCE6 Zveltio Version Information
3302
+
3303
+ Engine: ${versionData.engine}
3304
+ Runtime: ${versionData.runtime}
3305
+ Platform: ${versionData.platform}
3306
+
3307
+ Schema: v${versionData.schema.current} / v${versionData.schema.maximum}
3308
+ ${versionData.schema.upToDate ? "\u2705 Up to date" : `\u26A0\uFE0F ${versionData.schema.pending} pending migration(s) \u2014 run: zveltio migrate`}
3309
+ `);
3310
+ if (updateData?.has_update) {
3311
+ console.log(` \u2B06\uFE0F Update available: v${updateData.current} \u2192 v${updateData.latest}`);
3312
+ console.log(` Run: zveltio update`);
3313
+ console.log(` Notes: ${updateData.release_url}
3314
+ `);
3315
+ } else if (updateData && !updateData.error) {
3316
+ console.log(` \u2705 Engine is up to date (v${updateData.current})
3317
+ `);
3318
+ }
3319
+ } catch {
3320
+ console.log(`
3321
+ \u26A0\uFE0F Could not connect to engine.
3322
+ `);
3323
+ }
3324
+ });
3325
+
3326
+ // src/commands/update.ts
3327
+ import { existsSync as existsSync7 } from "fs";
3328
+ import { join as join7 } from "path";
3329
+ var updateCommand = new Command("update").description("Update Zveltio to the latest version").option("--version <v>", "Target version (default: latest stable)").option("--channel <c>", "Channel: stable | beta", "stable").option("--check", "Check for updates without installing").option("--force", "Skip confirmation").option("--dir <path>", "Installation directory").action(async (opts) => {
3330
+ console.log(`
3331
+ Zveltio Update
3332
+ `);
3333
+ const installDir = opts.dir || process.env.ZVELTIO_DIR || join7(process.cwd(), "zveltio");
3334
+ const metaPath = join7(installDir, ".zveltio-install.json");
3335
+ let meta = null;
3336
+ if (existsSync7(metaPath)) {
3337
+ meta = JSON.parse(await Bun.file(metaPath).text());
3338
+ }
3339
+ const currentVersion = meta?.version || await getCurrentVersionFromAPI(meta?.port ?? 3000) || "0.0.0";
3340
+ console.log(` Current version: v${currentVersion}`);
3341
+ let versionsData;
3342
+ try {
3343
+ const res = await fetch("https://raw.githubusercontent.com/zveltio/zveltio/main/versions.json");
3344
+ versionsData = await res.json();
3345
+ } catch {
3346
+ console.error("Cannot fetch version information. Check your connection.");
3347
+ process.exit(1);
3348
+ }
3349
+ const targetVersion = opts.version || (opts.channel === "beta" ? versionsData.latest_beta ?? versionsData.latest : versionsData.latest);
3350
+ console.log(` Target version: v${targetVersion}`);
3351
+ if (opts.check) {
3352
+ const hasUpdate = compareVersions(targetVersion, currentVersion) > 0;
3353
+ if (hasUpdate) {
3354
+ const entry = versionsData.versions.find((v) => v.version === targetVersion);
3355
+ console.log(`
3356
+ Update available!
3357
+ `);
3358
+ if (entry?.breaking_changes) {
3359
+ console.log(` Contains BREAKING CHANGES`);
3360
+ }
3361
+ console.log(` Release notes: ${entry?.release_notes ?? ""}`);
3362
+ console.log(`
3363
+ Run: zveltio update
3364
+ `);
3365
+ } else {
3366
+ console.log(`
3367
+ Already up to date.
3368
+ `);
3369
+ }
3370
+ return;
3371
+ }
3372
+ if (compareVersions(targetVersion, currentVersion) <= 0) {
3373
+ console.log(`
3374
+ Already up to date.
3375
+ `);
3376
+ return;
3377
+ }
3378
+ const targetEntry = versionsData.versions.find((v) => v.version === targetVersion);
3379
+ if (targetEntry?.breaking_changes && !opts.force) {
3380
+ console.log(`
3381
+ This update contains BREAKING CHANGES.`);
3382
+ console.log(` Review: ${targetEntry.release_notes}`);
3383
+ console.log("");
3384
+ process.stdout.write(" Continue? (yes/no): ");
3385
+ const confirm = await readLine();
3386
+ if (confirm !== "yes") {
3387
+ console.log(`
3388
+ Update cancelled.
3389
+ `);
3390
+ return;
3391
+ }
3392
+ }
3393
+ console.log(`
3394
+ Upgrading v${currentVersion} -> v${targetVersion}...
3395
+ `);
3396
+ const envPath = join7(installDir, ".env");
3397
+ if (existsSync7(envPath)) {
3398
+ const backupPath = `${envPath}.backup.${Date.now()}`;
3399
+ const envContent = await Bun.file(envPath).text();
3400
+ await Bun.write(backupPath, envContent);
3401
+ console.log(` Backed up .env to ${backupPath}`);
3402
+ }
3403
+ const installScript = join7(installDir, "install.sh");
3404
+ if (existsSync7(installScript)) {
3405
+ const proc = Bun.spawn([
3406
+ "bash",
3407
+ installScript,
3408
+ "--version",
3409
+ targetVersion,
3410
+ "--unattended",
3411
+ "--dir",
3412
+ installDir,
3413
+ "--mode",
3414
+ meta?.mode ?? "auto"
3415
+ ], { stdout: "inherit", stderr: "inherit", stdin: "inherit" });
3416
+ const code = await proc.exited;
3417
+ if (code !== 0) {
3418
+ console.error(`
3419
+ Update failed. Your previous version is still running.`);
3420
+ console.log(` Restore .env: copy ${envPath}.backup.* to ${envPath}`);
3421
+ process.exit(1);
3422
+ }
3423
+ } else {
3424
+ console.log(" Downloading installer...");
3425
+ const dlProc = Bun.spawn([
3426
+ "bash",
3427
+ "-c",
3428
+ `curl -fsSL https://get.zveltio.com/install.sh -o /tmp/zveltio-update.sh && ` + `bash /tmp/zveltio-update.sh ` + `--version ${targetVersion} --unattended --dir ${installDir}`
3429
+ ], { stdout: "inherit", stderr: "inherit", stdin: "inherit" });
3430
+ const code = await dlProc.exited;
3431
+ if (code !== 0) {
3432
+ console.error(`
3433
+ Update download/install failed.`);
3434
+ process.exit(1);
3435
+ }
3436
+ }
3437
+ console.log(`
3438
+ Updated to Zveltio v${targetVersion}
3439
+ `);
3440
+ });
3441
+ async function getCurrentVersionFromAPI(port) {
3442
+ try {
3443
+ const res = await fetch(`http://localhost:${port}/api/health/version`);
3444
+ const data = await res.json();
3445
+ return data.engine ?? null;
3446
+ } catch {
3447
+ return null;
3448
+ }
3449
+ }
3450
+ function compareVersions(a, b) {
3451
+ const pa = a.split(".").map(Number);
3452
+ const pb = b.split(".").map(Number);
3453
+ for (let i = 0;i < 3; i++) {
3454
+ if ((pa[i] ?? 0) > (pb[i] ?? 0))
3455
+ return 1;
3456
+ if ((pa[i] ?? 0) < (pb[i] ?? 0))
3457
+ return -1;
3458
+ }
3459
+ return 0;
3460
+ }
3461
+ async function readLine() {
3462
+ return new Promise((resolve) => {
3463
+ process.stdin.once("data", (data) => resolve(data.toString().trim()));
3464
+ });
3465
+ }
3466
+
3467
+ // src/commands/status.ts
3468
+ var c6 = {
3469
+ bold: (s) => `\x1B[1m${s}\x1B[0m`,
3470
+ green: (s) => `\x1B[32m${s}\x1B[0m`,
3471
+ red: (s) => `\x1B[31m${s}\x1B[0m`,
3472
+ yellow: (s) => `\x1B[33m${s}\x1B[0m`,
3473
+ cyan: (s) => `\x1B[36m${s}\x1B[0m`,
3474
+ dim: (s) => `\x1B[2m${s}\x1B[0m`
3475
+ };
3476
+ function statusIcon(ok) {
3477
+ if (ok === true || ok === "ok" || ok === "healthy" || ok === "connected")
3478
+ return c6.green("OK");
3479
+ if (ok === false || ok === "error" || ok === "unhealthy")
3480
+ return c6.red("FAIL");
3481
+ return c6.yellow("UNKNOWN");
3482
+ }
3483
+ function formatUptime(seconds) {
3484
+ if (seconds < 60)
3485
+ return `${Math.floor(seconds)}s`;
3486
+ if (seconds < 3600)
3487
+ return `${Math.floor(seconds / 60)}m ${Math.floor(seconds % 60)}s`;
3488
+ const h = Math.floor(seconds / 3600);
3489
+ const m = Math.floor(seconds % 3600 / 60);
3490
+ return `${h}h ${m}m`;
3491
+ }
3492
+ async function statusCommand(opts) {
3493
+ const engineUrl = opts.url || process.env.ZVELTIO_URL || process.env.ENGINE_URL || "http://localhost:3000";
3494
+ if (!opts.json) {
3495
+ console.log(`
3496
+ ${c6.bold("Zveltio Status")}
3497
+ `);
3498
+ console.log(` Engine: ${c6.dim(engineUrl)}`);
3499
+ console.log("");
3500
+ }
3501
+ let healthData;
3502
+ try {
3503
+ const res = await fetch(`${engineUrl}/api/health`, {
3504
+ signal: AbortSignal.timeout(8000)
3505
+ });
3506
+ if (!res.ok) {
3507
+ if (opts.json) {
3508
+ console.log(JSON.stringify({ status: "error", code: res.status, message: res.statusText }));
3509
+ } else {
3510
+ console.error(c6.red(`Engine returned ${res.status} ${res.statusText}`));
3511
+ console.error(c6.dim(" Is the engine running? Try: zveltio dev"));
3512
+ }
3513
+ process.exit(1);
3514
+ }
3515
+ healthData = await res.json();
3516
+ } catch (err) {
3517
+ if (opts.json) {
3518
+ console.log(JSON.stringify({ status: "error", message: err.message }));
3519
+ } else {
3520
+ if (err.name === "TimeoutError") {
3521
+ console.error(c6.red("Connection timed out after 8s"));
3522
+ } else {
3523
+ console.error(c6.red(`Cannot reach engine at ${engineUrl}`));
3524
+ console.error(c6.dim(` ${err.message}`));
3525
+ }
3526
+ console.error(c6.dim(" Is the engine running? Try: zveltio dev"));
3527
+ }
3528
+ process.exit(1);
3529
+ }
3530
+ if (opts.json) {
3531
+ console.log(JSON.stringify(healthData, null, 2));
3532
+ return;
3533
+ }
3534
+ const db = healthData.database ?? healthData.db;
3535
+ const cache = healthData.cache ?? healthData.redis ?? healthData.valkey;
3536
+ const uptime = healthData.uptime_seconds ?? healthData.uptime;
3537
+ const version = healthData.version ?? healthData.engine_version ?? healthData.engine;
3538
+ const status = healthData.status ?? "ok";
3539
+ const overallIcon = status === "ok" || status === "healthy" ? c6.green("HEALTHY") : c6.red("DEGRADED");
3540
+ console.log(` Status: ${overallIcon}`);
3541
+ if (version) {
3542
+ console.log(` Version: ${version}`);
3543
+ }
3544
+ if (uptime !== undefined) {
3545
+ console.log(` Uptime: ${formatUptime(Number(uptime))}`);
3546
+ }
3547
+ console.log("");
3548
+ if (db !== undefined) {
3549
+ const dbStatus = typeof db === "object" ? db.status ?? db.ok : db;
3550
+ const dbLatency = typeof db === "object" ? db.latency_ms : undefined;
3551
+ const dbLabel = dbLatency !== undefined ? `${statusIcon(dbStatus)} ${c6.dim(`(${dbLatency}ms)`)}` : statusIcon(dbStatus);
3552
+ console.log(` Database: ${dbLabel}`);
3553
+ }
3554
+ if (cache !== undefined) {
3555
+ const cacheStatus = typeof cache === "object" ? cache.status ?? cache.ok : cache;
3556
+ const cacheLatency = typeof cache === "object" ? cache.latency_ms : undefined;
3557
+ const cacheLabel = cacheLatency !== undefined ? `${statusIcon(cacheStatus)} ${c6.dim(`(${cacheLatency}ms)`)}` : statusIcon(cacheStatus);
3558
+ console.log(` Cache: ${cacheLabel}`);
3559
+ }
3560
+ if (healthData.storage !== undefined) {
3561
+ const storageStatus = typeof healthData.storage === "object" ? healthData.storage.status ?? healthData.storage.ok : healthData.storage;
3562
+ console.log(` Storage: ${statusIcon(storageStatus)}`);
3563
+ }
3564
+ if (healthData.extensions !== undefined) {
3565
+ const extCount = typeof healthData.extensions === "number" ? healthData.extensions : Array.isArray(healthData.extensions) ? healthData.extensions.length : healthData.extensions;
3566
+ console.log(` Extensions: ${extCount} loaded`);
3567
+ }
3568
+ if (healthData.schema_version !== undefined || typeof db === "object" && db?.schema_version) {
3569
+ const sv = healthData.schema_version ?? db?.schema_version;
3570
+ console.log(` Schema: v${sv}`);
3571
+ }
3572
+ console.log("");
3573
+ }
3574
+
3575
+ // src/index.ts
3576
+ var program2 = new Command;
3577
+ program2.name("zveltio").description("The official Zveltio CLI").version("2.0.0");
3578
+ program2.command("init [dir]").description("Initialize a new Zveltio project (interactive)").option("--template <template>", "Starter template to use", "default").action(initCommand);
3579
+ program2.command("dev").description("Start Zveltio in development mode (with hot reload)").option("-p, --port <port>", "Port to listen on", "3000").option("--no-studio", "Disable Studio embed (API only)").action(devCommand);
3580
+ program2.command("start").description("Start Zveltio in production mode (uses compiled binary if available)").option("-p, --port <port>", "Port to listen on", "3000").option("--binary <path>", "Path to compiled binary").action(startCommand);
3581
+ program2.command("deploy").description("Build a Docker image and optionally push to a registry").option("--tag <tag>", "Docker image tag", "latest").option("--registry <registry>", "Container registry (e.g. ghcr.io/myorg)").option("--push", "Push image after build (auto-enabled when --registry is set)").option("--no-push", "Build only, do not push").option("--no-build", "Skip build, push existing image").option("--platform <platform>", "Target platform", "linux/amd64").option("-f, --dockerfile <path>", "Path to Dockerfile").option("--context <path>", "Docker build context", ".").option("--env <file>", "Env file to read build-args from", ".env").action(deployCommand);
3582
+ program2.addCommand(migrateCommand);
3583
+ program2.addCommand(rollbackCommand);
3584
+ program2.command("status").description("Show system status (DB, cache, uptime, version)").option("--url <url>", "Engine URL", "http://localhost:3000").option("--json", "Output as JSON").action(statusCommand);
3585
+ program2.addCommand(versionCommand);
3586
+ program2.addCommand(updateCommand);
3587
+ program2.command("create-god").description("Create the first super-admin (god) user interactively").option("--url <url>", "Engine URL", "http://localhost:3000").option("--email <email>", "Admin email (skip prompt)").option("--name <name>", "Admin name (skip prompt)").action(createGodCommand);
3588
+ var generate = program2.command("generate").description("Code generation utilities");
3589
+ generate.command("types [collection]").description("Generate TypeScript types for collections (writes to ./types/zveltio.d.ts)").option("-o, --output <path>", "Output file path", "./types/zveltio.d.ts").option("--url <url>", "Engine URL", "http://localhost:3000").action(generateTypesCommand);
3590
+ program2.command("generate-types [collection]").description("Generate TypeScript types for your collections").option("-o, --output <path>", "Output file path", "./types/zveltio.d.ts").option("--url <url>", "Engine URL", "http://localhost:3000").action(generateTypesCommand);
3591
+ program2.command("install <name>").description("Install a Zveltio extension from marketplace or local path").option("--path <path>", "Install from local directory (offline)").option("--url <url>", "Engine URL for marketplace install", "http://localhost:3000").option("--force", "Overwrite existing extension (local install only)").action((name, opts) => installCommand(name, opts));
3592
+ var extensions = program2.command("extensions").description("Manage Zveltio extensions");
3593
+ extensions.command("list").description("List all available and installed extensions").option("--url <url>", "Engine URL", "http://localhost:3000").option("--category <category>", "Filter by category").option("--json", "Output as JSON").action((opts) => extensionsListCommand(opts));
3594
+ extensions.command("install <name>").description("Install an extension from the marketplace or local path").option("--path <path>", "Install from local directory (offline)").option("--url <url>", "Engine URL", "http://localhost:3000").option("--force", "Overwrite existing extension (local install only)").action((name, opts) => installCommand(name, opts));
3595
+ extensions.command("enable <name>").description("Enable an installed extension").option("--url <url>", "Engine URL", "http://localhost:3000").action(async (name, opts) => {
3596
+ const url = opts.url || "http://localhost:3000";
3597
+ const res = await fetch(`${url}/api/marketplace/${name}/enable`, { method: "POST" }).catch(() => null);
3598
+ if (!res?.ok) {
3599
+ console.error(`Failed to enable ${name}`);
3600
+ process.exit(1);
3601
+ }
3602
+ const body = await res.json();
3603
+ console.log(body.hot_loaded ? `${name} is now active.` : `${name} will be active after restart.`);
3604
+ });
3605
+ extensions.command("disable <name>").description("Disable an active extension").option("--url <url>", "Engine URL", "http://localhost:3000").action(async (name, opts) => {
3606
+ const url = opts.url || "http://localhost:3000";
3607
+ const res = await fetch(`${url}/api/marketplace/${name}/disable`, { method: "POST" }).catch(() => null);
3608
+ if (!res?.ok) {
3609
+ console.error(`Failed to disable ${name}`);
3610
+ process.exit(1);
3611
+ }
3612
+ console.log(`${name} disabled.`);
3613
+ });
3614
+ var ext = program2.command("extension").description('Manage Zveltio extensions (use "extensions" for new commands)');
3615
+ ext.command("create <name>").description("Scaffold a new extension").option("--category <category>", "Extension category", "custom").action((name, opts) => extensionCommand("create", name, opts));
3616
+ ext.command("build").description("Build the current extension (.zvext bundle)").action(() => extensionCommand("build", "", {}));
3617
+ ext.command("dev").description("Start extension dev server with hot reload").action(() => extensionCommand("dev", "", {}));
3618
+ ext.command("publish").description("Publish extension to the Zveltio marketplace").option("--token <token>", "Marketplace auth token").action((_opts) => extensionCommand("publish", "", _opts));
3619
+ program2.parse(process.argv);