@openpkg-ts/extract 0.14.2 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/tspec.js CHANGED
@@ -1,71 +1,1572 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  extract
4
- } from "../shared/chunk-khwn5myc.js";
4
+ } from "../shared/chunk-axmbd6k1.js";
5
5
 
6
6
  // src/cli/spec.ts
7
7
  import * as fs from "node:fs";
8
8
  import * as path from "node:path";
9
+
10
+ // ../../node_modules/chalk/source/vendor/ansi-styles/index.js
11
+ var ANSI_BACKGROUND_OFFSET = 10;
12
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
13
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
14
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
15
+ var styles = {
16
+ modifier: {
17
+ reset: [0, 0],
18
+ bold: [1, 22],
19
+ dim: [2, 22],
20
+ italic: [3, 23],
21
+ underline: [4, 24],
22
+ overline: [53, 55],
23
+ inverse: [7, 27],
24
+ hidden: [8, 28],
25
+ strikethrough: [9, 29]
26
+ },
27
+ color: {
28
+ black: [30, 39],
29
+ red: [31, 39],
30
+ green: [32, 39],
31
+ yellow: [33, 39],
32
+ blue: [34, 39],
33
+ magenta: [35, 39],
34
+ cyan: [36, 39],
35
+ white: [37, 39],
36
+ blackBright: [90, 39],
37
+ gray: [90, 39],
38
+ grey: [90, 39],
39
+ redBright: [91, 39],
40
+ greenBright: [92, 39],
41
+ yellowBright: [93, 39],
42
+ blueBright: [94, 39],
43
+ magentaBright: [95, 39],
44
+ cyanBright: [96, 39],
45
+ whiteBright: [97, 39]
46
+ },
47
+ bgColor: {
48
+ bgBlack: [40, 49],
49
+ bgRed: [41, 49],
50
+ bgGreen: [42, 49],
51
+ bgYellow: [43, 49],
52
+ bgBlue: [44, 49],
53
+ bgMagenta: [45, 49],
54
+ bgCyan: [46, 49],
55
+ bgWhite: [47, 49],
56
+ bgBlackBright: [100, 49],
57
+ bgGray: [100, 49],
58
+ bgGrey: [100, 49],
59
+ bgRedBright: [101, 49],
60
+ bgGreenBright: [102, 49],
61
+ bgYellowBright: [103, 49],
62
+ bgBlueBright: [104, 49],
63
+ bgMagentaBright: [105, 49],
64
+ bgCyanBright: [106, 49],
65
+ bgWhiteBright: [107, 49]
66
+ }
67
+ };
68
+ var modifierNames = Object.keys(styles.modifier);
69
+ var foregroundColorNames = Object.keys(styles.color);
70
+ var backgroundColorNames = Object.keys(styles.bgColor);
71
+ var colorNames = [...foregroundColorNames, ...backgroundColorNames];
72
+ function assembleStyles() {
73
+ const codes = new Map;
74
+ for (const [groupName, group] of Object.entries(styles)) {
75
+ for (const [styleName, style] of Object.entries(group)) {
76
+ styles[styleName] = {
77
+ open: `\x1B[${style[0]}m`,
78
+ close: `\x1B[${style[1]}m`
79
+ };
80
+ group[styleName] = styles[styleName];
81
+ codes.set(style[0], style[1]);
82
+ }
83
+ Object.defineProperty(styles, groupName, {
84
+ value: group,
85
+ enumerable: false
86
+ });
87
+ }
88
+ Object.defineProperty(styles, "codes", {
89
+ value: codes,
90
+ enumerable: false
91
+ });
92
+ styles.color.close = "\x1B[39m";
93
+ styles.bgColor.close = "\x1B[49m";
94
+ styles.color.ansi = wrapAnsi16();
95
+ styles.color.ansi256 = wrapAnsi256();
96
+ styles.color.ansi16m = wrapAnsi16m();
97
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
98
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
99
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
100
+ Object.defineProperties(styles, {
101
+ rgbToAnsi256: {
102
+ value(red, green, blue) {
103
+ if (red === green && green === blue) {
104
+ if (red < 8) {
105
+ return 16;
106
+ }
107
+ if (red > 248) {
108
+ return 231;
109
+ }
110
+ return Math.round((red - 8) / 247 * 24) + 232;
111
+ }
112
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
113
+ },
114
+ enumerable: false
115
+ },
116
+ hexToRgb: {
117
+ value(hex) {
118
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
119
+ if (!matches) {
120
+ return [0, 0, 0];
121
+ }
122
+ let [colorString] = matches;
123
+ if (colorString.length === 3) {
124
+ colorString = [...colorString].map((character) => character + character).join("");
125
+ }
126
+ const integer = Number.parseInt(colorString, 16);
127
+ return [
128
+ integer >> 16 & 255,
129
+ integer >> 8 & 255,
130
+ integer & 255
131
+ ];
132
+ },
133
+ enumerable: false
134
+ },
135
+ hexToAnsi256: {
136
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
137
+ enumerable: false
138
+ },
139
+ ansi256ToAnsi: {
140
+ value(code) {
141
+ if (code < 8) {
142
+ return 30 + code;
143
+ }
144
+ if (code < 16) {
145
+ return 90 + (code - 8);
146
+ }
147
+ let red;
148
+ let green;
149
+ let blue;
150
+ if (code >= 232) {
151
+ red = ((code - 232) * 10 + 8) / 255;
152
+ green = red;
153
+ blue = red;
154
+ } else {
155
+ code -= 16;
156
+ const remainder = code % 36;
157
+ red = Math.floor(code / 36) / 5;
158
+ green = Math.floor(remainder / 6) / 5;
159
+ blue = remainder % 6 / 5;
160
+ }
161
+ const value = Math.max(red, green, blue) * 2;
162
+ if (value === 0) {
163
+ return 30;
164
+ }
165
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
166
+ if (value === 2) {
167
+ result += 60;
168
+ }
169
+ return result;
170
+ },
171
+ enumerable: false
172
+ },
173
+ rgbToAnsi: {
174
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
175
+ enumerable: false
176
+ },
177
+ hexToAnsi: {
178
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
179
+ enumerable: false
180
+ }
181
+ });
182
+ return styles;
183
+ }
184
+ var ansiStyles = assembleStyles();
185
+ var ansi_styles_default = ansiStyles;
186
+
187
+ // ../../node_modules/chalk/source/vendor/supports-color/index.js
188
+ import process2 from "node:process";
189
+ import os from "node:os";
190
+ import tty from "node:tty";
191
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
192
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
193
+ const position = argv.indexOf(prefix + flag);
194
+ const terminatorPosition = argv.indexOf("--");
195
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
196
+ }
197
+ var { env } = process2;
198
+ var flagForceColor;
199
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
200
+ flagForceColor = 0;
201
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
202
+ flagForceColor = 1;
203
+ }
204
+ function envForceColor() {
205
+ if ("FORCE_COLOR" in env) {
206
+ if (env.FORCE_COLOR === "true") {
207
+ return 1;
208
+ }
209
+ if (env.FORCE_COLOR === "false") {
210
+ return 0;
211
+ }
212
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
213
+ }
214
+ }
215
+ function translateLevel(level) {
216
+ if (level === 0) {
217
+ return false;
218
+ }
219
+ return {
220
+ level,
221
+ hasBasic: true,
222
+ has256: level >= 2,
223
+ has16m: level >= 3
224
+ };
225
+ }
226
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
227
+ const noFlagForceColor = envForceColor();
228
+ if (noFlagForceColor !== undefined) {
229
+ flagForceColor = noFlagForceColor;
230
+ }
231
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
232
+ if (forceColor === 0) {
233
+ return 0;
234
+ }
235
+ if (sniffFlags) {
236
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
237
+ return 3;
238
+ }
239
+ if (hasFlag("color=256")) {
240
+ return 2;
241
+ }
242
+ }
243
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
244
+ return 1;
245
+ }
246
+ if (haveStream && !streamIsTTY && forceColor === undefined) {
247
+ return 0;
248
+ }
249
+ const min = forceColor || 0;
250
+ if (env.TERM === "dumb") {
251
+ return min;
252
+ }
253
+ if (process2.platform === "win32") {
254
+ const osRelease = os.release().split(".");
255
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
256
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
257
+ }
258
+ return 1;
259
+ }
260
+ if ("CI" in env) {
261
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => (key in env))) {
262
+ return 3;
263
+ }
264
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => (sign in env)) || env.CI_NAME === "codeship") {
265
+ return 1;
266
+ }
267
+ return min;
268
+ }
269
+ if ("TEAMCITY_VERSION" in env) {
270
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
271
+ }
272
+ if (env.COLORTERM === "truecolor") {
273
+ return 3;
274
+ }
275
+ if (env.TERM === "xterm-kitty") {
276
+ return 3;
277
+ }
278
+ if (env.TERM === "xterm-ghostty") {
279
+ return 3;
280
+ }
281
+ if (env.TERM === "wezterm") {
282
+ return 3;
283
+ }
284
+ if ("TERM_PROGRAM" in env) {
285
+ const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
286
+ switch (env.TERM_PROGRAM) {
287
+ case "iTerm.app": {
288
+ return version >= 3 ? 3 : 2;
289
+ }
290
+ case "Apple_Terminal": {
291
+ return 2;
292
+ }
293
+ }
294
+ }
295
+ if (/-256(color)?$/i.test(env.TERM)) {
296
+ return 2;
297
+ }
298
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
299
+ return 1;
300
+ }
301
+ if ("COLORTERM" in env) {
302
+ return 1;
303
+ }
304
+ return min;
305
+ }
306
+ function createSupportsColor(stream, options = {}) {
307
+ const level = _supportsColor(stream, {
308
+ streamIsTTY: stream && stream.isTTY,
309
+ ...options
310
+ });
311
+ return translateLevel(level);
312
+ }
313
+ var supportsColor = {
314
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
315
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
316
+ };
317
+ var supports_color_default = supportsColor;
318
+
319
+ // ../../node_modules/chalk/source/utilities.js
320
+ function stringReplaceAll(string, substring, replacer) {
321
+ let index = string.indexOf(substring);
322
+ if (index === -1) {
323
+ return string;
324
+ }
325
+ const substringLength = substring.length;
326
+ let endIndex = 0;
327
+ let returnValue = "";
328
+ do {
329
+ returnValue += string.slice(endIndex, index) + substring + replacer;
330
+ endIndex = index + substringLength;
331
+ index = string.indexOf(substring, endIndex);
332
+ } while (index !== -1);
333
+ returnValue += string.slice(endIndex);
334
+ return returnValue;
335
+ }
336
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
337
+ let endIndex = 0;
338
+ let returnValue = "";
339
+ do {
340
+ const gotCR = string[index - 1] === "\r";
341
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? `\r
342
+ ` : `
343
+ `) + postfix;
344
+ endIndex = index + 1;
345
+ index = string.indexOf(`
346
+ `, endIndex);
347
+ } while (index !== -1);
348
+ returnValue += string.slice(endIndex);
349
+ return returnValue;
350
+ }
351
+
352
+ // ../../node_modules/chalk/source/index.js
353
+ var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
354
+ var GENERATOR = Symbol("GENERATOR");
355
+ var STYLER = Symbol("STYLER");
356
+ var IS_EMPTY = Symbol("IS_EMPTY");
357
+ var levelMapping = [
358
+ "ansi",
359
+ "ansi",
360
+ "ansi256",
361
+ "ansi16m"
362
+ ];
363
+ var styles2 = Object.create(null);
364
+ var applyOptions = (object, options = {}) => {
365
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
366
+ throw new Error("The `level` option should be an integer from 0 to 3");
367
+ }
368
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
369
+ object.level = options.level === undefined ? colorLevel : options.level;
370
+ };
371
+ var chalkFactory = (options) => {
372
+ const chalk = (...strings) => strings.join(" ");
373
+ applyOptions(chalk, options);
374
+ Object.setPrototypeOf(chalk, createChalk.prototype);
375
+ return chalk;
376
+ };
377
+ function createChalk(options) {
378
+ return chalkFactory(options);
379
+ }
380
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
381
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
382
+ styles2[styleName] = {
383
+ get() {
384
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
385
+ Object.defineProperty(this, styleName, { value: builder });
386
+ return builder;
387
+ }
388
+ };
389
+ }
390
+ styles2.visible = {
391
+ get() {
392
+ const builder = createBuilder(this, this[STYLER], true);
393
+ Object.defineProperty(this, "visible", { value: builder });
394
+ return builder;
395
+ }
396
+ };
397
+ var getModelAnsi = (model, level, type, ...arguments_) => {
398
+ if (model === "rgb") {
399
+ if (level === "ansi16m") {
400
+ return ansi_styles_default[type].ansi16m(...arguments_);
401
+ }
402
+ if (level === "ansi256") {
403
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
404
+ }
405
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
406
+ }
407
+ if (model === "hex") {
408
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
409
+ }
410
+ return ansi_styles_default[type][model](...arguments_);
411
+ };
412
+ var usedModels = ["rgb", "hex", "ansi256"];
413
+ for (const model of usedModels) {
414
+ styles2[model] = {
415
+ get() {
416
+ const { level } = this;
417
+ return function(...arguments_) {
418
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
419
+ return createBuilder(this, styler, this[IS_EMPTY]);
420
+ };
421
+ }
422
+ };
423
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
424
+ styles2[bgModel] = {
425
+ get() {
426
+ const { level } = this;
427
+ return function(...arguments_) {
428
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
429
+ return createBuilder(this, styler, this[IS_EMPTY]);
430
+ };
431
+ }
432
+ };
433
+ }
434
+ var proto = Object.defineProperties(() => {}, {
435
+ ...styles2,
436
+ level: {
437
+ enumerable: true,
438
+ get() {
439
+ return this[GENERATOR].level;
440
+ },
441
+ set(level) {
442
+ this[GENERATOR].level = level;
443
+ }
444
+ }
445
+ });
446
+ var createStyler = (open, close, parent) => {
447
+ let openAll;
448
+ let closeAll;
449
+ if (parent === undefined) {
450
+ openAll = open;
451
+ closeAll = close;
452
+ } else {
453
+ openAll = parent.openAll + open;
454
+ closeAll = close + parent.closeAll;
455
+ }
456
+ return {
457
+ open,
458
+ close,
459
+ openAll,
460
+ closeAll,
461
+ parent
462
+ };
463
+ };
464
+ var createBuilder = (self, _styler, _isEmpty) => {
465
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
466
+ Object.setPrototypeOf(builder, proto);
467
+ builder[GENERATOR] = self;
468
+ builder[STYLER] = _styler;
469
+ builder[IS_EMPTY] = _isEmpty;
470
+ return builder;
471
+ };
472
+ var applyStyle = (self, string) => {
473
+ if (self.level <= 0 || !string) {
474
+ return self[IS_EMPTY] ? "" : string;
475
+ }
476
+ let styler = self[STYLER];
477
+ if (styler === undefined) {
478
+ return string;
479
+ }
480
+ const { openAll, closeAll } = styler;
481
+ if (string.includes("\x1B")) {
482
+ while (styler !== undefined) {
483
+ string = stringReplaceAll(string, styler.close, styler.open);
484
+ styler = styler.parent;
485
+ }
486
+ }
487
+ const lfIndex = string.indexOf(`
488
+ `);
489
+ if (lfIndex !== -1) {
490
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
491
+ }
492
+ return openAll + string + closeAll;
493
+ };
494
+ Object.defineProperties(createChalk.prototype, styles2);
495
+ var chalk = createChalk();
496
+ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
497
+ var source_default = chalk;
498
+
499
+ // ../cli-utils/dist/index.js
500
+ var colors = {
501
+ success: source_default.green,
502
+ error: source_default.red,
503
+ warning: source_default.yellow,
504
+ info: source_default.cyan,
505
+ muted: source_default.gray,
506
+ bold: source_default.bold,
507
+ dim: source_default.dim,
508
+ underline: source_default.underline,
509
+ primary: source_default.cyan,
510
+ secondary: source_default.magenta,
511
+ path: source_default.cyan,
512
+ number: source_default.yellow,
513
+ code: source_default.gray
514
+ };
515
+ var symbols = {
516
+ success: "✓",
517
+ error: "✗",
518
+ warning: "⚠",
519
+ info: "ℹ",
520
+ spinner: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
521
+ bullet: "•",
522
+ arrow: "→",
523
+ arrowRight: "›",
524
+ line: "─",
525
+ corner: "└",
526
+ vertical: "│",
527
+ horizontalLine: "─"
528
+ };
529
+ var asciiSymbols = {
530
+ success: "+",
531
+ error: "x",
532
+ warning: "!",
533
+ info: "i",
534
+ spinner: ["-", "\\", "|", "/"],
535
+ bullet: "*",
536
+ arrow: "->",
537
+ arrowRight: ">",
538
+ line: "-",
539
+ corner: "\\",
540
+ vertical: "|",
541
+ horizontalLine: "-"
542
+ };
543
+ function getSymbols(unicodeSupport = true) {
544
+ return unicodeSupport ? symbols : asciiSymbols;
545
+ }
546
+ var prefix = {
547
+ success: colors.success(symbols.success),
548
+ error: colors.error(symbols.error),
549
+ warning: colors.warning(symbols.warning),
550
+ info: colors.info(symbols.info)
551
+ };
552
+ function isTTY() {
553
+ return Boolean(process.stdout.isTTY);
554
+ }
555
+ function isCI() {
556
+ return Boolean(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.TRAVIS || process.env.JENKINS_URL || process.env.BUILDKITE || process.env.TEAMCITY_VERSION || process.env.TF_BUILD || process.env.CODEBUILD_BUILD_ID || process.env.BITBUCKET_BUILD_NUMBER);
557
+ }
558
+ function isInteractive() {
559
+ return isTTY() && !isCI();
560
+ }
561
+ function supportsUnicode() {
562
+ if (process.platform === "win32") {
563
+ return Boolean(process.env.WT_SESSION) || process.env.TERM_PROGRAM === "vscode";
564
+ }
565
+ return process.env.TERM !== "linux";
566
+ }
567
+ var MIN_TERMINAL_WIDTH = 40;
568
+ var DEFAULT_TERMINAL_WIDTH = 80;
569
+ function getTerminalWidth() {
570
+ const width = process.stdout.columns || DEFAULT_TERMINAL_WIDTH;
571
+ return Math.max(width, MIN_TERMINAL_WIDTH);
572
+ }
573
+ function formatDuration(ms) {
574
+ if (ms < 1000) {
575
+ return `${ms}ms`;
576
+ }
577
+ const seconds = ms / 1000;
578
+ if (seconds < 60) {
579
+ return `${seconds.toFixed(1)}s`;
580
+ }
581
+ const minutes = Math.floor(seconds / 60);
582
+ const remainingSeconds = Math.floor(seconds % 60);
583
+ return `${minutes}m ${remainingSeconds}s`;
584
+ }
585
+ var cursor = {
586
+ hide: "\x1B[?25l",
587
+ show: "\x1B[?25h",
588
+ up: (n = 1) => `\x1B[${n}A`,
589
+ down: (n = 1) => `\x1B[${n}B`,
590
+ forward: (n = 1) => `\x1B[${n}C`,
591
+ back: (n = 1) => `\x1B[${n}D`,
592
+ left: "\x1B[G",
593
+ clearLine: "\x1B[2K",
594
+ clearDown: "\x1B[J",
595
+ save: "\x1B[s",
596
+ restore: "\x1B[u"
597
+ };
598
+ function clearLine() {
599
+ if (isTTY()) {
600
+ process.stdout.write(cursor.clearLine + cursor.left);
601
+ }
602
+ }
603
+ function moveCursorUp(lines = 1) {
604
+ if (isTTY()) {
605
+ process.stdout.write(cursor.up(lines));
606
+ }
607
+ }
608
+ function hideCursor() {
609
+ if (isTTY()) {
610
+ process.stdout.write(cursor.hide);
611
+ }
612
+ }
613
+ function showCursor() {
614
+ if (isTTY()) {
615
+ process.stdout.write(cursor.show);
616
+ }
617
+ }
618
+ function truncate(text, maxLength) {
619
+ if (text.length <= maxLength)
620
+ return text;
621
+ return `${text.slice(0, maxLength - 1)}…`;
622
+ }
623
+ var ANSI_REGEX = /\x1B\[[0-9;]*[a-zA-Z]/g;
624
+ function stripAnsi(text) {
625
+ return text.replace(ANSI_REGEX, "");
626
+ }
627
+
628
+ class MultiProgress {
629
+ bars = new Map;
630
+ barOrder = [];
631
+ options;
632
+ spinnerFrames;
633
+ spinnerIndex = 0;
634
+ timer = null;
635
+ lastRenderedLines = 0;
636
+ symbols = getSymbols(supportsUnicode());
637
+ sigintHandler = null;
638
+ filledChar;
639
+ emptyChar;
640
+ constructor(options = {}) {
641
+ this.options = {
642
+ barWidth: options.barWidth,
643
+ showPercent: options.showPercent ?? true,
644
+ showCount: options.showCount ?? true,
645
+ spinnerInterval: options.spinnerInterval ?? 80
646
+ };
647
+ this.spinnerFrames = supportsUnicode() ? ["◐", "◓", "◑", "◒"] : ["-", "\\", "|", "/"];
648
+ const unicode = supportsUnicode();
649
+ this.filledChar = unicode ? "█" : "#";
650
+ this.emptyChar = unicode ? "░" : "-";
651
+ }
652
+ start() {
653
+ if (!isInteractive())
654
+ return this;
655
+ hideCursor();
656
+ this.setupSignalHandler();
657
+ this.timer = setInterval(() => {
658
+ this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
659
+ if (this.bars.size > 0 && [...this.bars.values()].some((b) => b.status === "active")) {
660
+ this.render();
661
+ }
662
+ }, this.options.spinnerInterval);
663
+ return this;
664
+ }
665
+ add(config) {
666
+ const state = {
667
+ id: config.id,
668
+ label: config.label,
669
+ total: config.total ?? 100,
670
+ current: config.current ?? 0,
671
+ status: "active",
672
+ startTime: Date.now()
673
+ };
674
+ this.bars.set(config.id, state);
675
+ if (!this.barOrder.includes(config.id)) {
676
+ this.barOrder.push(config.id);
677
+ }
678
+ if (!isInteractive()) {
679
+ console.log(`${this.symbols.bullet} ${config.label}`);
680
+ } else {
681
+ this.render();
682
+ }
683
+ return this;
684
+ }
685
+ update(id, current, label) {
686
+ const bar = this.bars.get(id);
687
+ if (!bar)
688
+ return this;
689
+ bar.current = Math.min(current, bar.total);
690
+ if (label !== undefined)
691
+ bar.label = label;
692
+ if (isInteractive()) {
693
+ this.render();
694
+ }
695
+ return this;
696
+ }
697
+ increment(id, amount = 1) {
698
+ const bar = this.bars.get(id);
699
+ if (!bar)
700
+ return this;
701
+ return this.update(id, bar.current + amount);
702
+ }
703
+ complete(id, label) {
704
+ const bar = this.bars.get(id);
705
+ if (!bar)
706
+ return this;
707
+ bar.status = "completed";
708
+ bar.current = bar.total;
709
+ if (label !== undefined)
710
+ bar.label = label;
711
+ if (!isInteractive()) {
712
+ console.log(`${colors.success(this.symbols.success)} ${bar.label}`);
713
+ } else {
714
+ this.render();
715
+ }
716
+ return this;
717
+ }
718
+ fail(id, label) {
719
+ const bar = this.bars.get(id);
720
+ if (!bar)
721
+ return this;
722
+ bar.status = "failed";
723
+ if (label !== undefined)
724
+ bar.label = label;
725
+ if (!isInteractive()) {
726
+ console.log(`${colors.error(this.symbols.error)} ${bar.label}`);
727
+ } else {
728
+ this.render();
729
+ }
730
+ return this;
731
+ }
732
+ remove(id) {
733
+ this.bars.delete(id);
734
+ this.barOrder = this.barOrder.filter((i) => i !== id);
735
+ if (isInteractive()) {
736
+ this.render();
737
+ }
738
+ return this;
739
+ }
740
+ get(id) {
741
+ return this.bars.get(id);
742
+ }
743
+ get allDone() {
744
+ if (this.bars.size === 0)
745
+ return true;
746
+ return [...this.bars.values()].every((b) => b.status !== "active");
747
+ }
748
+ stop() {
749
+ if (this.timer) {
750
+ clearInterval(this.timer);
751
+ this.timer = null;
752
+ }
753
+ this.cleanup();
754
+ return this;
755
+ }
756
+ render() {
757
+ if (!isTTY())
758
+ return;
759
+ this.clearOutput();
760
+ const width = getTerminalWidth();
761
+ const lines = [];
762
+ for (const id of this.barOrder) {
763
+ const bar = this.bars.get(id);
764
+ if (!bar)
765
+ continue;
766
+ const line = this.renderBar(bar, width);
767
+ lines.push(line);
768
+ }
769
+ if (lines.length > 0) {
770
+ process.stdout.write(lines.join(`
771
+ `));
772
+ this.lastRenderedLines = lines.length;
773
+ }
774
+ }
775
+ renderBar(bar, termWidth) {
776
+ const parts = [];
777
+ let symbol;
778
+ switch (bar.status) {
779
+ case "completed":
780
+ symbol = colors.success(this.symbols.success);
781
+ break;
782
+ case "failed":
783
+ symbol = colors.error(this.symbols.error);
784
+ break;
785
+ default:
786
+ symbol = colors.primary(this.spinnerFrames[this.spinnerIndex]);
787
+ }
788
+ parts.push(symbol);
789
+ parts.push(bar.label);
790
+ const suffixParts = [];
791
+ if (this.options.showPercent) {
792
+ const pct = bar.total === 0 ? 0 : Math.round(bar.current / bar.total * 100);
793
+ suffixParts.push(`${pct}%`);
794
+ }
795
+ if (this.options.showCount) {
796
+ suffixParts.push(`${bar.current}/${bar.total}`);
797
+ }
798
+ const suffix = suffixParts.length > 0 ? ` ${suffixParts.join(" ")}` : "";
799
+ const labelLen = stripAnsi(parts.join(" ")).length + 1;
800
+ const bracketLen = 2;
801
+ const suffixLen = stripAnsi(suffix).length;
802
+ const minBarWidth = 10;
803
+ const availableWidth = termWidth - labelLen - bracketLen - suffixLen - 1;
804
+ const barWidth = this.options.barWidth ?? Math.max(minBarWidth, Math.min(30, availableWidth));
805
+ const filledWidth = Math.round(bar.current / bar.total * barWidth);
806
+ const emptyWidth = barWidth - filledWidth;
807
+ const barViz = `[${this.filledChar.repeat(filledWidth)}${this.emptyChar.repeat(emptyWidth)}]`;
808
+ parts.push(barViz);
809
+ return truncate(parts.join(" ") + suffix, termWidth);
810
+ }
811
+ clearOutput() {
812
+ if (!isTTY() || this.lastRenderedLines === 0)
813
+ return;
814
+ for (let i = 0;i < this.lastRenderedLines; i++) {
815
+ if (i > 0)
816
+ process.stdout.write(cursor.up(1));
817
+ clearLine();
818
+ }
819
+ this.lastRenderedLines = 0;
820
+ }
821
+ setupSignalHandler() {
822
+ this.sigintHandler = () => {
823
+ this.cleanup();
824
+ process.exit(130);
825
+ };
826
+ process.on("SIGINT", this.sigintHandler);
827
+ }
828
+ cleanup() {
829
+ if (this.sigintHandler) {
830
+ process.removeListener("SIGINT", this.sigintHandler);
831
+ this.sigintHandler = null;
832
+ }
833
+ showCursor();
834
+ if (isTTY() && this.lastRenderedLines > 0) {
835
+ process.stdout.write(`
836
+ `);
837
+ }
838
+ }
839
+ }
840
+ class ProgressBar {
841
+ total;
842
+ current;
843
+ label;
844
+ width;
845
+ showPercent;
846
+ showCount;
847
+ showETA;
848
+ filledChar;
849
+ emptyChar;
850
+ startTime = null;
851
+ lastRender = "";
852
+ symbols = getSymbols(supportsUnicode());
853
+ sigintHandler = null;
854
+ isComplete = false;
855
+ constructor(options = {}) {
856
+ this.total = options.total ?? 100;
857
+ this.current = options.current ?? 0;
858
+ this.label = options.label ?? "";
859
+ this.width = options.width;
860
+ this.showPercent = options.showPercent ?? true;
861
+ this.showCount = options.showCount ?? true;
862
+ this.showETA = options.showETA ?? true;
863
+ const unicode = supportsUnicode();
864
+ this.filledChar = options.chars?.filled ?? (unicode ? "█" : "#");
865
+ this.emptyChar = options.chars?.empty ?? (unicode ? "░" : "-");
866
+ }
867
+ start(label) {
868
+ if (label !== undefined)
869
+ this.label = label;
870
+ this.startTime = Date.now();
871
+ this.current = 0;
872
+ this.isComplete = false;
873
+ if (!isInteractive()) {
874
+ console.log(`${this.symbols.bullet} ${this.label}`);
875
+ return this;
876
+ }
877
+ hideCursor();
878
+ this.setupSignalHandler();
879
+ this.render();
880
+ return this;
881
+ }
882
+ update(current) {
883
+ this.current = Math.min(current, this.total);
884
+ if (isInteractive()) {
885
+ this.render();
886
+ }
887
+ return this;
888
+ }
889
+ increment(amount = 1) {
890
+ return this.update(this.current + amount);
891
+ }
892
+ setLabel(label) {
893
+ this.label = label;
894
+ if (isInteractive()) {
895
+ this.render();
896
+ }
897
+ return this;
898
+ }
899
+ setTotal(total) {
900
+ this.total = total;
901
+ if (isInteractive()) {
902
+ this.render();
903
+ }
904
+ return this;
905
+ }
906
+ complete(label) {
907
+ if (label !== undefined)
908
+ this.label = label;
909
+ this.current = this.total;
910
+ this.isComplete = true;
911
+ if (!isInteractive()) {
912
+ console.log(`${colors.success(this.symbols.success)} ${this.label}`);
913
+ } else {
914
+ clearLine();
915
+ process.stdout.write(`${colors.success(this.symbols.success)} ${this.label}
916
+ `);
917
+ }
918
+ this.cleanup();
919
+ return this;
920
+ }
921
+ fail(label) {
922
+ if (label !== undefined)
923
+ this.label = label;
924
+ this.isComplete = true;
925
+ if (!isInteractive()) {
926
+ console.log(`${colors.error(this.symbols.error)} ${this.label}`);
927
+ } else {
928
+ clearLine();
929
+ process.stdout.write(`${colors.error(this.symbols.error)} ${this.label}
930
+ `);
931
+ }
932
+ this.cleanup();
933
+ return this;
934
+ }
935
+ get percentage() {
936
+ return this.total === 0 ? 0 : Math.round(this.current / this.total * 100);
937
+ }
938
+ get isDone() {
939
+ return this.isComplete || this.current >= this.total;
940
+ }
941
+ render() {
942
+ if (!isTTY())
943
+ return;
944
+ const termWidth = getTerminalWidth();
945
+ const parts = [];
946
+ if (this.label) {
947
+ parts.push(this.label);
948
+ }
949
+ const suffixParts = [];
950
+ if (this.showPercent) {
951
+ suffixParts.push(`${this.percentage}%`);
952
+ }
953
+ if (this.showCount) {
954
+ suffixParts.push(`${this.current}/${this.total}`);
955
+ }
956
+ if (this.showETA && this.startTime) {
957
+ const eta = this.calculateETA();
958
+ if (eta)
959
+ suffixParts.push(eta);
960
+ }
961
+ const suffix = suffixParts.length > 0 ? ` ${suffixParts.join(" ")}` : "";
962
+ const labelLen = this.label ? stripAnsi(this.label).length + 1 : 0;
963
+ const bracketLen = 2;
964
+ const suffixLen = stripAnsi(suffix).length;
965
+ const minBarWidth = 10;
966
+ const availableWidth = termWidth - labelLen - bracketLen - suffixLen - 1;
967
+ const barWidth = this.width ?? Math.max(minBarWidth, Math.min(40, availableWidth));
968
+ const filledWidth = Math.round(this.current / this.total * barWidth);
969
+ const emptyWidth = barWidth - filledWidth;
970
+ const bar = `[${this.filledChar.repeat(filledWidth)}${this.emptyChar.repeat(emptyWidth)}]`;
971
+ parts.push(bar);
972
+ const line = truncate(parts.join(" ") + suffix, termWidth);
973
+ if (line !== this.lastRender) {
974
+ clearLine();
975
+ process.stdout.write(line);
976
+ this.lastRender = line;
977
+ }
978
+ }
979
+ calculateETA() {
980
+ if (!this.startTime || this.current === 0)
981
+ return null;
982
+ const elapsed = Date.now() - this.startTime;
983
+ if (elapsed < 1000)
984
+ return null;
985
+ const rate = this.current / elapsed;
986
+ const remaining = this.total - this.current;
987
+ const etaMs = remaining / rate;
988
+ return `ETA ${formatDuration(etaMs)}`;
989
+ }
990
+ setupSignalHandler() {
991
+ this.sigintHandler = () => {
992
+ this.cleanup();
993
+ process.exit(130);
994
+ };
995
+ process.on("SIGINT", this.sigintHandler);
996
+ }
997
+ cleanup() {
998
+ if (this.sigintHandler) {
999
+ process.removeListener("SIGINT", this.sigintHandler);
1000
+ this.sigintHandler = null;
1001
+ }
1002
+ showCursor();
1003
+ }
1004
+ }
1005
+ var spinnerColors = {
1006
+ cyan: source_default.cyan,
1007
+ yellow: source_default.yellow,
1008
+ green: source_default.green,
1009
+ red: source_default.red,
1010
+ magenta: source_default.magenta,
1011
+ blue: source_default.blue,
1012
+ white: source_default.white
1013
+ };
1014
+ var FRAME_SETS = {
1015
+ dots: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
1016
+ circle: ["◐", "◓", "◑", "◒"]
1017
+ };
1018
+ var ASCII_FRAME_SET = ["-", "\\", "|", "/"];
1019
+
1020
+ class Spinner {
1021
+ label;
1022
+ detail;
1023
+ frames;
1024
+ interval;
1025
+ colorFn;
1026
+ frameIndex = 0;
1027
+ timer = null;
1028
+ state = "stopped";
1029
+ symbols = getSymbols(supportsUnicode());
1030
+ lastRenderedLines = 0;
1031
+ sigintHandler = null;
1032
+ constructor(options = {}) {
1033
+ this.label = options.label ?? "";
1034
+ this.detail = options.detail;
1035
+ this.interval = options.interval ?? 80;
1036
+ this.colorFn = spinnerColors[options.color ?? "cyan"];
1037
+ const style = options.style ?? "circle";
1038
+ this.frames = supportsUnicode() ? FRAME_SETS[style] : ASCII_FRAME_SET;
1039
+ }
1040
+ start(label) {
1041
+ if (label !== undefined)
1042
+ this.label = label;
1043
+ if (this.state === "spinning")
1044
+ return this;
1045
+ this.state = "spinning";
1046
+ this.frameIndex = 0;
1047
+ this.lastRenderedLines = 0;
1048
+ if (!isInteractive()) {
1049
+ console.log(`${this.symbols.bullet} ${this.label}`);
1050
+ return this;
1051
+ }
1052
+ hideCursor();
1053
+ this.setupSignalHandler();
1054
+ this.render();
1055
+ this.timer = setInterval(() => {
1056
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
1057
+ this.render();
1058
+ }, this.interval);
1059
+ return this;
1060
+ }
1061
+ stop() {
1062
+ if (this.timer) {
1063
+ clearInterval(this.timer);
1064
+ this.timer = null;
1065
+ }
1066
+ this.state = "stopped";
1067
+ this.clearOutput();
1068
+ this.cleanup();
1069
+ return this;
1070
+ }
1071
+ success(label) {
1072
+ if (label !== undefined)
1073
+ this.label = label;
1074
+ this.finish("success");
1075
+ return this;
1076
+ }
1077
+ fail(label) {
1078
+ if (label !== undefined)
1079
+ this.label = label;
1080
+ this.finish("error");
1081
+ return this;
1082
+ }
1083
+ update(label) {
1084
+ this.label = label;
1085
+ if (this.state === "spinning" && isInteractive()) {
1086
+ this.render();
1087
+ }
1088
+ return this;
1089
+ }
1090
+ setDetail(detail) {
1091
+ this.detail = detail;
1092
+ if (this.state === "spinning" && isInteractive()) {
1093
+ this.render();
1094
+ }
1095
+ return this;
1096
+ }
1097
+ get isSpinning() {
1098
+ return this.state === "spinning";
1099
+ }
1100
+ finish(state) {
1101
+ if (this.timer) {
1102
+ clearInterval(this.timer);
1103
+ this.timer = null;
1104
+ }
1105
+ this.state = state;
1106
+ if (!isInteractive()) {
1107
+ const symbol = state === "success" ? this.symbols.success : this.symbols.error;
1108
+ const colorFn = state === "success" ? colors.success : colors.error;
1109
+ console.log(`${colorFn(symbol)} ${this.label}`);
1110
+ } else {
1111
+ this.clearOutput();
1112
+ const symbol = state === "success" ? this.symbols.success : this.symbols.error;
1113
+ const colorFn = state === "success" ? colors.success : colors.error;
1114
+ process.stdout.write(`${colorFn(symbol)} ${this.label}
1115
+ `);
1116
+ }
1117
+ this.cleanup();
1118
+ }
1119
+ render() {
1120
+ if (!isTTY())
1121
+ return;
1122
+ this.clearOutput();
1123
+ const frame = this.colorFn(this.frames[this.frameIndex]);
1124
+ const width = getTerminalWidth();
1125
+ const mainLine = truncate(`${frame} ${this.label}`, width);
1126
+ process.stdout.write(mainLine);
1127
+ let lines = 1;
1128
+ if (this.detail) {
1129
+ const detailLine = truncate(` ${colors.muted(this.detail)}`, width);
1130
+ process.stdout.write(`
1131
+ ${detailLine}`);
1132
+ lines = 2;
1133
+ }
1134
+ this.lastRenderedLines = lines;
1135
+ }
1136
+ clearOutput() {
1137
+ if (!isTTY())
1138
+ return;
1139
+ for (let i = 0;i < this.lastRenderedLines; i++) {
1140
+ if (i > 0)
1141
+ process.stdout.write(cursor.up(1));
1142
+ clearLine();
1143
+ }
1144
+ }
1145
+ setupSignalHandler() {
1146
+ this.sigintHandler = () => {
1147
+ this.cleanup();
1148
+ process.exit(130);
1149
+ };
1150
+ process.on("SIGINT", this.sigintHandler);
1151
+ }
1152
+ cleanup() {
1153
+ if (this.sigintHandler) {
1154
+ process.removeListener("SIGINT", this.sigintHandler);
1155
+ this.sigintHandler = null;
1156
+ }
1157
+ showCursor();
1158
+ }
1159
+ }
1160
+ function spinner(label, options) {
1161
+ return new Spinner({ ...options, label }).start();
1162
+ }
1163
+
1164
+ class StepProgress {
1165
+ steps = [];
1166
+ showNumbers;
1167
+ spinnerInterval;
1168
+ spinnerFrames;
1169
+ spinnerIndex = 0;
1170
+ timer = null;
1171
+ symbols = getSymbols(supportsUnicode());
1172
+ lastRenderedLines = 0;
1173
+ sigintHandler = null;
1174
+ constructor(options = {}) {
1175
+ this.showNumbers = options.showNumbers ?? true;
1176
+ this.spinnerInterval = options.spinnerInterval ?? 80;
1177
+ this.spinnerFrames = supportsUnicode() ? ["◐", "◓", "◑", "◒"] : ["-", "\\", "|", "/"];
1178
+ if (options.steps) {
1179
+ this.steps = options.steps.map((label) => ({ label, status: "pending" }));
1180
+ }
1181
+ }
1182
+ start() {
1183
+ if (!isInteractive())
1184
+ return this;
1185
+ hideCursor();
1186
+ this.setupSignalHandler();
1187
+ this.render();
1188
+ this.timer = setInterval(() => {
1189
+ this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerFrames.length;
1190
+ if (this.steps.some((s) => s.status === "active")) {
1191
+ this.render();
1192
+ }
1193
+ }, this.spinnerInterval);
1194
+ return this;
1195
+ }
1196
+ addStep(label) {
1197
+ this.steps.push({ label, status: "pending" });
1198
+ if (isInteractive())
1199
+ this.render();
1200
+ return this;
1201
+ }
1202
+ startStep(index) {
1203
+ if (index >= 0 && index < this.steps.length) {
1204
+ this.steps[index].status = "active";
1205
+ this.steps[index].startTime = Date.now();
1206
+ if (isInteractive()) {
1207
+ this.render();
1208
+ } else {
1209
+ const step = this.steps[index];
1210
+ const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
1211
+ console.log(`${this.symbols.bullet} ${prefix2}${step.label}...`);
1212
+ }
1213
+ }
1214
+ return this;
1215
+ }
1216
+ completeStep(index) {
1217
+ if (index >= 0 && index < this.steps.length) {
1218
+ this.steps[index].status = "completed";
1219
+ this.steps[index].endTime = Date.now();
1220
+ if (isInteractive()) {
1221
+ this.render();
1222
+ } else {
1223
+ const step = this.steps[index];
1224
+ const duration = this.getStepDuration(step);
1225
+ const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
1226
+ console.log(`${colors.success(this.symbols.success)} ${prefix2}${step.label}${duration}`);
1227
+ }
1228
+ }
1229
+ return this;
1230
+ }
1231
+ failStep(index) {
1232
+ if (index >= 0 && index < this.steps.length) {
1233
+ this.steps[index].status = "failed";
1234
+ this.steps[index].endTime = Date.now();
1235
+ if (isInteractive()) {
1236
+ this.render();
1237
+ } else {
1238
+ const step = this.steps[index];
1239
+ const prefix2 = this.showNumbers ? `[${index + 1}/${this.steps.length}] ` : "";
1240
+ console.log(`${colors.error(this.symbols.error)} ${prefix2}${step.label}`);
1241
+ }
1242
+ }
1243
+ return this;
1244
+ }
1245
+ skipStep(index) {
1246
+ if (index >= 0 && index < this.steps.length) {
1247
+ this.steps[index].status = "skipped";
1248
+ if (isInteractive())
1249
+ this.render();
1250
+ }
1251
+ return this;
1252
+ }
1253
+ async run(tasks) {
1254
+ this.steps = tasks.map((t) => ({ label: t.label, status: "pending" }));
1255
+ this.start();
1256
+ const results = [];
1257
+ let failed = false;
1258
+ for (let i = 0;i < tasks.length; i++) {
1259
+ if (failed) {
1260
+ this.skipStep(i);
1261
+ continue;
1262
+ }
1263
+ this.startStep(i);
1264
+ try {
1265
+ results.push(await tasks[i].task());
1266
+ this.completeStep(i);
1267
+ } catch {
1268
+ this.failStep(i);
1269
+ failed = true;
1270
+ }
1271
+ }
1272
+ this.stop();
1273
+ return { results, failed };
1274
+ }
1275
+ stop() {
1276
+ if (this.timer) {
1277
+ clearInterval(this.timer);
1278
+ this.timer = null;
1279
+ }
1280
+ this.cleanup();
1281
+ return this;
1282
+ }
1283
+ get currentStepIndex() {
1284
+ const activeIdx = this.steps.findIndex((s) => s.status === "active");
1285
+ if (activeIdx >= 0)
1286
+ return activeIdx;
1287
+ return this.steps.findIndex((s) => s.status === "pending");
1288
+ }
1289
+ render() {
1290
+ if (!isTTY())
1291
+ return;
1292
+ if (this.lastRenderedLines > 0) {
1293
+ moveCursorUp(this.lastRenderedLines - 1);
1294
+ for (let i = 0;i < this.lastRenderedLines; i++) {
1295
+ clearLine();
1296
+ if (i < this.lastRenderedLines - 1) {
1297
+ process.stdout.write(cursor.down(1));
1298
+ }
1299
+ }
1300
+ moveCursorUp(this.lastRenderedLines - 1);
1301
+ }
1302
+ const width = getTerminalWidth();
1303
+ const lines = [];
1304
+ for (let i = 0;i < this.steps.length; i++) {
1305
+ const step = this.steps[i];
1306
+ const prefix2 = this.showNumbers ? `[${i + 1}/${this.steps.length}] ` : "";
1307
+ const duration = this.getStepDuration(step);
1308
+ let symbol;
1309
+ let text;
1310
+ switch (step.status) {
1311
+ case "completed":
1312
+ symbol = colors.success(this.symbols.success);
1313
+ text = `${prefix2}${step.label}${duration}`;
1314
+ break;
1315
+ case "failed":
1316
+ symbol = colors.error(this.symbols.error);
1317
+ text = `${prefix2}${step.label}`;
1318
+ break;
1319
+ case "active":
1320
+ symbol = colors.primary(this.spinnerFrames[this.spinnerIndex]);
1321
+ text = `${prefix2}${step.label}`;
1322
+ break;
1323
+ case "skipped":
1324
+ symbol = colors.muted(this.symbols.bullet);
1325
+ text = colors.muted(`${prefix2}${step.label} (skipped)`);
1326
+ break;
1327
+ default:
1328
+ symbol = colors.muted("○");
1329
+ text = colors.muted(`${prefix2}${step.label}`);
1330
+ }
1331
+ lines.push(truncate(`${symbol} ${text}`, width));
1332
+ }
1333
+ process.stdout.write(lines.join(`
1334
+ `));
1335
+ this.lastRenderedLines = lines.length;
1336
+ }
1337
+ getStepDuration(step) {
1338
+ if (step.startTime && step.endTime) {
1339
+ const ms = step.endTime - step.startTime;
1340
+ return colors.muted(` (${formatDuration(ms)})`);
1341
+ }
1342
+ return "";
1343
+ }
1344
+ setupSignalHandler() {
1345
+ this.sigintHandler = () => {
1346
+ this.cleanup();
1347
+ process.exit(130);
1348
+ };
1349
+ process.on("SIGINT", this.sigintHandler);
1350
+ }
1351
+ cleanup() {
1352
+ if (this.sigintHandler) {
1353
+ process.removeListener("SIGINT", this.sigintHandler);
1354
+ this.sigintHandler = null;
1355
+ }
1356
+ showCursor();
1357
+ if (isTTY() && this.lastRenderedLines > 0) {
1358
+ process.stdout.write(`
1359
+ `);
1360
+ }
1361
+ }
1362
+ }
1363
+ class Summary {
1364
+ items = [];
1365
+ title;
1366
+ boxed;
1367
+ keyWidth;
1368
+ symbols = getSymbols(supportsUnicode());
1369
+ constructor(options = {}) {
1370
+ this.title = options.title;
1371
+ this.boxed = options.boxed ?? false;
1372
+ this.keyWidth = options.keyWidth;
1373
+ }
1374
+ add(item) {
1375
+ this.items.push(item);
1376
+ return this;
1377
+ }
1378
+ addKeyValue(key, value, status) {
1379
+ return this.add({ key, value, status });
1380
+ }
1381
+ addWithThreshold(key, value, threshold) {
1382
+ const status = this.evaluateThreshold(value, threshold) ? "pass" : "fail";
1383
+ return this.add({ key, value, status, threshold });
1384
+ }
1385
+ print() {
1386
+ const output = this.render();
1387
+ console.log(output);
1388
+ }
1389
+ render() {
1390
+ if (this.items.length === 0)
1391
+ return "";
1392
+ const lines = [];
1393
+ const termWidth = getTerminalWidth();
1394
+ const calculatedKeyWidth = this.keyWidth ?? Math.max(...this.items.map((i) => i.key.length));
1395
+ if (this.boxed) {
1396
+ return this.renderBoxed(calculatedKeyWidth, termWidth);
1397
+ }
1398
+ if (this.title) {
1399
+ lines.push(colors.bold(this.title));
1400
+ lines.push("");
1401
+ }
1402
+ for (const item of this.items) {
1403
+ lines.push(this.formatItem(item, calculatedKeyWidth));
1404
+ }
1405
+ return lines.join(`
1406
+ `);
1407
+ }
1408
+ renderBoxed(keyWidth, termWidth) {
1409
+ const lines = [];
1410
+ const unicode = supportsUnicode();
1411
+ const box = unicode ? { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│" } : { tl: "+", tr: "+", bl: "+", br: "+", h: "-", v: "|" };
1412
+ const contentLines = this.items.map((item) => this.formatItem(item, keyWidth));
1413
+ const maxContentWidth = Math.max(...contentLines.map((l) => stripAnsi(l).length), this.title ? this.title.length : 0);
1414
+ const innerWidth = Math.min(maxContentWidth + 2, termWidth - 4);
1415
+ lines.push(box.tl + box.h.repeat(innerWidth) + box.tr);
1416
+ if (this.title) {
1417
+ const padding = innerWidth - this.title.length;
1418
+ const leftPad = Math.floor(padding / 2);
1419
+ const rightPad = padding - leftPad;
1420
+ lines.push(`${box.v}${" ".repeat(leftPad)}${colors.bold(this.title)}${" ".repeat(rightPad)}${box.v}`);
1421
+ lines.push(`${box.v}${" ".repeat(innerWidth)}${box.v}`);
1422
+ }
1423
+ for (const line of contentLines) {
1424
+ const visibleLen = stripAnsi(line).length;
1425
+ const padding = innerWidth - visibleLen - 1;
1426
+ lines.push(`${box.v} ${line}${" ".repeat(Math.max(0, padding))}${box.v}`);
1427
+ }
1428
+ lines.push(box.bl + box.h.repeat(innerWidth) + box.br);
1429
+ return lines.join(`
1430
+ `);
1431
+ }
1432
+ formatItem(item, keyWidth) {
1433
+ const key = item.key.padEnd(keyWidth);
1434
+ const value = String(item.value);
1435
+ let indicator = "";
1436
+ if (item.status) {
1437
+ switch (item.status) {
1438
+ case "pass":
1439
+ indicator = `${colors.success(this.symbols.success)} `;
1440
+ break;
1441
+ case "fail":
1442
+ indicator = `${colors.error(this.symbols.error)} `;
1443
+ break;
1444
+ case "warn":
1445
+ indicator = `${colors.warning(this.symbols.warning)} `;
1446
+ break;
1447
+ case "info":
1448
+ indicator = `${colors.info(this.symbols.info)} `;
1449
+ break;
1450
+ }
1451
+ }
1452
+ let thresholdStr = "";
1453
+ if (item.threshold) {
1454
+ const { operator, value: thresh } = item.threshold;
1455
+ thresholdStr = colors.muted(` (${operator} ${thresh})`);
1456
+ }
1457
+ let coloredValue = value;
1458
+ if (item.status === "pass")
1459
+ coloredValue = colors.success(value);
1460
+ else if (item.status === "fail")
1461
+ coloredValue = colors.error(value);
1462
+ else if (item.status === "warn")
1463
+ coloredValue = colors.warning(value);
1464
+ return `${indicator}${colors.muted(key)} ${coloredValue}${thresholdStr}`;
1465
+ }
1466
+ evaluateThreshold(value, threshold) {
1467
+ if (!threshold)
1468
+ return true;
1469
+ const { operator, value: thresh } = threshold;
1470
+ switch (operator) {
1471
+ case "<":
1472
+ return value < thresh;
1473
+ case ">":
1474
+ return value > thresh;
1475
+ case "<=":
1476
+ return value <= thresh;
1477
+ case ">=":
1478
+ return value >= thresh;
1479
+ }
1480
+ }
1481
+ }
1482
+ function summary(options) {
1483
+ return new Summary(options);
1484
+ }
1485
+
1486
+ // src/cli/spec.ts
9
1487
  import { normalize, validateSpec } from "@openpkg-ts/spec";
10
1488
  import { Command } from "commander";
11
1489
  function createProgram() {
12
- const program = new Command("tspec").description("Extract TypeScript package API to OpenPkg spec").argument("[entry]", "Entry point file").option("-o, --output <file>", "Output file", "openpkg.json").option("--max-depth <n>", "Max type depth (default: 4)").option("--skip-resolve", "Skip external type resolution").option("--runtime", "Enable Standard Schema runtime extraction").action(async (entry, options) => {
13
- const entryFile = entry || findEntryPoint(process.cwd());
14
- if (!entryFile) {
15
- console.error("No entry point found. Please specify an entry file.");
16
- process.exit(1);
1490
+ const program = new Command("tspec").description("Extract TypeScript package API to OpenPkg spec").argument("[entry]", "Entry point file").option("-o, --output <file>", "Output file", "openpkg.json").option("--max-depth <n>", "Max type depth (default: 4)").option("--skip-resolve", "Skip external type resolution").option("--runtime", "Enable Standard Schema runtime extraction").option("-v, --verbose", "Show detailed output").action(async (entry, options) => {
1491
+ let entryFile;
1492
+ let fromDts = false;
1493
+ if (entry) {
1494
+ entryFile = entry;
1495
+ fromDts = entry.endsWith(".d.ts");
1496
+ } else {
1497
+ const found = findEntryPoint(process.cwd());
1498
+ if (!found) {
1499
+ console.error("No entry point found. Please specify an entry file.");
1500
+ process.exit(1);
1501
+ }
1502
+ entryFile = found.path;
1503
+ fromDts = found.fromDts;
1504
+ }
1505
+ if (fromDts) {
1506
+ console.warn("⚠ Using .d.ts file. TSDoc comments may be missing.");
1507
+ console.warn(` Consider: tspec src/index.ts
1508
+ `);
17
1509
  }
18
- console.log(`Extracting from: ${entryFile}`);
1510
+ const spin = spinner("Extracting...");
19
1511
  const result = await extract({
20
1512
  entryFile: path.resolve(entryFile),
21
1513
  ...options.maxDepth ? { maxTypeDepth: parseInt(options.maxDepth) } : {},
22
1514
  resolveExternalTypes: !options.skipResolve,
23
1515
  schemaExtraction: options.runtime ? "hybrid" : "static"
24
1516
  });
25
- for (const diag of result.diagnostics) {
26
- const prefix = diag.severity === "error" ? "✗" : diag.severity === "warning" ? "⚠" : "ℹ";
27
- console.log(`${prefix} ${diag.message}`);
28
- }
29
1517
  const normalized = normalize(result.spec);
30
1518
  const validation = validateSpec(normalized);
31
1519
  if (!validation.ok) {
32
- console.error("Validation failed:");
1520
+ spin.fail("Extraction failed");
1521
+ console.error("Validation errors:");
33
1522
  for (const err of validation.errors) {
34
1523
  console.error(` - ${err.instancePath}: ${err.message}`);
35
1524
  }
36
1525
  process.exit(1);
37
1526
  }
38
1527
  fs.writeFileSync(options.output, JSON.stringify(normalized, null, 2));
39
- console.log(`Generated ${options.output}`);
40
- console.log(` ${normalized.exports.length} exports`);
41
- console.log(` ${normalized.types?.length || 0} types`);
1528
+ spin.success(`Extracted to ${options.output}`);
1529
+ for (const diag of result.diagnostics) {
1530
+ if (diag.severity === "info" && !options.verbose)
1531
+ continue;
1532
+ const prefix2 = diag.severity === "error" ? "✗" : diag.severity === "warning" ? "⚠" : "ℹ";
1533
+ console.log(`${prefix2} ${diag.message}`);
1534
+ }
1535
+ summary().addKeyValue("Exports", normalized.exports.length).addKeyValue("Types", normalized.types?.length || 0).print();
42
1536
  });
43
1537
  return program;
44
1538
  }
45
1539
  function findEntryPoint(cwd) {
1540
+ const sourceEntries = ["src/index.ts", "index.ts", "lib/index.ts"];
1541
+ for (const entry of sourceEntries) {
1542
+ const fullPath = path.join(cwd, entry);
1543
+ if (fs.existsSync(fullPath))
1544
+ return { path: fullPath, fromDts: false };
1545
+ }
46
1546
  const pkgPath = path.join(cwd, "package.json");
47
1547
  if (fs.existsSync(pkgPath)) {
48
1548
  try {
49
1549
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
50
- if (pkg.types)
51
- return path.join(cwd, pkg.types);
52
- if (pkg.typings)
53
- return path.join(cwd, pkg.typings);
54
- if (pkg.exports?.["."]?.types)
55
- return path.join(cwd, pkg.exports["."].types);
1550
+ if (pkg.types) {
1551
+ const p = path.join(cwd, pkg.types);
1552
+ return { path: p, fromDts: pkg.types.endsWith(".d.ts") };
1553
+ }
1554
+ if (pkg.typings) {
1555
+ const p = path.join(cwd, pkg.typings);
1556
+ return { path: p, fromDts: pkg.typings.endsWith(".d.ts") };
1557
+ }
1558
+ if (pkg.exports?.["."]?.types) {
1559
+ const p = path.join(cwd, pkg.exports["."].types);
1560
+ return { path: p, fromDts: pkg.exports["."].types.endsWith(".d.ts") };
1561
+ }
56
1562
  if (pkg.main) {
57
1563
  const mainTs = pkg.main.replace(/\.js$/, ".ts");
58
- if (fs.existsSync(path.join(cwd, mainTs)))
59
- return path.join(cwd, mainTs);
1564
+ const fullPath = path.join(cwd, mainTs);
1565
+ if (fs.existsSync(fullPath))
1566
+ return { path: fullPath, fromDts: false };
60
1567
  }
61
1568
  } catch {}
62
1569
  }
63
- const fallbacks = ["src/index.ts", "index.ts", "lib/index.ts"];
64
- for (const fallback of fallbacks) {
65
- const fullPath = path.join(cwd, fallback);
66
- if (fs.existsSync(fullPath))
67
- return fullPath;
68
- }
69
1570
  return null;
70
1571
  }
71
1572