@gjsify/util 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -3
- package/lib/esm/errors.js +261 -0
- package/lib/esm/index.js +578 -4
- package/lib/esm/types/index.js +297 -3
- package/lib/esm/types.js +6 -0
- package/lib/types/errors.d.ts +2 -0
- package/lib/types/index.d.ts +98 -3
- package/lib/types/types/index.d.ts +84 -2
- package/lib/types/types.d.ts +3 -0
- package/package.json +17 -28
- package/src/errors.ts +101 -0
- package/src/extended.spec.ts +469 -0
- package/src/index.spec.ts +368 -184
- package/src/index.ts +674 -3
- package/src/test.ts +2 -1
- package/src/types/index.ts +356 -3
- package/src/types.ts +4 -0
- package/tsconfig.json +22 -10
- package/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/index.js +0 -6
- package/lib/cjs/types/index.js +0 -6
- package/test.gjs.mjs +0 -35212
- package/test.node.mjs +0 -507
- package/tsconfig.types.json +0 -8
- package/tsconfig.types.tsbuildinfo +0 -1
package/src/index.ts
CHANGED
|
@@ -1,4 +1,675 @@
|
|
|
1
|
+
// Reference: Node.js lib/util.js
|
|
2
|
+
// Reimplemented for GJS
|
|
1
3
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import type { InspectOptions } from 'node:util';
|
|
5
|
+
|
|
6
|
+
import * as types from './types.js';
|
|
7
|
+
import { getSystemErrorName, getSystemErrorMap } from './errors.js';
|
|
8
|
+
|
|
9
|
+
export { types };
|
|
10
|
+
export { getSystemErrorName, getSystemErrorMap };
|
|
11
|
+
|
|
12
|
+
// ---- inspect ----
|
|
13
|
+
|
|
14
|
+
const kCustomInspect = Symbol.for('nodejs.util.inspect.custom');
|
|
15
|
+
|
|
16
|
+
function inspectValue(value: unknown, opts: InspectOptions, depth: number): string {
|
|
17
|
+
if (value === null) return opts.colors ? '\x1b[1mnull\x1b[22m' : 'null';
|
|
18
|
+
if (value === undefined) return opts.colors ? '\x1b[90mundefined\x1b[39m' : 'undefined';
|
|
19
|
+
|
|
20
|
+
const maxDepth = opts.depth ?? 2;
|
|
21
|
+
|
|
22
|
+
if (typeof value === 'string') {
|
|
23
|
+
const escaped = value.replace(/\\/g, '\\\\');
|
|
24
|
+
// Smart quoting: use double quotes if string contains single quote but no double quote
|
|
25
|
+
if (value.includes("'") && !value.includes('"')) {
|
|
26
|
+
const dq = escaped.replace(/"/g, '\\"');
|
|
27
|
+
return opts.colors ? `\x1b[32m"${dq}"\x1b[39m` : `"${dq}"`;
|
|
28
|
+
}
|
|
29
|
+
const sq = escaped.replace(/'/g, "\\'");
|
|
30
|
+
return opts.colors ? `\x1b[32m'${sq}'\x1b[39m` : `'${sq}'`;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === 'number') {
|
|
33
|
+
return opts.colors ? `\x1b[33m${value}\x1b[39m` : String(value);
|
|
34
|
+
}
|
|
35
|
+
if (typeof value === 'bigint') {
|
|
36
|
+
return opts.colors ? `\x1b[33m${value}n\x1b[39m` : `${value}n`;
|
|
37
|
+
}
|
|
38
|
+
if (typeof value === 'boolean') {
|
|
39
|
+
return opts.colors ? `\x1b[33m${value}\x1b[39m` : String(value);
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === 'symbol') {
|
|
42
|
+
return opts.colors ? `\x1b[32m${value.toString()}\x1b[39m` : value.toString();
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === 'function') {
|
|
45
|
+
const name = value.name ? `: ${value.name}` : '';
|
|
46
|
+
return opts.colors ? `\x1b[36m[Function${name}]\x1b[39m` : `[Function${name}]`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Custom inspect
|
|
50
|
+
if (value !== null && typeof value === 'object' && kCustomInspect in (value as Record<symbol, unknown>)) {
|
|
51
|
+
const custom = (value as Record<symbol, unknown>)[kCustomInspect];
|
|
52
|
+
if (typeof custom === 'function') {
|
|
53
|
+
const result = custom.call(value, depth, opts);
|
|
54
|
+
if (typeof result === 'string') return result;
|
|
55
|
+
return inspectValue(result, opts, depth);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (value instanceof Date) {
|
|
60
|
+
return value.toISOString();
|
|
61
|
+
}
|
|
62
|
+
if (value instanceof RegExp) {
|
|
63
|
+
return opts.colors ? `\x1b[31m${value.toString()}\x1b[39m` : value.toString();
|
|
64
|
+
}
|
|
65
|
+
if (value instanceof Error) {
|
|
66
|
+
return value.stack || value.toString();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (depth > maxDepth) {
|
|
70
|
+
return Array.isArray(value) ? '[Array]' : '[Object]';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
return inspectArray(value, opts, depth);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (value instanceof Map) {
|
|
78
|
+
const entries = [...value.entries()].map(([k, v]) =>
|
|
79
|
+
`${inspectValue(k, opts, depth + 1)} => ${inspectValue(v, opts, depth + 1)}`
|
|
80
|
+
);
|
|
81
|
+
return `Map(${value.size}) { ${entries.join(', ')} }`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (value instanceof Set) {
|
|
85
|
+
const entries = [...value].map(v => inspectValue(v, opts, depth + 1));
|
|
86
|
+
return `Set(${value.size}) { ${entries.join(', ')} }`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
|
|
90
|
+
const name = value.constructor?.name || 'TypedArray';
|
|
91
|
+
const arr = Array.from(value as Uint8Array);
|
|
92
|
+
return `${name}(${arr.length}) [ ${arr.join(', ')} ]`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return inspectObject(value as Record<string, unknown>, opts, depth);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function inspectArray(arr: unknown[], opts: InspectOptions, depth: number): string {
|
|
99
|
+
const maxLen = opts.maxArrayLength ?? 100;
|
|
100
|
+
const len = Math.min(arr.length, maxLen);
|
|
101
|
+
const items: string[] = [];
|
|
102
|
+
for (let i = 0; i < len; i++) {
|
|
103
|
+
items.push(inspectValue(arr[i], opts, depth + 1));
|
|
104
|
+
}
|
|
105
|
+
if (arr.length > maxLen) {
|
|
106
|
+
items.push(`... ${arr.length - maxLen} more items`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Show hidden properties like [length] when showHidden is true
|
|
110
|
+
if (opts.showHidden) {
|
|
111
|
+
items.push(`[length]: ${arr.length}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const breakLength = opts.breakLength ?? 72;
|
|
115
|
+
const compact = opts.compact ?? 3;
|
|
116
|
+
|
|
117
|
+
// Compact grouping: when array has more elements than compact threshold,
|
|
118
|
+
// use grouped multiline format (multiple items per line)
|
|
119
|
+
if (typeof compact === 'number' && compact > 0 && arr.length > compact) {
|
|
120
|
+
const indent = ' ';
|
|
121
|
+
const indentLen = indent.length;
|
|
122
|
+
// Calculate max item length (strip ANSI for measurement)
|
|
123
|
+
const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
124
|
+
const maxItemLen = Math.max(...items.map(item => stripAnsi(item).length));
|
|
125
|
+
const biasedMax = Math.max(maxItemLen - 2, 1);
|
|
126
|
+
const numItems = items.length;
|
|
127
|
+
const approxCharHeights = 2.5;
|
|
128
|
+
const columns = Math.min(
|
|
129
|
+
Math.round(Math.sqrt(approxCharHeights * biasedMax * numItems) / biasedMax),
|
|
130
|
+
Math.floor((breakLength - indentLen) / biasedMax),
|
|
131
|
+
Math.floor((2.5 + numItems - 1) / 2),
|
|
132
|
+
15
|
|
133
|
+
);
|
|
134
|
+
if (columns > 1) {
|
|
135
|
+
const rows: string[] = [];
|
|
136
|
+
for (let i = 0; i < numItems; i += columns) {
|
|
137
|
+
rows.push(indent + items.slice(i, Math.min(i + columns, numItems)).join(', '));
|
|
138
|
+
}
|
|
139
|
+
return `[\n${rows.join(',\n')}\n]`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const singleLine = `[ ${items.join(', ')} ]`;
|
|
144
|
+
if (singleLine.length <= breakLength) return singleLine;
|
|
145
|
+
|
|
146
|
+
return `[\n${items.map(i => ' ' + i).join(',\n')}\n]`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function inspectObject(obj: Record<string, unknown>, opts: InspectOptions, depth: number): string {
|
|
150
|
+
const keys = opts.showHidden
|
|
151
|
+
? Object.getOwnPropertyNames(obj)
|
|
152
|
+
: Object.keys(obj);
|
|
153
|
+
|
|
154
|
+
if (opts.sorted) keys.sort();
|
|
155
|
+
|
|
156
|
+
if (keys.length === 0) {
|
|
157
|
+
const tag = Object.prototype.toString.call(obj);
|
|
158
|
+
if (tag !== '[object Object]') return tag;
|
|
159
|
+
return '{}';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const items = keys.map(key => {
|
|
163
|
+
const val = inspectValue(obj[key], opts, depth + 1);
|
|
164
|
+
return `${key}: ${val}`;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const breakLength = opts.breakLength ?? 72;
|
|
168
|
+
const singleLine = `{ ${items.join(', ')} }`;
|
|
169
|
+
if (singleLine.length <= breakLength) return singleLine;
|
|
170
|
+
|
|
171
|
+
return `{\n${items.map(i => ' ' + i).join(',\n')}\n}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function inspect(value: unknown, opts?: boolean | InspectOptions): string {
|
|
175
|
+
const options: InspectOptions = typeof opts === 'boolean'
|
|
176
|
+
? { showHidden: opts }
|
|
177
|
+
: { ...opts };
|
|
178
|
+
|
|
179
|
+
if (options.colors === undefined) options.colors = false;
|
|
180
|
+
return inspectValue(value, options, 0);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
inspect.custom = kCustomInspect;
|
|
184
|
+
inspect.defaultOptions = {
|
|
185
|
+
showHidden: false,
|
|
186
|
+
depth: 2,
|
|
187
|
+
colors: false,
|
|
188
|
+
maxArrayLength: 100,
|
|
189
|
+
maxStringLength: 10000,
|
|
190
|
+
breakLength: 72,
|
|
191
|
+
compact: 3,
|
|
192
|
+
sorted: false,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** ANSI color code pairs [open, close] for terminal coloring. */
|
|
196
|
+
inspect.colors = {
|
|
197
|
+
reset: [0, 0],
|
|
198
|
+
bold: [1, 22],
|
|
199
|
+
dim: [2, 22],
|
|
200
|
+
italic: [3, 23],
|
|
201
|
+
underline: [4, 24],
|
|
202
|
+
blink: [5, 25],
|
|
203
|
+
inverse: [7, 27],
|
|
204
|
+
hidden: [8, 28],
|
|
205
|
+
strikethrough: [9, 29],
|
|
206
|
+
doubleunderline: [21, 24],
|
|
207
|
+
black: [30, 39],
|
|
208
|
+
red: [31, 39],
|
|
209
|
+
green: [32, 39],
|
|
210
|
+
yellow: [33, 39],
|
|
211
|
+
blue: [34, 39],
|
|
212
|
+
magenta: [35, 39],
|
|
213
|
+
cyan: [36, 39],
|
|
214
|
+
white: [37, 39],
|
|
215
|
+
bgBlack: [40, 49],
|
|
216
|
+
bgRed: [41, 49],
|
|
217
|
+
bgGreen: [42, 49],
|
|
218
|
+
bgYellow: [43, 49],
|
|
219
|
+
bgBlue: [44, 49],
|
|
220
|
+
bgMagenta: [45, 49],
|
|
221
|
+
bgCyan: [46, 49],
|
|
222
|
+
bgWhite: [47, 49],
|
|
223
|
+
framed: [51, 54],
|
|
224
|
+
overlined: [53, 55],
|
|
225
|
+
gray: [90, 39],
|
|
226
|
+
grey: [90, 39],
|
|
227
|
+
redBright: [91, 39],
|
|
228
|
+
greenBright: [92, 39],
|
|
229
|
+
yellowBright: [93, 39],
|
|
230
|
+
blueBright: [94, 39],
|
|
231
|
+
magentaBright: [95, 39],
|
|
232
|
+
cyanBright: [96, 39],
|
|
233
|
+
whiteBright: [97, 39],
|
|
234
|
+
bgBlackBright: [100, 49],
|
|
235
|
+
bgRedBright: [101, 49],
|
|
236
|
+
bgGreenBright: [102, 49],
|
|
237
|
+
bgYellowBright: [103, 49],
|
|
238
|
+
bgBlueBright: [104, 49],
|
|
239
|
+
bgMagentaBright: [105, 49],
|
|
240
|
+
bgCyanBright: [106, 49],
|
|
241
|
+
bgWhiteBright: [107, 49],
|
|
242
|
+
} as Record<string, [number, number]>;
|
|
243
|
+
|
|
244
|
+
/** Maps type names to color names for util.inspect output styling. */
|
|
245
|
+
inspect.styles = {
|
|
246
|
+
special: 'cyan',
|
|
247
|
+
number: 'yellow',
|
|
248
|
+
bigint: 'yellow',
|
|
249
|
+
boolean: 'yellow',
|
|
250
|
+
undefined: 'grey',
|
|
251
|
+
null: 'bold',
|
|
252
|
+
string: 'green',
|
|
253
|
+
symbol: 'green',
|
|
254
|
+
date: 'magenta',
|
|
255
|
+
regexp: 'red',
|
|
256
|
+
module: 'underline',
|
|
257
|
+
} as Record<string, string>;
|
|
258
|
+
|
|
259
|
+
// ---- format ----
|
|
260
|
+
|
|
261
|
+
export function format(fmt: string, ...args: unknown[]): string {
|
|
262
|
+
// format() with no args returns ''
|
|
263
|
+
if (fmt === undefined && args.length === 0) return '';
|
|
264
|
+
|
|
265
|
+
if (typeof fmt !== 'string') {
|
|
266
|
+
if (args.length === 0) return inspect(fmt);
|
|
267
|
+
const parts = [inspect(fmt)];
|
|
268
|
+
for (const arg of args) parts.push(inspect(arg));
|
|
269
|
+
return parts.join(' ');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let i = 0;
|
|
273
|
+
let result = '';
|
|
274
|
+
let lastIdx = 0;
|
|
275
|
+
|
|
276
|
+
for (let p = 0; p < fmt.length - 1; p++) {
|
|
277
|
+
if (fmt[p] !== '%') continue;
|
|
278
|
+
|
|
279
|
+
if (p > lastIdx) result += fmt.slice(lastIdx, p);
|
|
280
|
+
|
|
281
|
+
const next = fmt[p + 1];
|
|
282
|
+
|
|
283
|
+
// %% always produces literal % (no arg consumed)
|
|
284
|
+
if (next === '%') {
|
|
285
|
+
result += '%';
|
|
286
|
+
lastIdx = p + 2;
|
|
287
|
+
p++;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (i >= args.length) {
|
|
292
|
+
result += '%' + next;
|
|
293
|
+
lastIdx = p + 2;
|
|
294
|
+
p++;
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const arg = args[i];
|
|
299
|
+
switch (next) {
|
|
300
|
+
case 's': {
|
|
301
|
+
if (typeof arg === 'bigint') {
|
|
302
|
+
result += `${arg}n`;
|
|
303
|
+
} else if (typeof arg === 'symbol') {
|
|
304
|
+
result += arg.toString();
|
|
305
|
+
} else if (typeof arg === 'number' && Object.is(arg, -0)) {
|
|
306
|
+
result += '-0';
|
|
307
|
+
} else if (typeof arg === 'object' && arg !== null) {
|
|
308
|
+
// Objects with custom toString use it, others get inspect
|
|
309
|
+
const proto = Object.getPrototypeOf(arg);
|
|
310
|
+
if (proto === null || (typeof arg.toString === 'function' && arg.toString !== Object.prototype.toString && arg.toString !== Array.prototype.toString)) {
|
|
311
|
+
try {
|
|
312
|
+
const str = arg.toString();
|
|
313
|
+
if (typeof str === 'string' && str !== '[object Object]') {
|
|
314
|
+
result += str;
|
|
315
|
+
} else {
|
|
316
|
+
result += inspect(arg, { depth: 0 });
|
|
317
|
+
}
|
|
318
|
+
} catch {
|
|
319
|
+
result += inspect(arg, { depth: 0 });
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
result += inspect(arg, { depth: 0 });
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
result += String(arg);
|
|
326
|
+
}
|
|
327
|
+
i++;
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
case 'd': {
|
|
331
|
+
if (typeof arg === 'bigint') {
|
|
332
|
+
result += `${arg}n`;
|
|
333
|
+
} else if (typeof arg === 'symbol') {
|
|
334
|
+
result += 'NaN';
|
|
335
|
+
} else {
|
|
336
|
+
const n = Number(arg);
|
|
337
|
+
result += Object.is(n, -0) ? '-0' : String(n);
|
|
338
|
+
}
|
|
339
|
+
i++;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
case 'i': {
|
|
343
|
+
if (typeof arg === 'bigint') {
|
|
344
|
+
result += `${arg}n`;
|
|
345
|
+
} else if (typeof arg === 'symbol') {
|
|
346
|
+
result += 'NaN';
|
|
347
|
+
} else {
|
|
348
|
+
const n = Number(arg);
|
|
349
|
+
if (!isFinite(n)) {
|
|
350
|
+
// Node.js: parseInt('Infinity') → NaN, parseInt('-Infinity') → NaN
|
|
351
|
+
result += 'NaN';
|
|
352
|
+
} else {
|
|
353
|
+
const truncated = Math.trunc(n);
|
|
354
|
+
result += Object.is(truncated, -0) ? '-0' : String(truncated);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
i++;
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
case 'f': {
|
|
361
|
+
if (typeof arg === 'bigint') {
|
|
362
|
+
result += Number(arg).toString();
|
|
363
|
+
} else if (typeof arg === 'symbol') {
|
|
364
|
+
result += 'NaN';
|
|
365
|
+
} else {
|
|
366
|
+
const n = parseFloat(String(arg));
|
|
367
|
+
result += Object.is(n, -0) ? '-0' : String(n);
|
|
368
|
+
}
|
|
369
|
+
i++;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
case 'j':
|
|
373
|
+
try {
|
|
374
|
+
result += JSON.stringify(args[i++]);
|
|
375
|
+
} catch {
|
|
376
|
+
result += '[Circular]';
|
|
377
|
+
}
|
|
378
|
+
break;
|
|
379
|
+
case 'o':
|
|
380
|
+
result += inspect(args[i++], { showHidden: true, depth: 4 });
|
|
381
|
+
break;
|
|
382
|
+
case 'O':
|
|
383
|
+
result += inspect(args[i++], { depth: 4 });
|
|
384
|
+
break;
|
|
385
|
+
default:
|
|
386
|
+
result += '%' + next;
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
lastIdx = p + 2;
|
|
390
|
+
p++;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (lastIdx < fmt.length) {
|
|
394
|
+
result += fmt.slice(lastIdx);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Append remaining args (strings passed as-is, objects inspected)
|
|
398
|
+
for (; i < args.length; i++) {
|
|
399
|
+
const arg = args[i];
|
|
400
|
+
if (typeof arg === 'string') {
|
|
401
|
+
result += ' ' + arg;
|
|
402
|
+
} else {
|
|
403
|
+
result += ' ' + inspect(arg);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function formatWithOptions(inspectOptions: InspectOptions, fmt: string, ...args: unknown[]): string {
|
|
411
|
+
// Apply inspect options to embedded inspect calls — simplified implementation
|
|
412
|
+
return format(fmt, ...args);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ---- promisify / callbackify ----
|
|
416
|
+
|
|
417
|
+
const kCustomPromisify = Symbol.for('nodejs.util.promisify.custom');
|
|
418
|
+
|
|
419
|
+
export function promisify<T extends (...args: unknown[]) => void>(fn: T): (...args: unknown[]) => Promise<unknown> {
|
|
420
|
+
if (typeof fn !== 'function') {
|
|
421
|
+
throw new TypeError('The "original" argument must be of type Function');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Check for custom promisify
|
|
425
|
+
const custom = (fn as unknown as Record<symbol, unknown>)[kCustomPromisify];
|
|
426
|
+
if (typeof custom === 'function') return custom as (...args: unknown[]) => Promise<unknown>;
|
|
427
|
+
|
|
428
|
+
function promisified(this: unknown, ...args: unknown[]): Promise<unknown> {
|
|
429
|
+
return new Promise((resolve, reject) => {
|
|
430
|
+
fn.call(this, ...args, (err: Error | null, ...values: unknown[]) => {
|
|
431
|
+
if (err) {
|
|
432
|
+
reject(err);
|
|
433
|
+
} else if (values.length <= 1) {
|
|
434
|
+
resolve(values[0]);
|
|
435
|
+
} else {
|
|
436
|
+
resolve(values);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
Object.setPrototypeOf(promisified, Object.getPrototypeOf(fn));
|
|
443
|
+
Object.defineProperty(promisified, kCustomPromisify, { value: promisified });
|
|
444
|
+
return promisified;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
promisify.custom = kCustomPromisify;
|
|
448
|
+
|
|
449
|
+
export function callbackify<T>(fn: () => Promise<T>): (callback: (err: Error | null, result?: T) => void) => void;
|
|
450
|
+
export function callbackify<T>(fn: (...args: unknown[]) => Promise<T>): (...args: unknown[]) => void;
|
|
451
|
+
export function callbackify(fn: (...args: unknown[]) => Promise<unknown>): (...args: unknown[]) => void {
|
|
452
|
+
if (typeof fn !== 'function') {
|
|
453
|
+
throw new TypeError('The "original" argument must be of type Function');
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
return function (this: unknown, ...args: unknown[]) {
|
|
457
|
+
const callback = args.pop();
|
|
458
|
+
if (typeof callback !== 'function') {
|
|
459
|
+
throw new TypeError('The last argument must be of type Function');
|
|
460
|
+
}
|
|
461
|
+
fn.apply(this, args).then(
|
|
462
|
+
(result: unknown) => Promise.resolve().then(() => callback(null, result)),
|
|
463
|
+
(err: Error) => Promise.resolve().then(() => callback(err || new Error()))
|
|
464
|
+
);
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// ---- deprecate ----
|
|
469
|
+
|
|
470
|
+
export function deprecate<T extends (...args: unknown[]) => unknown>(fn: T, msg: string, code?: string): T {
|
|
471
|
+
let warned = false;
|
|
472
|
+
function deprecated(this: unknown, ...args: unknown[]): unknown {
|
|
473
|
+
if (!warned) {
|
|
474
|
+
warned = true;
|
|
475
|
+
const warning = code ? `[${code}] ${msg}` : msg;
|
|
476
|
+
console.warn(`DeprecationWarning: ${warning}`);
|
|
477
|
+
}
|
|
478
|
+
return fn.apply(this, args);
|
|
479
|
+
}
|
|
480
|
+
Object.setPrototypeOf(deprecated, fn);
|
|
481
|
+
return deprecated as unknown as T;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ---- debuglog ----
|
|
485
|
+
|
|
486
|
+
export function debuglog(section: string): (...args: unknown[]) => void {
|
|
487
|
+
let debug: ((...args: unknown[]) => void) | undefined;
|
|
488
|
+
|
|
489
|
+
return (...args: unknown[]) => {
|
|
490
|
+
if (debug === undefined) {
|
|
491
|
+
const nodeDebug = typeof globalThis.process?.env?.NODE_DEBUG === 'string'
|
|
492
|
+
? globalThis.process.env.NODE_DEBUG
|
|
493
|
+
: '';
|
|
494
|
+
const regex = new RegExp(`\\b${section}\\b`, 'i');
|
|
495
|
+
if (regex.test(nodeDebug)) {
|
|
496
|
+
const pid = typeof globalThis.process?.pid === 'number' ? globalThis.process.pid : 0;
|
|
497
|
+
debug = (...a: unknown[]) => {
|
|
498
|
+
console.error(`${section.toUpperCase()} ${pid}:`, ...a);
|
|
499
|
+
};
|
|
500
|
+
} else {
|
|
501
|
+
debug = () => {};
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
debug(...args);
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// ---- inherits ----
|
|
509
|
+
|
|
510
|
+
export function inherits(ctor: Function, superCtor: Function): void {
|
|
511
|
+
if (ctor === undefined || ctor === null) {
|
|
512
|
+
throw new TypeError('The constructor to "inherits" must not be null or undefined');
|
|
513
|
+
}
|
|
514
|
+
if (superCtor === undefined || superCtor === null) {
|
|
515
|
+
throw new TypeError('The super constructor to "inherits" must not be null or undefined');
|
|
516
|
+
}
|
|
517
|
+
if (superCtor.prototype === undefined) {
|
|
518
|
+
throw new TypeError('The super constructor to "inherits" must have a prototype');
|
|
519
|
+
}
|
|
520
|
+
Object.defineProperty(ctor, 'super_', { value: superCtor, writable: true, configurable: true });
|
|
521
|
+
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ---- Legacy type checking (deprecated but still used) ----
|
|
525
|
+
|
|
526
|
+
export function isBoolean(value: unknown): value is boolean {
|
|
527
|
+
return typeof value === 'boolean';
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
export function isNull(value: unknown): value is null {
|
|
531
|
+
return value === null;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function isNullOrUndefined(value: unknown): value is null | undefined {
|
|
535
|
+
return value == null;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export function isNumber(value: unknown): value is number {
|
|
539
|
+
return typeof value === 'number';
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function isString(value: unknown): value is string {
|
|
543
|
+
return typeof value === 'string';
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
export function isSymbol(value: unknown): value is symbol {
|
|
547
|
+
return typeof value === 'symbol';
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export function isUndefined(value: unknown): value is undefined {
|
|
551
|
+
return value === undefined;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
export function isObject(value: unknown): value is object {
|
|
555
|
+
return value !== null && typeof value === 'object';
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
export function isError(value: unknown): value is Error {
|
|
559
|
+
return value instanceof Error;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export function isFunction(value: unknown): value is Function {
|
|
563
|
+
return typeof value === 'function';
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function isRegExp(value: unknown): value is RegExp {
|
|
567
|
+
return value instanceof RegExp;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
export function isArray(value: unknown): value is unknown[] {
|
|
571
|
+
return Array.isArray(value);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export function isPrimitive(value: unknown): boolean {
|
|
575
|
+
return value === null || (typeof value !== 'object' && typeof value !== 'function');
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
export function isDate(value: unknown): value is Date {
|
|
579
|
+
return value instanceof Date;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export function isBuffer(value: unknown): boolean {
|
|
583
|
+
return value instanceof Uint8Array && (value as unknown as { constructor?: { name?: string } }).constructor?.name === 'Buffer';
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// ---- Re-export globals ----
|
|
587
|
+
|
|
588
|
+
export const TextDecoder = globalThis.TextDecoder;
|
|
589
|
+
export const TextEncoder = globalThis.TextEncoder;
|
|
590
|
+
|
|
591
|
+
// ---- isDeepStrictEqual ----
|
|
592
|
+
|
|
593
|
+
export function isDeepStrictEqual(a: unknown, b: unknown): boolean {
|
|
594
|
+
if (Object.is(a, b)) return true;
|
|
595
|
+
if (typeof a !== typeof b) return false;
|
|
596
|
+
if (a === null || b === null) return false;
|
|
597
|
+
if (typeof a !== 'object') return false;
|
|
598
|
+
|
|
599
|
+
const aObj = a as Record<string, unknown>;
|
|
600
|
+
const bObj = b as Record<string, unknown>;
|
|
601
|
+
|
|
602
|
+
if (Array.isArray(aObj) && Array.isArray(bObj)) {
|
|
603
|
+
if (aObj.length !== bObj.length) return false;
|
|
604
|
+
for (let i = 0; i < aObj.length; i++) {
|
|
605
|
+
if (!isDeepStrictEqual(aObj[i], bObj[i])) return false;
|
|
606
|
+
}
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (Array.isArray(aObj) !== Array.isArray(bObj)) return false;
|
|
611
|
+
|
|
612
|
+
if (aObj instanceof Date && bObj instanceof Date) {
|
|
613
|
+
return aObj.getTime() === bObj.getTime();
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (aObj instanceof RegExp && bObj instanceof RegExp) {
|
|
617
|
+
return aObj.source === bObj.source && aObj.flags === bObj.flags;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const aKeys = Object.keys(aObj);
|
|
621
|
+
const bKeys = Object.keys(bObj);
|
|
622
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
623
|
+
|
|
624
|
+
for (const key of aKeys) {
|
|
625
|
+
if (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;
|
|
626
|
+
if (!isDeepStrictEqual(aObj[key], bObj[key])) return false;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// ---- toUSVString ----
|
|
633
|
+
|
|
634
|
+
export function toUSVString(string: string): string {
|
|
635
|
+
if (typeof (string as unknown as { toWellFormed?: () => string }).toWellFormed === 'function') {
|
|
636
|
+
return (string as unknown as { toWellFormed: () => string }).toWellFormed();
|
|
637
|
+
}
|
|
638
|
+
// Fallback
|
|
639
|
+
return string.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, '\uFFFD');
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// ---- Default export ----
|
|
643
|
+
|
|
644
|
+
export default {
|
|
645
|
+
format,
|
|
646
|
+
formatWithOptions,
|
|
647
|
+
inspect,
|
|
648
|
+
promisify,
|
|
649
|
+
callbackify,
|
|
650
|
+
deprecate,
|
|
651
|
+
debuglog,
|
|
652
|
+
inherits,
|
|
653
|
+
types,
|
|
654
|
+
isBoolean,
|
|
655
|
+
isNull,
|
|
656
|
+
isNullOrUndefined,
|
|
657
|
+
isNumber,
|
|
658
|
+
isString,
|
|
659
|
+
isSymbol,
|
|
660
|
+
isUndefined,
|
|
661
|
+
isObject,
|
|
662
|
+
isError,
|
|
663
|
+
isFunction,
|
|
664
|
+
isRegExp,
|
|
665
|
+
isArray,
|
|
666
|
+
isPrimitive,
|
|
667
|
+
isDate,
|
|
668
|
+
isBuffer,
|
|
669
|
+
isDeepStrictEqual,
|
|
670
|
+
toUSVString,
|
|
671
|
+
TextDecoder: globalThis.TextDecoder,
|
|
672
|
+
TextEncoder: globalThis.TextEncoder,
|
|
673
|
+
getSystemErrorName,
|
|
674
|
+
getSystemErrorMap,
|
|
675
|
+
};
|