@socketsecurity/lib 5.19.0 → 5.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/cache-with-ttl.d.ts +7 -0
  3. package/dist/cache-with-ttl.js +26 -7
  4. package/dist/constants/socket.js +1 -1
  5. package/dist/dlx/lockfile.js +4 -1
  6. package/dist/dlx/manifest.d.ts +10 -4
  7. package/dist/dlx/package.d.ts +1 -1
  8. package/dist/dlx/package.js +5 -2
  9. package/dist/external/@inquirer/checkbox.js +5 -0
  10. package/dist/external/@inquirer/confirm.js +5 -0
  11. package/dist/external/@inquirer/input.js +5 -0
  12. package/dist/external/@inquirer/password.js +5 -0
  13. package/dist/external/@inquirer/search.js +5 -0
  14. package/dist/external/@inquirer/select.js +5 -0
  15. package/dist/external/@npmcli/package-json/lib/read-package.js +40 -32
  16. package/dist/external/@npmcli/package-json/lib/sort.js +104 -92
  17. package/dist/external/@sinclair/typebox/value.js +9007 -0
  18. package/dist/external/@sinclair/typebox.js +7891 -0
  19. package/dist/external/external-pack.js +2749 -28
  20. package/dist/http-request.d.ts +0 -25
  21. package/dist/http-request.js +6 -5
  22. package/dist/ipc.js +43 -10
  23. package/dist/json/edit.d.ts +1 -1
  24. package/dist/memoization.js +6 -0
  25. package/dist/paths/packages.js +6 -2
  26. package/dist/promise-queue.js +1 -1
  27. package/dist/stdio/clear.d.ts +163 -0
  28. package/dist/stdio/clear.js +96 -0
  29. package/dist/stdio/progress.d.ts +152 -0
  30. package/dist/stdio/progress.js +217 -0
  31. package/dist/stdio/prompts.d.ts +196 -0
  32. package/dist/stdio/prompts.js +177 -0
  33. package/dist/tables.js +2 -3
  34. package/dist/validation/validate-schema.d.ts +124 -0
  35. package/dist/validation/validate-schema.js +108 -0
  36. package/package.json +25 -6
  37. package/dist/external/zod.js +0 -7825
  38. package/dist/zod.d.ts +0 -5
  39. package/dist/zod.js +0 -30
@@ -890,31 +890,6 @@ export declare function httpRequest(url: string, options?: HttpRequestOptions |
890
890
  * ```
891
891
  */
892
892
  export declare function httpText(url: string, options?: HttpRequestOptions | undefined): Promise<string>;
893
- /**
894
- * Parse a checksums file text into a filename-to-hash map.
895
- *
896
- * Supports standard checksums file formats:
897
- * - BSD style: "SHA256 (filename) = hash"
898
- * - GNU style: "hash filename" (two spaces)
899
- * - Simple style: "hash filename" (single space)
900
- *
901
- * Lines starting with '#' are treated as comments and ignored.
902
- * Empty lines are ignored.
903
- *
904
- * @param text - Raw text content of a checksums file
905
- * @returns Map of filenames to lowercase SHA256 hashes
906
- *
907
- * @example
908
- * ```ts
909
- * const text = `
910
- * # SHA256 checksums
911
- * e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file.zip
912
- * abc123def456... other.tar.gz
913
- * `
914
- * const checksums = parseChecksums(text)
915
- * console.log(checksums['file.zip']) // 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
916
- * ```
917
- */
918
893
  export declare function parseChecksums(text: string): Checksums;
919
894
  /**
920
895
  * Parse a `Retry-After` HTTP header value into milliseconds.
@@ -644,6 +644,9 @@ async function httpText(url, options) {
644
644
  }
645
645
  return response.text();
646
646
  }
647
+ const CHECKSUM_BSD_RE = /^SHA256\s+\((.+)\)\s+=\s+([a-fA-F0-9]{64})$/;
648
+ const CHECKSUM_GNU_RE = /^([a-fA-F0-9]{64})\s+(.+)$/;
649
+ const RETRY_AFTER_INT_RE = /^\d+$/;
647
650
  function parseChecksums(text) {
648
651
  const checksums = { __proto__: null };
649
652
  for (const line of text.split("\n")) {
@@ -651,14 +654,12 @@ function parseChecksums(text) {
651
654
  if (!trimmed || trimmed.startsWith("#")) {
652
655
  continue;
653
656
  }
654
- const bsdMatch = trimmed.match(
655
- /^SHA256\s+\((.+)\)\s+=\s+([a-fA-F0-9]{64})$/
656
- );
657
+ const bsdMatch = CHECKSUM_BSD_RE.exec(trimmed);
657
658
  if (bsdMatch) {
658
659
  checksums[bsdMatch[1]] = bsdMatch[2].toLowerCase();
659
660
  continue;
660
661
  }
661
- const gnuMatch = trimmed.match(/^([a-fA-F0-9]{64})\s+(.+)$/);
662
+ const gnuMatch = CHECKSUM_GNU_RE.exec(trimmed);
662
663
  if (gnuMatch) {
663
664
  checksums[gnuMatch[2]] = gnuMatch[1].toLowerCase();
664
665
  }
@@ -674,7 +675,7 @@ function parseRetryAfterHeader(value) {
674
675
  return void 0;
675
676
  }
676
677
  const trimmed = raw.trim();
677
- if (/^\d+$/.test(trimmed)) {
678
+ if (RETRY_AFTER_INT_RE.test(trimmed)) {
678
679
  const seconds = Number(trimmed);
679
680
  return seconds * 1e3;
680
681
  }
package/dist/ipc.js CHANGED
@@ -35,15 +35,16 @@ __export(ipc_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(ipc_exports);
37
37
  var import_node_process = __toESM(require("node:process"));
38
+ var import_typebox = require("./external/@sinclair/typebox");
38
39
  var import_socket = require("./paths/socket");
39
- var import_zod = require("./zod");
40
- const IpcStubSchema = import_zod.z.object({
40
+ var import_validate_schema = require("./validation/validate-schema");
41
+ const IpcStubSchema = import_typebox.Type.Object({
41
42
  /** Process ID that created the stub. */
42
- pid: import_zod.z.number().int().positive(),
43
+ pid: import_typebox.Type.Integer({ minimum: 1 }),
43
44
  /** Creation timestamp for age validation. */
44
- timestamp: import_zod.z.number().positive(),
45
+ timestamp: import_typebox.Type.Number({ exclusiveMinimum: 0 }),
45
46
  /** The actual data payload. */
46
- data: import_zod.z.unknown()
47
+ data: import_typebox.Type.Unknown()
47
48
  });
48
49
  let _fs;
49
50
  let _path;
@@ -52,6 +53,24 @@ async function ensureIpcDirectory(filePath) {
52
53
  const path = /* @__PURE__ */ getPath();
53
54
  const dir = path.dirname(filePath);
54
55
  await fs.promises.mkdir(dir, { recursive: true, mode: 448 });
56
+ if (import_node_process.default.platform === "win32") {
57
+ return;
58
+ }
59
+ const stats = await fs.promises.lstat(dir);
60
+ if (!stats.isDirectory()) {
61
+ throw new Error(`IPC path is not a directory: ${dir}`);
62
+ }
63
+ const getuid = import_node_process.default.getuid;
64
+ const ownUid = typeof getuid === "function" ? getuid.call(import_node_process.default) : -1;
65
+ if (ownUid !== -1 && stats.uid !== ownUid) {
66
+ throw new Error(
67
+ `IPC directory ${dir} is owned by another user (uid ${stats.uid}); refusing to use it.`
68
+ );
69
+ }
70
+ const mode = stats.mode & 511;
71
+ if ((mode & 63) !== 0) {
72
+ await fs.promises.chmod(dir, 448);
73
+ }
55
74
  }
56
75
  // @__NO_SIDE_EFFECTS__
57
76
  function getFs() {
@@ -81,12 +100,26 @@ async function writeIpcStub(appName, data) {
81
100
  pid: import_node_process.default.pid,
82
101
  timestamp: Date.now()
83
102
  };
84
- const validated = IpcStubSchema.parse(ipcData);
103
+ const validated = (0, import_validate_schema.parseSchema)(IpcStubSchema, ipcData);
85
104
  const fs = /* @__PURE__ */ getFs();
86
- await fs.promises.writeFile(stubPath, JSON.stringify(validated, null, 2), {
87
- encoding: "utf8",
88
- mode: 384
89
- });
105
+ const flags = fs.constants.O_CREAT | fs.constants.O_WRONLY | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW;
106
+ let handle;
107
+ try {
108
+ handle = await fs.promises.open(stubPath, flags, 384);
109
+ } catch (e) {
110
+ const err = e;
111
+ if (err.code === "EEXIST") {
112
+ await fs.promises.unlink(stubPath);
113
+ handle = await fs.promises.open(stubPath, flags, 384);
114
+ } else {
115
+ throw err;
116
+ }
117
+ }
118
+ try {
119
+ await handle.writeFile(JSON.stringify(validated, null, 2), "utf8");
120
+ } finally {
121
+ await handle.close();
122
+ }
90
123
  return stubPath;
91
124
  }
92
125
  // Annotate the CommonJS export names for ESM import in node:
@@ -7,7 +7,7 @@ import type { EditableJsonConstructor } from './types';
7
7
  *
8
8
  * @example
9
9
  * ```ts
10
- * import { getEditableJsonClass } from '@socketsecurity/lib/json'
10
+ * import { getEditableJsonClass } from '@socketsecurity/lib/json/edit'
11
11
  *
12
12
  * const EditableJson = getEditableJsonClass<MyConfigType>()
13
13
  * const config = await EditableJson.load('./config.json')
@@ -183,6 +183,11 @@ function memoizeAsync(fn, options = {}) {
183
183
  const inflight = refreshing.get(key);
184
184
  if (inflight) {
185
185
  (0, import_debug.debugLog)(`[memoizeAsync:${name}] stale-dedup`, { key });
186
+ const inflightIndex = accessOrder.indexOf(key);
187
+ if (inflightIndex !== -1) {
188
+ accessOrder.splice(inflightIndex, 1);
189
+ }
190
+ accessOrder.push(key);
186
191
  return await inflight;
187
192
  }
188
193
  cache.delete(key);
@@ -198,6 +203,7 @@ function memoizeAsync(fn, options = {}) {
198
203
  const entry = cache.get(key);
199
204
  if (entry) {
200
205
  entry.value = Promise.resolve(result);
206
+ entry.timestamp = Date.now();
201
207
  }
202
208
  return result;
203
209
  },
@@ -34,8 +34,12 @@ function getPath() {
34
34
  return _path;
35
35
  }
36
36
  // @__NO_SIDE_EFFECTS__
37
+ function isPackageJsonFile(filepath) {
38
+ return filepath === "package.json" || filepath.endsWith("/package.json") || filepath.endsWith("\\package.json");
39
+ }
40
+ // @__NO_SIDE_EFFECTS__
37
41
  function resolvePackageJsonDirname(filepath) {
38
- if (filepath.endsWith("package.json")) {
42
+ if (/* @__PURE__ */ isPackageJsonFile(filepath)) {
39
43
  const path = /* @__PURE__ */ getPath();
40
44
  return (0, import_normalize.normalizePath)(path.dirname(filepath));
41
45
  }
@@ -43,7 +47,7 @@ function resolvePackageJsonDirname(filepath) {
43
47
  }
44
48
  // @__NO_SIDE_EFFECTS__
45
49
  function resolvePackageJsonPath(filepath) {
46
- if (filepath.endsWith("package.json")) {
50
+ if (/* @__PURE__ */ isPackageJsonFile(filepath)) {
47
51
  return (0, import_normalize.normalizePath)(filepath);
48
52
  }
49
53
  const path = /* @__PURE__ */ getPath();
@@ -69,7 +69,7 @@ class PromiseQueue {
69
69
  return;
70
70
  }
71
71
  this.running++;
72
- task.fn().then(task.resolve).catch(task.reject).finally(() => {
72
+ Promise.resolve().then(() => task.fn()).then(task.resolve).catch(task.reject).finally(() => {
73
73
  this.running--;
74
74
  this.runNext();
75
75
  });
@@ -0,0 +1,163 @@
1
+ /**
2
+ * @fileoverview Terminal clearing and cursor utilities.
3
+ * Provides functions for clearing lines, screens, and managing cursor position.
4
+ */
5
+ /**
6
+ * Clear the current line in the terminal.
7
+ * Uses native TTY methods when available, falls back to ANSI escape codes.
8
+ * Uses native TTY methods when available and falls back to `\r\x1b[K` ANSI
9
+ * escapes on non-TTY streams.
10
+ *
11
+ * ANSI Sequences:
12
+ * - `\r`: Carriage return (move to line start)
13
+ * - `\x1b[K`: Clear from cursor to end of line
14
+ *
15
+ * @param stream - Output stream to clear (defaults to `process.stdout`)
16
+ * @default stream process.stdout
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * clearLine() // Clear current line on stdout
21
+ * clearLine(process.stderr) // Clear on stderr
22
+ * ```
23
+ */
24
+ export declare function clearLine(stream?: NodeJS.WriteStream): void;
25
+ /**
26
+ * Clear multiple lines above the current cursor position.
27
+ * Useful for clearing multi-line output like progress bars or status messages.
28
+ *
29
+ * ANSI Sequences:
30
+ * - `\x1b[1A`: Move cursor up one line
31
+ * - `\x1b[2K`: Erase entire line
32
+ *
33
+ * @param count - Number of lines to clear
34
+ * @param stream - Output stream to clear
35
+ * @default stream process.stdout
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * console.log('Line 1')
40
+ * console.log('Line 2')
41
+ * console.log('Line 3')
42
+ * clearLines(2) // Clears lines 2 and 3
43
+ * ```
44
+ */
45
+ export declare function clearLines(count: number, stream?: NodeJS.WriteStream): void;
46
+ /**
47
+ * Clear the entire screen and reset cursor to top-left.
48
+ * Only works in TTY environments.
49
+ *
50
+ * ANSI Sequence:
51
+ * - `\x1bc`: Full reset (clear screen and move cursor home)
52
+ *
53
+ * @param stream - Output stream to clear
54
+ * @default stream process.stdout
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * clearScreen() // Clear entire terminal
59
+ * ```
60
+ */
61
+ export declare function clearScreen(stream?: NodeJS.WriteStream): void;
62
+ /**
63
+ * Clear the visible terminal screen.
64
+ * Alias for `clearScreen()`.
65
+ *
66
+ * @param stream - Output stream to clear
67
+ * @default stream process.stdout
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * clearVisible() // Same as clearScreen()
72
+ * ```
73
+ */
74
+ export declare function clearVisible(stream?: NodeJS.WriteStream): void;
75
+ /**
76
+ * Move cursor to the beginning of the current line.
77
+ * Uses native TTY methods when available, falls back to carriage return.
78
+ *
79
+ * @param stream - Output stream to manipulate
80
+ * @default stream process.stdout
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * process.stdout.write('Some text...')
85
+ * cursorToStart()
86
+ * process.stdout.write('New text') // Overwrites from start
87
+ * ```
88
+ */
89
+ export declare function cursorToStart(stream?: NodeJS.WriteStream): void;
90
+ /**
91
+ * Hide the terminal cursor.
92
+ * Useful for cleaner output during animations or progress indicators.
93
+ *
94
+ * ANSI Sequence:
95
+ * - `\x1b[?25l`: DECTCEM hide cursor
96
+ *
97
+ * @param stream - Output stream to manipulate
98
+ * @default stream process.stdout
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * hideCursor()
103
+ * // ... show animation
104
+ * showCursor()
105
+ * ```
106
+ */
107
+ export declare function hideCursor(stream?: NodeJS.WriteStream): void;
108
+ /**
109
+ * Restore cursor to previously saved position.
110
+ * Must be called after `saveCursor()`.
111
+ *
112
+ * ANSI Sequence:
113
+ * - `\x1b8`: DECRC restore cursor
114
+ *
115
+ * @param stream - Output stream to manipulate
116
+ * @default stream process.stdout
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * saveCursor()
121
+ * console.log('Temporary text')
122
+ * restoreCursor()
123
+ * console.log('Back at saved position')
124
+ * ```
125
+ */
126
+ export declare function restoreCursor(stream?: NodeJS.WriteStream): void;
127
+ /**
128
+ * Save the current cursor position.
129
+ * Can be restored later with `restoreCursor()`.
130
+ *
131
+ * ANSI Sequence:
132
+ * - `\x1b7`: DECSC save cursor
133
+ *
134
+ * @param stream - Output stream to manipulate
135
+ * @default stream process.stdout
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * saveCursor()
140
+ * console.log('Temporary text')
141
+ * restoreCursor()
142
+ * console.log('Back at saved position')
143
+ * ```
144
+ */
145
+ export declare function saveCursor(stream?: NodeJS.WriteStream): void;
146
+ /**
147
+ * Show the terminal cursor.
148
+ * Should be called after `hideCursor()` to restore normal cursor visibility.
149
+ *
150
+ * ANSI Sequence:
151
+ * - `\x1b[?25h`: DECTCEM show cursor
152
+ *
153
+ * @param stream - Output stream to manipulate
154
+ * @default stream process.stdout
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * hideCursor()
159
+ * // ... show animation
160
+ * showCursor()
161
+ * ```
162
+ */
163
+ export declare function showCursor(stream?: NodeJS.WriteStream): void;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ /* Socket Lib - Built with esbuild */
3
+ "use strict";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
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(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+ var clear_exports = {};
32
+ __export(clear_exports, {
33
+ clearLine: () => clearLine,
34
+ clearLines: () => clearLines,
35
+ clearScreen: () => clearScreen,
36
+ clearVisible: () => clearVisible,
37
+ cursorToStart: () => cursorToStart,
38
+ hideCursor: () => hideCursor,
39
+ restoreCursor: () => restoreCursor,
40
+ saveCursor: () => saveCursor,
41
+ showCursor: () => showCursor
42
+ });
43
+ module.exports = __toCommonJS(clear_exports);
44
+ var import_node_process = __toESM(require("node:process"));
45
+ function clearLine(stream = import_node_process.default.stdout) {
46
+ if (stream.isTTY) {
47
+ stream.cursorTo(0);
48
+ stream.clearLine(0);
49
+ } else {
50
+ stream.write("\r\x1B[K");
51
+ }
52
+ }
53
+ function clearLines(count, stream = import_node_process.default.stdout) {
54
+ for (let i = 0; i < count; i++) {
55
+ stream.write("\x1B[1A\x1B[2K");
56
+ }
57
+ }
58
+ function clearScreen(stream = import_node_process.default.stdout) {
59
+ if (stream.isTTY) {
60
+ stream.write("\x1Bc");
61
+ }
62
+ }
63
+ function clearVisible(stream = import_node_process.default.stdout) {
64
+ clearScreen(stream);
65
+ }
66
+ function cursorToStart(stream = import_node_process.default.stdout) {
67
+ if (stream.isTTY) {
68
+ stream.cursorTo(0);
69
+ } else {
70
+ stream.write("\r");
71
+ }
72
+ }
73
+ function hideCursor(stream = import_node_process.default.stdout) {
74
+ stream.write("\x1B[?25l");
75
+ }
76
+ function restoreCursor(stream = import_node_process.default.stdout) {
77
+ stream.write("\x1B8");
78
+ }
79
+ function saveCursor(stream = import_node_process.default.stdout) {
80
+ stream.write("\x1B7");
81
+ }
82
+ function showCursor(stream = import_node_process.default.stdout) {
83
+ stream.write("\x1B[?25h");
84
+ }
85
+ // Annotate the CommonJS export names for ESM import in node:
86
+ 0 && (module.exports = {
87
+ clearLine,
88
+ clearLines,
89
+ clearScreen,
90
+ clearVisible,
91
+ cursorToStart,
92
+ hideCursor,
93
+ restoreCursor,
94
+ saveCursor,
95
+ showCursor
96
+ });
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @fileoverview Progress bar utilities for CLI applications.
3
+ * Provides various progress indicators including bars, percentages, and spinners.
4
+ */
5
+ export interface ProgressBarOptions {
6
+ /**
7
+ * Width of the progress bar in characters.
8
+ * @default 40
9
+ */
10
+ width?: number | undefined;
11
+ /**
12
+ * Format template for progress bar display.
13
+ * Available tokens: `:bar`, `:percent`, `:current`, `:total`, `:elapsed`, `:eta`.
14
+ * Custom tokens can be passed via the `tokens` parameter in `update()` or `tick()`.
15
+ * @default ':bar :percent :current/:total'
16
+ * @example
17
+ * ```ts
18
+ * format: ':bar :percent :current/:total :eta'
19
+ * ```
20
+ */
21
+ format?: string | undefined;
22
+ /**
23
+ * Character(s) to use for completed portion of bar.
24
+ * @default '█'
25
+ */
26
+ complete?: string | undefined;
27
+ /**
28
+ * Character(s) to use for incomplete portion of bar.
29
+ * @default '░'
30
+ */
31
+ incomplete?: string | undefined;
32
+ /**
33
+ * Character(s) to use for the head of the progress bar.
34
+ * @default ''
35
+ */
36
+ head?: string | undefined;
37
+ /**
38
+ * Clear the progress bar when complete.
39
+ * @default false
40
+ */
41
+ clear?: boolean | undefined;
42
+ /**
43
+ * Minimum time between renders in milliseconds.
44
+ * ~60fps = 16ms throttle.
45
+ * @default 16
46
+ */
47
+ renderThrottle?: number | undefined;
48
+ /**
49
+ * Stream to write progress bar output to.
50
+ * @default process.stderr
51
+ */
52
+ stream?: NodeJS.WriteStream | undefined;
53
+ /**
54
+ * Color to apply to the completed portion of the bar.
55
+ * @default 'cyan'
56
+ */
57
+ color?: 'cyan' | 'green' | 'yellow' | 'blue' | 'magenta' | undefined;
58
+ }
59
+ export declare class ProgressBar {
60
+ private current;
61
+ private total;
62
+ private startTime;
63
+ private lastRender;
64
+ private stream;
65
+ private options;
66
+ private terminated;
67
+ private lastDrawnWidth;
68
+ /**
69
+ * Create a new progress bar instance.
70
+ *
71
+ * @param total - Total number of units for the progress bar
72
+ * @param options - Configuration options for the progress bar
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const bar = new ProgressBar(100, {
77
+ * width: 50,
78
+ * format: ':bar :percent :current/:total :eta',
79
+ * color: 'green'
80
+ * })
81
+ * ```
82
+ */
83
+ constructor(total: number, options?: ProgressBarOptions);
84
+ /**
85
+ * Update progress to a specific value and redraw the bar.
86
+ * Updates are throttled to prevent excessive rendering (default ~60fps).
87
+ *
88
+ * @param current - Current progress value (will be clamped to total)
89
+ * @param tokens - Optional custom tokens to replace in format string
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * bar.update(50)
94
+ * bar.update(75, { status: 'Processing...' })
95
+ * ```
96
+ */
97
+ update(current: number, tokens?: Record<string, unknown>): void;
98
+ /**
99
+ * Increment progress by a specified amount.
100
+ * Convenience method for `update(current + amount)`.
101
+ *
102
+ * @param amount - Amount to increment by
103
+ * @param tokens - Optional custom tokens to replace in format string
104
+ * @default amount 1
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * bar.tick() // Increment by 1
109
+ * bar.tick(5) // Increment by 5
110
+ * bar.tick(1, { file: 'data.json' })
111
+ * ```
112
+ */
113
+ tick(amount?: number, tokens?: Record<string, unknown>): void;
114
+ /**
115
+ * Render the progress bar.
116
+ */
117
+ private render;
118
+ /**
119
+ * Clear the current line.
120
+ */
121
+ private clearLine;
122
+ /**
123
+ * Format time in seconds to human readable.
124
+ */
125
+ private formatTime;
126
+ /**
127
+ * Terminate the progress bar and optionally clear it.
128
+ * Called automatically when progress reaches 100%.
129
+ * If `clear` option is true, removes the bar from terminal.
130
+ * Otherwise, moves to next line to preserve the final state.
131
+ */
132
+ terminate(): void;
133
+ }
134
+ /**
135
+ * Create a simple progress indicator without a graphical bar.
136
+ * Returns a formatted string showing progress as percentage and fraction.
137
+ *
138
+ * @param current - Current progress value
139
+ * @param total - Total progress value
140
+ * @param label - Optional label prefix
141
+ * @returns Formatted progress indicator string
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * createProgressIndicator(50, 100)
146
+ * // Returns: '[50%] 50/100'
147
+ *
148
+ * createProgressIndicator(3, 10, 'Files')
149
+ * // Returns: 'Files: [30%] 3/10'
150
+ * ```
151
+ */
152
+ export declare function createProgressIndicator(current: number, total: number, label?: string | undefined): string;