lifecycleion 0.0.10 → 0.0.11

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 (32) hide show
  1. package/README.md +4 -2
  2. package/dist/lib/event-emitter.cjs.map +1 -1
  3. package/dist/lib/event-emitter.js.map +1 -1
  4. package/dist/lib/http-client/index.cjs.map +1 -1
  5. package/dist/lib/http-client/index.js.map +1 -1
  6. package/dist/lib/lifecycle-manager/index.cjs.map +1 -1
  7. package/dist/lib/lifecycle-manager/index.js.map +1 -1
  8. package/dist/lib/logger/index.cjs +6 -5
  9. package/dist/lib/logger/index.cjs.map +1 -1
  10. package/dist/lib/logger/index.d.cts +3 -3
  11. package/dist/lib/logger/index.d.ts +3 -3
  12. package/dist/lib/logger/index.js +6 -5
  13. package/dist/lib/logger/index.js.map +1 -1
  14. package/dist/lib/lru-cache/index.cjs +896 -29
  15. package/dist/lib/lru-cache/index.cjs.map +1 -1
  16. package/dist/lib/lru-cache/index.d.cts +33 -17
  17. package/dist/lib/lru-cache/index.d.ts +33 -17
  18. package/dist/lib/lru-cache/index.js +884 -29
  19. package/dist/lib/lru-cache/index.js.map +1 -1
  20. package/dist/lib/process-signal-manager.cjs.map +1 -1
  21. package/dist/lib/process-signal-manager.js.map +1 -1
  22. package/dist/lib/promise-protected-resolver.cjs.map +1 -1
  23. package/dist/lib/promise-protected-resolver.js.map +1 -1
  24. package/dist/lib/retry-utils/index.cjs.map +1 -1
  25. package/dist/lib/retry-utils/index.js.map +1 -1
  26. package/dist/lib/safe-handle-callback.cjs.map +1 -1
  27. package/dist/lib/safe-handle-callback.d.cts +2 -2
  28. package/dist/lib/safe-handle-callback.d.ts +2 -2
  29. package/dist/lib/safe-handle-callback.js.map +1 -1
  30. package/dist/lib/single-event-observer.cjs.map +1 -1
  31. package/dist/lib/single-event-observer.js.map +1 -1
  32. package/package.json +2 -2
@@ -1,4 +1,757 @@
1
+ // src/lib/strings.ts
2
+ function isString(value) {
3
+ return typeof value === "string";
4
+ }
5
+ function splitGraphemes(text) {
6
+ const graphemes = [];
7
+ let grapheme = "";
8
+ let zwjSequence = "";
9
+ for (let i = 0; i < text.length; i++) {
10
+ const char = text[i];
11
+ const nextChar = text[i + 1] || "";
12
+ const code = char.charCodeAt(0);
13
+ if (code >= 768 && code <= 879 || // Combining Diacritical Marks
14
+ code >= 6832 && code <= 6911 || // Combining Diacritical Marks Extended
15
+ code >= 7616 && code <= 7679 || // Combining Diacritical Marks Supplement
16
+ code >= 65056 && code <= 65071 || // Combining Half Marks
17
+ code >= 3633 && code <= 3642 || // Thai combining marks
18
+ code >= 3655 && code <= 3662) {
19
+ grapheme += char;
20
+ } else if (char === "\u200D") {
21
+ zwjSequence += grapheme + char;
22
+ grapheme = "";
23
+ } else {
24
+ if (grapheme) {
25
+ if (zwjSequence) {
26
+ graphemes.push(zwjSequence + grapheme);
27
+ zwjSequence = "";
28
+ } else {
29
+ graphemes.push(grapheme);
30
+ }
31
+ }
32
+ grapheme = char;
33
+ if (char >= "\uD800" && char <= "\uDBFF" && nextChar >= "\uDC00" && nextChar <= "\uDFFF") {
34
+ grapheme += nextChar;
35
+ i++;
36
+ }
37
+ }
38
+ }
39
+ if (grapheme) {
40
+ if (zwjSequence) {
41
+ graphemes.push(zwjSequence + grapheme);
42
+ } else {
43
+ graphemes.push(grapheme);
44
+ }
45
+ }
46
+ return graphemes;
47
+ }
48
+
49
+ // src/lib/constants.ts
50
+ var BLANK_SPACE = " ";
51
+ var EOL = "\n";
52
+ var DOUBLE_EOL = EOL + EOL;
53
+ var INDENT = " ".repeat(4);
54
+ var DOUBLE_INDENT = INDENT + INDENT;
55
+ var ASCII_LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
56
+ var ASCII_UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
57
+ var ASCII_LETTERS = ASCII_LOWERCASE + ASCII_UPPERCASE;
58
+ var DIGITS = "0123456789";
59
+ var HEX_DIGITS = DIGITS + "abcdefABCDEF";
60
+ var PUNCTUATION = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
61
+ var WHITESPACE = " \n\r\v\f";
62
+ var PRINTABLE = DIGITS + ASCII_LETTERS + PUNCTUATION + WHITESPACE;
63
+
64
+ // src/lib/padding-utils.ts
65
+ function padLeft(str, length, padStr = BLANK_SPACE) {
66
+ return str.padStart(length, padStr);
67
+ }
68
+ function padRight(str, length, padStr = BLANK_SPACE) {
69
+ return str.padEnd(length, padStr);
70
+ }
71
+ function padCenter(str, length, prefer = "left", padStr = BLANK_SPACE) {
72
+ const midStrLength = length - str.length;
73
+ if (midStrLength > 0) {
74
+ const padLeftAmount = prefer === "left" ? Math.ceil(midStrLength / 2) : Math.floor(midStrLength / 2);
75
+ const padRightAmount = prefer === "left" ? Math.floor(midStrLength / 2) : Math.ceil(midStrLength / 2);
76
+ return padLeft("", padLeftAmount, padStr) + str + padRight("", padRightAmount, padStr);
77
+ } else {
78
+ return str;
79
+ }
80
+ }
81
+ function padCenterPreferRight(str, length, padStr = BLANK_SPACE) {
82
+ return padCenter(str, length, "right", padStr);
83
+ }
84
+
85
+ // src/lib/ascii-tables/ascii-table-utils.ts
86
+ import stringWidth from "string-width";
87
+ var ASCIITableUtils = class _ASCIITableUtils {
88
+ static centerText(text, width) {
89
+ return padCenterPreferRight(text, width, " ");
90
+ }
91
+ static createSeparator(columnWidths, character = "=") {
92
+ const totalWidth = columnWidths.reduce((sum, width) => sum + width + 3, 0) - 1;
93
+ return `+${padRight("", totalWidth, character)}+`;
94
+ }
95
+ static wrapText(text, maxLength) {
96
+ const words = text.split(" ");
97
+ const lines = [];
98
+ let currentLine = "";
99
+ for (const word of words) {
100
+ if (stringWidth(currentLine) + stringWidth(word) + 1 <= maxLength) {
101
+ currentLine += (currentLine ? " " : "") + word;
102
+ } else {
103
+ if (currentLine) {
104
+ lines.push(currentLine);
105
+ }
106
+ if (stringWidth(word) <= maxLength) {
107
+ currentLine = word;
108
+ } else {
109
+ const subWords = _ASCIITableUtils.splitWord(word, maxLength);
110
+ lines.push(...subWords.slice(0, -1));
111
+ currentLine = subWords[subWords.length - 1];
112
+ }
113
+ }
114
+ }
115
+ if (currentLine) {
116
+ lines.push(currentLine);
117
+ }
118
+ return lines;
119
+ }
120
+ static splitWord(word, maxLength) {
121
+ const graphemes = splitGraphemes(word);
122
+ const subWords = [];
123
+ let currentSubWord = "";
124
+ for (const grapheme of graphemes) {
125
+ if (stringWidth(currentSubWord + grapheme) <= maxLength) {
126
+ currentSubWord += grapheme;
127
+ } else {
128
+ subWords.push(currentSubWord);
129
+ currentSubWord = grapheme;
130
+ }
131
+ }
132
+ if (currentSubWord) {
133
+ subWords.push(currentSubWord);
134
+ }
135
+ return subWords;
136
+ }
137
+ };
138
+
139
+ // src/lib/ascii-tables/multi-column-ascii-table.ts
140
+ import stringWidth2 from "string-width";
141
+ var MultiColumnASCIITable = class {
142
+ headers;
143
+ rows;
144
+ tableWidth;
145
+ emptyMessage;
146
+ widthMode;
147
+ constructor(headers, options = {}) {
148
+ this.headers = headers;
149
+ this.rows = [];
150
+ this.tableWidth = options.tableWidth || 80;
151
+ this.emptyMessage = options.emptyMessage || "";
152
+ this.widthMode = options.widthMode || "flex";
153
+ const minTableWidth = this.getMinimumWidth();
154
+ if (this.tableWidth < minTableWidth) {
155
+ throw new Error(
156
+ `Table width must be at least ${minTableWidth} to accommodate the headers.`
157
+ );
158
+ }
159
+ }
160
+ getMinimumWidth() {
161
+ return this.headers.length * 4 + 1;
162
+ }
163
+ addRow(row) {
164
+ if (row.length !== this.headers.length) {
165
+ throw new Error(
166
+ `Number of values in the row (${row.length}) must match the number of headers (${this.headers.length}).`
167
+ );
168
+ }
169
+ this.rows.push(row);
170
+ }
171
+ toString(options = {}) {
172
+ const tableWidth = options.tableWidth || this.tableWidth;
173
+ const emptyMessage = options.emptyMessage || this.emptyMessage;
174
+ if (this.rows.length === 0) {
175
+ const emptyTableWidth = Math.min(tableWidth, 40);
176
+ const separator = "+" + "-".repeat(emptyTableWidth - 2) + "+";
177
+ const emptyMessageLines = ASCIITableUtils.wrapText(
178
+ emptyMessage,
179
+ emptyTableWidth - 4
180
+ );
181
+ const emptyRows = emptyMessageLines.map((line) => {
182
+ const paddingLeft = " ".repeat(
183
+ Math.floor((emptyTableWidth - stringWidth2(line) - 4) / 2)
184
+ );
185
+ const paddingRight = " ".repeat(
186
+ Math.ceil((emptyTableWidth - stringWidth2(line) - 4) / 2)
187
+ );
188
+ return `| ${paddingLeft}${line}${paddingRight} |`;
189
+ });
190
+ if (emptyRows.length === 0) {
191
+ emptyRows.push(`| ${" ".repeat(emptyTableWidth - 4)} |`);
192
+ }
193
+ return [separator, ...emptyRows, separator].join("\n");
194
+ }
195
+ const columnWidths = this.calculateColumnWidths(options);
196
+ const headerSeparator = ASCIITableUtils.createSeparator(columnWidths);
197
+ const rowSeparator = ASCIITableUtils.createSeparator(columnWidths, "-");
198
+ let tableString = headerSeparator + "\n";
199
+ const header = this.renderRow(this.headers, columnWidths);
200
+ tableString += header + "\n" + rowSeparator + "\n";
201
+ const rows = this.rows.map((row) => {
202
+ return this.renderRow(row, columnWidths);
203
+ });
204
+ tableString += rows.join("\n" + rowSeparator + "\n");
205
+ tableString += "\n" + headerSeparator;
206
+ return tableString;
207
+ }
208
+ calculateColumnWidths(options = {}) {
209
+ const tableWidth = options.tableWidth || this.tableWidth;
210
+ const widthMode = options.widthMode || this.widthMode;
211
+ const numColumns = this.headers.length;
212
+ if (widthMode === "fixed") {
213
+ const availableWidth2 = tableWidth - (numColumns + 1) * 3 + 1;
214
+ const columnWidth = Math.floor(availableWidth2 / numColumns);
215
+ const extraWidth = availableWidth2 % numColumns;
216
+ const columnWidths = new Array(numColumns).fill(columnWidth);
217
+ for (let i = 0; i < extraWidth; i++) {
218
+ columnWidths[i] += 1;
219
+ }
220
+ return columnWidths;
221
+ }
222
+ const availableWidth = tableWidth - (numColumns + 1) * 3 + 1;
223
+ const maxColumnWidth = Math.floor(availableWidth / numColumns);
224
+ const totalContentWidth = this.headers.reduce(
225
+ (sum, header) => sum + stringWidth2(header),
226
+ 0
227
+ );
228
+ if (availableWidth >= totalContentWidth) {
229
+ const remainingWidth = availableWidth - totalContentWidth;
230
+ const extraCharWidth = Math.floor(remainingWidth / numColumns);
231
+ const extraCharRemainder = remainingWidth % numColumns;
232
+ const columnWidths = this.headers.map((header, index) => {
233
+ const extraWidth = index < extraCharRemainder ? 1 : 0;
234
+ return stringWidth2(header) + extraCharWidth + extraWidth;
235
+ });
236
+ return columnWidths;
237
+ } else {
238
+ const columnWidths = this.headers.map(() => maxColumnWidth);
239
+ return columnWidths;
240
+ }
241
+ }
242
+ renderRow(row, columnWidths) {
243
+ const wrappedCells = row.map((value, index) => {
244
+ const wrappedLines = ASCIITableUtils.wrapText(value, columnWidths[index]);
245
+ return wrappedLines.map((line) => line.padEnd(columnWidths[index])).join("\n");
246
+ });
247
+ const maxLines = Math.max(
248
+ ...wrappedCells.map((cell) => cell.split("\n").length)
249
+ );
250
+ const paddedRows = [];
251
+ for (let i = 0; i < maxLines; i++) {
252
+ const rowLine = wrappedCells.map((cell, index) => {
253
+ const cellLines = cell.split("\n");
254
+ const cellLine = cellLines[i] || "";
255
+ const padding = " ".repeat(columnWidths[index] - stringWidth2(cellLine));
256
+ return " " + cellLine + padding + " ";
257
+ });
258
+ paddedRows.push("|" + rowLine.join("|") + "|");
259
+ }
260
+ return paddedRows.join("\n");
261
+ }
262
+ };
263
+
264
+ // src/lib/ascii-tables/key-value-ascii-table.ts
265
+ import stringWidth3 from "string-width";
266
+
267
+ // src/lib/clamp.ts
268
+ function clamp(value, min, max) {
269
+ return Math.max(min, Math.min(value, max));
270
+ }
271
+
272
+ // src/lib/ascii-tables/key-value-ascii-table.ts
273
+ var KeyValueASCIITable = class _KeyValueASCIITable {
274
+ tableWidth;
275
+ emptyMessage;
276
+ autoAdjustWidthWhenPossible = true;
277
+ rows = [];
278
+ constructor(options = {}) {
279
+ const minTableWidth = this.getMinimumWidth();
280
+ if (options.tableWidth && options.tableWidth < minTableWidth) {
281
+ throw new Error(
282
+ `Table width must be at least ${minTableWidth} to accommodate the table structure.`
283
+ );
284
+ }
285
+ this.tableWidth = options.tableWidth || 80;
286
+ this.autoAdjustWidthWhenPossible = options.autoAdjustWidthWhenPossible ?? true;
287
+ this.emptyMessage = options.emptyMessage || "";
288
+ }
289
+ getMinimumWidth() {
290
+ return 9;
291
+ }
292
+ /**
293
+ * Adds key and value to the table but placing the value on its own row.
294
+ *
295
+ * @param key
296
+ * @param value
297
+ */
298
+ addValueOnSeparateRow(key, value) {
299
+ const row = { kind: "own", key, value };
300
+ this.rows.push(row);
301
+ }
302
+ /**
303
+ * Adds key and value to the table.
304
+ *
305
+ * If provided value is an instance of ASCIITable or MultiColumnASCIITable, it will be rendered as a nested table on its own row for readability.
306
+ *
307
+ * @param key
308
+ * @param value
309
+ */
310
+ addRow(key, value) {
311
+ const row = { kind: "regular", key, value };
312
+ this.rows.push(row);
313
+ }
314
+ toString(options = {}) {
315
+ const tableWidth = options.tableWidth || this.tableWidth;
316
+ const canAutoAdjustWidthWhenPossible = options.autoAdjustWidthWhenPossible ?? this.autoAdjustWidthWhenPossible;
317
+ const emptyMessage = options.emptyMessage || this.emptyMessage;
318
+ if (this.rows.length === 0) {
319
+ const emptyTableWidth = Math.min(tableWidth, 40);
320
+ const separator = "+" + "-".repeat(emptyTableWidth - 2) + "+";
321
+ const emptyMessageLines = ASCIITableUtils.wrapText(
322
+ emptyMessage,
323
+ emptyTableWidth - 4
324
+ );
325
+ const emptyRows = emptyMessageLines.map((line) => {
326
+ const paddingLeft = padRight(
327
+ "",
328
+ Math.floor((emptyTableWidth - stringWidth3(line) - 4) / 2),
329
+ " "
330
+ );
331
+ const paddingRight = padRight(
332
+ "",
333
+ Math.ceil((emptyTableWidth - stringWidth3(line) - 4) / 2),
334
+ " "
335
+ );
336
+ return `| ${paddingLeft}${line}${paddingRight} |`;
337
+ });
338
+ if (emptyRows.length === 0) {
339
+ emptyRows.push(`| ${" ".repeat(emptyTableWidth - 4)} |`);
340
+ }
341
+ return [separator, ...emptyRows, separator].join("\n");
342
+ }
343
+ const columnWidths = this.calculateColumnWidths(options);
344
+ const headerSeparator = ASCIITableUtils.createSeparator(columnWidths);
345
+ const rowSeparator = ASCIITableUtils.createSeparator(columnWidths, "-");
346
+ let tableString = headerSeparator + "\n";
347
+ for (const [rowIndex, row] of this.rows.entries()) {
348
+ const { kind, key, value } = row;
349
+ if (kind === "own" || value instanceof _KeyValueASCIITable || value instanceof MultiColumnASCIITable || Array.isArray(value)) {
350
+ const keyString = ASCIITableUtils.centerText(
351
+ key,
352
+ columnWidths[0] + columnWidths[1] + 3
353
+ );
354
+ tableString += `| ${keyString} |
355
+ `;
356
+ tableString += rowSeparator + "\n";
357
+ let valueString = "";
358
+ if (value instanceof _KeyValueASCIITable) {
359
+ valueString = this.formatValue(
360
+ value,
361
+ tableWidth - 4,
362
+ canAutoAdjustWidthWhenPossible,
363
+ ""
364
+ );
365
+ } else if (value instanceof MultiColumnASCIITable) {
366
+ valueString = this.formatValue(
367
+ value,
368
+ tableWidth - 4,
369
+ canAutoAdjustWidthWhenPossible,
370
+ ""
371
+ );
372
+ } else if (Array.isArray(value)) {
373
+ valueString = this.formatValue(
374
+ value,
375
+ tableWidth - 4,
376
+ canAutoAdjustWidthWhenPossible,
377
+ ""
378
+ );
379
+ } else if (row.kind === "own") {
380
+ valueString = this.formatTableRowOnOwnRow(
381
+ value,
382
+ tableWidth - 4,
383
+ tableWidth
384
+ );
385
+ }
386
+ const valueLines = valueString.split("\n");
387
+ const paddedValueLines = valueLines.map((line) => {
388
+ const padding = padRight("", tableWidth - stringWidth3(line) - 4, " ");
389
+ return `| ${line}${padding} |`;
390
+ });
391
+ tableString += paddedValueLines.join("\n") + "\n";
392
+ tableString += headerSeparator + "\n";
393
+ } else {
394
+ const keyLines = ASCIITableUtils.wrapText(key, columnWidths[0]);
395
+ const valueLines = ASCIITableUtils.wrapText(
396
+ this.formatValue(
397
+ value,
398
+ columnWidths[1],
399
+ canAutoAdjustWidthWhenPossible,
400
+ ""
401
+ ),
402
+ columnWidths[1]
403
+ );
404
+ const maxLines = Math.max(keyLines.length, valueLines.length);
405
+ for (let i = 0; i < maxLines; i++) {
406
+ const keyLine = keyLines[i] || "";
407
+ const valueLine = valueLines[i] || "";
408
+ const keyPadding = " ".repeat(columnWidths[0] - stringWidth3(keyLine));
409
+ const valuePadding = " ".repeat(
410
+ columnWidths[1] - stringWidth3(valueLine)
411
+ );
412
+ tableString += `| ${keyLine}${keyPadding} | ${valueLine}${valuePadding} |
413
+ `;
414
+ if (i === maxLines - 1) {
415
+ if (rowIndex === this.rows.length - 1) {
416
+ tableString += headerSeparator + "\n";
417
+ } else {
418
+ tableString += rowSeparator + "\n";
419
+ }
420
+ }
421
+ }
422
+ }
423
+ }
424
+ return tableString.trim();
425
+ }
426
+ calculateColumnWidths(options = {}) {
427
+ const tableWidth = options.tableWidth || this.tableWidth;
428
+ const canAutoAdjustWidthWhenPossible = options.autoAdjustWidthWhenPossible ?? this.autoAdjustWidthWhenPossible;
429
+ const columnWidths = [0, 0];
430
+ for (const row of this.rows) {
431
+ const { key, value } = row;
432
+ const keyWidth = stringWidth3(key);
433
+ const maxKeyWidth = Math.floor((tableWidth - 7) / 2);
434
+ if (keyWidth > columnWidths[0]) {
435
+ columnWidths[0] = Math.min(keyWidth, maxKeyWidth);
436
+ columnWidths[1] = Math.max(0, tableWidth - columnWidths[0] - 7);
437
+ }
438
+ if (typeof value === "string") {
439
+ const valueWidth = Math.max(
440
+ ...value.split("\n").map((line) => stringWidth3(line))
441
+ );
442
+ if (valueWidth > columnWidths[1]) {
443
+ columnWidths[1] = Math.min(
444
+ valueWidth,
445
+ tableWidth - columnWidths[0] - 7
446
+ );
447
+ columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);
448
+ }
449
+ } else if (row.kind === "own") {
450
+ let valueWidth = 0;
451
+ if (isString(value)) {
452
+ valueWidth = Math.max(
453
+ ...value.split("\n").map((line) => stringWidth3(line))
454
+ );
455
+ }
456
+ if (valueWidth > columnWidths[1]) {
457
+ columnWidths[1] = Math.min(
458
+ valueWidth,
459
+ tableWidth - columnWidths[0] - 7
460
+ );
461
+ columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);
462
+ }
463
+ } else if (value instanceof _KeyValueASCIITable) {
464
+ let nestedTableColumnWidths = [];
465
+ if (canAutoAdjustWidthWhenPossible) {
466
+ const minWidth = value.getMinimumWidth();
467
+ const availableWidth2 = tableWidth - columnWidths[0] - 7;
468
+ const adjustedWidth = clamp(availableWidth2, minWidth, availableWidth2);
469
+ nestedTableColumnWidths = value.calculateColumnWidths({
470
+ tableWidth: adjustedWidth
471
+ });
472
+ } else {
473
+ nestedTableColumnWidths = value.calculateColumnWidths();
474
+ }
475
+ const nestedTableWidth = nestedTableColumnWidths.reduce((sum, width) => sum + width, 0) + nestedTableColumnWidths.length * 3 - 1;
476
+ const availableWidth = tableWidth - columnWidths[0] - 7;
477
+ if (nestedTableWidth > availableWidth) {
478
+ columnWidths[1] = availableWidth;
479
+ } else {
480
+ columnWidths[1] = Math.max(columnWidths[1], nestedTableWidth);
481
+ }
482
+ } else if (value instanceof MultiColumnASCIITable) {
483
+ let nestedTableColumnWidths = [];
484
+ if (canAutoAdjustWidthWhenPossible) {
485
+ const minWidth = value.getMinimumWidth();
486
+ const availableWidth2 = tableWidth - columnWidths[0] - 7;
487
+ const adjustedWidth = clamp(availableWidth2, minWidth, availableWidth2);
488
+ nestedTableColumnWidths = value.calculateColumnWidths({
489
+ tableWidth: adjustedWidth
490
+ });
491
+ } else {
492
+ nestedTableColumnWidths = value.calculateColumnWidths();
493
+ }
494
+ const nestedTableWidth = nestedTableColumnWidths.reduce((sum, width) => sum + width, 0) + nestedTableColumnWidths.length * 3 - 1;
495
+ const availableWidth = tableWidth - columnWidths[0] - 7;
496
+ if (nestedTableWidth > availableWidth) {
497
+ columnWidths[1] = availableWidth;
498
+ } else {
499
+ columnWidths[1] = Math.max(columnWidths[1], nestedTableWidth);
500
+ }
501
+ } else if (Array.isArray(value)) {
502
+ for (const nestedCell of value) {
503
+ const nestedKeyWidth = stringWidth3(nestedCell.key);
504
+ const maxNestedKeyWidth = Math.floor((tableWidth - 7) / 2);
505
+ if (nestedKeyWidth > columnWidths[0]) {
506
+ columnWidths[0] = Math.min(nestedKeyWidth, maxNestedKeyWidth);
507
+ columnWidths[1] = Math.max(0, tableWidth - columnWidths[0] - 7);
508
+ }
509
+ if (typeof nestedCell.value === "string") {
510
+ const nestedValueWidth = Math.max(
511
+ ...nestedCell.value.split("\n").map((line) => stringWidth3(line))
512
+ );
513
+ if (nestedValueWidth > columnWidths[1]) {
514
+ columnWidths[1] = Math.min(
515
+ nestedValueWidth,
516
+ tableWidth - columnWidths[0] - 7
517
+ );
518
+ columnWidths[0] = Math.max(0, tableWidth - columnWidths[1] - 7);
519
+ }
520
+ }
521
+ }
522
+ }
523
+ }
524
+ return columnWidths;
525
+ }
526
+ formatValue(value, cellWidth, canAutoAdjustWidthWhenPossible, indent = "") {
527
+ if (typeof value === "string") {
528
+ return value;
529
+ } else if (typeof value === "number") {
530
+ return String(value);
531
+ } else if (typeof value === "boolean") {
532
+ return String(value);
533
+ } else if (value === null) {
534
+ return "null";
535
+ } else if (value === void 0) {
536
+ return "undefined";
537
+ } else if (value instanceof _KeyValueASCIITable) {
538
+ let nestedTableLines;
539
+ if (canAutoAdjustWidthWhenPossible) {
540
+ const minWidth = value.getMinimumWidth();
541
+ const adjustedWidth = clamp(cellWidth, minWidth, cellWidth);
542
+ nestedTableLines = value.toString({ tableWidth: adjustedWidth }).split("\n");
543
+ } else {
544
+ nestedTableLines = value.toString().split("\n");
545
+ }
546
+ const indentedLines = nestedTableLines.map((line) => `${indent}${line}`);
547
+ return indentedLines.join("\n");
548
+ } else if (value instanceof MultiColumnASCIITable) {
549
+ let nestedTableLines;
550
+ if (canAutoAdjustWidthWhenPossible) {
551
+ const minWidth = value.getMinimumWidth();
552
+ const adjustedWidth = clamp(cellWidth, minWidth, cellWidth);
553
+ nestedTableLines = value.toString({ tableWidth: adjustedWidth }).split("\n");
554
+ } else {
555
+ nestedTableLines = value.toString().split("\n");
556
+ }
557
+ const indentedLines = nestedTableLines.map((line) => `${indent}${line}`);
558
+ return indentedLines.join("\n");
559
+ } else if (Array.isArray(value)) {
560
+ const nestedValueLines = [];
561
+ for (const { key, value: nestedValue } of value) {
562
+ const formattedKey = `${indent}${key}:`;
563
+ const formattedValue = this.formatValue(
564
+ nestedValue,
565
+ cellWidth - indent.length - stringWidth3(key) - 2,
566
+ canAutoAdjustWidthWhenPossible,
567
+ `${indent}`
568
+ );
569
+ const wrappedSpacer = padRight("", 4, " ");
570
+ const wrappedValue = formattedValue.split("\n").map((line) => `${indent}${wrappedSpacer}${line}`);
571
+ nestedValueLines.push(formattedKey);
572
+ nestedValueLines.push(...wrappedValue);
573
+ nestedValueLines.push("");
574
+ }
575
+ return nestedValueLines.slice(0, -1).join("\n");
576
+ } else {
577
+ throw new TypeError("Invalid value type provided");
578
+ }
579
+ }
580
+ formatTableRowOnOwnRow(value, width, maxRowLength) {
581
+ const lines = value.split("\n");
582
+ const paddedLines = lines.map((line) => {
583
+ const wrappedLines = ASCIITableUtils.wrapText(line, maxRowLength - 4);
584
+ return wrappedLines.map((wrappedLine) => {
585
+ const padding = padRight(
586
+ "",
587
+ width - stringWidth3(wrappedLine) - 2,
588
+ " "
589
+ );
590
+ return `${wrappedLine}${padding}`;
591
+ }).join("\n");
592
+ });
593
+ return paddedLines.join("\n");
594
+ }
595
+ };
596
+
597
+ // src/lib/error-to-string.ts
598
+ function safeStringify(value) {
599
+ if (value === null || value === void 0) {
600
+ return String(value);
601
+ }
602
+ switch (typeof value) {
603
+ case "string":
604
+ return value;
605
+ case "number":
606
+ case "boolean":
607
+ case "bigint":
608
+ return String(value);
609
+ case "object":
610
+ return JSON.stringify(value);
611
+ case "function":
612
+ return "[Function]";
613
+ case "symbol":
614
+ return value.toString();
615
+ default:
616
+ return String(value);
617
+ }
618
+ }
619
+ function errorToString(error, maxRowLength = 80) {
620
+ const table = errorToASCIITable(error, maxRowLength);
621
+ return table.toString();
622
+ }
623
+ function errorToASCIITable(error, maxRowLength) {
624
+ const table = new KeyValueASCIITable({
625
+ tableWidth: maxRowLength,
626
+ autoAdjustWidthWhenPossible: true
627
+ });
628
+ if (error && typeof error === "object") {
629
+ const err = error;
630
+ table.addRow("Key", "Value");
631
+ if (err["message"]) {
632
+ table.addRow("Message", safeStringify(err["message"]));
633
+ }
634
+ if (err["name"]) {
635
+ table.addRow("Name", safeStringify(err["name"]));
636
+ }
637
+ if (err["code"]) {
638
+ table.addRow("Code", safeStringify(err["code"]));
639
+ }
640
+ if (err["errno"]) {
641
+ table.addRow("Errno", safeStringify(err["errno"]));
642
+ }
643
+ if (err["errPrefix"]) {
644
+ table.addRow("Prefix", safeStringify(err["errPrefix"]));
645
+ }
646
+ if (err["errType"]) {
647
+ table.addRow("errType", safeStringify(err["errType"]));
648
+ }
649
+ if (err["errCode"]) {
650
+ table.addRow("errCode", safeStringify(err["errCode"]));
651
+ }
652
+ if (err["additionalInfo"]) {
653
+ const additionalInfo = err["additionalInfo"];
654
+ const sensitiveFieldNames = err["sensitiveFieldNames"] || [];
655
+ for (const key in additionalInfo) {
656
+ if (sensitiveFieldNames.includes(key)) {
657
+ table.addRow(`AdditionalInfo.${key}`, "***");
658
+ } else {
659
+ const value = additionalInfo[key];
660
+ table.addRow(
661
+ `AdditionalInfo.${key}`,
662
+ stringifyValue(value, table, maxRowLength)
663
+ );
664
+ }
665
+ }
666
+ }
667
+ if (err["stack"]) {
668
+ table.addValueOnSeparateRow("Stack", safeStringify(err["stack"]));
669
+ }
670
+ }
671
+ return table;
672
+ }
673
+ function stringifyValue(value, table, maxRowLength) {
674
+ if (typeof value === "string") {
675
+ return value;
676
+ } else if (Array.isArray(value)) {
677
+ return value.map((item) => {
678
+ const result = stringifyValue(item, table, maxRowLength);
679
+ if (typeof result === "string") {
680
+ return result;
681
+ } else if (result instanceof KeyValueASCIITable) {
682
+ return result.toString();
683
+ } else {
684
+ return JSON.stringify(result);
685
+ }
686
+ }).join(", ");
687
+ } else if (typeof value === "object" && value !== null) {
688
+ if (value instanceof Error) {
689
+ return errorToASCIITable(value, maxRowLength - 4);
690
+ } else {
691
+ const entries = Object.entries(value).map(
692
+ ([key, val]) => ({
693
+ key,
694
+ value: stringifyValue(val, table, maxRowLength - 4)
695
+ })
696
+ );
697
+ return entries;
698
+ }
699
+ } else {
700
+ return String(value);
701
+ }
702
+ }
703
+
704
+ // src/lib/is-promise.ts
705
+ function isPromise(obj) {
706
+ return !!obj && (typeof obj === "object" || typeof obj === "function") && // @ts-expect-error - obj is checked to be object/function, then property access works at runtime
707
+ typeof obj["then"] === "function";
708
+ }
709
+
710
+ // src/lib/is-function.ts
711
+ function isFunction(value) {
712
+ return typeof value === "function" || value instanceof Function;
713
+ }
714
+
715
+ // src/lib/safe-handle-callback.ts
716
+ function safeHandleCallback(callbackName, callback, ...args) {
717
+ const handleError = (error) => {
718
+ if (typeof globalThis.dispatchEvent === "function") {
719
+ globalThis.dispatchEvent(
720
+ new ErrorEvent("reportError", {
721
+ error: new Error(
722
+ `Error in a callback ${callbackName}: ${DOUBLE_EOL}${errorToString(error)}`
723
+ )
724
+ })
725
+ );
726
+ }
727
+ };
728
+ if (isFunction(callback)) {
729
+ try {
730
+ const result = callback(...args);
731
+ if (isPromise(result)) {
732
+ result.catch((error) => {
733
+ handleError(error);
734
+ });
735
+ }
736
+ } catch (error) {
737
+ handleError(error);
738
+ }
739
+ } else {
740
+ handleError(
741
+ new Error(`Callback provided for ${callbackName} is not a function`)
742
+ );
743
+ }
744
+ }
745
+
1
746
  // src/lib/lru-cache/index.ts
747
+ var VALID_CHANGE_REASONS = /* @__PURE__ */ new Set([
748
+ "evict",
749
+ "expired",
750
+ "delete",
751
+ "clear",
752
+ "set",
753
+ "skip"
754
+ ]);
2
755
  var LRUCache = class {
3
756
  maxEntries;
4
757
  maxSize;
@@ -14,6 +767,8 @@ var LRUCache = class {
14
767
  // Track how many entries currently have expirations
15
768
  sizeCalculator;
16
769
  // Optional function to calculate item size
770
+ onChange;
771
+ onChangeReasons;
17
772
  // Store values with their expiration time and size
18
773
  map = /* @__PURE__ */ new Map();
19
774
  /**
@@ -23,6 +778,8 @@ var LRUCache = class {
23
778
  * @param options.defaultTtl Default time to live in milliseconds for all entries
24
779
  * @param options.maxSize Maximum total size in bytes
25
780
  * @param options.sizeCalculator Function to calculate the size of a value
781
+ * @param options.onChange Callback invoked for cache changes
782
+ * @param options.onChangeReasons Optional list of change reasons that should trigger onChange
26
783
  */
27
784
  constructor(maxEntries, options) {
28
785
  if (!Number.isInteger(maxEntries) || maxEntries <= 0) {
@@ -42,10 +799,25 @@ var LRUCache = class {
42
799
  if (options?.sizeCalculator !== void 0 && typeof options.sizeCalculator !== "function") {
43
800
  throw new TypeError("sizeCalculator must be a function");
44
801
  }
802
+ if (options?.onChange !== void 0 && typeof options.onChange !== "function") {
803
+ throw new TypeError("onChange must be a function");
804
+ }
805
+ if (options?.onChangeReasons !== void 0) {
806
+ if (!Array.isArray(options.onChangeReasons)) {
807
+ throw new TypeError("onChangeReasons must be an array");
808
+ }
809
+ for (const reason of options.onChangeReasons) {
810
+ if (!VALID_CHANGE_REASONS.has(reason)) {
811
+ throw new RangeError(`Invalid onChange reason: ${String(reason)}`);
812
+ }
813
+ }
814
+ }
45
815
  this.maxEntries = maxEntries;
46
816
  this.defaultTtl = options?.defaultTtl;
47
817
  this.maxSize = options?.maxSize;
48
818
  this.sizeCalculator = options?.sizeCalculator;
819
+ this.onChange = options?.onChange;
820
+ this.onChangeReasons = options?.onChangeReasons ? new Set(options.onChangeReasons) : void 0;
49
821
  }
50
822
  /**
51
823
  * Get the current number of entries in the cache
@@ -68,7 +840,9 @@ var LRUCache = class {
68
840
  const entry = this.map.get(key);
69
841
  if (entry) {
70
842
  if (entry.expires && Date.now() > entry.expires) {
71
- this.delete(key);
843
+ const changeEvents = this.createLocalChangeQueue();
844
+ this.removeEntry(key, "expired", changeEvents);
845
+ this.flushLocalChangeQueue(changeEvents);
72
846
  return false;
73
847
  }
74
848
  return true;
@@ -79,7 +853,9 @@ var LRUCache = class {
79
853
  const entry = this.map.get(key);
80
854
  if (entry) {
81
855
  if (entry.expires && Date.now() > entry.expires) {
82
- this.delete(key);
856
+ const changeEvents = this.createLocalChangeQueue();
857
+ this.removeEntry(key, "expired", changeEvents);
858
+ this.flushLocalChangeQueue(changeEvents);
83
859
  return void 0;
84
860
  }
85
861
  this.map.delete(key);
@@ -97,8 +873,29 @@ var LRUCache = class {
97
873
  );
98
874
  }
99
875
  const size = this.calculateSize(value);
100
- if (this.map.has(key)) {
101
- this.delete(key);
876
+ const changeEvents = this.createLocalChangeQueue();
877
+ this.cleanupExpiredInternal(changeEvents);
878
+ const existingEntry = this.map.get(key);
879
+ if (this.maxSize !== void 0 && size > this.maxSize) {
880
+ changeEvents.push(
881
+ existingEntry ? {
882
+ reason: "skip",
883
+ key,
884
+ currentValue: existingEntry.value,
885
+ newValue: value,
886
+ cause: "maxSize"
887
+ } : {
888
+ reason: "skip",
889
+ key,
890
+ newValue: value,
891
+ cause: "maxSize"
892
+ }
893
+ );
894
+ this.flushLocalChangeQueue(changeEvents);
895
+ return;
896
+ }
897
+ if (existingEntry) {
898
+ this.removeEntry(key);
102
899
  }
103
900
  const ttl = customTtl ?? this.defaultTtl;
104
901
  const expires = ttl && ttl > 0 ? Date.now() + ttl : void 0;
@@ -107,51 +904,75 @@ var LRUCache = class {
107
904
  if (expires !== void 0) {
108
905
  this.expirableEntryCount++;
109
906
  }
110
- this.cleanupExpired();
111
- this.evictIfNeeded();
907
+ changeEvents?.push(
908
+ existingEntry ? {
909
+ reason: "set",
910
+ key,
911
+ oldValue: existingEntry.value,
912
+ newValue: value
913
+ } : {
914
+ reason: "set",
915
+ key,
916
+ newValue: value
917
+ }
918
+ );
919
+ this.evictIfNeeded(changeEvents);
920
+ this.flushLocalChangeQueue(changeEvents);
112
921
  }
113
922
  /**
114
923
  * Clear all entries from the cache
115
924
  */
116
925
  clear() {
926
+ const changeEvents = this.createLocalChangeQueue();
927
+ const shouldEmitClear = this.onChange !== void 0 && (this.onChangeReasons === void 0 || this.onChangeReasons.has("clear"));
928
+ if (shouldEmitClear) {
929
+ for (const [key, entry] of this.map.entries()) {
930
+ changeEvents.push({
931
+ reason: "clear",
932
+ key,
933
+ value: entry.value
934
+ });
935
+ }
936
+ }
117
937
  this.map.clear();
118
938
  this.currentSize = 0;
119
939
  this.expirableEntryCount = 0;
120
940
  this.lastCleanup = Date.now();
941
+ this.flushLocalChangeQueue(changeEvents);
942
+ }
943
+ /**
944
+ * Delete a specific entry from the cache
945
+ * @param key The key to delete
946
+ * @returns True if the entry was deleted, false if it didn't exist
947
+ */
948
+ delete(key) {
949
+ const changeEvents = this.createLocalChangeQueue();
950
+ const wasDeleted = this.removeEntry(key, "delete", changeEvents);
951
+ this.flushLocalChangeQueue(changeEvents);
952
+ return wasDeleted;
121
953
  }
122
954
  /**
123
955
  * Remove all expired entries from the cache
124
956
  * @returns The number of entries removed
125
957
  */
126
958
  cleanupExpired() {
959
+ const changeEvents = this.createLocalChangeQueue();
960
+ const removed = this.cleanupExpiredInternal(changeEvents);
961
+ this.flushLocalChangeQueue(changeEvents);
962
+ return removed;
963
+ }
964
+ cleanupExpiredInternal(changeEvents) {
127
965
  let removed = 0;
128
966
  const now = Date.now();
129
967
  for (const [key, entry] of this.map.entries()) {
130
968
  if (entry.expires && now > entry.expires) {
131
- this.delete(key);
969
+ this.removeEntry(key, "expired", changeEvents);
132
970
  removed++;
133
971
  }
134
972
  }
135
973
  this.lastCleanup = now;
136
974
  return removed;
137
975
  }
138
- /**
139
- * Delete a specific entry from the cache
140
- * @param key The key to delete
141
- * @returns True if the entry was deleted, false if it didn't exist
142
- */
143
- delete(key) {
144
- const entry = this.map.get(key);
145
- if (entry) {
146
- this.currentSize -= entry.size;
147
- if (entry.expires !== void 0) {
148
- this.expirableEntryCount--;
149
- }
150
- this.map.delete(key);
151
- return true;
152
- }
153
- return false;
154
- }
155
976
  isBufferValue(value) {
156
977
  const globalBuffer = globalThis.Buffer;
157
978
  if (globalBuffer === void 0) {
@@ -212,23 +1033,23 @@ var LRUCache = class {
212
1033
  /**
213
1034
  * Evict entries if we exceed either max entries or max size
214
1035
  */
215
- evictIfNeeded() {
1036
+ evictIfNeeded(changeEvents) {
216
1037
  if (this.map.size > this.maxEntries) {
217
- this.evictOldest();
1038
+ this.evictOldest(changeEvents);
218
1039
  }
219
1040
  if (this.maxSize !== void 0 && this.currentSize > this.maxSize) {
220
1041
  while (this.currentSize > this.maxSize && this.map.size > 0) {
221
- this.evictOldest();
1042
+ this.evictOldest(changeEvents);
222
1043
  }
223
1044
  }
224
1045
  }
225
1046
  /**
226
1047
  * Evict the oldest (least recently used) entry
227
1048
  */
228
- evictOldest() {
1049
+ evictOldest(changeEvents) {
229
1050
  if (this.map.size > 0) {
230
1051
  const oldest = this.map.keys().next().value;
231
- this.delete(oldest);
1052
+ this.removeEntry(oldest, "evict", changeEvents);
232
1053
  }
233
1054
  }
234
1055
  maybeCleanup() {
@@ -237,6 +1058,40 @@ var LRUCache = class {
237
1058
  this.cleanupExpired();
238
1059
  }
239
1060
  }
1061
+ // Collect changes locally so each cache operation flushes its own events in order.
1062
+ createLocalChangeQueue() {
1063
+ return [];
1064
+ }
1065
+ flushLocalChangeQueue(changeEvents) {
1066
+ if (!this.onChange || changeEvents.length === 0) {
1067
+ return;
1068
+ }
1069
+ for (const changeEvent of changeEvents) {
1070
+ if (this.onChangeReasons !== void 0 && !this.onChangeReasons.has(changeEvent.reason)) {
1071
+ continue;
1072
+ }
1073
+ safeHandleCallback("LRUCache onChange", this.onChange, changeEvent);
1074
+ }
1075
+ }
1076
+ removeEntry(key, reason, changeEvents) {
1077
+ const entry = this.map.get(key);
1078
+ if (!entry) {
1079
+ return false;
1080
+ }
1081
+ this.currentSize -= entry.size;
1082
+ if (entry.expires !== void 0) {
1083
+ this.expirableEntryCount--;
1084
+ }
1085
+ this.map.delete(key);
1086
+ if (reason && changeEvents) {
1087
+ changeEvents.push({
1088
+ reason,
1089
+ key,
1090
+ value: entry.value
1091
+ });
1092
+ }
1093
+ return true;
1094
+ }
240
1095
  assertNonNegativeFiniteNumber(value, message) {
241
1096
  if (!Number.isFinite(value) || value < 0) {
242
1097
  throw new RangeError(message);