bunwright 0.1.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.
@@ -0,0 +1,1903 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // node_modules/@drizzle-team/brocli/index.js
5
+ var __create = Object.create;
6
+ var __defProp = Object.defineProperty;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __commonJS = (cb, mod) => function __require() {
12
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
23
+ var require_clone = __commonJS({
24
+ "node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js"(exports, module) {
25
+ var clone2 = function() {
26
+ function _instanceof(obj, type) {
27
+ return type != null && obj instanceof type;
28
+ }
29
+ var nativeMap;
30
+ try {
31
+ nativeMap = Map;
32
+ } catch (_) {
33
+ nativeMap = function() {};
34
+ }
35
+ var nativeSet;
36
+ try {
37
+ nativeSet = Set;
38
+ } catch (_) {
39
+ nativeSet = function() {};
40
+ }
41
+ var nativePromise;
42
+ try {
43
+ nativePromise = Promise;
44
+ } catch (_) {
45
+ nativePromise = function() {};
46
+ }
47
+ function clone3(parent, circular, depth, prototype, includeNonEnumerable) {
48
+ if (typeof circular === "object") {
49
+ depth = circular.depth;
50
+ prototype = circular.prototype;
51
+ includeNonEnumerable = circular.includeNonEnumerable;
52
+ circular = circular.circular;
53
+ }
54
+ var allParents = [];
55
+ var allChildren = [];
56
+ var useBuffer = typeof Buffer != "undefined";
57
+ if (typeof circular == "undefined")
58
+ circular = true;
59
+ if (typeof depth == "undefined")
60
+ depth = Infinity;
61
+ function _clone(parent2, depth2) {
62
+ if (parent2 === null)
63
+ return null;
64
+ if (depth2 === 0)
65
+ return parent2;
66
+ var child;
67
+ var proto;
68
+ if (typeof parent2 != "object") {
69
+ return parent2;
70
+ }
71
+ if (_instanceof(parent2, nativeMap)) {
72
+ child = new nativeMap;
73
+ } else if (_instanceof(parent2, nativeSet)) {
74
+ child = new nativeSet;
75
+ } else if (_instanceof(parent2, nativePromise)) {
76
+ child = new nativePromise(function(resolve, reject) {
77
+ parent2.then(function(value) {
78
+ resolve(_clone(value, depth2 - 1));
79
+ }, function(err) {
80
+ reject(_clone(err, depth2 - 1));
81
+ });
82
+ });
83
+ } else if (clone3.__isArray(parent2)) {
84
+ child = [];
85
+ } else if (clone3.__isRegExp(parent2)) {
86
+ child = new RegExp(parent2.source, __getRegExpFlags(parent2));
87
+ if (parent2.lastIndex)
88
+ child.lastIndex = parent2.lastIndex;
89
+ } else if (clone3.__isDate(parent2)) {
90
+ child = new Date(parent2.getTime());
91
+ } else if (useBuffer && Buffer.isBuffer(parent2)) {
92
+ if (Buffer.allocUnsafe) {
93
+ child = Buffer.allocUnsafe(parent2.length);
94
+ } else {
95
+ child = new Buffer(parent2.length);
96
+ }
97
+ parent2.copy(child);
98
+ return child;
99
+ } else if (_instanceof(parent2, Error)) {
100
+ child = Object.create(parent2);
101
+ } else {
102
+ if (typeof prototype == "undefined") {
103
+ proto = Object.getPrototypeOf(parent2);
104
+ child = Object.create(proto);
105
+ } else {
106
+ child = Object.create(prototype);
107
+ proto = prototype;
108
+ }
109
+ }
110
+ if (circular) {
111
+ var index = allParents.indexOf(parent2);
112
+ if (index != -1) {
113
+ return allChildren[index];
114
+ }
115
+ allParents.push(parent2);
116
+ allChildren.push(child);
117
+ }
118
+ if (_instanceof(parent2, nativeMap)) {
119
+ parent2.forEach(function(value, key) {
120
+ var keyChild = _clone(key, depth2 - 1);
121
+ var valueChild = _clone(value, depth2 - 1);
122
+ child.set(keyChild, valueChild);
123
+ });
124
+ }
125
+ if (_instanceof(parent2, nativeSet)) {
126
+ parent2.forEach(function(value) {
127
+ var entryChild = _clone(value, depth2 - 1);
128
+ child.add(entryChild);
129
+ });
130
+ }
131
+ for (var i in parent2) {
132
+ var attrs;
133
+ if (proto) {
134
+ attrs = Object.getOwnPropertyDescriptor(proto, i);
135
+ }
136
+ if (attrs && attrs.set == null) {
137
+ continue;
138
+ }
139
+ child[i] = _clone(parent2[i], depth2 - 1);
140
+ }
141
+ if (Object.getOwnPropertySymbols) {
142
+ var symbols = Object.getOwnPropertySymbols(parent2);
143
+ for (var i = 0;i < symbols.length; i++) {
144
+ var symbol = symbols[i];
145
+ var descriptor = Object.getOwnPropertyDescriptor(parent2, symbol);
146
+ if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
147
+ continue;
148
+ }
149
+ child[symbol] = _clone(parent2[symbol], depth2 - 1);
150
+ if (!descriptor.enumerable) {
151
+ Object.defineProperty(child, symbol, {
152
+ enumerable: false
153
+ });
154
+ }
155
+ }
156
+ }
157
+ if (includeNonEnumerable) {
158
+ var allPropertyNames = Object.getOwnPropertyNames(parent2);
159
+ for (var i = 0;i < allPropertyNames.length; i++) {
160
+ var propertyName = allPropertyNames[i];
161
+ var descriptor = Object.getOwnPropertyDescriptor(parent2, propertyName);
162
+ if (descriptor && descriptor.enumerable) {
163
+ continue;
164
+ }
165
+ child[propertyName] = _clone(parent2[propertyName], depth2 - 1);
166
+ Object.defineProperty(child, propertyName, {
167
+ enumerable: false
168
+ });
169
+ }
170
+ }
171
+ return child;
172
+ }
173
+ return _clone(parent, depth);
174
+ }
175
+ clone3.clonePrototype = function clonePrototype(parent) {
176
+ if (parent === null)
177
+ return null;
178
+ var c = function() {};
179
+ c.prototype = parent;
180
+ return new c;
181
+ };
182
+ function __objToStr(o) {
183
+ return Object.prototype.toString.call(o);
184
+ }
185
+ clone3.__objToStr = __objToStr;
186
+ function __isDate(o) {
187
+ return typeof o === "object" && __objToStr(o) === "[object Date]";
188
+ }
189
+ clone3.__isDate = __isDate;
190
+ function __isArray(o) {
191
+ return typeof o === "object" && __objToStr(o) === "[object Array]";
192
+ }
193
+ clone3.__isArray = __isArray;
194
+ function __isRegExp(o) {
195
+ return typeof o === "object" && __objToStr(o) === "[object RegExp]";
196
+ }
197
+ clone3.__isRegExp = __isRegExp;
198
+ function __getRegExpFlags(re) {
199
+ var flags = "";
200
+ if (re.global)
201
+ flags += "g";
202
+ if (re.ignoreCase)
203
+ flags += "i";
204
+ if (re.multiline)
205
+ flags += "m";
206
+ return flags;
207
+ }
208
+ clone3.__getRegExpFlags = __getRegExpFlags;
209
+ return clone3;
210
+ }();
211
+ if (typeof module === "object" && module.exports) {
212
+ module.exports = clone2;
213
+ }
214
+ }
215
+ });
216
+ var require_quote = __commonJS({
217
+ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/quote.js"(exports, module) {
218
+ module.exports = function quote(xs) {
219
+ return xs.map(function(s) {
220
+ if (s && typeof s === "object") {
221
+ return s.op.replace(/(.)/g, "\\$1");
222
+ }
223
+ if (/["\s]/.test(s) && !/'/.test(s)) {
224
+ return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
225
+ }
226
+ if (/["'\s]/.test(s)) {
227
+ return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
228
+ }
229
+ return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
230
+ }).join(" ");
231
+ };
232
+ }
233
+ });
234
+ var require_parse = __commonJS({
235
+ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/parse.js"(exports, module) {
236
+ var CONTROL = "(?:" + [
237
+ "\\|\\|",
238
+ "\\&\\&",
239
+ ";;",
240
+ "\\|\\&",
241
+ "\\<\\(",
242
+ "\\<\\<\\<",
243
+ ">>",
244
+ ">\\&",
245
+ "<\\&",
246
+ "[&;()|<>]"
247
+ ].join("|") + ")";
248
+ var controlRE = new RegExp("^" + CONTROL + "$");
249
+ var META = "|&;()<> \\t";
250
+ var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
251
+ var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
252
+ var hash = /^#$/;
253
+ var SQ = "'";
254
+ var DQ = '"';
255
+ var DS = "$";
256
+ var TOKEN = "";
257
+ var mult = 4294967296;
258
+ for (i = 0;i < 4; i++) {
259
+ TOKEN += (mult * Math.random()).toString(16);
260
+ }
261
+ var i;
262
+ var startsWithToken = new RegExp("^" + TOKEN);
263
+ function matchAll(s, r) {
264
+ var origIndex = r.lastIndex;
265
+ var matches = [];
266
+ var matchObj;
267
+ while (matchObj = r.exec(s)) {
268
+ matches.push(matchObj);
269
+ if (r.lastIndex === matchObj.index) {
270
+ r.lastIndex += 1;
271
+ }
272
+ }
273
+ r.lastIndex = origIndex;
274
+ return matches;
275
+ }
276
+ function getVar(env, pre, key) {
277
+ var r = typeof env === "function" ? env(key) : env[key];
278
+ if (typeof r === "undefined" && key != "") {
279
+ r = "";
280
+ } else if (typeof r === "undefined") {
281
+ r = "$";
282
+ }
283
+ if (typeof r === "object") {
284
+ return pre + TOKEN + JSON.stringify(r) + TOKEN;
285
+ }
286
+ return pre + r;
287
+ }
288
+ function parseInternal(string2, env, opts) {
289
+ if (!opts) {
290
+ opts = {};
291
+ }
292
+ var BS = opts.escape || "\\";
293
+ var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
294
+ var chunker = new RegExp([
295
+ "(" + CONTROL + ")",
296
+ "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"
297
+ ].join("|"), "g");
298
+ var matches = matchAll(string2, chunker);
299
+ if (matches.length === 0) {
300
+ return [];
301
+ }
302
+ if (!env) {
303
+ env = {};
304
+ }
305
+ var commented = false;
306
+ return matches.map(function(match) {
307
+ var s = match[0];
308
+ if (!s || commented) {
309
+ return;
310
+ }
311
+ if (controlRE.test(s)) {
312
+ return { op: s };
313
+ }
314
+ var quote = false;
315
+ var esc = false;
316
+ var out = "";
317
+ var isGlob = false;
318
+ var i2;
319
+ function parseEnvVar() {
320
+ i2 += 1;
321
+ var varend;
322
+ var varname;
323
+ var char = s.charAt(i2);
324
+ if (char === "{") {
325
+ i2 += 1;
326
+ if (s.charAt(i2) === "}") {
327
+ throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
328
+ }
329
+ varend = s.indexOf("}", i2);
330
+ if (varend < 0) {
331
+ throw new Error("Bad substitution: " + s.slice(i2));
332
+ }
333
+ varname = s.slice(i2, varend);
334
+ i2 = varend;
335
+ } else if (/[*@#?$!_-]/.test(char)) {
336
+ varname = char;
337
+ i2 += 1;
338
+ } else {
339
+ var slicedFromI = s.slice(i2);
340
+ varend = slicedFromI.match(/[^\w\d_]/);
341
+ if (!varend) {
342
+ varname = slicedFromI;
343
+ i2 = s.length;
344
+ } else {
345
+ varname = slicedFromI.slice(0, varend.index);
346
+ i2 += varend.index - 1;
347
+ }
348
+ }
349
+ return getVar(env, "", varname);
350
+ }
351
+ for (i2 = 0;i2 < s.length; i2++) {
352
+ var c = s.charAt(i2);
353
+ isGlob = isGlob || !quote && (c === "*" || c === "?");
354
+ if (esc) {
355
+ out += c;
356
+ esc = false;
357
+ } else if (quote) {
358
+ if (c === quote) {
359
+ quote = false;
360
+ } else if (quote == SQ) {
361
+ out += c;
362
+ } else {
363
+ if (c === BS) {
364
+ i2 += 1;
365
+ c = s.charAt(i2);
366
+ if (c === DQ || c === BS || c === DS) {
367
+ out += c;
368
+ } else {
369
+ out += BS + c;
370
+ }
371
+ } else if (c === DS) {
372
+ out += parseEnvVar();
373
+ } else {
374
+ out += c;
375
+ }
376
+ }
377
+ } else if (c === DQ || c === SQ) {
378
+ quote = c;
379
+ } else if (controlRE.test(c)) {
380
+ return { op: s };
381
+ } else if (hash.test(c)) {
382
+ commented = true;
383
+ var commentObj = { comment: string2.slice(match.index + i2 + 1) };
384
+ if (out.length) {
385
+ return [out, commentObj];
386
+ }
387
+ return [commentObj];
388
+ } else if (c === BS) {
389
+ esc = true;
390
+ } else if (c === DS) {
391
+ out += parseEnvVar();
392
+ } else {
393
+ out += c;
394
+ }
395
+ }
396
+ if (isGlob) {
397
+ return { op: "glob", pattern: out };
398
+ }
399
+ return out;
400
+ }).reduce(function(prev, arg) {
401
+ return typeof arg === "undefined" ? prev : prev.concat(arg);
402
+ }, []);
403
+ }
404
+ module.exports = function parse(s, env, opts) {
405
+ var mapped = parseInternal(s, env, opts);
406
+ if (typeof env !== "function") {
407
+ return mapped;
408
+ }
409
+ return mapped.reduce(function(acc, s2) {
410
+ if (typeof s2 === "object") {
411
+ return acc.concat(s2);
412
+ }
413
+ var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
414
+ if (xs.length === 1) {
415
+ return acc.concat(xs[0]);
416
+ }
417
+ return acc.concat(xs.filter(Boolean).map(function(x) {
418
+ if (startsWithToken.test(x)) {
419
+ return JSON.parse(x.split(TOKEN)[1]);
420
+ }
421
+ return x;
422
+ }));
423
+ }, []);
424
+ };
425
+ }
426
+ });
427
+ var require_shell_quote = __commonJS({
428
+ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/index.js"(exports) {
429
+ exports.quote = require_quote();
430
+ exports.parse = require_parse();
431
+ }
432
+ });
433
+ var BroCliError = class extends Error {
434
+ constructor(message, event) {
435
+ const errPrefix = "BroCli error: ";
436
+ super(message === undefined ? message : `${errPrefix}${message}`);
437
+ this.event = event;
438
+ }
439
+ };
440
+ var import_clone = __toESM(require_clone(), 1);
441
+ var getOptionTypeText = (option) => {
442
+ let result = "";
443
+ switch (option.type) {
444
+ case "boolean":
445
+ result = "";
446
+ break;
447
+ case "number": {
448
+ if ((option.minVal ?? option.maxVal) !== undefined) {
449
+ let text = "";
450
+ if (option.isInt)
451
+ text = text + `integer `;
452
+ if (option.minVal !== undefined)
453
+ text = text + `[${option.minVal};`;
454
+ else
455
+ text = text + `(\u221E;`;
456
+ if (option.maxVal !== undefined)
457
+ text = text + `${option.maxVal}]`;
458
+ else
459
+ text = text + `\u221E)`;
460
+ result = text;
461
+ break;
462
+ }
463
+ if (option.isInt) {
464
+ result = "integer";
465
+ break;
466
+ }
467
+ result = "number";
468
+ break;
469
+ }
470
+ case "string": {
471
+ if (option.enumVals) {
472
+ result = "[ " + option.enumVals.join(" | ") + " ]";
473
+ break;
474
+ }
475
+ result = "string";
476
+ break;
477
+ }
478
+ case "positional": {
479
+ result = `${option.isRequired ? "<" : "["}${option.enumVals ? option.enumVals.join("|") : option.name}${option.isRequired ? ">" : "]"}`;
480
+ break;
481
+ }
482
+ }
483
+ if (option.isRequired && option.type !== "positional")
484
+ result = "!" + result.length ? " " : "" + result;
485
+ return result;
486
+ };
487
+ var defaultEventHandler = async (event) => {
488
+ switch (event.type) {
489
+ case "command_help": {
490
+ const command3 = event.command;
491
+ const commandName = getCommandNameWithParents(command3);
492
+ const cliName = event.name;
493
+ const desc = command3.desc ?? command3.shortDesc;
494
+ const subs = command3.subcommands?.filter((s) => !s.hidden);
495
+ const subcommands = subs && subs.length ? subs : undefined;
496
+ if (desc !== undefined) {
497
+ console.log(`
498
+ ${desc}`);
499
+ }
500
+ const opts = Object.values(command3.options ?? {}).filter((opt) => !opt.config.isHidden);
501
+ const positionals = opts.filter((opt) => opt.config.type === "positional");
502
+ const options = opts.filter((opt) => opt.config.type !== "positional");
503
+ console.log(`
504
+ Usage:`);
505
+ if (command3.handler) {
506
+ console.log(` ${cliName ? cliName + " " : ""}${commandName}${positionals.length ? " " + positionals.map(({ config: p }) => getOptionTypeText(p)).join(" ") : ""} [flags]`);
507
+ } else
508
+ console.log(` ${cliName ? cliName + " " : ""}${commandName} [command]`);
509
+ if (command3.aliases) {
510
+ console.log(`
511
+ Aliases:`);
512
+ console.log(` ${[command3.name, ...command3.aliases].join(", ")}`);
513
+ }
514
+ if (subcommands) {
515
+ console.log(`
516
+ Available Commands:`);
517
+ const padding = 3;
518
+ const maxLength = subcommands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0);
519
+ const paddedLength = maxLength + padding;
520
+ const preDescPad = 2 + paddedLength;
521
+ const data = subcommands.map((s) => ` ${s.name.padEnd(paddedLength)}${(() => {
522
+ const description = s.shortDesc ?? s.desc;
523
+ if (!description?.length)
524
+ return "";
525
+ const split = description.split(`
526
+ `);
527
+ const first = split.shift();
528
+ const final = [first, ...split.map((s2) => "".padEnd(preDescPad) + s2)].join(`
529
+ `);
530
+ return final;
531
+ })()}`).join(`
532
+ `);
533
+ console.log(data);
534
+ }
535
+ if (options.length) {
536
+ const aliasLength = options.reduce((p, e) => {
537
+ const currentLength = e.config.aliases.reduce((pa, a) => pa + a.length, 0) + (e.config.aliases.length - 1) * 2 + 1;
538
+ return currentLength > p ? currentLength : p;
539
+ }, 0);
540
+ const paddedAliasLength = aliasLength > 0 ? aliasLength + 1 : 0;
541
+ const nameLength = options.reduce((p, e) => {
542
+ const typeLen = getOptionTypeText(e.config).length;
543
+ const length = typeLen > 0 ? e.config.name.length + 1 + typeLen : e.config.name.length;
544
+ return length > p ? length : p;
545
+ }, 0) + 3;
546
+ const preDescPad = paddedAliasLength + nameLength + 2;
547
+ const data = options.map(({ config: opt }) => ` ${`${opt.aliases.length ? opt.aliases.join(", ") + "," : ""}`.padEnd(paddedAliasLength)}${`${opt.name}${(() => {
548
+ const typeText = getOptionTypeText(opt);
549
+ return typeText.length ? " " + typeText : "";
550
+ })()}`.padEnd(nameLength)}${(() => {
551
+ if (!opt.description?.length) {
552
+ return opt.default !== undefined ? `default: ${JSON.stringify(opt.default)}` : "";
553
+ }
554
+ const split = opt.description.split(`
555
+ `);
556
+ const first = split.shift();
557
+ const def = opt.default !== undefined ? ` (default: ${JSON.stringify(opt.default)})` : "";
558
+ const final = [first, ...split.map((s) => "".padEnd(preDescPad) + s)].join(`
559
+ `) + def;
560
+ return final;
561
+ })()}`).join(`
562
+ `);
563
+ console.log(`
564
+ Flags:`);
565
+ console.log(data);
566
+ }
567
+ console.log(`
568
+ Global flags:`);
569
+ console.log(` -h, --help help for ${commandName}`);
570
+ console.log(` -v, --version version${cliName ? ` for ${cliName}` : ""}`);
571
+ if (subcommands) {
572
+ console.log(`
573
+ Use "${cliName ? cliName + " " : ""}${commandName} [command] --help" for more information about a command.
574
+ `);
575
+ }
576
+ return true;
577
+ }
578
+ case "global_help": {
579
+ const cliName = event.name;
580
+ const desc = event.description;
581
+ const commands = event.commands.filter((c) => !c.hidden);
582
+ if (desc !== undefined) {
583
+ console.log(`${desc}
584
+ `);
585
+ }
586
+ console.log("Usage:");
587
+ console.log(` ${cliName ? cliName + " " : ""}[command]`);
588
+ if (commands.length) {
589
+ console.log(`
590
+ Available Commands:`);
591
+ const padding = 3;
592
+ const maxLength = commands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0);
593
+ const paddedLength = maxLength + padding;
594
+ const data = commands.map((c) => ` ${c.name.padEnd(paddedLength)}${(() => {
595
+ const desc2 = c.shortDesc ?? c.desc;
596
+ if (!desc2?.length)
597
+ return "";
598
+ const split = desc2.split(`
599
+ `);
600
+ const first = split.shift();
601
+ const final = [first, ...split.map((s) => "".padEnd(paddedLength + 2) + s)].join(`
602
+ `);
603
+ return final;
604
+ })()}`).join(`
605
+ `);
606
+ console.log(data);
607
+ } else {
608
+ console.log(`
609
+ No available commands.`);
610
+ }
611
+ console.log(`
612
+ Flags:`);
613
+ console.log(` -h, --help help${cliName ? ` for ${cliName}` : ""}`);
614
+ console.log(` -v, --version version${cliName ? ` for ${cliName}` : ""}`);
615
+ console.log(`
616
+ `);
617
+ return true;
618
+ }
619
+ case "version": {
620
+ return true;
621
+ }
622
+ case "error": {
623
+ let msg;
624
+ switch (event.violation) {
625
+ case "above_max": {
626
+ const matchedName = event.offender.namePart;
627
+ const data = event.offender.dataPart;
628
+ const option = event.option;
629
+ const max = option.maxVal;
630
+ msg = `Invalid value: number type argument '${matchedName}' expects maximal value of ${max} as an input, got: ${data}`;
631
+ break;
632
+ }
633
+ case "below_min": {
634
+ const matchedName = event.offender.namePart;
635
+ const data = event.offender.dataPart;
636
+ const option = event.option;
637
+ const min = option.minVal;
638
+ msg = `Invalid value: number type argument '${matchedName}' expects minimal value of ${min} as an input, got: ${data}`;
639
+ break;
640
+ }
641
+ case "expected_int": {
642
+ const matchedName = event.offender.namePart;
643
+ const data = event.offender.dataPart;
644
+ msg = `Invalid value: number type argument '${matchedName}' expects an integer as an input, got: ${data}`;
645
+ break;
646
+ }
647
+ case "invalid_boolean_syntax": {
648
+ const matchedName = event.offender.namePart;
649
+ const data = event.offender.dataPart;
650
+ msg = `Invalid syntax: boolean type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value> | ${matchedName}.
651
+ Allowed values: true, false, 0, 1`;
652
+ break;
653
+ }
654
+ case "invalid_string_syntax": {
655
+ const matchedName = event.offender.namePart;
656
+ msg = `Invalid syntax: string type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
657
+ break;
658
+ }
659
+ case "invalid_number_syntax": {
660
+ const matchedName = event.offender.namePart;
661
+ msg = `Invalid syntax: number type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
662
+ break;
663
+ }
664
+ case "invalid_number_value": {
665
+ const matchedName = event.offender.namePart;
666
+ const data = event.offender.dataPart;
667
+ msg = `Invalid value: number type argument '${matchedName}' expects a number as an input, got: ${data}`;
668
+ break;
669
+ }
670
+ case "enum_violation": {
671
+ const matchedName = event.offender.namePart;
672
+ const data = event.offender.dataPart;
673
+ const option = event.option;
674
+ const values = option.enumVals;
675
+ msg = option.type === "positional" ? `Invalid value: value for the positional argument '${option.name}' must be either one of the following: ${values.join(", ")}; Received: ${data}` : `Invalid value: value for the argument '${matchedName}' must be either one of the following: ${values.join(", ")}; Received: ${data}`;
676
+ break;
677
+ }
678
+ case "unknown_command_error": {
679
+ const msg2 = `Unknown command: '${event.offender}'.
680
+ Type '--help' to get help on the cli.`;
681
+ console.error(msg2);
682
+ return true;
683
+ }
684
+ case "unknown_subcommand_error": {
685
+ const cName = getCommandNameWithParents(event.command);
686
+ const msg2 = `Unknown command: ${cName} ${event.offender}.
687
+ Type '${cName} --help' to get the help on command.`;
688
+ console.error(msg2);
689
+ return true;
690
+ }
691
+ case "missing_args_error": {
692
+ const { missing: missingOpts, command: command3 } = event;
693
+ msg = `Command '${command3.name}' is missing following required options: ${missingOpts.map((opt) => {
694
+ const name = opt.shift();
695
+ const aliases = opt;
696
+ if (aliases.length)
697
+ return `${name} [${aliases.join(", ")}]`;
698
+ return name;
699
+ }).join(", ")}`;
700
+ break;
701
+ }
702
+ case "unrecognized_args_error": {
703
+ const { command: command3, unrecognized } = event;
704
+ msg = `Unrecognized options for command '${command3.name}': ${unrecognized.join(", ")}`;
705
+ break;
706
+ }
707
+ case "unknown_error": {
708
+ const e = event.error;
709
+ console.error(typeof e === "object" && e !== null && "message" in e ? e.message : e);
710
+ return true;
711
+ }
712
+ }
713
+ console.error(msg);
714
+ return true;
715
+ }
716
+ }
717
+ return false;
718
+ };
719
+ var eventHandlerWrapper = (customEventHandler) => async (event) => await customEventHandler(event) ? true : await defaultEventHandler(event);
720
+ var import_shell_quote = __toESM(require_shell_quote(), 1);
721
+ function isInt(value) {
722
+ return value === Math.floor(value);
723
+ }
724
+ var executeOrLog = async (target) => typeof target === "string" ? console.log(target) : target ? await target() : undefined;
725
+ var generatePrefix = (name) => name.startsWith("-") ? name : name.length > 1 ? `--${name}` : `-${name}`;
726
+ var validateOptions = (config) => {
727
+ const cloned = (0, import_clone.default)(config);
728
+ const entries = [];
729
+ const storedNames = [];
730
+ const cfgEntries = Object.entries(cloned);
731
+ for (const [key, value] of cfgEntries) {
732
+ const cfg = value._.config;
733
+ if (cfg.name === undefined)
734
+ cfg.name = key;
735
+ if (cfg.type === "positional")
736
+ continue;
737
+ if (cfg.name.includes("=")) {
738
+ throw new BroCliError(`Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`);
739
+ }
740
+ for (const alias of cfg.aliases) {
741
+ if (alias.includes("=")) {
742
+ throw new BroCliError(`Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`);
743
+ }
744
+ }
745
+ cfg.name = generatePrefix(cfg.name);
746
+ cfg.aliases = cfg.aliases.map((a) => generatePrefix(a));
747
+ }
748
+ for (const [key, value] of cfgEntries) {
749
+ const cfg = value._.config;
750
+ if (cfg.type === "positional") {
751
+ entries.push([key, { config: cfg, $output: undefined }]);
752
+ continue;
753
+ }
754
+ const reservedNames = ["--help", "-h", "--version", "-v"];
755
+ const allNames = [cfg.name, ...cfg.aliases];
756
+ for (const name of allNames) {
757
+ const match = reservedNames.find((n) => n === name);
758
+ if (match)
759
+ throw new BroCliError(`Can't define option '${cfg.name}' - name '${match}' is reserved!`);
760
+ }
761
+ for (const storage of storedNames) {
762
+ const nameOccupier = storage.find((e) => e === cfg.name);
763
+ if (!nameOccupier)
764
+ continue;
765
+ throw new BroCliError(`Can't define option '${cfg.name}' - name is already in use by option '${storage[0]}'!`);
766
+ }
767
+ for (const alias of cfg.aliases) {
768
+ for (const storage of storedNames) {
769
+ const nameOccupier = storage.find((e) => e === alias);
770
+ if (!nameOccupier)
771
+ continue;
772
+ throw new BroCliError(`Can't define option '${cfg.name}' - alias '${alias}' is already in use by option '${storage[0]}'!`);
773
+ }
774
+ }
775
+ const currentNames = [cfg.name, ...cfg.aliases];
776
+ storedNames.push(currentNames);
777
+ currentNames.forEach((name, idx) => {
778
+ if (currentNames.findIndex((e) => e === name) === idx)
779
+ return;
780
+ throw new BroCliError(`Can't define option '${cfg.name}' - duplicate alias '${name}'!`);
781
+ });
782
+ entries.push([key, { config: cfg, $output: undefined }]);
783
+ }
784
+ return Object.fromEntries(entries);
785
+ };
786
+ var assignParent = (parent, subcommands) => subcommands.forEach((e) => {
787
+ e.parent = parent;
788
+ if (e.subcommands)
789
+ assignParent(e, e.subcommands);
790
+ });
791
+ var command2 = (command3) => {
792
+ const allNames = command3.aliases ? [command3.name, ...command3.aliases] : [command3.name];
793
+ const cmd = (0, import_clone.default)(command3);
794
+ if (command3.subcommands && command3.options && Object.values(command3.options).find((opt) => opt._.config.type === "positional")) {
795
+ throw new BroCliError(`Can't define command '${cmd.name}' - command can't have subcommands and positional args at the same time!`);
796
+ }
797
+ if (!command3.handler && !command3.subcommands) {
798
+ throw new BroCliError(`Can't define command '${cmd.name}' - command without subcommands must have a handler present!`);
799
+ }
800
+ const processedOptions = command3.options ? validateOptions(command3.options) : undefined;
801
+ cmd.options = processedOptions;
802
+ cmd.name = cmd.name ?? cmd.aliases?.shift();
803
+ if (!cmd.name)
804
+ throw new BroCliError(`Can't define command without name!`);
805
+ cmd.aliases = cmd.aliases?.length ? cmd.aliases : undefined;
806
+ if (cmd.name.startsWith("-")) {
807
+ throw new BroCliError(`Can't define command '${cmd.name}' - command name can't start with '-'!`);
808
+ }
809
+ cmd.aliases?.forEach((a) => {
810
+ if (a.startsWith("-")) {
811
+ throw new BroCliError(`Can't define command '${cmd.name}' - command aliases can't start with '-'!`);
812
+ }
813
+ });
814
+ allNames.forEach((n, i) => {
815
+ if (n === "help") {
816
+ throw new BroCliError(`Can't define command '${cmd.name}' - 'help' is a reserved name. If you want to redefine help message - do so in runCli's config.`);
817
+ }
818
+ const lCaseName = n?.toLowerCase();
819
+ if (lCaseName === "0" || lCaseName === "1" || lCaseName === "true" || lCaseName === "false") {
820
+ throw new BroCliError(`Can't define command '${cmd.name}' - '${n}' is a reserved for boolean values name!`);
821
+ }
822
+ const idx = allNames.findIndex((an) => an === n);
823
+ if (idx !== i)
824
+ throw new BroCliError(`Can't define command '${cmd.name}' - duplicate alias '${n}'!`);
825
+ });
826
+ if (cmd.subcommands) {
827
+ assignParent(cmd, cmd.subcommands);
828
+ }
829
+ return cmd;
830
+ };
831
+ var getCommandInner = (commands, candidates, args, cliName, cliDescription) => {
832
+ const { data: arg, originalIndex: index } = candidates.shift();
833
+ const command3 = commands.find((c) => {
834
+ const names = c.aliases ? [c.name, ...c.aliases] : [c.name];
835
+ const res = names.find((name) => name === arg);
836
+ return res;
837
+ });
838
+ if (!command3) {
839
+ return {
840
+ command: command3,
841
+ args
842
+ };
843
+ }
844
+ const newArgs = removeByIndex(args, index);
845
+ if (!candidates.length || !command3.subcommands) {
846
+ return {
847
+ command: command3,
848
+ args: newArgs
849
+ };
850
+ }
851
+ const newCandidates = candidates.map((c) => ({ data: c.data, originalIndex: c.originalIndex - 1 }));
852
+ const subcommand = getCommandInner(command3.subcommands, newCandidates, newArgs, cliName, cliDescription);
853
+ if (!subcommand.command) {
854
+ throw new BroCliError(undefined, {
855
+ type: "error",
856
+ violation: "unknown_subcommand_error",
857
+ name: cliName,
858
+ description: cliDescription,
859
+ command: command3,
860
+ offender: candidates[0].data
861
+ });
862
+ }
863
+ return subcommand;
864
+ };
865
+ var getCommand = (commands, args, cliName, cliDescription) => {
866
+ const candidates = [];
867
+ for (let i = 0;i < args.length; ++i) {
868
+ const arg = args[i];
869
+ if (arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v") {
870
+ const lCaseNext = args[i + 1]?.toLowerCase();
871
+ if (lCaseNext === "0" || lCaseNext === "1" || lCaseNext === "true" || lCaseNext === "false")
872
+ ++i;
873
+ continue;
874
+ }
875
+ if (arg?.startsWith("-")) {
876
+ if (!arg.includes("="))
877
+ ++i;
878
+ continue;
879
+ }
880
+ candidates.push({
881
+ data: arg,
882
+ originalIndex: i
883
+ });
884
+ }
885
+ if (!candidates.length) {
886
+ return {
887
+ command: undefined,
888
+ args
889
+ };
890
+ }
891
+ const firstCandidate = candidates[0];
892
+ if (firstCandidate.data === "help") {
893
+ return {
894
+ command: "help",
895
+ args: removeByIndex(args, firstCandidate.originalIndex)
896
+ };
897
+ }
898
+ const { command: command3, args: argsRes } = getCommandInner(commands, candidates, args, cliName, cliDescription);
899
+ if (!command3) {
900
+ throw new BroCliError(undefined, {
901
+ type: "error",
902
+ violation: "unknown_command_error",
903
+ commands,
904
+ name: cliName,
905
+ description: cliDescription,
906
+ offender: firstCandidate.data
907
+ });
908
+ }
909
+ return {
910
+ command: command3,
911
+ args: argsRes
912
+ };
913
+ };
914
+ var parseArg = (command3, options, positionals, arg, nextArg, cliName, cliDescription) => {
915
+ let data = undefined;
916
+ const argSplit = arg.split("=");
917
+ const hasEq = arg.includes("=");
918
+ const namePart = argSplit.shift();
919
+ const dataPart = hasEq ? argSplit.join("=") : nextArg;
920
+ let skipNext = !hasEq;
921
+ if (namePart === "--help" || namePart === "-h") {
922
+ return {
923
+ isHelp: true
924
+ };
925
+ }
926
+ if (namePart === "--version" || namePart === "-v") {
927
+ return {
928
+ isVersion: true
929
+ };
930
+ }
931
+ if (!arg.startsWith("-")) {
932
+ if (!positionals.length)
933
+ return {};
934
+ const pos = positionals.shift();
935
+ if (pos[1].enumVals && !pos[1].enumVals.find((val) => val === arg)) {
936
+ throw new BroCliError(undefined, {
937
+ type: "error",
938
+ name: cliName,
939
+ description: cliDescription,
940
+ violation: "enum_violation",
941
+ command: command3,
942
+ option: pos[1],
943
+ offender: {
944
+ dataPart: arg
945
+ }
946
+ });
947
+ }
948
+ data = arg;
949
+ return {
950
+ data,
951
+ skipNext: false,
952
+ name: pos[0],
953
+ option: pos[1]
954
+ };
955
+ }
956
+ const option = options.find(([optKey, opt]) => {
957
+ const names = [opt.name, ...opt.aliases];
958
+ if (opt.type === "boolean") {
959
+ const match = names.find((name) => name === namePart);
960
+ if (!match)
961
+ return false;
962
+ let lcaseData = dataPart?.toLowerCase();
963
+ if (!hasEq && nextArg?.startsWith("-")) {
964
+ data = true;
965
+ skipNext = false;
966
+ return true;
967
+ }
968
+ if (lcaseData === undefined || lcaseData === "" || lcaseData === "true" || lcaseData === "1") {
969
+ data = true;
970
+ return true;
971
+ }
972
+ if (lcaseData === "false" || lcaseData === "0") {
973
+ data = false;
974
+ return true;
975
+ }
976
+ if (!hasEq) {
977
+ data = true;
978
+ skipNext = false;
979
+ return true;
980
+ }
981
+ throw new BroCliError(undefined, {
982
+ type: "error",
983
+ name: cliName,
984
+ description: cliDescription,
985
+ violation: "invalid_boolean_syntax",
986
+ option: opt,
987
+ command: command3,
988
+ offender: {
989
+ namePart,
990
+ dataPart
991
+ }
992
+ });
993
+ } else {
994
+ const match = names.find((name) => name === namePart);
995
+ if (!match)
996
+ return false;
997
+ if (opt.type === "string") {
998
+ if (!hasEq && nextArg === undefined) {
999
+ throw new BroCliError(undefined, {
1000
+ type: "error",
1001
+ name: cliName,
1002
+ description: cliDescription,
1003
+ violation: "invalid_string_syntax",
1004
+ option: opt,
1005
+ command: command3,
1006
+ offender: {
1007
+ namePart,
1008
+ dataPart
1009
+ }
1010
+ });
1011
+ }
1012
+ if (opt.enumVals && !opt.enumVals.find((val) => val === dataPart)) {
1013
+ throw new BroCliError(undefined, {
1014
+ type: "error",
1015
+ name: cliName,
1016
+ description: cliDescription,
1017
+ violation: "enum_violation",
1018
+ option: opt,
1019
+ command: command3,
1020
+ offender: {
1021
+ namePart,
1022
+ dataPart
1023
+ }
1024
+ });
1025
+ }
1026
+ data = dataPart;
1027
+ return true;
1028
+ }
1029
+ if (!hasEq && nextArg === undefined) {
1030
+ throw new BroCliError(undefined, {
1031
+ type: "error",
1032
+ name: cliName,
1033
+ description: cliDescription,
1034
+ violation: "invalid_number_syntax",
1035
+ option: opt,
1036
+ command: command3,
1037
+ offender: {
1038
+ namePart,
1039
+ dataPart
1040
+ }
1041
+ });
1042
+ }
1043
+ const numData = Number(dataPart);
1044
+ if (isNaN(numData)) {
1045
+ throw new BroCliError(undefined, {
1046
+ type: "error",
1047
+ name: cliName,
1048
+ description: cliDescription,
1049
+ violation: "invalid_number_value",
1050
+ option: opt,
1051
+ command: command3,
1052
+ offender: {
1053
+ namePart,
1054
+ dataPart
1055
+ }
1056
+ });
1057
+ }
1058
+ if (opt.isInt && !isInt(numData)) {
1059
+ throw new BroCliError(undefined, {
1060
+ type: "error",
1061
+ name: cliName,
1062
+ description: cliDescription,
1063
+ violation: "expected_int",
1064
+ option: opt,
1065
+ command: command3,
1066
+ offender: {
1067
+ namePart,
1068
+ dataPart
1069
+ }
1070
+ });
1071
+ }
1072
+ if (opt.minVal !== undefined && numData < opt.minVal) {
1073
+ throw new BroCliError(undefined, {
1074
+ type: "error",
1075
+ name: cliName,
1076
+ description: cliDescription,
1077
+ violation: "below_min",
1078
+ option: opt,
1079
+ command: command3,
1080
+ offender: {
1081
+ namePart,
1082
+ dataPart
1083
+ }
1084
+ });
1085
+ }
1086
+ if (opt.maxVal !== undefined && numData > opt.maxVal) {
1087
+ throw new BroCliError(undefined, {
1088
+ type: "error",
1089
+ name: cliName,
1090
+ description: cliDescription,
1091
+ violation: "above_max",
1092
+ option: opt,
1093
+ command: command3,
1094
+ offender: {
1095
+ namePart,
1096
+ dataPart
1097
+ }
1098
+ });
1099
+ }
1100
+ data = numData;
1101
+ return true;
1102
+ }
1103
+ });
1104
+ return {
1105
+ data,
1106
+ skipNext,
1107
+ name: option?.[0],
1108
+ option: option?.[1]
1109
+ };
1110
+ };
1111
+ var parseOptions = (command3, args, cliName, cliDescription, omitKeysOfUndefinedOptions) => {
1112
+ const options = command3.options;
1113
+ const optEntries = Object.entries(options ?? {}).map((opt) => [opt[0], opt[1].config]);
1114
+ const nonPositionalEntries = optEntries.filter(([key, opt]) => opt.type !== "positional");
1115
+ const positionalEntries = optEntries.filter(([key, opt]) => opt.type === "positional");
1116
+ const result = {};
1117
+ const missingRequiredArr = [];
1118
+ const unrecognizedArgsArr = [];
1119
+ for (let i = 0;i < args.length; ++i) {
1120
+ const arg = args[i];
1121
+ const nextArg = args[i + 1];
1122
+ const {
1123
+ data,
1124
+ name,
1125
+ option,
1126
+ skipNext,
1127
+ isHelp,
1128
+ isVersion
1129
+ } = parseArg(command3, nonPositionalEntries, positionalEntries, arg, nextArg, cliName, cliDescription);
1130
+ if (!option)
1131
+ unrecognizedArgsArr.push(arg.split("=")[0]);
1132
+ if (skipNext)
1133
+ ++i;
1134
+ if (isHelp)
1135
+ return "help";
1136
+ if (isVersion)
1137
+ return "version";
1138
+ result[name] = data;
1139
+ }
1140
+ for (const [optKey, option] of optEntries) {
1141
+ const data = result[optKey] ?? option.default;
1142
+ if (!omitKeysOfUndefinedOptions) {
1143
+ result[optKey] = data;
1144
+ } else {
1145
+ if (data !== undefined)
1146
+ result[optKey] = data;
1147
+ }
1148
+ if (option.isRequired && result[optKey] === undefined)
1149
+ missingRequiredArr.push([option.name, ...option.aliases]);
1150
+ }
1151
+ if (missingRequiredArr.length) {
1152
+ throw new BroCliError(undefined, {
1153
+ type: "error",
1154
+ violation: "missing_args_error",
1155
+ name: cliName,
1156
+ description: cliDescription,
1157
+ command: command3,
1158
+ missing: missingRequiredArr
1159
+ });
1160
+ }
1161
+ if (unrecognizedArgsArr.length) {
1162
+ throw new BroCliError(undefined, {
1163
+ type: "error",
1164
+ violation: "unrecognized_args_error",
1165
+ name: cliName,
1166
+ description: cliDescription,
1167
+ command: command3,
1168
+ unrecognized: unrecognizedArgsArr
1169
+ });
1170
+ }
1171
+ return Object.keys(result).length ? result : undefined;
1172
+ };
1173
+ var getCommandNameWithParents = (command3) => command3.parent ? `${getCommandNameWithParents(command3.parent)} ${command3.name}` : command3.name;
1174
+ var validateCommands = (commands, parent) => {
1175
+ const storedNames = {};
1176
+ for (const cmd of commands) {
1177
+ const storageVals = Object.values(storedNames);
1178
+ for (const storage of storageVals) {
1179
+ const nameOccupier = storage.find((e) => e === cmd.name);
1180
+ if (!nameOccupier)
1181
+ continue;
1182
+ throw new BroCliError(`Can't define command '${getCommandNameWithParents(cmd)}': name is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`);
1183
+ }
1184
+ if (cmd.aliases) {
1185
+ for (const alias of cmd.aliases) {
1186
+ for (const storage of storageVals) {
1187
+ const nameOccupier = storage.find((e) => e === alias);
1188
+ if (!nameOccupier)
1189
+ continue;
1190
+ throw new BroCliError(`Can't define command '${getCommandNameWithParents(cmd)}': alias '${alias}' is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`);
1191
+ }
1192
+ }
1193
+ }
1194
+ storedNames[cmd.name] = cmd.aliases ? [cmd.name, ...cmd.aliases] : [cmd.name];
1195
+ if (cmd.subcommands)
1196
+ cmd.subcommands = validateCommands(cmd.subcommands, cmd);
1197
+ }
1198
+ return commands;
1199
+ };
1200
+ var removeByIndex = (arr, idx) => [...arr.slice(0, idx), ...arr.slice(idx + 1, arr.length)];
1201
+ var run = async (commands, config) => {
1202
+ const eventHandler = config?.theme ? eventHandlerWrapper(config.theme) : defaultEventHandler;
1203
+ const argSource = config?.argSource ?? process.argv;
1204
+ const version = config?.version;
1205
+ const help = config?.help;
1206
+ const omitKeysOfUndefinedOptions = config?.omitKeysOfUndefinedOptions ?? false;
1207
+ const cliName = config?.name;
1208
+ const cliDescription = config?.description;
1209
+ try {
1210
+ const processedCmds = validateCommands(commands);
1211
+ let args = argSource.slice(2, argSource.length);
1212
+ if (!args.length) {
1213
+ return help !== undefined ? await executeOrLog(help) : await eventHandler({
1214
+ type: "global_help",
1215
+ description: cliDescription,
1216
+ name: cliName,
1217
+ commands: processedCmds
1218
+ });
1219
+ }
1220
+ const helpIndex = args.findIndex((arg) => arg === "--help" || arg === "-h");
1221
+ if (helpIndex !== -1 && (helpIndex > 0 ? args[helpIndex - 1]?.startsWith("-") && !args[helpIndex - 1].includes("=") ? false : true : true)) {
1222
+ const command4 = getCommand(processedCmds, args, cliName, cliDescription).command;
1223
+ if (typeof command4 === "object") {
1224
+ return command4.help !== undefined ? await executeOrLog(command4.help) : await eventHandler({
1225
+ type: "command_help",
1226
+ description: cliDescription,
1227
+ name: cliName,
1228
+ command: command4
1229
+ });
1230
+ } else {
1231
+ return help !== undefined ? await executeOrLog(help) : await eventHandler({
1232
+ type: "global_help",
1233
+ description: cliDescription,
1234
+ name: cliName,
1235
+ commands: processedCmds
1236
+ });
1237
+ }
1238
+ }
1239
+ const versionIndex = args.findIndex((arg) => arg === "--version" || arg === "-v");
1240
+ if (versionIndex !== -1 && (versionIndex > 0 ? args[versionIndex - 1]?.startsWith("-") ? false : true : true)) {
1241
+ return version !== undefined ? await executeOrLog(version) : await eventHandler({
1242
+ type: "version",
1243
+ name: cliName,
1244
+ description: cliDescription
1245
+ });
1246
+ }
1247
+ const { command: command3, args: newArgs } = getCommand(processedCmds, args, cliName, cliDescription);
1248
+ if (!command3) {
1249
+ return help !== undefined ? await executeOrLog(help) : await eventHandler({
1250
+ type: "global_help",
1251
+ description: cliDescription,
1252
+ name: cliName,
1253
+ commands: processedCmds
1254
+ });
1255
+ }
1256
+ if (command3 === "help") {
1257
+ let helpCommand;
1258
+ let newestArgs = newArgs;
1259
+ do {
1260
+ const res = getCommand(processedCmds, newestArgs, cliName, cliDescription);
1261
+ helpCommand = res.command;
1262
+ newestArgs = res.args;
1263
+ } while (helpCommand === "help");
1264
+ return helpCommand ? helpCommand.help !== undefined ? await executeOrLog(helpCommand.help) : await eventHandler({
1265
+ type: "command_help",
1266
+ description: cliDescription,
1267
+ name: cliName,
1268
+ command: helpCommand
1269
+ }) : help !== undefined ? await executeOrLog(help) : await eventHandler({
1270
+ type: "global_help",
1271
+ description: cliDescription,
1272
+ name: cliName,
1273
+ commands: processedCmds
1274
+ });
1275
+ }
1276
+ const optionResult = parseOptions(command3, newArgs, cliName, cliDescription, omitKeysOfUndefinedOptions);
1277
+ if (optionResult === "help") {
1278
+ return command3.help !== undefined ? await executeOrLog(command3.help) : await eventHandler({
1279
+ type: "command_help",
1280
+ description: cliDescription,
1281
+ name: cliName,
1282
+ command: command3
1283
+ });
1284
+ }
1285
+ if (optionResult === "version") {
1286
+ return version !== undefined ? await executeOrLog(version) : await eventHandler({
1287
+ type: "version",
1288
+ name: cliName,
1289
+ description: cliDescription
1290
+ });
1291
+ }
1292
+ if (command3.handler) {
1293
+ if (config?.hook)
1294
+ await config.hook("before", command3);
1295
+ await command3.handler(command3.transform ? await command3.transform(optionResult) : optionResult);
1296
+ if (config?.hook)
1297
+ await config.hook("after", command3);
1298
+ return;
1299
+ } else {
1300
+ return command3.help !== undefined ? await executeOrLog(command3.help) : await eventHandler({
1301
+ type: "command_help",
1302
+ description: cliDescription,
1303
+ name: cliName,
1304
+ command: command3
1305
+ });
1306
+ }
1307
+ } catch (e) {
1308
+ if (e instanceof BroCliError) {
1309
+ if (e.event)
1310
+ await eventHandler(e.event);
1311
+ else {
1312
+ if (!config?.noExit)
1313
+ console.error(e.message);
1314
+ else
1315
+ return e.message;
1316
+ }
1317
+ } else {
1318
+ await eventHandler({
1319
+ type: "error",
1320
+ violation: "unknown_error",
1321
+ name: cliName,
1322
+ description: cliDescription,
1323
+ error: e
1324
+ });
1325
+ }
1326
+ if (!config?.noExit)
1327
+ process.exit(1);
1328
+ return;
1329
+ }
1330
+ };
1331
+ var OptionBuilderBase = class _OptionBuilderBase {
1332
+ _;
1333
+ config = () => this._.config;
1334
+ constructor(config) {
1335
+ this._ = {
1336
+ config: config ?? {
1337
+ aliases: [],
1338
+ type: "string"
1339
+ },
1340
+ $output: undefined
1341
+ };
1342
+ }
1343
+ string(name) {
1344
+ const config = this.config();
1345
+ return new _OptionBuilderBase({ ...config, type: "string", name });
1346
+ }
1347
+ number(name) {
1348
+ const config = this.config();
1349
+ return new _OptionBuilderBase({ ...config, type: "number", name });
1350
+ }
1351
+ boolean(name) {
1352
+ const config = this.config();
1353
+ return new _OptionBuilderBase({ ...config, type: "boolean", name });
1354
+ }
1355
+ positional(displayName) {
1356
+ const config = this.config();
1357
+ return new _OptionBuilderBase({ ...config, type: "positional", name: displayName });
1358
+ }
1359
+ alias(...aliases) {
1360
+ const config = this.config();
1361
+ return new _OptionBuilderBase({ ...config, aliases });
1362
+ }
1363
+ desc(description) {
1364
+ const config = this.config();
1365
+ return new _OptionBuilderBase({ ...config, description });
1366
+ }
1367
+ hidden() {
1368
+ const config = this.config();
1369
+ return new _OptionBuilderBase({ ...config, isHidden: true });
1370
+ }
1371
+ required() {
1372
+ const config = this.config();
1373
+ return new _OptionBuilderBase({ ...config, isRequired: true });
1374
+ }
1375
+ default(value) {
1376
+ const config = this.config();
1377
+ const enums = config.enumVals;
1378
+ if (enums && !enums.find((v) => value === v)) {
1379
+ throw new Error(`Option enums [ ${enums.join(", ")} ] are incompatible with default value ${value}`);
1380
+ }
1381
+ return new _OptionBuilderBase({ ...config, default: value });
1382
+ }
1383
+ enum(...values) {
1384
+ const config = this.config();
1385
+ const defaultVal = config.default;
1386
+ if (defaultVal !== undefined && !values.find((v) => defaultVal === v)) {
1387
+ throw new Error(`Option enums [ ${values.join(", ")} ] are incompatible with default value ${defaultVal}`);
1388
+ }
1389
+ return new _OptionBuilderBase({ ...config, enumVals: values });
1390
+ }
1391
+ min(value) {
1392
+ const config = this.config();
1393
+ const maxVal = config.maxVal;
1394
+ if (maxVal !== undefined && maxVal < value) {
1395
+ throw new BroCliError("Unable to define option's min value to be higher than max value!");
1396
+ }
1397
+ return new _OptionBuilderBase({ ...config, minVal: value });
1398
+ }
1399
+ max(value) {
1400
+ const config = this.config();
1401
+ const minVal = config.minVal;
1402
+ if (minVal !== undefined && minVal > value) {
1403
+ throw new BroCliError("Unable to define option's max value to be lower than min value!");
1404
+ }
1405
+ return new _OptionBuilderBase({ ...config, maxVal: value });
1406
+ }
1407
+ int() {
1408
+ const config = this.config();
1409
+ return new _OptionBuilderBase({ ...config, isInt: true });
1410
+ }
1411
+ };
1412
+ function string(name) {
1413
+ return typeof name === "string" ? new OptionBuilderBase().string(name) : new OptionBuilderBase().string();
1414
+ }
1415
+
1416
+ // src/bunwright.ts
1417
+ var CLI_VERSION = "0.2.0";
1418
+ var MAX_STEP_ATTEMPTS = 3;
1419
+ var DEFAULT_WIDTH = 1280;
1420
+ var DEFAULT_HEIGHT = 800;
1421
+ var DEFAULT_BACKEND = "chrome";
1422
+ var POST_RUN_DELAY_MS = 1e4;
1423
+ var CLI_NAME = "bunwright";
1424
+ var CLI_DESCRIPTION = "JSON-driven Bun.WebView automation CLI";
1425
+ function fail(error) {
1426
+ console.error(JSON.stringify({ ok: false, error }));
1427
+ process.exit(1);
1428
+ }
1429
+ function sleep(ms) {
1430
+ return Bun.sleep(ms);
1431
+ }
1432
+ function isRecord(value) {
1433
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1434
+ }
1435
+ function isNumber(value) {
1436
+ return typeof value === "number" && Number.isFinite(value);
1437
+ }
1438
+ function isPositiveNumber(value) {
1439
+ return isNumber(value) && value > 0;
1440
+ }
1441
+ function isNonNegativeNumber(value) {
1442
+ return isNumber(value) && value >= 0;
1443
+ }
1444
+ function isString(value) {
1445
+ return typeof value === "string";
1446
+ }
1447
+ function renderHelp() {
1448
+ return `Usage:
1449
+ ${CLI_NAME} --file instructions.json
1450
+ ${CLI_NAME} --instructions '{"steps":[...]}'
1451
+
1452
+ Options:
1453
+ --file <path> Read instructions from a JSON file
1454
+ --instructions <json> Read instructions from an inline JSON string
1455
+ --help Show this message
1456
+ --version Show the CLI version`;
1457
+ }
1458
+ function printHelp() {
1459
+ console.log(renderHelp());
1460
+ }
1461
+ function normalizeArgumentError(error) {
1462
+ if (error instanceof Error && error.message) {
1463
+ return error.message;
1464
+ }
1465
+ return "Invalid CLI arguments.";
1466
+ }
1467
+ function formatCliError(event) {
1468
+ switch (event.violation) {
1469
+ case "unrecognized_args_error":
1470
+ return `Unknown argument: ${event.unrecognized?.[0] ?? "<unknown>"}`;
1471
+ case "unknown_command_error":
1472
+ case "unknown_subcommand_error":
1473
+ return `Unknown argument: ${typeof event.offender === "string" ? event.offender : "<unknown>"}`;
1474
+ case "missing_args_error":
1475
+ return `Missing required argument: ${event.missing?.[0]?.join("/") ?? "<unknown>"}`;
1476
+ case "invalid_boolean_syntax":
1477
+ case "invalid_string_syntax":
1478
+ case "invalid_number_syntax":
1479
+ case "invalid_number_value":
1480
+ case "above_max":
1481
+ case "below_min":
1482
+ case "expected_int":
1483
+ case "enum_violation": {
1484
+ const offender = typeof event.offender === "object" ? event.offender.namePart ?? event.offender.dataPart ?? "<unknown>" : event.offender;
1485
+ return `Invalid value for argument: ${offender}`;
1486
+ }
1487
+ default:
1488
+ return "Invalid CLI arguments.";
1489
+ }
1490
+ }
1491
+ async function loadInstructionSource(args) {
1492
+ const hasFile = isString(args.file);
1493
+ const hasInstructions = isString(args.instructions);
1494
+ if (hasFile === hasInstructions) {
1495
+ fail({
1496
+ code: "ARGUMENT_ERROR",
1497
+ message: "Provide exactly one of --file or --instructions."
1498
+ });
1499
+ }
1500
+ try {
1501
+ if (hasFile) {
1502
+ const filePath = args.file;
1503
+ if (!isString(filePath)) {
1504
+ fail({
1505
+ code: "ARGUMENT_ERROR",
1506
+ message: "`--file` requires a path."
1507
+ });
1508
+ }
1509
+ return JSON.parse(await Bun.file(filePath).text());
1510
+ }
1511
+ const instructions = args.instructions;
1512
+ if (!isString(instructions)) {
1513
+ fail({
1514
+ code: "ARGUMENT_ERROR",
1515
+ message: "`--instructions` requires a JSON string."
1516
+ });
1517
+ }
1518
+ return JSON.parse(instructions);
1519
+ } catch (error) {
1520
+ fail({
1521
+ code: "ARGUMENT_ERROR",
1522
+ message: "Failed to parse instruction JSON.",
1523
+ details: error instanceof Error ? error.message : error
1524
+ });
1525
+ }
1526
+ }
1527
+ function validateBackend(value) {
1528
+ if (value === "chrome" || value === "webkit") {
1529
+ return true;
1530
+ }
1531
+ if (!isRecord(value)) {
1532
+ return false;
1533
+ }
1534
+ if (value.type !== "chrome") {
1535
+ return false;
1536
+ }
1537
+ if (value.path !== undefined && !isString(value.path)) {
1538
+ return false;
1539
+ }
1540
+ if (value.argv !== undefined && (!Array.isArray(value.argv) || value.argv.some((item) => !isString(item)))) {
1541
+ return false;
1542
+ }
1543
+ return true;
1544
+ }
1545
+ function validateConfig(config) {
1546
+ if (config === undefined) {
1547
+ return;
1548
+ }
1549
+ if (!isRecord(config)) {
1550
+ fail({
1551
+ code: "VALIDATION_ERROR",
1552
+ message: "`config` must be an object."
1553
+ });
1554
+ }
1555
+ if (config.backend !== undefined && !validateBackend(config.backend)) {
1556
+ fail({
1557
+ code: "VALIDATION_ERROR",
1558
+ message: "`config.backend` must be `chrome`, `webkit`, or a chrome backend object.",
1559
+ details: config.backend
1560
+ });
1561
+ }
1562
+ if (config.width !== undefined && !isPositiveNumber(config.width)) {
1563
+ fail({
1564
+ code: "VALIDATION_ERROR",
1565
+ message: "`config.width` must be a positive number.",
1566
+ details: config.width
1567
+ });
1568
+ }
1569
+ if (config.height !== undefined && !isPositiveNumber(config.height)) {
1570
+ fail({
1571
+ code: "VALIDATION_ERROR",
1572
+ message: "`config.height` must be a positive number.",
1573
+ details: config.height
1574
+ });
1575
+ }
1576
+ if (config.url !== undefined && !isString(config.url)) {
1577
+ fail({
1578
+ code: "VALIDATION_ERROR",
1579
+ message: "`config.url` must be a string.",
1580
+ details: config.url
1581
+ });
1582
+ }
1583
+ if (config.console !== undefined && typeof config.console !== "boolean") {
1584
+ fail({
1585
+ code: "VALIDATION_ERROR",
1586
+ message: "`config.console` must be a boolean.",
1587
+ details: config.console
1588
+ });
1589
+ }
1590
+ if (config.dataStore !== undefined) {
1591
+ const { dataStore } = config;
1592
+ if (dataStore !== "ephemeral") {
1593
+ if (!isRecord(dataStore) || !isString(dataStore.directory)) {
1594
+ fail({
1595
+ code: "VALIDATION_ERROR",
1596
+ message: "`config.dataStore` must be `ephemeral` or an object with a string `directory`.",
1597
+ details: dataStore
1598
+ });
1599
+ }
1600
+ }
1601
+ }
1602
+ return config;
1603
+ }
1604
+ function expectString(value, message, details) {
1605
+ if (!isString(value)) {
1606
+ fail({ code: "VALIDATION_ERROR", message, details });
1607
+ }
1608
+ return value;
1609
+ }
1610
+ function expectNumber(value, message, details) {
1611
+ if (!isNumber(value)) {
1612
+ fail({ code: "VALIDATION_ERROR", message, details });
1613
+ }
1614
+ return value;
1615
+ }
1616
+ function expectPositiveNumber(value, message, details) {
1617
+ if (!isPositiveNumber(value)) {
1618
+ fail({ code: "VALIDATION_ERROR", message, details });
1619
+ }
1620
+ return value;
1621
+ }
1622
+ function validateScreenshotFormat(value) {
1623
+ return value === "png" || value === "jpeg" || value === "webp";
1624
+ }
1625
+ function validateStep(step, index) {
1626
+ if (!isRecord(step)) {
1627
+ fail({
1628
+ code: "VALIDATION_ERROR",
1629
+ message: `Step ${index} must be an object.`,
1630
+ details: step
1631
+ });
1632
+ }
1633
+ const action = expectString(step.action, `Step ${index} is missing a string \`action\`.`, step.action);
1634
+ switch (action) {
1635
+ case "navigate":
1636
+ return { action, url: expectString(step.url, `Step ${index} \`navigate.url\` must be a string.`, step.url) };
1637
+ case "click":
1638
+ if (isString(step.selector)) {
1639
+ return { action, selector: step.selector };
1640
+ }
1641
+ return {
1642
+ action,
1643
+ x: expectNumber(step.x, `Step ${index} \`click.x\` must be a number when no selector is provided.`, step.x),
1644
+ y: expectNumber(step.y, `Step ${index} \`click.y\` must be a number when no selector is provided.`, step.y)
1645
+ };
1646
+ case "type":
1647
+ return {
1648
+ action,
1649
+ selector: expectString(step.selector, `Step ${index} \`type.selector\` must be a string.`, step.selector),
1650
+ text: expectString(step.text, `Step ${index} \`type.text\` must be a string.`, step.text)
1651
+ };
1652
+ case "press": {
1653
+ const key = expectString(step.key, `Step ${index} \`press.key\` must be a string.`, step.key);
1654
+ const modifiers = step.modifiers;
1655
+ if (modifiers !== undefined && (!Array.isArray(modifiers) || modifiers.some((item) => !isString(item)))) {
1656
+ fail({
1657
+ code: "VALIDATION_ERROR",
1658
+ message: `Step ${index} \`press.modifiers\` must be an array of strings.`,
1659
+ details: modifiers
1660
+ });
1661
+ }
1662
+ return { action, key, modifiers };
1663
+ }
1664
+ case "evaluate":
1665
+ return { action, script: expectString(step.script, `Step ${index} \`evaluate.script\` must be a string.`, step.script) };
1666
+ case "wait":
1667
+ return { action, ms: expectNonNegativeNumber(step.ms, `Step ${index} \`wait.ms\` must be a non-negative number.`, step.ms) };
1668
+ case "screenshot": {
1669
+ if (step.path !== undefined && !isString(step.path)) {
1670
+ fail({
1671
+ code: "VALIDATION_ERROR",
1672
+ message: `Step ${index} \`screenshot.path\` must be a string when provided.`,
1673
+ details: step.path
1674
+ });
1675
+ }
1676
+ if (step.format !== undefined && !validateScreenshotFormat(step.format)) {
1677
+ fail({
1678
+ code: "VALIDATION_ERROR",
1679
+ message: `Step ${index} \`screenshot.format\` must be \`png\`, \`jpeg\`, or \`webp\`.`,
1680
+ details: step.format
1681
+ });
1682
+ }
1683
+ if (step.quality !== undefined && !isNonNegativeNumber(step.quality)) {
1684
+ fail({
1685
+ code: "VALIDATION_ERROR",
1686
+ message: `Step ${index} \`screenshot.quality\` must be a non-negative number.`,
1687
+ details: step.quality
1688
+ });
1689
+ }
1690
+ return {
1691
+ action,
1692
+ path: step.path,
1693
+ format: step.format,
1694
+ quality: step.quality
1695
+ };
1696
+ }
1697
+ case "scroll":
1698
+ return {
1699
+ action,
1700
+ dx: expectNumber(step.dx, `Step ${index} \`scroll.dx\` must be a number.`, step.dx),
1701
+ dy: expectNumber(step.dy, `Step ${index} \`scroll.dy\` must be a number.`, step.dy)
1702
+ };
1703
+ case "scrollTo":
1704
+ return {
1705
+ action,
1706
+ selector: expectString(step.selector, `Step ${index} \`scrollTo.selector\` must be a string.`, step.selector),
1707
+ block: step.block
1708
+ };
1709
+ case "resize":
1710
+ return {
1711
+ action,
1712
+ width: expectPositiveNumber(step.width, `Step ${index} \`resize.width\` must be a positive number.`, step.width),
1713
+ height: expectPositiveNumber(step.height, `Step ${index} \`resize.height\` must be a positive number.`, step.height)
1714
+ };
1715
+ case "back":
1716
+ case "forward":
1717
+ case "reload":
1718
+ return { action };
1719
+ default:
1720
+ fail({
1721
+ code: "VALIDATION_ERROR",
1722
+ message: `Step ${index} has an unsupported action: ${action}`
1723
+ });
1724
+ }
1725
+ }
1726
+ function expectNonNegativeNumber(value, message, details) {
1727
+ if (!isNonNegativeNumber(value)) {
1728
+ fail({ code: "VALIDATION_ERROR", message, details });
1729
+ }
1730
+ return value;
1731
+ }
1732
+ function validateDocument(input) {
1733
+ if (!isRecord(input)) {
1734
+ fail({
1735
+ code: "VALIDATION_ERROR",
1736
+ message: "Instruction document must be an object.",
1737
+ details: input
1738
+ });
1739
+ }
1740
+ if (!Array.isArray(input.steps)) {
1741
+ fail({
1742
+ code: "VALIDATION_ERROR",
1743
+ message: "`steps` must be an array.",
1744
+ details: input.steps
1745
+ });
1746
+ }
1747
+ return {
1748
+ config: validateConfig(input.config),
1749
+ steps: input.steps.map((step, index) => validateStep(step, index))
1750
+ };
1751
+ }
1752
+ function resolveViewOptions(config) {
1753
+ return {
1754
+ backend: config?.backend ?? DEFAULT_BACKEND,
1755
+ width: config?.width ?? DEFAULT_WIDTH,
1756
+ height: config?.height ?? DEFAULT_HEIGHT,
1757
+ url: config?.url,
1758
+ console: config?.console ? globalThis.console : undefined,
1759
+ dataStore: config?.dataStore
1760
+ };
1761
+ }
1762
+ async function executeStep(view, step) {
1763
+ switch (step.action) {
1764
+ case "navigate":
1765
+ await view.navigate(step.url);
1766
+ return {};
1767
+ case "click":
1768
+ if ("selector" in step) {
1769
+ await view.click(step.selector);
1770
+ } else {
1771
+ await view.click(step.x, step.y);
1772
+ }
1773
+ return {};
1774
+ case "type":
1775
+ await view.click(step.selector);
1776
+ await view.type(step.text);
1777
+ return {};
1778
+ case "press":
1779
+ await view.press(step.key, step.modifiers ? { modifiers: step.modifiers } : undefined);
1780
+ return {};
1781
+ case "evaluate": {
1782
+ const result = await view.evaluate(step.script);
1783
+ return { result };
1784
+ }
1785
+ case "wait":
1786
+ await sleep(step.ms);
1787
+ return {};
1788
+ case "screenshot": {
1789
+ const image = await view.screenshot({
1790
+ encoding: "blob",
1791
+ format: step.format,
1792
+ quality: step.quality
1793
+ });
1794
+ if (!step.path) {
1795
+ return {};
1796
+ }
1797
+ await Bun.write(step.path, image);
1798
+ return { screenshotPath: step.path };
1799
+ }
1800
+ case "scroll":
1801
+ await view.scroll(step.dx, step.dy);
1802
+ return {};
1803
+ case "scrollTo":
1804
+ await view.scrollTo(step.selector, step.block ? { block: step.block } : undefined);
1805
+ return {};
1806
+ case "resize":
1807
+ await view.resize(step.width, step.height);
1808
+ return {};
1809
+ case "back":
1810
+ await view.back();
1811
+ return {};
1812
+ case "forward":
1813
+ await view.forward();
1814
+ return {};
1815
+ case "reload":
1816
+ await view.reload();
1817
+ return {};
1818
+ }
1819
+ }
1820
+ async function runStepWithRetry(view, step, index) {
1821
+ let lastError;
1822
+ for (let attempt = 1;attempt <= MAX_STEP_ATTEMPTS; attempt += 1) {
1823
+ try {
1824
+ const outcome = await executeStep(view, step);
1825
+ return {
1826
+ index,
1827
+ action: step.action,
1828
+ attempt,
1829
+ ...outcome
1830
+ };
1831
+ } catch (error) {
1832
+ lastError = error;
1833
+ if (attempt === MAX_STEP_ATTEMPTS) {
1834
+ fail({
1835
+ code: "STEP_FAILED",
1836
+ message: `Step ${index} failed after ${MAX_STEP_ATTEMPTS} attempts.`,
1837
+ stepIndex: index,
1838
+ stepAction: step.action,
1839
+ attempts: MAX_STEP_ATTEMPTS,
1840
+ details: error instanceof Error ? { name: error.name, message: error.message } : error
1841
+ });
1842
+ }
1843
+ }
1844
+ }
1845
+ throw lastError;
1846
+ }
1847
+ async function executeRun(args) {
1848
+ const rawInput = await loadInstructionSource(args);
1849
+ const document = validateDocument(rawInput);
1850
+ const view = new Bun.WebView(resolveViewOptions(document.config));
1851
+ try {
1852
+ const results = [];
1853
+ for (const [index, step] of document.steps.entries()) {
1854
+ const result = await runStepWithRetry(view, step, index);
1855
+ results.push(result);
1856
+ }
1857
+ console.log(JSON.stringify({
1858
+ ok: true,
1859
+ steps: results,
1860
+ closingInMs: POST_RUN_DELAY_MS
1861
+ }));
1862
+ await sleep(POST_RUN_DELAY_MS);
1863
+ } finally {
1864
+ view.close();
1865
+ }
1866
+ }
1867
+ var runCommand = command2({
1868
+ name: "run",
1869
+ desc: "Execute a Bun.WebView instruction document.",
1870
+ help: printHelp,
1871
+ options: {
1872
+ file: string().desc("Read instructions from a JSON file."),
1873
+ instructions: string().desc("Read instructions from an inline JSON string.")
1874
+ },
1875
+ handler: async (options) => {
1876
+ await executeRun(options);
1877
+ }
1878
+ });
1879
+ var args = Bun.argv.slice(2);
1880
+ var implicitRunArgs = args.length > 0 && !args[0]?.startsWith("-") ? args : ["run", ...args];
1881
+ try {
1882
+ await run([runCommand], {
1883
+ name: CLI_NAME,
1884
+ description: CLI_DESCRIPTION,
1885
+ version: CLI_VERSION,
1886
+ omitKeysOfUndefinedOptions: true,
1887
+ argSource: [Bun.argv[0] ?? "bun", Bun.argv[1] ?? "bunwright.ts", ...implicitRunArgs],
1888
+ theme: (event) => {
1889
+ if (event.type === "error") {
1890
+ fail({
1891
+ code: "ARGUMENT_ERROR",
1892
+ message: event.violation === "unknown_error" ? normalizeArgumentError(event.error) : formatCliError(event)
1893
+ });
1894
+ }
1895
+ return false;
1896
+ }
1897
+ });
1898
+ } catch (error) {
1899
+ fail({
1900
+ code: "ARGUMENT_ERROR",
1901
+ message: normalizeArgumentError(error)
1902
+ });
1903
+ }