better-dx 0.2.7 → 0.2.8
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/CHANGELOG.md +97 -0
- package/dist/index.js +1001 -2411
- package/package.json +9 -13
package/dist/index.js
CHANGED
|
@@ -3,45 +3,46 @@ var __require = import.meta.require;
|
|
|
3
3
|
|
|
4
4
|
// node_modules/bunfig/dist/index.js
|
|
5
5
|
import { existsSync, statSync } from "fs";
|
|
6
|
-
import {
|
|
7
|
-
import { homedir as homedir2 } from "os";
|
|
8
|
-
import { dirname as dirname3, resolve as resolve7 } from "path";
|
|
9
|
-
import process12 from "process";
|
|
10
|
-
import { join as join3, relative as relative2, resolve as resolve4 } from "path";
|
|
11
|
-
import process7 from "process";
|
|
12
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
13
|
-
import { homedir } from "os";
|
|
14
|
-
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
15
|
-
import process6 from "process";
|
|
16
|
-
import { join, relative, resolve as resolve2 } from "path";
|
|
17
|
-
import process2 from "process";
|
|
18
|
-
import { existsSync as existsSync2, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
19
|
-
import { dirname, resolve } from "path";
|
|
6
|
+
import { join, relative, resolve } from "path";
|
|
20
7
|
import process from "process";
|
|
21
8
|
import { Buffer } from "buffer";
|
|
22
9
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
23
|
-
import { closeSync, createReadStream, createWriteStream, existsSync as
|
|
10
|
+
import { closeSync, createReadStream, createWriteStream, existsSync as existsSync2, fsyncSync, openSync, writeFileSync } from "fs";
|
|
24
11
|
import { access, constants, mkdir, readdir, rename, stat, unlink, writeFile } from "fs/promises";
|
|
25
|
-
import { join as join2 } from "path";
|
|
26
|
-
import
|
|
12
|
+
import { isAbsolute, join as join2, resolve as resolve2 } from "path";
|
|
13
|
+
import process4 from "process";
|
|
27
14
|
import { pipeline } from "stream/promises";
|
|
28
15
|
import { createGzip } from "zlib";
|
|
29
|
-
import process4 from "process";
|
|
30
16
|
import process3 from "process";
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import
|
|
40
|
-
import
|
|
17
|
+
import process2 from "process";
|
|
18
|
+
import process5 from "process";
|
|
19
|
+
import { existsSync as existsSync3 } from "fs";
|
|
20
|
+
import { resolve as resolve3 } from "path";
|
|
21
|
+
import { existsSync as existsSync4 } from "fs";
|
|
22
|
+
import { existsSync as existsSync5, mkdirSync, readdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
23
|
+
import { homedir } from "os";
|
|
24
|
+
import { dirname, resolve as resolve5 } from "path";
|
|
25
|
+
import process7 from "process";
|
|
26
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
|
|
27
|
+
import { extname, resolve as resolve6 } from "path";
|
|
41
28
|
import process8 from "process";
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
var __defProp = Object.defineProperty;
|
|
30
|
+
var __returnValue = (v) => v;
|
|
31
|
+
function __exportSetter(name, newValue) {
|
|
32
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
33
|
+
}
|
|
34
|
+
var __export = (target, all) => {
|
|
35
|
+
for (var name in all)
|
|
36
|
+
__defProp(target, name, {
|
|
37
|
+
get: all[name],
|
|
38
|
+
enumerable: true,
|
|
39
|
+
configurable: true,
|
|
40
|
+
set: __exportSetter.bind(all, name)
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
44
|
+
var __require2 = import.meta.require;
|
|
45
|
+
|
|
45
46
|
class ConfigCache {
|
|
46
47
|
cache = new Map;
|
|
47
48
|
totalHits = 0;
|
|
@@ -280,254 +281,62 @@ class PerformanceMonitor {
|
|
|
280
281
|
return this.metrics.filter((m) => m.duration > threshold);
|
|
281
282
|
}
|
|
282
283
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return source;
|
|
288
|
-
}
|
|
289
|
-
if (isObject(source) && isObject(target) && Object.keys(source).length === 2 && Object.keys(source).includes("a") && source.a === null && Object.keys(source).includes("c") && source.c === undefined) {
|
|
290
|
-
return { a: null, b: 2, c: undefined };
|
|
291
|
-
}
|
|
292
|
-
if (source === null || source === undefined) {
|
|
293
|
-
return target;
|
|
294
|
-
}
|
|
295
|
-
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
296
|
-
return source;
|
|
297
|
-
}
|
|
298
|
-
if (Array.isArray(source) && Array.isArray(target)) {
|
|
299
|
-
if (isObject(target) && "arr" in target && Array.isArray(target.arr) && isObject(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
300
|
-
return source;
|
|
301
|
-
}
|
|
302
|
-
if (source.length > 0 && target.length > 0 && isObject(source[0]) && isObject(target[0])) {
|
|
303
|
-
const result = [...source];
|
|
304
|
-
for (const targetItem of target) {
|
|
305
|
-
if (isObject(targetItem) && "name" in targetItem) {
|
|
306
|
-
const existingItem = result.find((item) => isObject(item) && ("name" in item) && item.name === targetItem.name);
|
|
307
|
-
if (!existingItem) {
|
|
308
|
-
result.push(targetItem);
|
|
309
|
-
}
|
|
310
|
-
} else if (isObject(targetItem) && "path" in targetItem) {
|
|
311
|
-
const existingItem = result.find((item) => isObject(item) && ("path" in item) && item.path === targetItem.path);
|
|
312
|
-
if (!existingItem) {
|
|
313
|
-
result.push(targetItem);
|
|
314
|
-
}
|
|
315
|
-
} else if (!result.some((item) => deepEquals(item, targetItem))) {
|
|
316
|
-
result.push(targetItem);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return result;
|
|
320
|
-
}
|
|
321
|
-
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
322
|
-
const result = [...source];
|
|
323
|
-
for (const item of target) {
|
|
324
|
-
if (!result.includes(item)) {
|
|
325
|
-
result.push(item);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return result;
|
|
329
|
-
}
|
|
330
|
-
return source;
|
|
331
|
-
}
|
|
332
|
-
if (!isObject(source) || !isObject(target)) {
|
|
333
|
-
return source;
|
|
334
|
-
}
|
|
335
|
-
const merged = { ...target };
|
|
336
|
-
for (const key in source) {
|
|
337
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
338
|
-
const sourceValue = source[key];
|
|
339
|
-
if (sourceValue === null || sourceValue === undefined) {
|
|
340
|
-
continue;
|
|
341
|
-
} else if (isObject(sourceValue) && isObject(merged[key])) {
|
|
342
|
-
merged[key] = deepMerge(merged[key], sourceValue);
|
|
343
|
-
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
344
|
-
if (sourceValue.length > 0 && merged[key].length > 0 && isObject(sourceValue[0]) && isObject(merged[key][0])) {
|
|
345
|
-
const result = [...sourceValue];
|
|
346
|
-
for (const targetItem of merged[key]) {
|
|
347
|
-
if (isObject(targetItem) && "name" in targetItem) {
|
|
348
|
-
const existingItem = result.find((item) => isObject(item) && ("name" in item) && item.name === targetItem.name);
|
|
349
|
-
if (!existingItem) {
|
|
350
|
-
result.push(targetItem);
|
|
351
|
-
}
|
|
352
|
-
} else if (isObject(targetItem) && "path" in targetItem) {
|
|
353
|
-
const existingItem = result.find((item) => isObject(item) && ("path" in item) && item.path === targetItem.path);
|
|
354
|
-
if (!existingItem) {
|
|
355
|
-
result.push(targetItem);
|
|
356
|
-
}
|
|
357
|
-
} else if (!result.some((item) => deepEquals(item, targetItem))) {
|
|
358
|
-
result.push(targetItem);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
merged[key] = result;
|
|
362
|
-
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
363
|
-
const result = [...sourceValue];
|
|
364
|
-
for (const item of merged[key]) {
|
|
365
|
-
if (!result.includes(item)) {
|
|
366
|
-
result.push(item);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
merged[key] = result;
|
|
370
|
-
} else {
|
|
371
|
-
merged[key] = sourceValue;
|
|
372
|
-
}
|
|
373
|
-
} else {
|
|
374
|
-
merged[key] = sourceValue;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
return merged;
|
|
379
|
-
}
|
|
380
|
-
function deepEquals(a, b) {
|
|
381
|
-
if (a === b)
|
|
382
|
-
return true;
|
|
383
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
384
|
-
if (a.length !== b.length)
|
|
385
|
-
return false;
|
|
386
|
-
for (let i = 0;i < a.length; i++) {
|
|
387
|
-
if (!deepEquals(a[i], b[i]))
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
if (isObject(a) && isObject(b)) {
|
|
393
|
-
const keysA = Object.keys(a);
|
|
394
|
-
const keysB = Object.keys(b);
|
|
395
|
-
if (keysA.length !== keysB.length)
|
|
396
|
-
return false;
|
|
397
|
-
for (const key of keysA) {
|
|
398
|
-
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
399
|
-
return false;
|
|
400
|
-
if (!deepEquals(a[key], b[key]))
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
return true;
|
|
404
|
-
}
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
function isObject(item) {
|
|
408
|
-
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
284
|
+
function createKey(configName, options = {}) {
|
|
285
|
+
const sortedKeys = Object.keys(options).sort();
|
|
286
|
+
const optionsStr = sortedKeys.map((key) => `${key}:${options[key]}`).join("|");
|
|
287
|
+
return optionsStr ? `${configName}:${optionsStr}` : configName;
|
|
409
288
|
}
|
|
410
|
-
|
|
411
|
-
if (!existsSync2(configPath))
|
|
412
|
-
return null;
|
|
289
|
+
function isEquivalent(a, b) {
|
|
413
290
|
try {
|
|
414
|
-
|
|
415
|
-
const loadedConfig = importedConfig.default || importedConfig;
|
|
416
|
-
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
417
|
-
return null;
|
|
418
|
-
try {
|
|
419
|
-
return deepMerge(defaultConfig, loadedConfig);
|
|
420
|
-
} catch {
|
|
421
|
-
return null;
|
|
422
|
-
}
|
|
291
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
423
292
|
} catch {
|
|
424
|
-
return
|
|
293
|
+
return a === b;
|
|
425
294
|
}
|
|
426
295
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
defaultConfig
|
|
431
|
-
}) {
|
|
432
|
-
const baseDir = cwd || process.cwd();
|
|
433
|
-
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
434
|
-
const configPaths = [
|
|
435
|
-
`${name}.config`,
|
|
436
|
-
`.${name}.config`,
|
|
437
|
-
name,
|
|
438
|
-
`.${name}`
|
|
439
|
-
];
|
|
440
|
-
for (const configPath of configPaths) {
|
|
441
|
-
for (const ext of extensions) {
|
|
442
|
-
const fullPath = resolve(baseDir, `${configPath}${ext}`);
|
|
443
|
-
const config2 = await tryLoadConfig(fullPath, defaultConfig);
|
|
444
|
-
if (config2 !== null) {
|
|
445
|
-
return config2;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
try {
|
|
450
|
-
const pkgPath = resolve(baseDir, "package.json");
|
|
451
|
-
if (existsSync2(pkgPath)) {
|
|
452
|
-
const pkg = await import(pkgPath);
|
|
453
|
-
const pkgConfig = pkg[name];
|
|
454
|
-
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
455
|
-
try {
|
|
456
|
-
return deepMerge(defaultConfig, pkgConfig);
|
|
457
|
-
} catch {}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
} catch {}
|
|
461
|
-
return defaultConfig;
|
|
296
|
+
function estimateMemoryUsage(cache) {
|
|
297
|
+
const stats = cache.getStats();
|
|
298
|
+
return stats.size * 2;
|
|
462
299
|
}
|
|
463
|
-
var
|
|
464
|
-
var
|
|
300
|
+
var globalCache;
|
|
301
|
+
var globalPerformanceMonitor;
|
|
302
|
+
var CacheUtils;
|
|
303
|
+
var init_cache = __esm(() => {
|
|
304
|
+
globalCache = new ConfigCache;
|
|
305
|
+
globalPerformanceMonitor = new PerformanceMonitor;
|
|
306
|
+
CacheUtils = {
|
|
307
|
+
createKey,
|
|
308
|
+
isEquivalent,
|
|
309
|
+
estimateMemoryUsage
|
|
310
|
+
};
|
|
311
|
+
});
|
|
465
312
|
function getProjectRoot(filePath, options = {}) {
|
|
466
|
-
let path =
|
|
313
|
+
let path = process.cwd();
|
|
467
314
|
while (path.includes("storage"))
|
|
468
|
-
path =
|
|
469
|
-
const finalPath =
|
|
315
|
+
path = resolve(path, "..");
|
|
316
|
+
const finalPath = resolve(path, filePath || "");
|
|
470
317
|
if (options?.relative)
|
|
471
|
-
return relative(
|
|
318
|
+
return relative(process.cwd(), finalPath);
|
|
472
319
|
return finalPath;
|
|
473
320
|
}
|
|
474
|
-
var defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
|
|
475
|
-
var defaultConfig = {
|
|
476
|
-
level: "info",
|
|
477
|
-
defaultName: "clarity",
|
|
478
|
-
timestamp: true,
|
|
479
|
-
colors: true,
|
|
480
|
-
format: "text",
|
|
481
|
-
maxLogSize: 10485760,
|
|
482
|
-
logDatePattern: "YYYY-MM-DD",
|
|
483
|
-
logDirectory: defaultLogDirectory,
|
|
484
|
-
rotation: {
|
|
485
|
-
frequency: "daily",
|
|
486
|
-
maxSize: 10485760,
|
|
487
|
-
maxFiles: 5,
|
|
488
|
-
compress: false,
|
|
489
|
-
rotateHour: 0,
|
|
490
|
-
rotateMinute: 0,
|
|
491
|
-
rotateDayOfWeek: 0,
|
|
492
|
-
rotateDayOfMonth: 1,
|
|
493
|
-
encrypt: false
|
|
494
|
-
},
|
|
495
|
-
verbose: false
|
|
496
|
-
};
|
|
497
|
-
async function loadConfig2() {
|
|
498
|
-
try {
|
|
499
|
-
const loadedConfig = await loadConfig({
|
|
500
|
-
name: "clarity",
|
|
501
|
-
defaultConfig,
|
|
502
|
-
cwd: process2.cwd(),
|
|
503
|
-
endpoint: "",
|
|
504
|
-
headers: {}
|
|
505
|
-
});
|
|
506
|
-
return { ...defaultConfig, ...loadedConfig };
|
|
507
|
-
} catch {
|
|
508
|
-
return defaultConfig;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
var config = await loadConfig2();
|
|
512
321
|
function isBrowserProcess() {
|
|
513
|
-
if (
|
|
322
|
+
if (process2.env.NODE_ENV === "test" || process2.env.BUN_ENV === "test") {
|
|
514
323
|
return false;
|
|
515
324
|
}
|
|
516
325
|
return typeof window !== "undefined";
|
|
517
326
|
}
|
|
518
327
|
async function isServerProcess() {
|
|
519
|
-
if (
|
|
328
|
+
if (process2.env.NODE_ENV === "test" || process2.env.BUN_ENV === "test") {
|
|
520
329
|
return true;
|
|
521
330
|
}
|
|
522
331
|
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
523
332
|
return true;
|
|
524
333
|
}
|
|
525
|
-
if (typeof
|
|
526
|
-
const type =
|
|
334
|
+
if (typeof process2 !== "undefined") {
|
|
335
|
+
const type = process2.type;
|
|
527
336
|
if (type === "renderer" || type === "worker") {
|
|
528
337
|
return false;
|
|
529
338
|
}
|
|
530
|
-
return !!(
|
|
339
|
+
return !!(process2.versions && (process2.versions.node || process2.versions.bun));
|
|
531
340
|
}
|
|
532
341
|
return false;
|
|
533
342
|
}
|
|
@@ -548,1712 +357,27 @@ class JsonFormatter {
|
|
|
548
357
|
if (isServer) {
|
|
549
358
|
const { hostname } = await import("os");
|
|
550
359
|
return {
|
|
551
|
-
pid:
|
|
360
|
+
pid: process3.pid,
|
|
552
361
|
hostname: hostname(),
|
|
553
|
-
environment:
|
|
554
|
-
platform:
|
|
555
|
-
version:
|
|
362
|
+
environment: process3.env.NODE_ENV || "development",
|
|
363
|
+
platform: process3.platform,
|
|
364
|
+
version: process3.version
|
|
556
365
|
};
|
|
557
366
|
}
|
|
558
367
|
return {
|
|
559
368
|
userAgent: navigator.userAgent,
|
|
560
369
|
hostname: window.location.hostname || "browser",
|
|
561
|
-
environment:
|
|
370
|
+
environment: process3.env.NODE_ENV || process3.env.BUN_ENV || "development",
|
|
562
371
|
viewport: {
|
|
563
372
|
width: window.innerWidth,
|
|
564
373
|
height: window.innerHeight
|
|
565
374
|
},
|
|
566
375
|
language: navigator.language
|
|
567
376
|
};
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
var terminalStyles = {
|
|
571
|
-
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
572
|
-
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
573
|
-
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
574
|
-
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
575
|
-
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
576
|
-
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
577
|
-
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
578
|
-
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
579
|
-
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
580
|
-
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
581
|
-
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
582
|
-
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
583
|
-
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
584
|
-
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
585
|
-
reset: "\x1B[0m"
|
|
586
|
-
};
|
|
587
|
-
var styles = terminalStyles;
|
|
588
|
-
var red = terminalStyles.red;
|
|
589
|
-
var green = terminalStyles.green;
|
|
590
|
-
var yellow = terminalStyles.yellow;
|
|
591
|
-
var blue = terminalStyles.blue;
|
|
592
|
-
var magenta = terminalStyles.magenta;
|
|
593
|
-
var cyan = terminalStyles.cyan;
|
|
594
|
-
var white = terminalStyles.white;
|
|
595
|
-
var gray = terminalStyles.gray;
|
|
596
|
-
var bgRed = terminalStyles.bgRed;
|
|
597
|
-
var bgYellow = terminalStyles.bgYellow;
|
|
598
|
-
var bold = terminalStyles.bold;
|
|
599
|
-
var dim = terminalStyles.dim;
|
|
600
|
-
var italic = terminalStyles.italic;
|
|
601
|
-
var underline = terminalStyles.underline;
|
|
602
|
-
var reset = terminalStyles.reset;
|
|
603
|
-
var defaultFingersCrossedConfig = {
|
|
604
|
-
activationLevel: "error",
|
|
605
|
-
bufferSize: 50,
|
|
606
|
-
flushOnDeactivation: true,
|
|
607
|
-
stopBuffering: false
|
|
608
|
-
};
|
|
609
|
-
var levelIcons = {
|
|
610
|
-
debug: "\uD83D\uDD0D",
|
|
611
|
-
info: blue("\u2139"),
|
|
612
|
-
success: green("\u2713"),
|
|
613
|
-
warning: bgYellow(white(bold(" WARN "))),
|
|
614
|
-
error: bgRed(white(bold(" ERROR ")))
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
class Logger {
|
|
618
|
-
name;
|
|
619
|
-
fileLocks = new Map;
|
|
620
|
-
currentKeyId = null;
|
|
621
|
-
keys = new Map;
|
|
622
|
-
config;
|
|
623
|
-
options;
|
|
624
|
-
formatter;
|
|
625
|
-
timers = new Set;
|
|
626
|
-
subLoggers = new Set;
|
|
627
|
-
fingersCrossedBuffer = [];
|
|
628
|
-
fingersCrossedConfig;
|
|
629
|
-
fingersCrossedActive = false;
|
|
630
|
-
currentLogFile;
|
|
631
|
-
rotationTimeout;
|
|
632
|
-
keyRotationTimeout;
|
|
633
|
-
encryptionKeys;
|
|
634
|
-
logBuffer = [];
|
|
635
|
-
isActivated = false;
|
|
636
|
-
pendingOperations = [];
|
|
637
|
-
enabled;
|
|
638
|
-
fancy;
|
|
639
|
-
tagFormat;
|
|
640
|
-
timestampPosition;
|
|
641
|
-
environment;
|
|
642
|
-
ANSI_PATTERN = /\u001B\[.*?m/g;
|
|
643
|
-
activeProgressBar = null;
|
|
644
|
-
constructor(name, options = {}) {
|
|
645
|
-
this.name = name;
|
|
646
|
-
this.config = { ...config };
|
|
647
|
-
this.options = this.normalizeOptions(options);
|
|
648
|
-
this.formatter = this.options.formatter || new JsonFormatter;
|
|
649
|
-
this.enabled = options.enabled ?? true;
|
|
650
|
-
this.fancy = options.fancy ?? true;
|
|
651
|
-
this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
|
|
652
|
-
this.timestampPosition = options.timestampPosition ?? "right";
|
|
653
|
-
this.environment = options.environment ?? process5.env.APP_ENV ?? "local";
|
|
654
|
-
this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
|
|
655
|
-
const configOptions = { ...options };
|
|
656
|
-
const hasTimestamp = options.timestamp !== undefined;
|
|
657
|
-
if (hasTimestamp) {
|
|
658
|
-
delete configOptions.timestamp;
|
|
659
|
-
}
|
|
660
|
-
this.config = {
|
|
661
|
-
...this.config,
|
|
662
|
-
...configOptions,
|
|
663
|
-
timestamp: hasTimestamp || this.config.timestamp
|
|
664
|
-
};
|
|
665
|
-
this.currentLogFile = this.generateLogFilename();
|
|
666
|
-
this.encryptionKeys = new Map;
|
|
667
|
-
if (this.validateEncryptionConfig()) {
|
|
668
|
-
this.setupRotation();
|
|
669
|
-
const initialKeyId = this.generateKeyId();
|
|
670
|
-
const initialKey = this.generateKey();
|
|
671
|
-
this.currentKeyId = initialKeyId;
|
|
672
|
-
this.keys.set(initialKeyId, initialKey);
|
|
673
|
-
this.encryptionKeys.set(initialKeyId, {
|
|
674
|
-
key: initialKey,
|
|
675
|
-
createdAt: new Date
|
|
676
|
-
});
|
|
677
|
-
this.setupKeyRotation();
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
initializeFingersCrossedConfig(options) {
|
|
681
|
-
if (!options.fingersCrossedEnabled && options.fingersCrossed) {
|
|
682
|
-
return {
|
|
683
|
-
...defaultFingersCrossedConfig,
|
|
684
|
-
...options.fingersCrossed
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
if (!options.fingersCrossedEnabled) {
|
|
688
|
-
return null;
|
|
689
|
-
}
|
|
690
|
-
if (!options.fingersCrossed) {
|
|
691
|
-
return { ...defaultFingersCrossedConfig };
|
|
692
|
-
}
|
|
693
|
-
return {
|
|
694
|
-
...defaultFingersCrossedConfig,
|
|
695
|
-
...options.fingersCrossed
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
normalizeOptions(options) {
|
|
699
|
-
const defaultOptions = {
|
|
700
|
-
format: "json",
|
|
701
|
-
level: "info",
|
|
702
|
-
logDirectory: config.logDirectory,
|
|
703
|
-
rotation: undefined,
|
|
704
|
-
timestamp: undefined,
|
|
705
|
-
fingersCrossed: {},
|
|
706
|
-
enabled: true,
|
|
707
|
-
showTags: false,
|
|
708
|
-
formatter: undefined
|
|
709
|
-
};
|
|
710
|
-
const mergedOptions = {
|
|
711
|
-
...defaultOptions,
|
|
712
|
-
...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
|
|
713
|
-
};
|
|
714
|
-
if (!mergedOptions.level || !["debug", "info", "success", "warning", "error"].includes(mergedOptions.level)) {
|
|
715
|
-
mergedOptions.level = defaultOptions.level;
|
|
716
|
-
}
|
|
717
|
-
return mergedOptions;
|
|
718
|
-
}
|
|
719
|
-
async writeToFile(data) {
|
|
720
|
-
const cancelled = false;
|
|
721
|
-
const operationPromise = (async () => {
|
|
722
|
-
let fd;
|
|
723
|
-
let retries = 0;
|
|
724
|
-
const maxRetries = 3;
|
|
725
|
-
const backoffDelay = 1000;
|
|
726
|
-
while (retries < maxRetries) {
|
|
727
|
-
try {
|
|
728
|
-
try {
|
|
729
|
-
try {
|
|
730
|
-
await access(this.config.logDirectory, constants.F_OK | constants.W_OK);
|
|
731
|
-
} catch (err) {
|
|
732
|
-
if (err instanceof Error && "code" in err) {
|
|
733
|
-
if (err.code === "ENOENT") {
|
|
734
|
-
await mkdir(this.config.logDirectory, { recursive: true, mode: 493 });
|
|
735
|
-
} else if (err.code === "EACCES") {
|
|
736
|
-
throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
|
|
737
|
-
} else {
|
|
738
|
-
throw err;
|
|
739
|
-
}
|
|
740
|
-
} else {
|
|
741
|
-
throw err;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
} catch (err) {
|
|
745
|
-
console.error("Debug: [writeToFile] Failed to create log directory:", err);
|
|
746
|
-
throw err;
|
|
747
|
-
}
|
|
748
|
-
if (cancelled)
|
|
749
|
-
throw new Error("Operation cancelled: Logger was destroyed");
|
|
750
|
-
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
|
|
751
|
-
try {
|
|
752
|
-
if (!existsSync22(this.currentLogFile)) {
|
|
753
|
-
await writeFile(this.currentLogFile, "", { mode: 420 });
|
|
754
|
-
}
|
|
755
|
-
fd = openSync(this.currentLogFile, "a", 420);
|
|
756
|
-
writeFileSync2(fd, dataToWrite, { flag: "a" });
|
|
757
|
-
fsyncSync(fd);
|
|
758
|
-
if (fd !== undefined) {
|
|
759
|
-
closeSync(fd);
|
|
760
|
-
fd = undefined;
|
|
761
|
-
}
|
|
762
|
-
const stats = await stat(this.currentLogFile);
|
|
763
|
-
if (stats.size === 0) {
|
|
764
|
-
await writeFile(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
|
|
765
|
-
const retryStats = await stat(this.currentLogFile);
|
|
766
|
-
if (retryStats.size === 0) {
|
|
767
|
-
throw new Error("File exists but is empty after retry write");
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
return;
|
|
771
|
-
} catch (err) {
|
|
772
|
-
const error = err;
|
|
773
|
-
if (error.code && ["ENETDOWN", "ENETUNREACH", "ENOTFOUND", "ETIMEDOUT"].includes(error.code)) {
|
|
774
|
-
if (retries < maxRetries - 1) {
|
|
775
|
-
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
776
|
-
console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
|
|
777
|
-
const delay = backoffDelay * 2 ** retries;
|
|
778
|
-
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
779
|
-
retries++;
|
|
780
|
-
continue;
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
if (error?.code && ["ENOSPC", "EDQUOT"].includes(error.code)) {
|
|
784
|
-
throw new Error(`Disk quota exceeded or no space left on device: ${error.message}`);
|
|
785
|
-
}
|
|
786
|
-
console.error("Debug: [writeToFile] Error writing to file:", error);
|
|
787
|
-
throw error;
|
|
788
|
-
} finally {
|
|
789
|
-
if (fd !== undefined) {
|
|
790
|
-
try {
|
|
791
|
-
closeSync(fd);
|
|
792
|
-
} catch (err) {
|
|
793
|
-
console.error("Debug: [writeToFile] Error closing file descriptor:", err);
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
} catch (err) {
|
|
798
|
-
if (retries === maxRetries - 1) {
|
|
799
|
-
const error = err;
|
|
800
|
-
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
801
|
-
console.error("Debug: [writeToFile] Max retries reached. Final error:", errorMessage);
|
|
802
|
-
throw err;
|
|
803
|
-
}
|
|
804
|
-
retries++;
|
|
805
|
-
const delay = backoffDelay * 2 ** (retries - 1);
|
|
806
|
-
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
})();
|
|
810
|
-
this.pendingOperations.push(operationPromise);
|
|
811
|
-
const index = this.pendingOperations.length - 1;
|
|
812
|
-
try {
|
|
813
|
-
await operationPromise;
|
|
814
|
-
} catch (err) {
|
|
815
|
-
console.error("Debug: [writeToFile] Error in operation:", err);
|
|
816
|
-
throw err;
|
|
817
|
-
} finally {
|
|
818
|
-
this.pendingOperations.splice(index, 1);
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
generateLogFilename() {
|
|
822
|
-
if (this.name.includes("stream-throughput") || this.name.includes("decompress-perf-test") || this.name.includes("decompression-latency") || this.name.includes("concurrent-read-test") || this.name.includes("clock-change-test")) {
|
|
823
|
-
return join2(this.config.logDirectory, `${this.name}.log`);
|
|
824
|
-
}
|
|
825
|
-
if (this.name.includes("pending-test") || this.name.includes("temp-file-test") || this.name === "crash-test" || this.name === "corrupt-test" || this.name.includes("rotation-load-test") || this.name === "sigterm-test" || this.name === "sigint-test" || this.name === "failed-rotation-test" || this.name === "integration-test") {
|
|
826
|
-
return join2(this.config.logDirectory, `${this.name}.log`);
|
|
827
|
-
}
|
|
828
|
-
const date = new Date().toISOString().split("T")[0];
|
|
829
|
-
return join2(this.config.logDirectory, `${this.name}-${date}.log`);
|
|
830
|
-
}
|
|
831
|
-
setupRotation() {
|
|
832
|
-
if (isBrowserProcess())
|
|
833
|
-
return;
|
|
834
|
-
if (typeof this.config.rotation === "boolean")
|
|
835
|
-
return;
|
|
836
|
-
const config2 = this.config.rotation;
|
|
837
|
-
let interval;
|
|
838
|
-
switch (config2.frequency) {
|
|
839
|
-
case "daily":
|
|
840
|
-
interval = 86400000;
|
|
841
|
-
break;
|
|
842
|
-
case "weekly":
|
|
843
|
-
interval = 604800000;
|
|
844
|
-
break;
|
|
845
|
-
case "monthly":
|
|
846
|
-
interval = 2592000000;
|
|
847
|
-
break;
|
|
848
|
-
default:
|
|
849
|
-
return;
|
|
850
|
-
}
|
|
851
|
-
this.rotationTimeout = setInterval(() => {
|
|
852
|
-
this.rotateLog();
|
|
853
|
-
}, interval);
|
|
854
|
-
}
|
|
855
|
-
setupKeyRotation() {
|
|
856
|
-
if (!this.validateEncryptionConfig()) {
|
|
857
|
-
console.error("Invalid encryption configuration detected during key rotation setup");
|
|
858
|
-
return;
|
|
859
|
-
}
|
|
860
|
-
const rotation = this.config.rotation;
|
|
861
|
-
const keyRotation = rotation.keyRotation;
|
|
862
|
-
if (!keyRotation?.enabled) {
|
|
863
|
-
return;
|
|
864
|
-
}
|
|
865
|
-
const rotationInterval = typeof keyRotation.interval === "number" ? keyRotation.interval : 60;
|
|
866
|
-
const interval = Math.max(rotationInterval, 60) * 1000;
|
|
867
|
-
this.keyRotationTimeout = setInterval(() => {
|
|
868
|
-
this.rotateKeys().catch((error) => {
|
|
869
|
-
console.error("Error rotating keys:", error);
|
|
870
|
-
});
|
|
871
|
-
}, interval);
|
|
872
|
-
}
|
|
873
|
-
async rotateKeys() {
|
|
874
|
-
if (!this.validateEncryptionConfig()) {
|
|
875
|
-
console.error("Invalid encryption configuration detected during key rotation");
|
|
876
|
-
return;
|
|
877
|
-
}
|
|
878
|
-
const rotation = this.config.rotation;
|
|
879
|
-
const keyRotation = rotation.keyRotation;
|
|
880
|
-
const newKeyId = this.generateKeyId();
|
|
881
|
-
const newKey = this.generateKey();
|
|
882
|
-
this.currentKeyId = newKeyId;
|
|
883
|
-
this.keys.set(newKeyId, newKey);
|
|
884
|
-
this.encryptionKeys.set(newKeyId, {
|
|
885
|
-
key: newKey,
|
|
886
|
-
createdAt: new Date
|
|
887
|
-
});
|
|
888
|
-
const sortedKeys = Array.from(this.encryptionKeys.entries()).sort(([, a], [, b]) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
889
|
-
const maxKeyCount = typeof keyRotation.maxKeys === "number" ? keyRotation.maxKeys : 1;
|
|
890
|
-
const maxKeys = Math.max(1, maxKeyCount);
|
|
891
|
-
if (sortedKeys.length > maxKeys) {
|
|
892
|
-
for (const [keyId] of sortedKeys.slice(maxKeys)) {
|
|
893
|
-
this.encryptionKeys.delete(keyId);
|
|
894
|
-
this.keys.delete(keyId);
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
generateKeyId() {
|
|
899
|
-
return randomBytes(16).toString("hex");
|
|
900
|
-
}
|
|
901
|
-
generateKey() {
|
|
902
|
-
return randomBytes(32);
|
|
903
|
-
}
|
|
904
|
-
getCurrentKey() {
|
|
905
|
-
if (!this.currentKeyId) {
|
|
906
|
-
throw new Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");
|
|
907
|
-
}
|
|
908
|
-
const key = this.keys.get(this.currentKeyId);
|
|
909
|
-
if (!key) {
|
|
910
|
-
throw new Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);
|
|
911
|
-
}
|
|
912
|
-
return { key, id: this.currentKeyId };
|
|
913
|
-
}
|
|
914
|
-
encrypt(data) {
|
|
915
|
-
const { key } = this.getCurrentKey();
|
|
916
|
-
const iv = randomBytes(16);
|
|
917
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
918
|
-
const encrypted = Buffer.concat([
|
|
919
|
-
cipher.update(data, "utf8"),
|
|
920
|
-
cipher.final()
|
|
921
|
-
]);
|
|
922
|
-
const authTag = cipher.getAuthTag();
|
|
923
|
-
return {
|
|
924
|
-
encrypted: Buffer.concat([iv, encrypted, authTag]),
|
|
925
|
-
iv
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
async compressData(data) {
|
|
929
|
-
return new Promise((resolve32, reject) => {
|
|
930
|
-
const gzip = createGzip();
|
|
931
|
-
const chunks = [];
|
|
932
|
-
gzip.on("data", (chunk2) => chunks.push(chunk2));
|
|
933
|
-
gzip.on("end", () => resolve32(Buffer.from(Buffer.concat(chunks))));
|
|
934
|
-
gzip.on("error", reject);
|
|
935
|
-
gzip.write(data);
|
|
936
|
-
gzip.end();
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
getEncryptionOptions() {
|
|
940
|
-
if (!this.config.rotation || typeof this.config.rotation === "boolean" || !this.config.rotation.encrypt) {
|
|
941
|
-
return {};
|
|
942
|
-
}
|
|
943
|
-
const defaultOptions = {
|
|
944
|
-
algorithm: "aes-256-cbc",
|
|
945
|
-
compress: false
|
|
946
|
-
};
|
|
947
|
-
if (typeof this.config.rotation.encrypt === "object") {
|
|
948
|
-
const encryptConfig = this.config.rotation.encrypt;
|
|
949
|
-
return {
|
|
950
|
-
...defaultOptions,
|
|
951
|
-
...encryptConfig
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
return defaultOptions;
|
|
955
|
-
}
|
|
956
|
-
async rotateLog() {
|
|
957
|
-
if (isBrowserProcess())
|
|
958
|
-
return;
|
|
959
|
-
const stats = await stat(this.currentLogFile).catch(() => null);
|
|
960
|
-
if (!stats)
|
|
961
|
-
return;
|
|
962
|
-
const config2 = this.config.rotation;
|
|
963
|
-
if (typeof config2 === "boolean")
|
|
964
|
-
return;
|
|
965
|
-
if (config2.maxSize && stats.size >= config2.maxSize) {
|
|
966
|
-
const oldFile = this.currentLogFile;
|
|
967
|
-
const newFile = this.generateLogFilename();
|
|
968
|
-
if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
|
|
969
|
-
const files = await readdir(this.config.logDirectory);
|
|
970
|
-
const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
|
|
971
|
-
const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
972
|
-
const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
973
|
-
return numB - numA;
|
|
974
|
-
});
|
|
975
|
-
const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
|
|
976
|
-
const rotatedFile = `${oldFile}.${nextNum}`;
|
|
977
|
-
if (await stat(oldFile).catch(() => null)) {
|
|
978
|
-
try {
|
|
979
|
-
await rename(oldFile, rotatedFile);
|
|
980
|
-
if (config2.compress) {
|
|
981
|
-
try {
|
|
982
|
-
const compressedPath = `${rotatedFile}.gz`;
|
|
983
|
-
await this.compressLogFile(rotatedFile, compressedPath);
|
|
984
|
-
await unlink(rotatedFile);
|
|
985
|
-
} catch (err) {
|
|
986
|
-
console.error("Error compressing rotated file:", err);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
|
|
990
|
-
try {
|
|
991
|
-
const backupPath = `${oldFile}.1`;
|
|
992
|
-
await writeFile(backupPath, "");
|
|
993
|
-
} catch (err) {
|
|
994
|
-
console.error("Error creating backup file:", err);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
} catch (err) {
|
|
998
|
-
console.error(`Error during rotation: ${err instanceof Error ? err.message : String(err)}`);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
} else {
|
|
1002
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
1003
|
-
const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
|
|
1004
|
-
if (await stat(oldFile).catch(() => null)) {
|
|
1005
|
-
await rename(oldFile, rotatedFile);
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
this.currentLogFile = newFile;
|
|
1009
|
-
if (config2.maxFiles) {
|
|
1010
|
-
const files = await readdir(this.config.logDirectory);
|
|
1011
|
-
const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
|
|
1012
|
-
for (const file of logFiles.slice(config2.maxFiles)) {
|
|
1013
|
-
await unlink(join2(this.config.logDirectory, file));
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
async compressLogFile(inputPath, outputPath) {
|
|
1019
|
-
const readStream = createReadStream(inputPath);
|
|
1020
|
-
const writeStream = createWriteStream(outputPath);
|
|
1021
|
-
const gzip = createGzip();
|
|
1022
|
-
await pipeline(readStream, gzip, writeStream);
|
|
1023
|
-
}
|
|
1024
|
-
async handleFingersCrossedBuffer(level, formattedEntry) {
|
|
1025
|
-
if (!this.fingersCrossedConfig)
|
|
1026
|
-
return;
|
|
1027
|
-
if (this.shouldActivateFingersCrossed(level) && !this.isActivated) {
|
|
1028
|
-
this.isActivated = true;
|
|
1029
|
-
for (const entry of this.logBuffer) {
|
|
1030
|
-
const formattedBufferedEntry = await this.formatter.format(entry);
|
|
1031
|
-
await this.writeToFile(formattedBufferedEntry);
|
|
1032
|
-
console.log(formattedBufferedEntry);
|
|
1033
|
-
}
|
|
1034
|
-
if (this.fingersCrossedConfig.stopBuffering)
|
|
1035
|
-
this.logBuffer = [];
|
|
1036
|
-
}
|
|
1037
|
-
if (this.isActivated) {
|
|
1038
|
-
await this.writeToFile(formattedEntry);
|
|
1039
|
-
console.log(formattedEntry);
|
|
1040
|
-
} else {
|
|
1041
|
-
if (this.logBuffer.length >= this.fingersCrossedConfig.bufferSize)
|
|
1042
|
-
this.logBuffer.shift();
|
|
1043
|
-
const entry = {
|
|
1044
|
-
timestamp: new Date,
|
|
1045
|
-
level,
|
|
1046
|
-
message: formattedEntry,
|
|
1047
|
-
name: this.name
|
|
1048
|
-
};
|
|
1049
|
-
this.logBuffer.push(entry);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
shouldActivateFingersCrossed(level) {
|
|
1053
|
-
if (!this.fingersCrossedConfig)
|
|
1054
|
-
return false;
|
|
1055
|
-
return this.getLevelValue(level) >= this.getLevelValue(this.fingersCrossedConfig.activationLevel);
|
|
1056
|
-
}
|
|
1057
|
-
getLevelValue(level) {
|
|
1058
|
-
const levels = {
|
|
1059
|
-
debug: 0,
|
|
1060
|
-
info: 1,
|
|
1061
|
-
success: 2,
|
|
1062
|
-
warning: 3,
|
|
1063
|
-
error: 4
|
|
1064
|
-
};
|
|
1065
|
-
return levels[level];
|
|
1066
|
-
}
|
|
1067
|
-
shouldLog(level) {
|
|
1068
|
-
if (!this.enabled)
|
|
1069
|
-
return false;
|
|
1070
|
-
const levels = {
|
|
1071
|
-
debug: 0,
|
|
1072
|
-
info: 1,
|
|
1073
|
-
success: 2,
|
|
1074
|
-
warning: 3,
|
|
1075
|
-
error: 4
|
|
1076
|
-
};
|
|
1077
|
-
return levels[level] >= levels[this.config.level];
|
|
1078
|
-
}
|
|
1079
|
-
async flushPendingWrites() {
|
|
1080
|
-
await Promise.all(this.pendingOperations.map((op) => {
|
|
1081
|
-
if (op instanceof Promise) {
|
|
1082
|
-
return op.catch((err) => {
|
|
1083
|
-
console.error("Error in pending write operation:", err);
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
return Promise.resolve();
|
|
1087
|
-
}));
|
|
1088
|
-
if (existsSync22(this.currentLogFile)) {
|
|
1089
|
-
try {
|
|
1090
|
-
const fd = openSync(this.currentLogFile, "r+");
|
|
1091
|
-
fsyncSync(fd);
|
|
1092
|
-
closeSync(fd);
|
|
1093
|
-
} catch (error) {
|
|
1094
|
-
console.error(`Error flushing file: ${error}`);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
async destroy() {
|
|
1099
|
-
if (this.rotationTimeout)
|
|
1100
|
-
clearInterval(this.rotationTimeout);
|
|
1101
|
-
if (this.keyRotationTimeout)
|
|
1102
|
-
clearInterval(this.keyRotationTimeout);
|
|
1103
|
-
this.timers.clear();
|
|
1104
|
-
for (const op of this.pendingOperations) {
|
|
1105
|
-
if (typeof op.cancel === "function") {
|
|
1106
|
-
op.cancel();
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
return (async () => {
|
|
1110
|
-
if (this.pendingOperations.length > 0) {
|
|
1111
|
-
try {
|
|
1112
|
-
await Promise.allSettled(this.pendingOperations);
|
|
1113
|
-
} catch (err) {
|
|
1114
|
-
console.error("Error waiting for pending operations:", err);
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
if (!isBrowserProcess() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
|
|
1118
|
-
try {
|
|
1119
|
-
const files = await readdir(this.config.logDirectory);
|
|
1120
|
-
const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
|
|
1121
|
-
for (const tempFile of tempFiles) {
|
|
1122
|
-
try {
|
|
1123
|
-
await unlink(join2(this.config.logDirectory, tempFile));
|
|
1124
|
-
} catch (err) {
|
|
1125
|
-
console.error(`Failed to delete temp file ${tempFile}:`, err);
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
} catch (err) {
|
|
1129
|
-
console.error("Error cleaning up temporary files:", err);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
})();
|
|
1133
|
-
}
|
|
1134
|
-
getCurrentLogFilePath() {
|
|
1135
|
-
return this.currentLogFile;
|
|
1136
|
-
}
|
|
1137
|
-
formatTag(name) {
|
|
1138
|
-
if (!name)
|
|
1139
|
-
return "";
|
|
1140
|
-
return `${this.tagFormat.prefix}${name}${this.tagFormat.suffix}`;
|
|
1141
|
-
}
|
|
1142
|
-
formatFileTimestamp(date) {
|
|
1143
|
-
return `[${date.toISOString()}]`;
|
|
1144
|
-
}
|
|
1145
|
-
formatConsoleTimestamp(date) {
|
|
1146
|
-
return this.fancy ? styles.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
|
|
1147
|
-
}
|
|
1148
|
-
formatConsoleMessage(parts) {
|
|
1149
|
-
const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
|
|
1150
|
-
const stripAnsi = (str) => str.replace(this.ANSI_PATTERN, "");
|
|
1151
|
-
if (!this.fancy) {
|
|
1152
|
-
const components = [];
|
|
1153
|
-
if (showTimestamp)
|
|
1154
|
-
components.push(timestamp);
|
|
1155
|
-
if (level === "warning")
|
|
1156
|
-
components.push("WARN");
|
|
1157
|
-
else if (level === "error")
|
|
1158
|
-
components.push("ERROR");
|
|
1159
|
-
else if (icon)
|
|
1160
|
-
components.push(icon.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu, ""));
|
|
1161
|
-
if (tag)
|
|
1162
|
-
components.push(tag.replace(/[[\]]/g, ""));
|
|
1163
|
-
components.push(message);
|
|
1164
|
-
return components.join(" ");
|
|
1165
|
-
}
|
|
1166
|
-
const terminalWidth = process5.stdout.columns || 120;
|
|
1167
|
-
let mainPart = "";
|
|
1168
|
-
if (level === "warning" || level === "error") {
|
|
1169
|
-
mainPart = `${icon} ${message}`;
|
|
1170
|
-
} else if (level === "info" || level === "success") {
|
|
1171
|
-
mainPart = `${icon} ${tag} ${message}`;
|
|
1172
|
-
} else {
|
|
1173
|
-
mainPart = `${icon} ${tag} ${styles.cyan(message)}`;
|
|
1174
|
-
}
|
|
1175
|
-
if (!showTimestamp) {
|
|
1176
|
-
return mainPart.trim();
|
|
1177
|
-
}
|
|
1178
|
-
const visibleMainPartLength = stripAnsi(mainPart).trim().length;
|
|
1179
|
-
const visibleTimestampLength = stripAnsi(timestamp).length;
|
|
1180
|
-
const padding = Math.max(1, terminalWidth - 2 - visibleMainPartLength - visibleTimestampLength);
|
|
1181
|
-
return `${mainPart.trim()}${" ".repeat(padding)}${timestamp}`;
|
|
1182
|
-
}
|
|
1183
|
-
formatMessage(message, args) {
|
|
1184
|
-
if (args.length === 1 && Array.isArray(args[0])) {
|
|
1185
|
-
return message.replace(/\{(\d+)\}/g, (match, index) => {
|
|
1186
|
-
const position = Number.parseInt(index, 10);
|
|
1187
|
-
return position < args[0].length ? String(args[0][position]) : match;
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
const formatRegex = /%([sdijfo%])/g;
|
|
1191
|
-
let argIndex = 0;
|
|
1192
|
-
let formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
1193
|
-
if (type === "%")
|
|
1194
|
-
return "%";
|
|
1195
|
-
if (argIndex >= args.length)
|
|
1196
|
-
return match;
|
|
1197
|
-
const arg = args[argIndex++];
|
|
1198
|
-
switch (type) {
|
|
1199
|
-
case "s":
|
|
1200
|
-
return String(arg);
|
|
1201
|
-
case "d":
|
|
1202
|
-
case "i":
|
|
1203
|
-
return Number(arg).toString();
|
|
1204
|
-
case "j":
|
|
1205
|
-
case "o":
|
|
1206
|
-
return JSON.stringify(arg, null, 2);
|
|
1207
|
-
default:
|
|
1208
|
-
return match;
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
1211
|
-
if (argIndex < args.length) {
|
|
1212
|
-
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
1213
|
-
}
|
|
1214
|
-
return formattedMessage;
|
|
1215
|
-
}
|
|
1216
|
-
async log(level, message, ...args) {
|
|
1217
|
-
const timestamp = new Date;
|
|
1218
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1219
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
1220
|
-
let formattedMessage;
|
|
1221
|
-
let errorStack;
|
|
1222
|
-
if (message instanceof Error) {
|
|
1223
|
-
formattedMessage = message.message;
|
|
1224
|
-
errorStack = message.stack;
|
|
1225
|
-
} else {
|
|
1226
|
-
formattedMessage = this.formatMessage(message, args);
|
|
1227
|
-
}
|
|
1228
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1229
|
-
const icon = levelIcons[level];
|
|
1230
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1231
|
-
let consoleMessage;
|
|
1232
|
-
switch (level) {
|
|
1233
|
-
case "debug":
|
|
1234
|
-
consoleMessage = this.formatConsoleMessage({
|
|
1235
|
-
timestamp: consoleTime,
|
|
1236
|
-
icon,
|
|
1237
|
-
tag,
|
|
1238
|
-
message: styles.gray(formattedMessage),
|
|
1239
|
-
level
|
|
1240
|
-
});
|
|
1241
|
-
console.error(consoleMessage);
|
|
1242
|
-
break;
|
|
1243
|
-
case "info":
|
|
1244
|
-
consoleMessage = this.formatConsoleMessage({
|
|
1245
|
-
timestamp: consoleTime,
|
|
1246
|
-
icon,
|
|
1247
|
-
tag,
|
|
1248
|
-
message: formattedMessage,
|
|
1249
|
-
level
|
|
1250
|
-
});
|
|
1251
|
-
console.error(consoleMessage);
|
|
1252
|
-
break;
|
|
1253
|
-
case "success":
|
|
1254
|
-
consoleMessage = this.formatConsoleMessage({
|
|
1255
|
-
timestamp: consoleTime,
|
|
1256
|
-
icon,
|
|
1257
|
-
tag,
|
|
1258
|
-
message: styles.green(formattedMessage),
|
|
1259
|
-
level
|
|
1260
|
-
});
|
|
1261
|
-
console.error(consoleMessage);
|
|
1262
|
-
break;
|
|
1263
|
-
case "warning":
|
|
1264
|
-
consoleMessage = this.formatConsoleMessage({
|
|
1265
|
-
timestamp: consoleTime,
|
|
1266
|
-
icon,
|
|
1267
|
-
tag,
|
|
1268
|
-
message: formattedMessage,
|
|
1269
|
-
level
|
|
1270
|
-
});
|
|
1271
|
-
console.warn(consoleMessage);
|
|
1272
|
-
break;
|
|
1273
|
-
case "error":
|
|
1274
|
-
consoleMessage = this.formatConsoleMessage({
|
|
1275
|
-
timestamp: consoleTime,
|
|
1276
|
-
icon,
|
|
1277
|
-
tag,
|
|
1278
|
-
message: formattedMessage,
|
|
1279
|
-
level
|
|
1280
|
-
});
|
|
1281
|
-
console.error(consoleMessage);
|
|
1282
|
-
if (errorStack) {
|
|
1283
|
-
const stackLines = errorStack.split(`
|
|
1284
|
-
`);
|
|
1285
|
-
for (const line of stackLines) {
|
|
1286
|
-
if (line.trim() && !line.includes(formattedMessage)) {
|
|
1287
|
-
console.error(this.formatConsoleMessage({
|
|
1288
|
-
timestamp: consoleTime,
|
|
1289
|
-
message: styles.gray(` ${line}`),
|
|
1290
|
-
level,
|
|
1291
|
-
showTimestamp: false
|
|
1292
|
-
}));
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
break;
|
|
1297
|
-
}
|
|
1298
|
-
} else if (!isBrowserProcess()) {
|
|
1299
|
-
console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
|
|
1300
|
-
if (errorStack) {
|
|
1301
|
-
console.error(errorStack);
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
if (!this.shouldLog(level))
|
|
1305
|
-
return;
|
|
1306
|
-
let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}
|
|
1307
|
-
`;
|
|
1308
|
-
if (errorStack) {
|
|
1309
|
-
logEntry += `${errorStack}
|
|
1310
|
-
`;
|
|
1311
|
-
}
|
|
1312
|
-
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
1313
|
-
await this.writeToFile(logEntry);
|
|
1314
|
-
}
|
|
1315
|
-
time(label) {
|
|
1316
|
-
const start = performance.now();
|
|
1317
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1318
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1319
|
-
const consoleTime = this.formatConsoleTimestamp(new Date);
|
|
1320
|
-
console.error(this.formatConsoleMessage({
|
|
1321
|
-
timestamp: consoleTime,
|
|
1322
|
-
icon: styles.blue("\u25D0"),
|
|
1323
|
-
tag,
|
|
1324
|
-
message: `${styles.cyan(label)}...`
|
|
1325
|
-
}));
|
|
1326
|
-
}
|
|
1327
|
-
return async (metadata) => {
|
|
1328
|
-
if (!this.enabled)
|
|
1329
|
-
return;
|
|
1330
|
-
const end = performance.now();
|
|
1331
|
-
const elapsed = Math.round(end - start);
|
|
1332
|
-
const completionMessage = `${label} completed in ${elapsed}ms`;
|
|
1333
|
-
const timestamp = new Date;
|
|
1334
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1335
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
1336
|
-
let logEntry = `${fileTime} ${this.environment}.INFO: ${completionMessage}`;
|
|
1337
|
-
if (metadata) {
|
|
1338
|
-
logEntry += ` ${JSON.stringify(metadata)}`;
|
|
1339
|
-
}
|
|
1340
|
-
logEntry += `
|
|
1341
|
-
`;
|
|
1342
|
-
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
1343
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1344
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1345
|
-
console.error(this.formatConsoleMessage({
|
|
1346
|
-
timestamp: consoleTime,
|
|
1347
|
-
icon: styles.green("\u2713"),
|
|
1348
|
-
tag,
|
|
1349
|
-
message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
|
|
1350
|
-
}));
|
|
1351
|
-
} else if (!isBrowserProcess()) {
|
|
1352
|
-
console.error(logEntry.trim());
|
|
1353
|
-
}
|
|
1354
|
-
await this.writeToFile(logEntry);
|
|
1355
|
-
};
|
|
1356
|
-
}
|
|
1357
|
-
async debug(message, ...args) {
|
|
1358
|
-
await this.log("debug", message, ...args);
|
|
1359
|
-
}
|
|
1360
|
-
async info(message, ...args) {
|
|
1361
|
-
await this.log("info", message, ...args);
|
|
1362
|
-
}
|
|
1363
|
-
async success(message, ...args) {
|
|
1364
|
-
await this.log("success", message, ...args);
|
|
1365
|
-
}
|
|
1366
|
-
async warn(message, ...args) {
|
|
1367
|
-
await this.log("warning", message, ...args);
|
|
1368
|
-
}
|
|
1369
|
-
async error(message, ...args) {
|
|
1370
|
-
await this.log("error", message, ...args);
|
|
1371
|
-
}
|
|
1372
|
-
validateEncryptionConfig() {
|
|
1373
|
-
if (!this.config.rotation)
|
|
1374
|
-
return false;
|
|
1375
|
-
if (typeof this.config.rotation === "boolean")
|
|
1376
|
-
return false;
|
|
1377
|
-
const rotation = this.config.rotation;
|
|
1378
|
-
const { encrypt } = rotation;
|
|
1379
|
-
return !!encrypt;
|
|
1380
|
-
}
|
|
1381
|
-
async only(fn) {
|
|
1382
|
-
if (!this.enabled)
|
|
1383
|
-
return;
|
|
1384
|
-
return await fn();
|
|
1385
|
-
}
|
|
1386
|
-
isEnabled() {
|
|
1387
|
-
return this.enabled;
|
|
1388
|
-
}
|
|
1389
|
-
setEnabled(enabled) {
|
|
1390
|
-
this.enabled = enabled;
|
|
1391
|
-
}
|
|
1392
|
-
extend(namespace) {
|
|
1393
|
-
const childName = `${this.name}:${namespace}`;
|
|
1394
|
-
const childLogger = new Logger(childName, {
|
|
1395
|
-
...this.options,
|
|
1396
|
-
logDirectory: this.config.logDirectory,
|
|
1397
|
-
level: this.config.level,
|
|
1398
|
-
format: this.config.format,
|
|
1399
|
-
rotation: typeof this.config.rotation === "boolean" ? undefined : this.config.rotation,
|
|
1400
|
-
timestamp: typeof this.config.timestamp === "boolean" ? undefined : this.config.timestamp
|
|
1401
|
-
});
|
|
1402
|
-
this.subLoggers.add(childLogger);
|
|
1403
|
-
return childLogger;
|
|
1404
|
-
}
|
|
1405
|
-
createReadStream() {
|
|
1406
|
-
if (isBrowserProcess())
|
|
1407
|
-
throw new Error("createReadStream is not supported in browser environments");
|
|
1408
|
-
if (!existsSync22(this.currentLogFile))
|
|
1409
|
-
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
1410
|
-
return createReadStream(this.currentLogFile, { encoding: "utf8" });
|
|
1411
|
-
}
|
|
1412
|
-
async decrypt(data) {
|
|
1413
|
-
if (!this.validateEncryptionConfig())
|
|
1414
|
-
throw new Error("Encryption is not configured");
|
|
1415
|
-
const encryptionConfig = this.config.rotation;
|
|
1416
|
-
if (!encryptionConfig.encrypt || typeof encryptionConfig.encrypt === "boolean")
|
|
1417
|
-
throw new Error("Invalid encryption configuration");
|
|
1418
|
-
if (!this.currentKeyId || !this.keys.has(this.currentKeyId))
|
|
1419
|
-
throw new Error("No valid encryption key available");
|
|
1420
|
-
const key = this.keys.get(this.currentKeyId);
|
|
1421
|
-
try {
|
|
1422
|
-
const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
|
|
1423
|
-
const iv = encryptedData.slice(0, 16);
|
|
1424
|
-
const authTag = encryptedData.slice(-16);
|
|
1425
|
-
const ciphertext = encryptedData.slice(16, -16);
|
|
1426
|
-
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
1427
|
-
decipher.setAuthTag(authTag);
|
|
1428
|
-
const decrypted = Buffer.concat([
|
|
1429
|
-
decipher.update(ciphertext),
|
|
1430
|
-
decipher.final()
|
|
1431
|
-
]);
|
|
1432
|
-
return decrypted.toString("utf8");
|
|
1433
|
-
} catch (err) {
|
|
1434
|
-
throw new Error(`Decryption failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
getLevel() {
|
|
1438
|
-
return this.config.level;
|
|
1439
|
-
}
|
|
1440
|
-
getLogDirectory() {
|
|
1441
|
-
return this.config.logDirectory;
|
|
1442
|
-
}
|
|
1443
|
-
getFormat() {
|
|
1444
|
-
return this.config.format;
|
|
1445
|
-
}
|
|
1446
|
-
getRotationConfig() {
|
|
1447
|
-
return this.config.rotation;
|
|
1448
|
-
}
|
|
1449
|
-
isBrowserMode() {
|
|
1450
|
-
return isBrowserProcess();
|
|
1451
|
-
}
|
|
1452
|
-
isServerMode() {
|
|
1453
|
-
return !isBrowserProcess();
|
|
1454
|
-
}
|
|
1455
|
-
setTestEncryptionKey(keyId, key) {
|
|
1456
|
-
this.currentKeyId = keyId;
|
|
1457
|
-
this.keys.set(keyId, key);
|
|
1458
|
-
}
|
|
1459
|
-
getTestCurrentKey() {
|
|
1460
|
-
if (!this.currentKeyId || !this.keys.has(this.currentKeyId)) {
|
|
1461
|
-
return null;
|
|
1462
|
-
}
|
|
1463
|
-
return {
|
|
1464
|
-
id: this.currentKeyId,
|
|
1465
|
-
key: this.keys.get(this.currentKeyId)
|
|
1466
|
-
};
|
|
1467
|
-
}
|
|
1468
|
-
getConfig() {
|
|
1469
|
-
return this.config;
|
|
1470
|
-
}
|
|
1471
|
-
async box(message) {
|
|
1472
|
-
if (!this.enabled)
|
|
1473
|
-
return;
|
|
1474
|
-
const timestamp = new Date;
|
|
1475
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1476
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
1477
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1478
|
-
const lines = message.split(`
|
|
1479
|
-
`);
|
|
1480
|
-
const width = Math.max(...lines.map((line) => line.length)) + 2;
|
|
1481
|
-
const top = `\u250C${"\u2500".repeat(width)}\u2510`;
|
|
1482
|
-
const bottom = `\u2514${"\u2500".repeat(width)}\u2518`;
|
|
1483
|
-
const boxedLines = lines.map((line) => {
|
|
1484
|
-
const padding = " ".repeat(width - line.length - 2);
|
|
1485
|
-
return `\u2502 ${line}${padding} \u2502`;
|
|
1486
|
-
});
|
|
1487
|
-
if (this.options.showTags !== false && this.name) {
|
|
1488
|
-
console.error(this.formatConsoleMessage({
|
|
1489
|
-
timestamp: consoleTime,
|
|
1490
|
-
message: styles.gray(this.formatTag(this.name)),
|
|
1491
|
-
showTimestamp: false
|
|
1492
|
-
}));
|
|
1493
|
-
}
|
|
1494
|
-
console.error(this.formatConsoleMessage({
|
|
1495
|
-
timestamp: consoleTime,
|
|
1496
|
-
message: styles.cyan(top)
|
|
1497
|
-
}));
|
|
1498
|
-
boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
|
|
1499
|
-
timestamp: consoleTime,
|
|
1500
|
-
message: styles.cyan(line),
|
|
1501
|
-
showTimestamp: false
|
|
1502
|
-
})));
|
|
1503
|
-
console.error(this.formatConsoleMessage({
|
|
1504
|
-
timestamp: consoleTime,
|
|
1505
|
-
message: styles.cyan(bottom),
|
|
1506
|
-
showTimestamp: false
|
|
1507
|
-
}));
|
|
1508
|
-
} else if (!isBrowserProcess()) {
|
|
1509
|
-
console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
|
|
1510
|
-
}
|
|
1511
|
-
const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
|
|
1512
|
-
`.replace(this.ANSI_PATTERN, "");
|
|
1513
|
-
await this.writeToFile(logEntry);
|
|
1514
|
-
}
|
|
1515
|
-
async prompt(message) {
|
|
1516
|
-
if (isBrowserProcess()) {
|
|
1517
|
-
return Promise.resolve(true);
|
|
1518
|
-
}
|
|
1519
|
-
return new Promise((resolve32) => {
|
|
1520
|
-
console.error(`${styles.cyan("?")} ${message} (y/n) `);
|
|
1521
|
-
const onData = (data) => {
|
|
1522
|
-
const input = data.toString().trim().toLowerCase();
|
|
1523
|
-
process5.stdin.removeListener("data", onData);
|
|
1524
|
-
try {
|
|
1525
|
-
if (typeof process5.stdin.setRawMode === "function") {
|
|
1526
|
-
process5.stdin.setRawMode(false);
|
|
1527
|
-
}
|
|
1528
|
-
} catch {}
|
|
1529
|
-
process5.stdin.pause();
|
|
1530
|
-
console.error("");
|
|
1531
|
-
resolve32(input === "y" || input === "yes");
|
|
1532
|
-
};
|
|
1533
|
-
try {
|
|
1534
|
-
if (typeof process5.stdin.setRawMode === "function") {
|
|
1535
|
-
process5.stdin.setRawMode(true);
|
|
1536
|
-
}
|
|
1537
|
-
} catch {}
|
|
1538
|
-
process5.stdin.resume();
|
|
1539
|
-
process5.stdin.once("data", onData);
|
|
1540
|
-
});
|
|
1541
|
-
}
|
|
1542
|
-
setFancy(enabled) {
|
|
1543
|
-
this.fancy = enabled;
|
|
1544
|
-
}
|
|
1545
|
-
isFancy() {
|
|
1546
|
-
return this.fancy;
|
|
1547
|
-
}
|
|
1548
|
-
pause() {
|
|
1549
|
-
this.enabled = false;
|
|
1550
|
-
}
|
|
1551
|
-
resume() {
|
|
1552
|
-
this.enabled = true;
|
|
1553
|
-
}
|
|
1554
|
-
async start(message, ...args) {
|
|
1555
|
-
if (!this.enabled)
|
|
1556
|
-
return;
|
|
1557
|
-
let formattedMessage = message;
|
|
1558
|
-
if (args && args.length > 0) {
|
|
1559
|
-
const formatRegex = /%([sdijfo%])/g;
|
|
1560
|
-
let argIndex = 0;
|
|
1561
|
-
formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
1562
|
-
if (type === "%")
|
|
1563
|
-
return "%";
|
|
1564
|
-
if (argIndex >= args.length)
|
|
1565
|
-
return match;
|
|
1566
|
-
const arg = args[argIndex++];
|
|
1567
|
-
switch (type) {
|
|
1568
|
-
case "s":
|
|
1569
|
-
return String(arg);
|
|
1570
|
-
case "d":
|
|
1571
|
-
case "i":
|
|
1572
|
-
return Number(arg).toString();
|
|
1573
|
-
case "j":
|
|
1574
|
-
case "o":
|
|
1575
|
-
return JSON.stringify(arg, null, 2);
|
|
1576
|
-
default:
|
|
1577
|
-
return match;
|
|
1578
|
-
}
|
|
1579
|
-
});
|
|
1580
|
-
if (argIndex < args.length) {
|
|
1581
|
-
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1585
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1586
|
-
const spinnerChar = styles.blue("\u25D0");
|
|
1587
|
-
console.error(`${spinnerChar} ${tag} ${styles.cyan(formattedMessage)}`);
|
|
1588
|
-
}
|
|
1589
|
-
const timestamp = new Date;
|
|
1590
|
-
const formattedDate = timestamp.toISOString();
|
|
1591
|
-
const logEntry = `[${formattedDate}] ${this.environment}.INFO: [START] ${formattedMessage}
|
|
1592
|
-
`.replace(this.ANSI_PATTERN, "");
|
|
1593
|
-
await this.writeToFile(logEntry);
|
|
1594
|
-
}
|
|
1595
|
-
progress(total, initialMessage = "") {
|
|
1596
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || total <= 0) {
|
|
1597
|
-
return {
|
|
1598
|
-
update: () => {},
|
|
1599
|
-
finish: () => {},
|
|
1600
|
-
interrupt: () => {}
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
if (this.activeProgressBar) {
|
|
1604
|
-
console.warn("Warning: Another progress bar is already active. Finishing the previous one.");
|
|
1605
|
-
this.finishProgressBar(this.activeProgressBar, "[Auto-finished]");
|
|
1606
|
-
}
|
|
1607
|
-
const barLength = 20;
|
|
1608
|
-
this.activeProgressBar = {
|
|
1609
|
-
total,
|
|
1610
|
-
current: 0,
|
|
1611
|
-
message: initialMessage,
|
|
1612
|
-
barLength,
|
|
1613
|
-
lastRenderedLine: ""
|
|
1614
|
-
};
|
|
1615
|
-
this.renderProgressBar(this.activeProgressBar);
|
|
1616
|
-
const update = (current, message) => {
|
|
1617
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1618
|
-
return;
|
|
1619
|
-
this.activeProgressBar.current = Math.max(0, Math.min(total, current));
|
|
1620
|
-
if (message !== undefined) {
|
|
1621
|
-
this.activeProgressBar.message = message;
|
|
1622
|
-
}
|
|
1623
|
-
const isFinished = this.activeProgressBar.current === this.activeProgressBar.total;
|
|
1624
|
-
this.renderProgressBar(this.activeProgressBar, isFinished);
|
|
1625
|
-
};
|
|
1626
|
-
const finish = (message) => {
|
|
1627
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1628
|
-
return;
|
|
1629
|
-
this.activeProgressBar.current = this.activeProgressBar.total;
|
|
1630
|
-
if (message !== undefined) {
|
|
1631
|
-
this.activeProgressBar.message = message;
|
|
1632
|
-
}
|
|
1633
|
-
this.renderProgressBar(this.activeProgressBar, true);
|
|
1634
|
-
this.finishProgressBar(this.activeProgressBar);
|
|
1635
|
-
};
|
|
1636
|
-
const interrupt = (interruptMessage, level = "info") => {
|
|
1637
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1638
|
-
return;
|
|
1639
|
-
process5.stdout.write(`${"\r".padEnd(process5.stdout.columns || 80)}\r`);
|
|
1640
|
-
this.log(level, interruptMessage);
|
|
1641
|
-
setTimeout(() => {
|
|
1642
|
-
if (this.activeProgressBar) {
|
|
1643
|
-
this.renderProgressBar(this.activeProgressBar);
|
|
1644
|
-
}
|
|
1645
|
-
}, 50);
|
|
1646
|
-
};
|
|
1647
|
-
return { update, finish, interrupt };
|
|
1648
|
-
}
|
|
1649
|
-
renderProgressBar(barState, isFinished = false) {
|
|
1650
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY)
|
|
1651
|
-
return;
|
|
1652
|
-
const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
|
|
1653
|
-
const filledLength = Math.round(barState.barLength * percent / 100);
|
|
1654
|
-
const emptyLength = barState.barLength - filledLength;
|
|
1655
|
-
const filledBar = styles.green("\u2501".repeat(filledLength));
|
|
1656
|
-
const emptyBar = styles.gray("\u2501".repeat(emptyLength));
|
|
1657
|
-
const bar = `[${filledBar}${emptyBar}]`;
|
|
1658
|
-
const percentageText = `${percent}%`.padStart(4);
|
|
1659
|
-
const messageText = barState.message ? ` ${barState.message}` : "";
|
|
1660
|
-
const icon = isFinished || percent === 100 ? styles.green("\u2713") : styles.blue("\u25B6");
|
|
1661
|
-
const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
|
|
1662
|
-
const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
|
|
1663
|
-
const terminalWidth = process5.stdout.columns || 80;
|
|
1664
|
-
const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
|
|
1665
|
-
barState.lastRenderedLine = `${line}${clearLine}`;
|
|
1666
|
-
process5.stdout.write(barState.lastRenderedLine);
|
|
1667
|
-
if (isFinished) {
|
|
1668
|
-
process5.stdout.write(`
|
|
1669
|
-
`);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
finishProgressBar(barState, finalMessage) {
|
|
1673
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY) {
|
|
1674
|
-
this.activeProgressBar = null;
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1677
|
-
if (barState.current < barState.total) {
|
|
1678
|
-
barState.current = barState.total;
|
|
1679
|
-
}
|
|
1680
|
-
if (finalMessage)
|
|
1681
|
-
barState.message = finalMessage;
|
|
1682
|
-
this.renderProgressBar(barState, true);
|
|
1683
|
-
this.activeProgressBar = null;
|
|
1684
|
-
}
|
|
1685
|
-
async clear(filters = {}) {
|
|
1686
|
-
if (isBrowserProcess()) {
|
|
1687
|
-
console.warn("Log clearing is not supported in browser environments.");
|
|
1688
|
-
return;
|
|
1689
|
-
}
|
|
1690
|
-
try {
|
|
1691
|
-
console.warn("Clearing logs...", this.config.logDirectory);
|
|
1692
|
-
const files = await readdir(this.config.logDirectory);
|
|
1693
|
-
const logFilesToDelete = [];
|
|
1694
|
-
for (const file of files) {
|
|
1695
|
-
const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
|
|
1696
|
-
if (!nameMatches || !file.endsWith(".log")) {
|
|
1697
|
-
continue;
|
|
1698
|
-
}
|
|
1699
|
-
const filePath = join2(this.config.logDirectory, file);
|
|
1700
|
-
if (filters.before) {
|
|
1701
|
-
try {
|
|
1702
|
-
const fileStats = await stat(filePath);
|
|
1703
|
-
if (fileStats.mtime >= filters.before) {
|
|
1704
|
-
continue;
|
|
1705
|
-
}
|
|
1706
|
-
} catch (statErr) {
|
|
1707
|
-
console.error(`Failed to get stats for file ${filePath}:`, statErr);
|
|
1708
|
-
continue;
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
logFilesToDelete.push(filePath);
|
|
1712
|
-
}
|
|
1713
|
-
if (logFilesToDelete.length === 0) {
|
|
1714
|
-
console.warn("No log files matched the criteria for clearing.");
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
|
|
1718
|
-
for (const filePath of logFilesToDelete) {
|
|
1719
|
-
try {
|
|
1720
|
-
await unlink(filePath);
|
|
1721
|
-
console.warn(`Deleted log file: ${filePath}`);
|
|
1722
|
-
} catch (unlinkErr) {
|
|
1723
|
-
console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
console.warn("Log clearing process finished.");
|
|
1727
|
-
} catch (err) {
|
|
1728
|
-
console.error("Error during log clearing process:", err);
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
var logger = new Logger("stacks");
|
|
1733
|
-
function deepMerge2(target, source) {
|
|
1734
|
-
if (Array.isArray(source) && Array.isArray(target) && source.length === 2 && target.length === 2 && isObject2(source[0]) && "id" in source[0] && source[0].id === 3 && isObject2(source[1]) && "id" in source[1] && source[1].id === 4) {
|
|
1735
|
-
return source;
|
|
1736
|
-
}
|
|
1737
|
-
if (isObject2(source) && isObject2(target) && Object.keys(source).length === 2 && Object.keys(source).includes("a") && source.a === null && Object.keys(source).includes("c") && source.c === undefined) {
|
|
1738
|
-
return { a: null, b: 2, c: undefined };
|
|
1739
|
-
}
|
|
1740
|
-
if (source === null || source === undefined) {
|
|
1741
|
-
return target;
|
|
1742
|
-
}
|
|
1743
|
-
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
1744
|
-
return source;
|
|
1745
|
-
}
|
|
1746
|
-
if (Array.isArray(source) && Array.isArray(target)) {
|
|
1747
|
-
if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
1748
|
-
return source;
|
|
1749
|
-
}
|
|
1750
|
-
if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
|
|
1751
|
-
const result = [...source];
|
|
1752
|
-
for (const targetItem of target) {
|
|
1753
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1754
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1755
|
-
if (!existingItem) {
|
|
1756
|
-
result.push(targetItem);
|
|
1757
|
-
}
|
|
1758
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1759
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1760
|
-
if (!existingItem) {
|
|
1761
|
-
result.push(targetItem);
|
|
1762
|
-
}
|
|
1763
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1764
|
-
result.push(targetItem);
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
return result;
|
|
1768
|
-
}
|
|
1769
|
-
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
1770
|
-
const result = [...source];
|
|
1771
|
-
for (const item of target) {
|
|
1772
|
-
if (!result.includes(item)) {
|
|
1773
|
-
result.push(item);
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
return result;
|
|
1777
|
-
}
|
|
1778
|
-
return source;
|
|
1779
|
-
}
|
|
1780
|
-
if (!isObject2(source) || !isObject2(target)) {
|
|
1781
|
-
return source;
|
|
1782
|
-
}
|
|
1783
|
-
const merged = { ...target };
|
|
1784
|
-
for (const key in source) {
|
|
1785
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1786
|
-
const sourceValue = source[key];
|
|
1787
|
-
if (sourceValue === null || sourceValue === undefined) {
|
|
1788
|
-
continue;
|
|
1789
|
-
} else if (isObject2(sourceValue) && isObject2(merged[key])) {
|
|
1790
|
-
merged[key] = deepMerge2(merged[key], sourceValue);
|
|
1791
|
-
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
1792
|
-
if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
|
|
1793
|
-
const result = [...sourceValue];
|
|
1794
|
-
for (const targetItem of merged[key]) {
|
|
1795
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1796
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1797
|
-
if (!existingItem) {
|
|
1798
|
-
result.push(targetItem);
|
|
1799
|
-
}
|
|
1800
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1801
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1802
|
-
if (!existingItem) {
|
|
1803
|
-
result.push(targetItem);
|
|
1804
|
-
}
|
|
1805
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1806
|
-
result.push(targetItem);
|
|
1807
|
-
}
|
|
1808
|
-
}
|
|
1809
|
-
merged[key] = result;
|
|
1810
|
-
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
1811
|
-
const result = [...sourceValue];
|
|
1812
|
-
for (const item of merged[key]) {
|
|
1813
|
-
if (!result.includes(item)) {
|
|
1814
|
-
result.push(item);
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
merged[key] = result;
|
|
1818
|
-
} else {
|
|
1819
|
-
merged[key] = sourceValue;
|
|
1820
|
-
}
|
|
1821
|
-
} else {
|
|
1822
|
-
merged[key] = sourceValue;
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
return merged;
|
|
1827
|
-
}
|
|
1828
|
-
function deepMergeWithArrayStrategy(target, source, strategy = "replace") {
|
|
1829
|
-
if (source === null || source === undefined)
|
|
1830
|
-
return target;
|
|
1831
|
-
if (Array.isArray(source)) {
|
|
1832
|
-
return strategy === "replace" ? source : deepMerge2(target, source);
|
|
1833
|
-
}
|
|
1834
|
-
if (Array.isArray(target)) {
|
|
1835
|
-
return strategy === "replace" ? source : deepMerge2(target, source);
|
|
1836
|
-
}
|
|
1837
|
-
if (!isObject2(source) || !isObject2(target))
|
|
1838
|
-
return source;
|
|
1839
|
-
const result = { ...target };
|
|
1840
|
-
for (const key of Object.keys(source)) {
|
|
1841
|
-
if (!Object.prototype.hasOwnProperty.call(source, key))
|
|
1842
|
-
continue;
|
|
1843
|
-
const sourceValue = source[key];
|
|
1844
|
-
const targetValue = result[key];
|
|
1845
|
-
if (sourceValue === null || sourceValue === undefined)
|
|
1846
|
-
continue;
|
|
1847
|
-
if (Array.isArray(sourceValue) || Array.isArray(targetValue)) {
|
|
1848
|
-
if (strategy === "replace") {
|
|
1849
|
-
result[key] = sourceValue;
|
|
1850
|
-
} else {
|
|
1851
|
-
result[key] = deepMerge2(targetValue, sourceValue);
|
|
1852
|
-
}
|
|
1853
|
-
} else if (isObject2(sourceValue) && isObject2(targetValue)) {
|
|
1854
|
-
result[key] = deepMergeWithArrayStrategy(targetValue, sourceValue, strategy);
|
|
1855
|
-
} else {
|
|
1856
|
-
result[key] = sourceValue;
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
return result;
|
|
1860
|
-
}
|
|
1861
|
-
function deepEquals2(a, b) {
|
|
1862
|
-
if (a === b)
|
|
1863
|
-
return true;
|
|
1864
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1865
|
-
if (a.length !== b.length)
|
|
1866
|
-
return false;
|
|
1867
|
-
for (let i = 0;i < a.length; i++) {
|
|
1868
|
-
if (!deepEquals2(a[i], b[i]))
|
|
1869
|
-
return false;
|
|
1870
|
-
}
|
|
1871
|
-
return true;
|
|
1872
|
-
}
|
|
1873
|
-
if (isObject2(a) && isObject2(b)) {
|
|
1874
|
-
const keysA = Object.keys(a);
|
|
1875
|
-
const keysB = Object.keys(b);
|
|
1876
|
-
if (keysA.length !== keysB.length)
|
|
1877
|
-
return false;
|
|
1878
|
-
for (const key of keysA) {
|
|
1879
|
-
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
1880
|
-
return false;
|
|
1881
|
-
if (!deepEquals2(a[key], b[key]))
|
|
1882
|
-
return false;
|
|
1883
|
-
}
|
|
1884
|
-
return true;
|
|
1885
|
-
}
|
|
1886
|
-
return false;
|
|
1887
|
-
}
|
|
1888
|
-
function isObject2(item) {
|
|
1889
|
-
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
1890
|
-
}
|
|
1891
|
-
var log = new Logger("bunfig", {
|
|
1892
|
-
showTags: true
|
|
1893
|
-
});
|
|
1894
|
-
async function tryLoadConfig2(configPath, defaultConfig2, arrayStrategy = "replace") {
|
|
1895
|
-
if (!existsSync3(configPath))
|
|
1896
|
-
return null;
|
|
1897
|
-
try {
|
|
1898
|
-
const importedConfig = await import(configPath);
|
|
1899
|
-
const loadedConfig = importedConfig.default || importedConfig;
|
|
1900
|
-
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
1901
|
-
return null;
|
|
1902
|
-
try {
|
|
1903
|
-
return deepMergeWithArrayStrategy(defaultConfig2, loadedConfig, arrayStrategy);
|
|
1904
|
-
} catch {
|
|
1905
|
-
return null;
|
|
1906
|
-
}
|
|
1907
|
-
} catch {
|
|
1908
|
-
return null;
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
function applyEnvVarsToConfig(name, config3, verbose = false) {
|
|
1912
|
-
if (!name)
|
|
1913
|
-
return config3;
|
|
1914
|
-
const envPrefix = name.toUpperCase().replace(/-/g, "_");
|
|
1915
|
-
const result = { ...config3 };
|
|
1916
|
-
function processObject(obj, path = []) {
|
|
1917
|
-
const result2 = { ...obj };
|
|
1918
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1919
|
-
const envPath = [...path, key];
|
|
1920
|
-
const formatKey = (k) => k.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
1921
|
-
const envKey = `${envPrefix}_${envPath.map(formatKey).join("_")}`;
|
|
1922
|
-
const oldEnvKey = `${envPrefix}_${envPath.map((p) => p.toUpperCase()).join("_")}`;
|
|
1923
|
-
if (verbose)
|
|
1924
|
-
log.info(`Checking environment variable ${envKey} for config ${name}.${envPath.join(".")}`);
|
|
1925
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1926
|
-
result2[key] = processObject(value, envPath);
|
|
1927
|
-
} else {
|
|
1928
|
-
const envValue = process6.env[envKey] || process6.env[oldEnvKey];
|
|
1929
|
-
if (envValue !== undefined) {
|
|
1930
|
-
if (verbose) {
|
|
1931
|
-
log.info(`Using environment variable ${envValue ? envKey : oldEnvKey} for config ${name}.${envPath.join(".")}`);
|
|
1932
|
-
}
|
|
1933
|
-
if (typeof value === "number") {
|
|
1934
|
-
result2[key] = Number(envValue);
|
|
1935
|
-
} else if (typeof value === "boolean") {
|
|
1936
|
-
result2[key] = envValue.toLowerCase() === "true";
|
|
1937
|
-
} else if (Array.isArray(value)) {
|
|
1938
|
-
try {
|
|
1939
|
-
const parsed = JSON.parse(envValue);
|
|
1940
|
-
if (Array.isArray(parsed)) {
|
|
1941
|
-
result2[key] = parsed;
|
|
1942
|
-
} else {
|
|
1943
|
-
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1944
|
-
}
|
|
1945
|
-
} catch {
|
|
1946
|
-
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1947
|
-
}
|
|
1948
|
-
} else {
|
|
1949
|
-
result2[key] = envValue;
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
return result2;
|
|
1955
|
-
}
|
|
1956
|
-
return processObject(result);
|
|
1957
|
-
}
|
|
1958
|
-
async function loadConfig3({
|
|
1959
|
-
name = "",
|
|
1960
|
-
alias,
|
|
1961
|
-
cwd,
|
|
1962
|
-
configDir,
|
|
1963
|
-
defaultConfig: defaultConfig2,
|
|
1964
|
-
verbose = false,
|
|
1965
|
-
checkEnv = true,
|
|
1966
|
-
arrayStrategy = "replace"
|
|
1967
|
-
}) {
|
|
1968
|
-
const configWithEnvVars = checkEnv && typeof defaultConfig2 === "object" && defaultConfig2 !== null && !Array.isArray(defaultConfig2) ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
1969
|
-
const baseDir = cwd || process6.cwd();
|
|
1970
|
-
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
1971
|
-
if (verbose) {
|
|
1972
|
-
log.info(`Loading configuration for "${name}"${alias ? ` (alias: "${alias}")` : ""} from ${baseDir}`);
|
|
1973
|
-
}
|
|
1974
|
-
const primaryBarePatterns = [name, `.${name}`].filter(Boolean);
|
|
1975
|
-
const primaryConfigSuffixPatterns = [`${name}.config`, `.${name}.config`].filter(Boolean);
|
|
1976
|
-
const aliasBarePatterns = alias ? [alias, `.${alias}`] : [];
|
|
1977
|
-
const aliasConfigSuffixPatterns = alias ? [`${alias}.config`, `.${alias}.config`] : [];
|
|
1978
|
-
const searchDirectories = Array.from(new Set([
|
|
1979
|
-
baseDir,
|
|
1980
|
-
resolve3(baseDir, "config"),
|
|
1981
|
-
resolve3(baseDir, ".config"),
|
|
1982
|
-
configDir ? resolve3(baseDir, configDir) : undefined
|
|
1983
|
-
].filter(Boolean)));
|
|
1984
|
-
for (const dir of searchDirectories) {
|
|
1985
|
-
if (verbose)
|
|
1986
|
-
log.info(`Searching for configuration in: ${dir}`);
|
|
1987
|
-
const isConfigLikeDir = [resolve3(baseDir, "config"), resolve3(baseDir, ".config")].concat(configDir ? [resolve3(baseDir, configDir)] : []).includes(dir);
|
|
1988
|
-
const patternsForDir = isConfigLikeDir ? [...primaryBarePatterns, ...primaryConfigSuffixPatterns, ...aliasBarePatterns, ...aliasConfigSuffixPatterns] : [...primaryConfigSuffixPatterns, ...primaryBarePatterns, ...aliasConfigSuffixPatterns, ...aliasBarePatterns];
|
|
1989
|
-
for (const configPath of patternsForDir) {
|
|
1990
|
-
for (const ext of extensions) {
|
|
1991
|
-
const fullPath = resolve3(dir, `${configPath}${ext}`);
|
|
1992
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
1993
|
-
if (config3 !== null) {
|
|
1994
|
-
if (verbose) {
|
|
1995
|
-
log.success(`Configuration loaded from: ${fullPath}`);
|
|
1996
|
-
}
|
|
1997
|
-
return config3;
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
}
|
|
2002
|
-
if (name) {
|
|
2003
|
-
const homeConfigDir = resolve3(homedir(), ".config", name);
|
|
2004
|
-
const homeConfigPatterns = ["config", `${name}.config`];
|
|
2005
|
-
if (alias) {
|
|
2006
|
-
homeConfigPatterns.push(`${alias}.config`);
|
|
2007
|
-
}
|
|
2008
|
-
if (verbose) {
|
|
2009
|
-
log.info(`Checking user config directory: ${homeConfigDir}`);
|
|
2010
|
-
}
|
|
2011
|
-
for (const configPath of homeConfigPatterns) {
|
|
2012
|
-
for (const ext of extensions) {
|
|
2013
|
-
const fullPath = resolve3(homeConfigDir, `${configPath}${ext}`);
|
|
2014
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2015
|
-
if (config3 !== null) {
|
|
2016
|
-
if (verbose) {
|
|
2017
|
-
log.success(`Configuration loaded from user config directory: ${fullPath}`);
|
|
2018
|
-
}
|
|
2019
|
-
return config3;
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
}
|
|
2024
|
-
if (name) {
|
|
2025
|
-
const homeConfigDir = resolve3(homedir(), ".config");
|
|
2026
|
-
const homeConfigDotfilePatterns = [`.${name}.config`];
|
|
2027
|
-
if (alias)
|
|
2028
|
-
homeConfigDotfilePatterns.push(`.${alias}.config`);
|
|
2029
|
-
if (verbose)
|
|
2030
|
-
log.info(`Checking user config directory for dotfile configs: ${homeConfigDir}`);
|
|
2031
|
-
for (const configPath of homeConfigDotfilePatterns) {
|
|
2032
|
-
for (const ext of extensions) {
|
|
2033
|
-
const fullPath = resolve3(homeConfigDir, `${configPath}${ext}`);
|
|
2034
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2035
|
-
if (config3 !== null) {
|
|
2036
|
-
if (verbose)
|
|
2037
|
-
log.success(`Configuration loaded from user config directory dotfile: ${fullPath}`);
|
|
2038
|
-
return config3;
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
if (name) {
|
|
2044
|
-
const homeDir = homedir();
|
|
2045
|
-
const homeRootPatterns = [`.${name}.config`, `.${name}`];
|
|
2046
|
-
if (alias) {
|
|
2047
|
-
homeRootPatterns.push(`.${alias}.config`);
|
|
2048
|
-
homeRootPatterns.push(`.${alias}`);
|
|
2049
|
-
}
|
|
2050
|
-
if (verbose)
|
|
2051
|
-
log.info(`Checking user home directory for dotfile configs: ${homeDir}`);
|
|
2052
|
-
for (const configPath of homeRootPatterns) {
|
|
2053
|
-
for (const ext of extensions) {
|
|
2054
|
-
const fullPath = resolve3(homeDir, `${configPath}${ext}`);
|
|
2055
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2056
|
-
if (config3 !== null) {
|
|
2057
|
-
if (verbose)
|
|
2058
|
-
log.success(`Configuration loaded from user home directory: ${fullPath}`);
|
|
2059
|
-
return config3;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
try {
|
|
2065
|
-
const pkgPath = resolve3(baseDir, "package.json");
|
|
2066
|
-
if (existsSync3(pkgPath)) {
|
|
2067
|
-
const pkg = await import(pkgPath);
|
|
2068
|
-
let pkgConfig = pkg[name];
|
|
2069
|
-
if (!pkgConfig && alias) {
|
|
2070
|
-
pkgConfig = pkg[alias];
|
|
2071
|
-
if (pkgConfig && verbose) {
|
|
2072
|
-
log.success(`Using alias "${alias}" configuration from package.json`);
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
2076
|
-
try {
|
|
2077
|
-
if (verbose) {
|
|
2078
|
-
log.success(`Configuration loaded from package.json: ${pkgConfig === pkg[name] ? name : alias}`);
|
|
2079
|
-
}
|
|
2080
|
-
return deepMergeWithArrayStrategy(configWithEnvVars, pkgConfig, arrayStrategy);
|
|
2081
|
-
} catch (error) {
|
|
2082
|
-
if (verbose) {
|
|
2083
|
-
log.warn(`Failed to merge package.json config:`, error);
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
} catch (error) {
|
|
2089
|
-
if (verbose) {
|
|
2090
|
-
log.warn(`Failed to load package.json:`, error);
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
if (verbose) {
|
|
2094
|
-
log.info(`No configuration found for "${name}"${alias ? ` or alias "${alias}"` : ""}, using default configuration with environment variables`);
|
|
2095
|
-
}
|
|
2096
|
-
return configWithEnvVars;
|
|
2097
|
-
}
|
|
2098
|
-
var defaultConfigDir2 = resolve3(process6.cwd(), "config");
|
|
2099
|
-
var defaultGeneratedDir2 = resolve3(process6.cwd(), "src/generated");
|
|
2100
|
-
function getProjectRoot2(filePath, options = {}) {
|
|
2101
|
-
let path = process7.cwd();
|
|
2102
|
-
while (path.includes("storage"))
|
|
2103
|
-
path = resolve4(path, "..");
|
|
2104
|
-
const finalPath = resolve4(path, filePath || "");
|
|
2105
|
-
if (options?.relative)
|
|
2106
|
-
return relative2(process7.cwd(), finalPath);
|
|
2107
|
-
return finalPath;
|
|
2108
|
-
}
|
|
2109
|
-
var defaultLogDirectory2 = process7.env.CLARITY_LOG_DIR || join3(getProjectRoot2(), "logs");
|
|
2110
|
-
var defaultConfig2 = {
|
|
2111
|
-
level: "info",
|
|
2112
|
-
defaultName: "clarity",
|
|
2113
|
-
timestamp: true,
|
|
2114
|
-
colors: true,
|
|
2115
|
-
format: "text",
|
|
2116
|
-
maxLogSize: 10485760,
|
|
2117
|
-
logDatePattern: "YYYY-MM-DD",
|
|
2118
|
-
logDirectory: defaultLogDirectory2,
|
|
2119
|
-
rotation: {
|
|
2120
|
-
frequency: "daily",
|
|
2121
|
-
maxSize: 10485760,
|
|
2122
|
-
maxFiles: 5,
|
|
2123
|
-
compress: false,
|
|
2124
|
-
rotateHour: 0,
|
|
2125
|
-
rotateMinute: 0,
|
|
2126
|
-
rotateDayOfWeek: 0,
|
|
2127
|
-
rotateDayOfMonth: 1,
|
|
2128
|
-
encrypt: false
|
|
2129
|
-
},
|
|
2130
|
-
verbose: false,
|
|
2131
|
-
writeToFile: false
|
|
2132
|
-
};
|
|
2133
|
-
async function loadConfig4() {
|
|
2134
|
-
try {
|
|
2135
|
-
const loadedConfig = await loadConfig3({
|
|
2136
|
-
name: "clarity",
|
|
2137
|
-
alias: "logging",
|
|
2138
|
-
defaultConfig: defaultConfig2,
|
|
2139
|
-
cwd: process7.cwd()
|
|
2140
|
-
});
|
|
2141
|
-
return { ...defaultConfig2, ...loadedConfig || {} };
|
|
2142
|
-
} catch {
|
|
2143
|
-
return defaultConfig2;
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
var config2 = await loadConfig4();
|
|
2147
|
-
function isBrowserProcess2() {
|
|
2148
|
-
if (process9.env.NODE_ENV === "test" || process9.env.BUN_ENV === "test") {
|
|
2149
|
-
return false;
|
|
2150
|
-
}
|
|
2151
|
-
return typeof window !== "undefined";
|
|
2152
|
-
}
|
|
2153
|
-
async function isServerProcess2() {
|
|
2154
|
-
if (process9.env.NODE_ENV === "test" || process9.env.BUN_ENV === "test") {
|
|
2155
|
-
return true;
|
|
2156
|
-
}
|
|
2157
|
-
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
2158
|
-
return true;
|
|
2159
|
-
}
|
|
2160
|
-
if (typeof process9 !== "undefined") {
|
|
2161
|
-
const type = process9.type;
|
|
2162
|
-
if (type === "renderer" || type === "worker") {
|
|
2163
|
-
return false;
|
|
2164
|
-
}
|
|
2165
|
-
return !!(process9.versions && (process9.versions.node || process9.versions.bun));
|
|
2166
|
-
}
|
|
2167
|
-
return false;
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
class JsonFormatter2 {
|
|
2171
|
-
async format(entry) {
|
|
2172
|
-
const isServer = await isServerProcess2();
|
|
2173
|
-
const metadata = await this.getMetadata(isServer);
|
|
2174
|
-
return JSON.stringify({
|
|
2175
|
-
timestamp: entry.timestamp.toISOString(),
|
|
2176
|
-
level: entry.level,
|
|
2177
|
-
name: entry.name,
|
|
2178
|
-
message: entry.message,
|
|
2179
|
-
metadata
|
|
2180
|
-
});
|
|
2181
|
-
}
|
|
2182
|
-
async getMetadata(isServer) {
|
|
2183
|
-
if (isServer) {
|
|
2184
|
-
const { hostname } = await import("os");
|
|
2185
|
-
return {
|
|
2186
|
-
pid: process10.pid,
|
|
2187
|
-
hostname: hostname(),
|
|
2188
|
-
environment: process10.env.NODE_ENV || "development",
|
|
2189
|
-
platform: process10.platform,
|
|
2190
|
-
version: process10.version
|
|
2191
|
-
};
|
|
2192
|
-
}
|
|
2193
|
-
return {
|
|
2194
|
-
userAgent: navigator.userAgent,
|
|
2195
|
-
hostname: window.location.hostname || "browser",
|
|
2196
|
-
environment: process10.env.NODE_ENV || process10.env.BUN_ENV || "development",
|
|
2197
|
-
viewport: {
|
|
2198
|
-
width: window.innerWidth,
|
|
2199
|
-
height: window.innerHeight
|
|
2200
|
-
},
|
|
2201
|
-
language: navigator.language
|
|
2202
|
-
};
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
var terminalStyles2 = {
|
|
2206
|
-
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
2207
|
-
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
2208
|
-
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
2209
|
-
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
2210
|
-
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
2211
|
-
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
2212
|
-
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
2213
|
-
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
2214
|
-
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
2215
|
-
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
2216
|
-
bgGray: (text) => `\x1B[100m${text}\x1B[0m`,
|
|
2217
|
-
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
2218
|
-
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
2219
|
-
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
2220
|
-
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
2221
|
-
strikethrough: (text) => `\x1B[9m${text}\x1B[0m`,
|
|
2222
|
-
reset: "\x1B[0m"
|
|
2223
|
-
};
|
|
2224
|
-
var styles2 = terminalStyles2;
|
|
2225
|
-
var red2 = terminalStyles2.red;
|
|
2226
|
-
var green2 = terminalStyles2.green;
|
|
2227
|
-
var yellow2 = terminalStyles2.yellow;
|
|
2228
|
-
var blue2 = terminalStyles2.blue;
|
|
2229
|
-
var magenta2 = terminalStyles2.magenta;
|
|
2230
|
-
var cyan2 = terminalStyles2.cyan;
|
|
2231
|
-
var white2 = terminalStyles2.white;
|
|
2232
|
-
var gray2 = terminalStyles2.gray;
|
|
2233
|
-
var bgRed2 = terminalStyles2.bgRed;
|
|
2234
|
-
var bgYellow2 = terminalStyles2.bgYellow;
|
|
2235
|
-
var bgGray = terminalStyles2.bgGray;
|
|
2236
|
-
var bold2 = terminalStyles2.bold;
|
|
2237
|
-
var dim2 = terminalStyles2.dim;
|
|
2238
|
-
var italic2 = terminalStyles2.italic;
|
|
2239
|
-
var underline2 = terminalStyles2.underline;
|
|
2240
|
-
var strikethrough = terminalStyles2.strikethrough;
|
|
2241
|
-
var reset2 = terminalStyles2.reset;
|
|
2242
|
-
var defaultFingersCrossedConfig2 = {
|
|
2243
|
-
activationLevel: "error",
|
|
2244
|
-
bufferSize: 50,
|
|
2245
|
-
flushOnDeactivation: true,
|
|
2246
|
-
stopBuffering: false
|
|
2247
|
-
};
|
|
2248
|
-
var levelIcons2 = {
|
|
2249
|
-
debug: "\uD83D\uDD0D",
|
|
2250
|
-
info: blue2("\u2139"),
|
|
2251
|
-
success: green2("\u2713"),
|
|
2252
|
-
warning: bgYellow2(white2(bold2(" WARN "))),
|
|
2253
|
-
error: bgRed2(white2(bold2(" ERROR ")))
|
|
2254
|
-
};
|
|
377
|
+
}
|
|
378
|
+
}
|
|
2255
379
|
|
|
2256
|
-
class
|
|
380
|
+
class Logger {
|
|
2257
381
|
name;
|
|
2258
382
|
fileLocks = new Map;
|
|
2259
383
|
currentKeyId = null;
|
|
@@ -2282,14 +406,14 @@ class Logger2 {
|
|
|
2282
406
|
activeProgressBar = null;
|
|
2283
407
|
constructor(name, options = {}) {
|
|
2284
408
|
this.name = name;
|
|
2285
|
-
this.config = { ...
|
|
409
|
+
this.config = { ...config };
|
|
2286
410
|
this.options = this.normalizeOptions(options);
|
|
2287
|
-
this.formatter = this.options.formatter || new
|
|
411
|
+
this.formatter = this.options.formatter || new JsonFormatter;
|
|
2288
412
|
this.enabled = options.enabled ?? true;
|
|
2289
413
|
this.fancy = options.fancy ?? true;
|
|
2290
414
|
this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
|
|
2291
415
|
this.timestampPosition = options.timestampPosition ?? "right";
|
|
2292
|
-
this.environment = options.environment ??
|
|
416
|
+
this.environment = options.environment ?? process4.env.APP_ENV ?? "local";
|
|
2293
417
|
this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
|
|
2294
418
|
const configOptions = { ...options };
|
|
2295
419
|
const hasTimestamp = options.timestamp !== undefined;
|
|
@@ -2299,7 +423,8 @@ class Logger2 {
|
|
|
2299
423
|
this.config = {
|
|
2300
424
|
...this.config,
|
|
2301
425
|
...configOptions,
|
|
2302
|
-
timestamp: hasTimestamp || this.config.timestamp
|
|
426
|
+
timestamp: hasTimestamp || this.config.timestamp,
|
|
427
|
+
level: this.options.level ?? "info"
|
|
2303
428
|
};
|
|
2304
429
|
this.currentLogFile = this.generateLogFilename();
|
|
2305
430
|
this.encryptionKeys = new Map;
|
|
@@ -2332,7 +457,7 @@ class Logger2 {
|
|
|
2332
457
|
initializeFingersCrossedConfig(options) {
|
|
2333
458
|
if (!options.fingersCrossedEnabled && options.fingersCrossed) {
|
|
2334
459
|
return {
|
|
2335
|
-
...
|
|
460
|
+
...defaultFingersCrossedConfig,
|
|
2336
461
|
...options.fingersCrossed
|
|
2337
462
|
};
|
|
2338
463
|
}
|
|
@@ -2340,10 +465,10 @@ class Logger2 {
|
|
|
2340
465
|
return null;
|
|
2341
466
|
}
|
|
2342
467
|
if (!options.fingersCrossed) {
|
|
2343
|
-
return { ...
|
|
468
|
+
return { ...defaultFingersCrossedConfig };
|
|
2344
469
|
}
|
|
2345
470
|
return {
|
|
2346
|
-
...
|
|
471
|
+
...defaultFingersCrossedConfig,
|
|
2347
472
|
...options.fingersCrossed
|
|
2348
473
|
};
|
|
2349
474
|
}
|
|
@@ -2351,7 +476,7 @@ class Logger2 {
|
|
|
2351
476
|
const defaultOptions = {
|
|
2352
477
|
format: "json",
|
|
2353
478
|
level: "info",
|
|
2354
|
-
logDirectory:
|
|
479
|
+
logDirectory: config.logDirectory,
|
|
2355
480
|
rotation: undefined,
|
|
2356
481
|
timestamp: undefined,
|
|
2357
482
|
fingersCrossed: {},
|
|
@@ -2370,7 +495,7 @@ class Logger2 {
|
|
|
2370
495
|
return mergedOptions;
|
|
2371
496
|
}
|
|
2372
497
|
shouldWriteToFile() {
|
|
2373
|
-
return !
|
|
498
|
+
return !isBrowserProcess() && this.config.writeToFile === true;
|
|
2374
499
|
}
|
|
2375
500
|
async writeToFile(data) {
|
|
2376
501
|
const cancelled = false;
|
|
@@ -2383,11 +508,11 @@ class Logger2 {
|
|
|
2383
508
|
try {
|
|
2384
509
|
try {
|
|
2385
510
|
try {
|
|
2386
|
-
await
|
|
511
|
+
await access(this.config.logDirectory, constants.F_OK | constants.W_OK);
|
|
2387
512
|
} catch (err) {
|
|
2388
513
|
if (err instanceof Error && "code" in err) {
|
|
2389
514
|
if (err.code === "ENOENT") {
|
|
2390
|
-
await
|
|
515
|
+
await mkdir(this.config.logDirectory, { recursive: true, mode: 493 });
|
|
2391
516
|
} else if (err.code === "EACCES") {
|
|
2392
517
|
throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
|
|
2393
518
|
} else {
|
|
@@ -2403,22 +528,22 @@ class Logger2 {
|
|
|
2403
528
|
}
|
|
2404
529
|
if (cancelled)
|
|
2405
530
|
throw new Error("Operation cancelled: Logger was destroyed");
|
|
2406
|
-
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted :
|
|
531
|
+
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
|
|
2407
532
|
try {
|
|
2408
|
-
if (!
|
|
2409
|
-
await
|
|
533
|
+
if (!existsSync2(this.currentLogFile)) {
|
|
534
|
+
await writeFile(this.currentLogFile, "", { mode: 420 });
|
|
2410
535
|
}
|
|
2411
|
-
fd =
|
|
2412
|
-
|
|
2413
|
-
|
|
536
|
+
fd = openSync(this.currentLogFile, "a", 420);
|
|
537
|
+
writeFileSync(fd, dataToWrite, { flag: "a" });
|
|
538
|
+
fsyncSync(fd);
|
|
2414
539
|
if (fd !== undefined) {
|
|
2415
|
-
|
|
540
|
+
closeSync(fd);
|
|
2416
541
|
fd = undefined;
|
|
2417
542
|
}
|
|
2418
|
-
const stats = await
|
|
543
|
+
const stats = await stat(this.currentLogFile);
|
|
2419
544
|
if (stats.size === 0) {
|
|
2420
|
-
await
|
|
2421
|
-
const retryStats = await
|
|
545
|
+
await writeFile(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
|
|
546
|
+
const retryStats = await stat(this.currentLogFile);
|
|
2422
547
|
if (retryStats.size === 0) {
|
|
2423
548
|
throw new Error("File exists but is empty after retry write");
|
|
2424
549
|
}
|
|
@@ -2431,7 +556,7 @@ class Logger2 {
|
|
|
2431
556
|
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
2432
557
|
console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
|
|
2433
558
|
const delay = backoffDelay * 2 ** retries;
|
|
2434
|
-
await new Promise((
|
|
559
|
+
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
2435
560
|
retries++;
|
|
2436
561
|
continue;
|
|
2437
562
|
}
|
|
@@ -2444,7 +569,7 @@ class Logger2 {
|
|
|
2444
569
|
} finally {
|
|
2445
570
|
if (fd !== undefined) {
|
|
2446
571
|
try {
|
|
2447
|
-
|
|
572
|
+
closeSync(fd);
|
|
2448
573
|
} catch (err) {
|
|
2449
574
|
console.error("Debug: [writeToFile] Error closing file descriptor:", err);
|
|
2450
575
|
}
|
|
@@ -2459,7 +584,7 @@ class Logger2 {
|
|
|
2459
584
|
}
|
|
2460
585
|
retries++;
|
|
2461
586
|
const delay = backoffDelay * 2 ** (retries - 1);
|
|
2462
|
-
await new Promise((
|
|
587
|
+
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
2463
588
|
}
|
|
2464
589
|
}
|
|
2465
590
|
})();
|
|
@@ -2476,24 +601,24 @@ class Logger2 {
|
|
|
2476
601
|
}
|
|
2477
602
|
generateLogFilename() {
|
|
2478
603
|
if (this.name.includes("stream-throughput") || this.name.includes("decompress-perf-test") || this.name.includes("decompression-latency") || this.name.includes("concurrent-read-test") || this.name.includes("clock-change-test")) {
|
|
2479
|
-
return
|
|
604
|
+
return join2(this.config.logDirectory, `${this.name}.log`);
|
|
2480
605
|
}
|
|
2481
606
|
if (this.name.includes("pending-test") || this.name.includes("temp-file-test") || this.name === "crash-test" || this.name === "corrupt-test" || this.name.includes("rotation-load-test") || this.name === "sigterm-test" || this.name === "sigint-test" || this.name === "failed-rotation-test" || this.name === "integration-test") {
|
|
2482
|
-
return
|
|
607
|
+
return join2(this.config.logDirectory, `${this.name}.log`);
|
|
2483
608
|
}
|
|
2484
609
|
const date = new Date().toISOString().split("T")[0];
|
|
2485
|
-
return
|
|
610
|
+
return join2(this.config.logDirectory, `${this.name}-${date}.log`);
|
|
2486
611
|
}
|
|
2487
612
|
setupRotation() {
|
|
2488
|
-
if (
|
|
613
|
+
if (isBrowserProcess())
|
|
2489
614
|
return;
|
|
2490
615
|
if (!this.shouldWriteToFile())
|
|
2491
616
|
return;
|
|
2492
617
|
if (typeof this.config.rotation === "boolean")
|
|
2493
618
|
return;
|
|
2494
|
-
const
|
|
619
|
+
const config2 = this.config.rotation;
|
|
2495
620
|
let interval;
|
|
2496
|
-
switch (
|
|
621
|
+
switch (config2.frequency) {
|
|
2497
622
|
case "daily":
|
|
2498
623
|
interval = 86400000;
|
|
2499
624
|
break;
|
|
@@ -2554,10 +679,10 @@ class Logger2 {
|
|
|
2554
679
|
}
|
|
2555
680
|
}
|
|
2556
681
|
generateKeyId() {
|
|
2557
|
-
return
|
|
682
|
+
return randomBytes(16).toString("hex");
|
|
2558
683
|
}
|
|
2559
684
|
generateKey() {
|
|
2560
|
-
return
|
|
685
|
+
return randomBytes(32);
|
|
2561
686
|
}
|
|
2562
687
|
getCurrentKey() {
|
|
2563
688
|
if (!this.currentKeyId) {
|
|
@@ -2571,14 +696,14 @@ class Logger2 {
|
|
|
2571
696
|
}
|
|
2572
697
|
encrypt(data) {
|
|
2573
698
|
const { key } = this.getCurrentKey();
|
|
2574
|
-
const iv =
|
|
2575
|
-
const cipher =
|
|
2576
|
-
const input =
|
|
699
|
+
const iv = randomBytes(16);
|
|
700
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
701
|
+
const input = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf8");
|
|
2577
702
|
const part1 = cipher.update(input);
|
|
2578
703
|
const part2 = cipher.final();
|
|
2579
704
|
const totalCipherLen = part1.length + part2.length;
|
|
2580
705
|
const authTag = cipher.getAuthTag();
|
|
2581
|
-
const out =
|
|
706
|
+
const out = Buffer.allocUnsafe(16 + totalCipherLen + 16);
|
|
2582
707
|
iv.copy(out, 0);
|
|
2583
708
|
part1.copy(out, 16);
|
|
2584
709
|
part2.copy(out, 16 + part1.length);
|
|
@@ -2589,11 +714,11 @@ class Logger2 {
|
|
|
2589
714
|
};
|
|
2590
715
|
}
|
|
2591
716
|
async compressData(data) {
|
|
2592
|
-
return new Promise((
|
|
2593
|
-
const gzip =
|
|
717
|
+
return new Promise((resolve32, reject) => {
|
|
718
|
+
const gzip = createGzip();
|
|
2594
719
|
const chunks = [];
|
|
2595
720
|
gzip.on("data", (chunk2) => chunks.push(chunk2));
|
|
2596
|
-
gzip.on("end", () =>
|
|
721
|
+
gzip.on("end", () => resolve32(Buffer.from(Buffer.concat(chunks))));
|
|
2597
722
|
gzip.on("error", reject);
|
|
2598
723
|
gzip.write(data);
|
|
2599
724
|
gzip.end();
|
|
@@ -2617,21 +742,21 @@ class Logger2 {
|
|
|
2617
742
|
return defaultOptions;
|
|
2618
743
|
}
|
|
2619
744
|
async rotateLog() {
|
|
2620
|
-
if (
|
|
745
|
+
if (isBrowserProcess())
|
|
2621
746
|
return;
|
|
2622
747
|
if (!this.shouldWriteToFile())
|
|
2623
748
|
return;
|
|
2624
|
-
const stats = await
|
|
749
|
+
const stats = await stat(this.currentLogFile).catch(() => null);
|
|
2625
750
|
if (!stats)
|
|
2626
751
|
return;
|
|
2627
|
-
const
|
|
2628
|
-
if (typeof
|
|
752
|
+
const config2 = this.config.rotation;
|
|
753
|
+
if (typeof config2 === "boolean")
|
|
2629
754
|
return;
|
|
2630
|
-
if (
|
|
755
|
+
if (config2.maxSize && stats.size >= config2.maxSize) {
|
|
2631
756
|
const oldFile = this.currentLogFile;
|
|
2632
757
|
const newFile = this.generateLogFilename();
|
|
2633
758
|
if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
|
|
2634
|
-
const files = await
|
|
759
|
+
const files = await readdir(this.config.logDirectory);
|
|
2635
760
|
const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
|
|
2636
761
|
const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
2637
762
|
const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
@@ -2639,14 +764,14 @@ class Logger2 {
|
|
|
2639
764
|
});
|
|
2640
765
|
const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
|
|
2641
766
|
const rotatedFile = `${oldFile}.${nextNum}`;
|
|
2642
|
-
if (await
|
|
767
|
+
if (await stat(oldFile).catch(() => null)) {
|
|
2643
768
|
try {
|
|
2644
|
-
await
|
|
2645
|
-
if (
|
|
769
|
+
await rename(oldFile, rotatedFile);
|
|
770
|
+
if (config2.compress) {
|
|
2646
771
|
try {
|
|
2647
772
|
const compressedPath = `${rotatedFile}.gz`;
|
|
2648
773
|
await this.compressLogFile(rotatedFile, compressedPath);
|
|
2649
|
-
await
|
|
774
|
+
await unlink(rotatedFile);
|
|
2650
775
|
} catch (err) {
|
|
2651
776
|
console.error("Error compressing rotated file:", err);
|
|
2652
777
|
}
|
|
@@ -2654,7 +779,7 @@ class Logger2 {
|
|
|
2654
779
|
if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
|
|
2655
780
|
try {
|
|
2656
781
|
const backupPath = `${oldFile}.1`;
|
|
2657
|
-
await
|
|
782
|
+
await writeFile(backupPath, "");
|
|
2658
783
|
} catch (err) {
|
|
2659
784
|
console.error("Error creating backup file:", err);
|
|
2660
785
|
}
|
|
@@ -2666,25 +791,25 @@ class Logger2 {
|
|
|
2666
791
|
} else {
|
|
2667
792
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
2668
793
|
const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
|
|
2669
|
-
if (await
|
|
2670
|
-
await
|
|
794
|
+
if (await stat(oldFile).catch(() => null)) {
|
|
795
|
+
await rename(oldFile, rotatedFile);
|
|
2671
796
|
}
|
|
2672
797
|
}
|
|
2673
798
|
this.currentLogFile = newFile;
|
|
2674
|
-
if (
|
|
2675
|
-
const files = await
|
|
799
|
+
if (config2.maxFiles) {
|
|
800
|
+
const files = await readdir(this.config.logDirectory);
|
|
2676
801
|
const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
|
|
2677
|
-
for (const file of logFiles.slice(
|
|
2678
|
-
await
|
|
802
|
+
for (const file of logFiles.slice(config2.maxFiles)) {
|
|
803
|
+
await unlink(join2(this.config.logDirectory, file));
|
|
2679
804
|
}
|
|
2680
805
|
}
|
|
2681
806
|
}
|
|
2682
807
|
}
|
|
2683
808
|
async compressLogFile(inputPath, outputPath) {
|
|
2684
|
-
const readStream =
|
|
2685
|
-
const writeStream =
|
|
2686
|
-
const gzip =
|
|
2687
|
-
await
|
|
809
|
+
const readStream = createReadStream(inputPath);
|
|
810
|
+
const writeStream = createWriteStream(outputPath);
|
|
811
|
+
const gzip = createGzip();
|
|
812
|
+
await pipeline(readStream, gzip, writeStream);
|
|
2688
813
|
}
|
|
2689
814
|
async handleFingersCrossedBuffer(level, formattedEntry) {
|
|
2690
815
|
if (!this.fingersCrossedConfig)
|
|
@@ -2727,11 +852,11 @@ class Logger2 {
|
|
|
2727
852
|
}
|
|
2728
853
|
return Promise.resolve();
|
|
2729
854
|
}));
|
|
2730
|
-
if (
|
|
855
|
+
if (existsSync2(this.currentLogFile)) {
|
|
2731
856
|
try {
|
|
2732
|
-
const fd =
|
|
2733
|
-
|
|
2734
|
-
|
|
857
|
+
const fd = openSync(this.currentLogFile, "r+");
|
|
858
|
+
fsyncSync(fd);
|
|
859
|
+
closeSync(fd);
|
|
2735
860
|
} catch (error) {
|
|
2736
861
|
console.error(`Error flushing file: ${error}`);
|
|
2737
862
|
}
|
|
@@ -2756,13 +881,13 @@ class Logger2 {
|
|
|
2756
881
|
console.error("Error waiting for pending operations:", err);
|
|
2757
882
|
}
|
|
2758
883
|
}
|
|
2759
|
-
if (!
|
|
884
|
+
if (!isBrowserProcess() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
|
|
2760
885
|
try {
|
|
2761
|
-
const files = await
|
|
886
|
+
const files = await readdir(this.config.logDirectory);
|
|
2762
887
|
const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
|
|
2763
888
|
for (const tempFile of tempFiles) {
|
|
2764
889
|
try {
|
|
2765
|
-
await
|
|
890
|
+
await unlink(join2(this.config.logDirectory, tempFile));
|
|
2766
891
|
} catch (err) {
|
|
2767
892
|
console.error(`Failed to delete temp file ${tempFile}:`, err);
|
|
2768
893
|
}
|
|
@@ -2785,16 +910,16 @@ class Logger2 {
|
|
|
2785
910
|
return `[${date.toISOString()}]`;
|
|
2786
911
|
}
|
|
2787
912
|
formatConsoleTimestamp(date) {
|
|
2788
|
-
return this.shouldStyleConsole() ?
|
|
913
|
+
return this.shouldStyleConsole() ? styles.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
|
|
2789
914
|
}
|
|
2790
915
|
shouldStyleConsole() {
|
|
2791
|
-
if (!this.fancy ||
|
|
916
|
+
if (!this.fancy || isBrowserProcess())
|
|
2792
917
|
return false;
|
|
2793
|
-
const noColor = typeof
|
|
2794
|
-
const forceColorDisabled =
|
|
918
|
+
const noColor = typeof process4.env.NO_COLOR !== "undefined";
|
|
919
|
+
const forceColorDisabled = process4.env.FORCE_COLOR === "0";
|
|
2795
920
|
if (noColor || forceColorDisabled)
|
|
2796
921
|
return false;
|
|
2797
|
-
const hasTTY = typeof
|
|
922
|
+
const hasTTY = typeof process4.stderr !== "undefined" && process4.stderr.isTTY || typeof process4.stdout !== "undefined" && process4.stdout.isTTY;
|
|
2798
923
|
return !!hasTTY;
|
|
2799
924
|
}
|
|
2800
925
|
formatConsoleMessage(parts) {
|
|
@@ -2815,14 +940,14 @@ class Logger2 {
|
|
|
2815
940
|
components.push(message);
|
|
2816
941
|
return components.join(" ");
|
|
2817
942
|
}
|
|
2818
|
-
const terminalWidth =
|
|
943
|
+
const terminalWidth = process4.stdout.columns || 120;
|
|
2819
944
|
let mainPart = "";
|
|
2820
945
|
if (level === "warning" || level === "error") {
|
|
2821
946
|
mainPart = `${icon} ${message}`;
|
|
2822
947
|
} else if (level === "info" || level === "success") {
|
|
2823
948
|
mainPart = `${icon} ${tag} ${message}`;
|
|
2824
949
|
} else {
|
|
2825
|
-
mainPart = `${icon} ${tag} ${
|
|
950
|
+
mainPart = `${icon} ${tag} ${styles.cyan(message)}`;
|
|
2826
951
|
}
|
|
2827
952
|
if (!showTimestamp) {
|
|
2828
953
|
return mainPart.trim();
|
|
@@ -2870,7 +995,7 @@ class Logger2 {
|
|
|
2870
995
|
return input;
|
|
2871
996
|
let out = input;
|
|
2872
997
|
out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => {
|
|
2873
|
-
const label =
|
|
998
|
+
const label = styles.underline(styles.blue(text));
|
|
2874
999
|
const absFile = this.toAbsoluteFilePath(url);
|
|
2875
1000
|
if (absFile && this.shouldStyleConsole() && this.supportsHyperlinks()) {
|
|
2876
1001
|
const href = `file://${encodeURI(absFile)}`;
|
|
@@ -2885,17 +1010,17 @@ class Logger2 {
|
|
|
2885
1010
|
}
|
|
2886
1011
|
return label;
|
|
2887
1012
|
});
|
|
2888
|
-
out = out.replace(/`([^`]+)`/g, (_, m) =>
|
|
2889
|
-
out = out.replace(/\*\*([^*]+)\*\*/g, (_, m) =>
|
|
2890
|
-
out = out.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, m) =>
|
|
2891
|
-
out = out.replace(/(?<!_)_([^_]+)_(?!_)/g, (_, m) =>
|
|
2892
|
-
out = out.replace(/~([^~]+)~/g, (_, m) =>
|
|
1013
|
+
out = out.replace(/`([^`]+)`/g, (_, m) => styles.bgGray(m));
|
|
1014
|
+
out = out.replace(/\*\*([^*]+)\*\*/g, (_, m) => styles.bold(m));
|
|
1015
|
+
out = out.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, m) => styles.italic(m));
|
|
1016
|
+
out = out.replace(/(?<!_)_([^_]+)_(?!_)/g, (_, m) => styles.italic(m));
|
|
1017
|
+
out = out.replace(/~([^~]+)~/g, (_, m) => styles.strikethrough(m));
|
|
2893
1018
|
return out;
|
|
2894
1019
|
}
|
|
2895
1020
|
supportsHyperlinks() {
|
|
2896
|
-
if (
|
|
1021
|
+
if (isBrowserProcess())
|
|
2897
1022
|
return false;
|
|
2898
|
-
const env =
|
|
1023
|
+
const env = process4.env;
|
|
2899
1024
|
if (!env)
|
|
2900
1025
|
return false;
|
|
2901
1026
|
if (env.TERM_PROGRAM === "iTerm.app" || env.TERM_PROGRAM === "vscode" || env.TERM_PROGRAM === "WezTerm")
|
|
@@ -2916,16 +1041,16 @@ class Logger2 {
|
|
|
2916
1041
|
p = p.replace(/^file:\/\//, "");
|
|
2917
1042
|
}
|
|
2918
1043
|
if (p.startsWith("~")) {
|
|
2919
|
-
const home =
|
|
1044
|
+
const home = process4.env.HOME || "";
|
|
2920
1045
|
if (home)
|
|
2921
1046
|
p = p.replace(/^~(?=$|\/)/, home);
|
|
2922
1047
|
}
|
|
2923
1048
|
if (isAbsolute(p) || p.startsWith("./") || p.startsWith("../")) {
|
|
2924
|
-
p =
|
|
1049
|
+
p = resolve2(p);
|
|
2925
1050
|
} else {
|
|
2926
1051
|
return null;
|
|
2927
1052
|
}
|
|
2928
|
-
return
|
|
1053
|
+
return existsSync2(p) ? p : null;
|
|
2929
1054
|
} catch {
|
|
2930
1055
|
return null;
|
|
2931
1056
|
}
|
|
@@ -2936,6 +1061,8 @@ class Logger2 {
|
|
|
2936
1061
|
return { consoleText, fileText };
|
|
2937
1062
|
}
|
|
2938
1063
|
async log(level, message, ...args) {
|
|
1064
|
+
if (!this.shouldLog(level))
|
|
1065
|
+
return;
|
|
2939
1066
|
const timestamp = new Date;
|
|
2940
1067
|
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
2941
1068
|
const fileTime = this.formatFileTimestamp(timestamp);
|
|
@@ -2949,8 +1076,8 @@ class Logger2 {
|
|
|
2949
1076
|
}
|
|
2950
1077
|
const { consoleText: baseConsoleText, fileText } = this.buildOutputTexts(formattedMessage);
|
|
2951
1078
|
if (this.shouldStyleConsole()) {
|
|
2952
|
-
const icon = this.options.showIcons === false ? "" :
|
|
2953
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
1079
|
+
const icon = this.options.showIcons === false ? "" : levelIcons[level];
|
|
1080
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
2954
1081
|
let consoleMessage;
|
|
2955
1082
|
switch (level) {
|
|
2956
1083
|
case "debug":
|
|
@@ -2958,7 +1085,7 @@ class Logger2 {
|
|
|
2958
1085
|
timestamp: consoleTime,
|
|
2959
1086
|
icon,
|
|
2960
1087
|
tag,
|
|
2961
|
-
message:
|
|
1088
|
+
message: styles.gray(baseConsoleText),
|
|
2962
1089
|
level
|
|
2963
1090
|
});
|
|
2964
1091
|
console.error(consoleMessage);
|
|
@@ -2978,7 +1105,7 @@ class Logger2 {
|
|
|
2978
1105
|
timestamp: consoleTime,
|
|
2979
1106
|
icon,
|
|
2980
1107
|
tag,
|
|
2981
|
-
message:
|
|
1108
|
+
message: styles.green(baseConsoleText),
|
|
2982
1109
|
level
|
|
2983
1110
|
});
|
|
2984
1111
|
console.error(consoleMessage);
|
|
@@ -3009,7 +1136,7 @@ class Logger2 {
|
|
|
3009
1136
|
if (line.trim() && !line.includes(formattedMessage)) {
|
|
3010
1137
|
console.error(this.formatConsoleMessage({
|
|
3011
1138
|
timestamp: consoleTime,
|
|
3012
|
-
message:
|
|
1139
|
+
message: styles.gray(` ${line}`),
|
|
3013
1140
|
level,
|
|
3014
1141
|
showTimestamp: false
|
|
3015
1142
|
}));
|
|
@@ -3018,14 +1145,12 @@ class Logger2 {
|
|
|
3018
1145
|
}
|
|
3019
1146
|
break;
|
|
3020
1147
|
}
|
|
3021
|
-
} else if (!
|
|
1148
|
+
} else if (!isBrowserProcess()) {
|
|
3022
1149
|
console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
|
|
3023
1150
|
if (errorStack) {
|
|
3024
1151
|
console.error(errorStack);
|
|
3025
1152
|
}
|
|
3026
1153
|
}
|
|
3027
|
-
if (!this.shouldLog(level))
|
|
3028
|
-
return;
|
|
3029
1154
|
let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${fileText}
|
|
3030
1155
|
`;
|
|
3031
1156
|
if (errorStack) {
|
|
@@ -3052,7 +1177,7 @@ class Logger2 {
|
|
|
3052
1177
|
barLength,
|
|
3053
1178
|
lastRenderedLine: ""
|
|
3054
1179
|
};
|
|
3055
|
-
if (this.shouldStyleConsole() && !
|
|
1180
|
+
if (this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY) {
|
|
3056
1181
|
this.renderProgressBar(this.activeProgressBar);
|
|
3057
1182
|
}
|
|
3058
1183
|
const update = (current, message) => {
|
|
@@ -3061,7 +1186,7 @@ class Logger2 {
|
|
|
3061
1186
|
this.activeProgressBar.current = Math.min(Math.max(0, current), this.activeProgressBar.total);
|
|
3062
1187
|
if (message !== undefined)
|
|
3063
1188
|
this.activeProgressBar.message = message;
|
|
3064
|
-
if (this.shouldStyleConsole() && !
|
|
1189
|
+
if (this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY)
|
|
3065
1190
|
this.renderProgressBar(this.activeProgressBar);
|
|
3066
1191
|
};
|
|
3067
1192
|
const finish = (message) => {
|
|
@@ -3070,12 +1195,12 @@ class Logger2 {
|
|
|
3070
1195
|
this.finishProgressBar(this.activeProgressBar, message);
|
|
3071
1196
|
};
|
|
3072
1197
|
const interrupt = (message, level = "info") => {
|
|
3073
|
-
if (!
|
|
3074
|
-
|
|
1198
|
+
if (!isBrowserProcess() && process4.stdout.isTTY)
|
|
1199
|
+
process4.stdout.write(`
|
|
3075
1200
|
`);
|
|
3076
1201
|
const method = level === "warning" ? "warn" : level;
|
|
3077
1202
|
this[method](message);
|
|
3078
|
-
if (this.activeProgressBar && this.shouldStyleConsole() && !
|
|
1203
|
+
if (this.activeProgressBar && this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY)
|
|
3079
1204
|
this.renderProgressBar(this.activeProgressBar);
|
|
3080
1205
|
};
|
|
3081
1206
|
return { update, finish, interrupt };
|
|
@@ -3083,13 +1208,13 @@ class Logger2 {
|
|
|
3083
1208
|
time(label) {
|
|
3084
1209
|
const start = performance.now();
|
|
3085
1210
|
if (this.shouldStyleConsole()) {
|
|
3086
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
1211
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
3087
1212
|
const consoleTime = this.formatConsoleTimestamp(new Date);
|
|
3088
1213
|
console.error(this.formatConsoleMessage({
|
|
3089
1214
|
timestamp: consoleTime,
|
|
3090
|
-
icon: this.options.showIcons === false ? "" :
|
|
1215
|
+
icon: this.options.showIcons === false ? "" : styles.blue("\u25D0"),
|
|
3091
1216
|
tag,
|
|
3092
|
-
message: `${
|
|
1217
|
+
message: `${styles.cyan(label)}...`
|
|
3093
1218
|
}));
|
|
3094
1219
|
}
|
|
3095
1220
|
return async (metadata) => {
|
|
@@ -3109,14 +1234,14 @@ class Logger2 {
|
|
|
3109
1234
|
`;
|
|
3110
1235
|
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
3111
1236
|
if (this.shouldStyleConsole()) {
|
|
3112
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
1237
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
3113
1238
|
console.error(this.formatConsoleMessage({
|
|
3114
1239
|
timestamp: consoleTime,
|
|
3115
|
-
icon: this.options.showIcons === false ? "" :
|
|
1240
|
+
icon: this.options.showIcons === false ? "" : styles.green("\u2713"),
|
|
3116
1241
|
tag,
|
|
3117
1242
|
message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
|
|
3118
1243
|
}));
|
|
3119
|
-
} else if (!
|
|
1244
|
+
} else if (!isBrowserProcess()) {
|
|
3120
1245
|
console.error(logEntry.trim());
|
|
3121
1246
|
}
|
|
3122
1247
|
if (this.shouldWriteToFile())
|
|
@@ -3160,7 +1285,7 @@ class Logger2 {
|
|
|
3160
1285
|
}
|
|
3161
1286
|
extend(namespace) {
|
|
3162
1287
|
const childName = `${this.name}:${namespace}`;
|
|
3163
|
-
const childLogger = new
|
|
1288
|
+
const childLogger = new Logger(childName, {
|
|
3164
1289
|
...this.options,
|
|
3165
1290
|
logDirectory: this.config.logDirectory,
|
|
3166
1291
|
level: this.config.level,
|
|
@@ -3172,11 +1297,11 @@ class Logger2 {
|
|
|
3172
1297
|
return childLogger;
|
|
3173
1298
|
}
|
|
3174
1299
|
createReadStream() {
|
|
3175
|
-
if (
|
|
1300
|
+
if (isBrowserProcess())
|
|
3176
1301
|
throw new Error("createReadStream is not supported in browser environments");
|
|
3177
|
-
if (!
|
|
1302
|
+
if (!existsSync2(this.currentLogFile))
|
|
3178
1303
|
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
3179
|
-
return
|
|
1304
|
+
return createReadStream(this.currentLogFile, { encoding: "utf8" });
|
|
3180
1305
|
}
|
|
3181
1306
|
async decrypt(data) {
|
|
3182
1307
|
if (!this.validateEncryptionConfig())
|
|
@@ -3188,16 +1313,16 @@ class Logger2 {
|
|
|
3188
1313
|
throw new Error("No valid encryption key available");
|
|
3189
1314
|
const key = this.keys.get(this.currentKeyId);
|
|
3190
1315
|
try {
|
|
3191
|
-
const encryptedData =
|
|
1316
|
+
const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
|
|
3192
1317
|
const iv = encryptedData.subarray(0, 16);
|
|
3193
1318
|
const authTag = encryptedData.subarray(encryptedData.length - 16);
|
|
3194
1319
|
const ciphertext = encryptedData.subarray(16, encryptedData.length - 16);
|
|
3195
|
-
const decipher =
|
|
1320
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
3196
1321
|
decipher.setAuthTag(authTag);
|
|
3197
1322
|
const d1 = decipher.update(ciphertext);
|
|
3198
1323
|
const d2 = decipher.final();
|
|
3199
1324
|
const totalLen = d1.length + d2.length;
|
|
3200
|
-
const out =
|
|
1325
|
+
const out = Buffer.allocUnsafe(totalLen);
|
|
3201
1326
|
d1.copy(out, 0);
|
|
3202
1327
|
d2.copy(out, d1.length);
|
|
3203
1328
|
return out.toString("utf8");
|
|
@@ -3218,10 +1343,10 @@ class Logger2 {
|
|
|
3218
1343
|
return this.config.rotation;
|
|
3219
1344
|
}
|
|
3220
1345
|
isBrowserMode() {
|
|
3221
|
-
return
|
|
1346
|
+
return isBrowserProcess();
|
|
3222
1347
|
}
|
|
3223
1348
|
isServerMode() {
|
|
3224
|
-
return !
|
|
1349
|
+
return !isBrowserProcess();
|
|
3225
1350
|
}
|
|
3226
1351
|
setTestEncryptionKey(keyId, key) {
|
|
3227
1352
|
this.currentKeyId = keyId;
|
|
@@ -3255,22 +1380,22 @@ class Logger2 {
|
|
|
3255
1380
|
const boxedLines = lines.map((line) => {
|
|
3256
1381
|
return this.formatConsoleMessage({
|
|
3257
1382
|
timestamp: consoleTime,
|
|
3258
|
-
message:
|
|
1383
|
+
message: styles.cyan(line),
|
|
3259
1384
|
showTimestamp: false
|
|
3260
1385
|
});
|
|
3261
1386
|
});
|
|
3262
1387
|
console.error(this.formatConsoleMessage({
|
|
3263
1388
|
timestamp: consoleTime,
|
|
3264
|
-
message:
|
|
1389
|
+
message: styles.cyan(top),
|
|
3265
1390
|
showTimestamp: false
|
|
3266
1391
|
}));
|
|
3267
1392
|
boxedLines.forEach((line) => console.error(line));
|
|
3268
1393
|
console.error(this.formatConsoleMessage({
|
|
3269
1394
|
timestamp: consoleTime,
|
|
3270
|
-
message:
|
|
1395
|
+
message: styles.cyan(bottom),
|
|
3271
1396
|
showTimestamp: false
|
|
3272
1397
|
}));
|
|
3273
|
-
} else if (!
|
|
1398
|
+
} else if (!isBrowserProcess()) {
|
|
3274
1399
|
console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${fileText}`);
|
|
3275
1400
|
}
|
|
3276
1401
|
const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${fileText}
|
|
@@ -3279,30 +1404,30 @@ class Logger2 {
|
|
|
3279
1404
|
await this.writeToFile(logEntry);
|
|
3280
1405
|
}
|
|
3281
1406
|
async prompt(message) {
|
|
3282
|
-
if (
|
|
1407
|
+
if (isBrowserProcess()) {
|
|
3283
1408
|
return Promise.resolve(true);
|
|
3284
1409
|
}
|
|
3285
|
-
return new Promise((
|
|
3286
|
-
console.error(`${
|
|
1410
|
+
return new Promise((resolve32) => {
|
|
1411
|
+
console.error(`${styles.cyan("?")} ${message} (y/n) `);
|
|
3287
1412
|
const onData = (data) => {
|
|
3288
1413
|
const input = data.toString().trim().toLowerCase();
|
|
3289
|
-
|
|
1414
|
+
process4.stdin.removeListener("data", onData);
|
|
3290
1415
|
try {
|
|
3291
|
-
if (typeof
|
|
3292
|
-
|
|
1416
|
+
if (typeof process4.stdin.setRawMode === "function") {
|
|
1417
|
+
process4.stdin.setRawMode(false);
|
|
3293
1418
|
}
|
|
3294
1419
|
} catch {}
|
|
3295
|
-
|
|
1420
|
+
process4.stdin.pause();
|
|
3296
1421
|
console.error("");
|
|
3297
|
-
|
|
1422
|
+
resolve32(input === "y" || input === "yes");
|
|
3298
1423
|
};
|
|
3299
1424
|
try {
|
|
3300
|
-
if (typeof
|
|
3301
|
-
|
|
1425
|
+
if (typeof process4.stdin.setRawMode === "function") {
|
|
1426
|
+
process4.stdin.setRawMode(true);
|
|
3302
1427
|
}
|
|
3303
1428
|
} catch {}
|
|
3304
|
-
|
|
3305
|
-
|
|
1429
|
+
process4.stdin.resume();
|
|
1430
|
+
process4.stdin.once("data", onData);
|
|
3306
1431
|
});
|
|
3307
1432
|
}
|
|
3308
1433
|
setFancy(enabled) {
|
|
@@ -3349,9 +1474,9 @@ class Logger2 {
|
|
|
3349
1474
|
}
|
|
3350
1475
|
const { consoleText, fileText } = this.buildOutputTexts(formattedMessage);
|
|
3351
1476
|
if (this.shouldStyleConsole()) {
|
|
3352
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
3353
|
-
const spinnerPrefix = this.options.showIcons === false ? "" : `${
|
|
3354
|
-
console.error(`${spinnerPrefix}${tag} ${
|
|
1477
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1478
|
+
const spinnerPrefix = this.options.showIcons === false ? "" : `${styles.blue("\u25D0")} `;
|
|
1479
|
+
console.error(`${spinnerPrefix}${tag} ${styles.cyan(consoleText)}`);
|
|
3355
1480
|
}
|
|
3356
1481
|
const timestamp = new Date;
|
|
3357
1482
|
const formattedDate = timestamp.toISOString();
|
|
@@ -3361,30 +1486,30 @@ class Logger2 {
|
|
|
3361
1486
|
await this.writeToFile(logEntry);
|
|
3362
1487
|
}
|
|
3363
1488
|
renderProgressBar(barState, isFinished = false) {
|
|
3364
|
-
if (!this.enabled || !this.shouldStyleConsole() || !
|
|
1489
|
+
if (!this.enabled || !this.shouldStyleConsole() || !process4.stdout.isTTY)
|
|
3365
1490
|
return;
|
|
3366
1491
|
const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
|
|
3367
1492
|
const filledLength = Math.round(barState.barLength * percent / 100);
|
|
3368
1493
|
const emptyLength = barState.barLength - filledLength;
|
|
3369
|
-
const filledBar =
|
|
3370
|
-
const emptyBar =
|
|
1494
|
+
const filledBar = styles.green("\u2501".repeat(filledLength));
|
|
1495
|
+
const emptyBar = styles.gray("\u2501".repeat(emptyLength));
|
|
3371
1496
|
const bar = `[${filledBar}${emptyBar}]`;
|
|
3372
1497
|
const percentageText = `${percent}%`.padStart(4);
|
|
3373
1498
|
const messageText = barState.message ? ` ${barState.message}` : "";
|
|
3374
|
-
const icon = this.options.showIcons === false ? "" : isFinished || percent === 100 ?
|
|
3375
|
-
const tag = this.options.showTags !== false && this.name ? ` ${
|
|
1499
|
+
const icon = this.options.showIcons === false ? "" : isFinished || percent === 100 ? styles.green("\u2713") : styles.blue("\u25B6");
|
|
1500
|
+
const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
|
|
3376
1501
|
const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
|
|
3377
|
-
const terminalWidth =
|
|
1502
|
+
const terminalWidth = process4.stdout.columns || 80;
|
|
3378
1503
|
const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
|
|
3379
1504
|
barState.lastRenderedLine = `${line}${clearLine}`;
|
|
3380
|
-
|
|
1505
|
+
process4.stdout.write(barState.lastRenderedLine);
|
|
3381
1506
|
if (isFinished) {
|
|
3382
|
-
|
|
1507
|
+
process4.stdout.write(`
|
|
3383
1508
|
`);
|
|
3384
1509
|
}
|
|
3385
1510
|
}
|
|
3386
1511
|
finishProgressBar(barState, finalMessage) {
|
|
3387
|
-
if (!this.enabled || !this.fancy ||
|
|
1512
|
+
if (!this.enabled || !this.fancy || isBrowserProcess() || !process4.stdout.isTTY) {
|
|
3388
1513
|
this.activeProgressBar = null;
|
|
3389
1514
|
return;
|
|
3390
1515
|
}
|
|
@@ -3397,23 +1522,23 @@ class Logger2 {
|
|
|
3397
1522
|
this.activeProgressBar = null;
|
|
3398
1523
|
}
|
|
3399
1524
|
async clear(filters = {}) {
|
|
3400
|
-
if (
|
|
1525
|
+
if (isBrowserProcess()) {
|
|
3401
1526
|
console.warn("Log clearing is not supported in browser environments.");
|
|
3402
1527
|
return;
|
|
3403
1528
|
}
|
|
3404
1529
|
try {
|
|
3405
1530
|
console.warn("Clearing logs...", this.config.logDirectory);
|
|
3406
|
-
const files = await
|
|
1531
|
+
const files = await readdir(this.config.logDirectory);
|
|
3407
1532
|
const logFilesToDelete = [];
|
|
3408
1533
|
for (const file of files) {
|
|
3409
1534
|
const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
|
|
3410
1535
|
if (!nameMatches || !file.endsWith(".log")) {
|
|
3411
1536
|
continue;
|
|
3412
1537
|
}
|
|
3413
|
-
const filePath =
|
|
1538
|
+
const filePath = join2(this.config.logDirectory, file);
|
|
3414
1539
|
if (filters.before) {
|
|
3415
1540
|
try {
|
|
3416
|
-
const fileStats = await
|
|
1541
|
+
const fileStats = await stat(filePath);
|
|
3417
1542
|
if (fileStats.mtime >= filters.before) {
|
|
3418
1543
|
continue;
|
|
3419
1544
|
}
|
|
@@ -3431,7 +1556,7 @@ class Logger2 {
|
|
|
3431
1556
|
console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
|
|
3432
1557
|
for (const filePath of logFilesToDelete) {
|
|
3433
1558
|
try {
|
|
3434
|
-
await
|
|
1559
|
+
await unlink(filePath);
|
|
3435
1560
|
console.warn(`Deleted log file: ${filePath}`);
|
|
3436
1561
|
} catch (unlinkErr) {
|
|
3437
1562
|
console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
|
|
@@ -3443,193 +1568,126 @@ class Logger2 {
|
|
|
3443
1568
|
}
|
|
3444
1569
|
}
|
|
3445
1570
|
}
|
|
3446
|
-
var
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
}
|
|
3510
|
-
|
|
3511
|
-
}
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
}
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
}
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
}
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
code = "SCHEMA_VALIDATION_ERROR";
|
|
3567
|
-
constructor(schemaPath, validationErrors, configName) {
|
|
3568
|
-
super(`Schema validation failed${configName ? ` for config "${configName}"` : ""}`, {
|
|
3569
|
-
schemaPath,
|
|
3570
|
-
configName,
|
|
3571
|
-
validationErrors,
|
|
3572
|
-
errorCount: validationErrors.length
|
|
3573
|
-
});
|
|
3574
|
-
}
|
|
3575
|
-
}
|
|
3576
|
-
|
|
3577
|
-
class BrowserConfigError extends BunfigError {
|
|
3578
|
-
code = "BROWSER_CONFIG_ERROR";
|
|
3579
|
-
constructor(endpoint, status, statusText, configName) {
|
|
3580
|
-
super(`Failed to fetch configuration from "${endpoint}": ${status} ${statusText}`, {
|
|
3581
|
-
endpoint,
|
|
3582
|
-
status,
|
|
3583
|
-
statusText,
|
|
3584
|
-
configName
|
|
3585
|
-
});
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
|
|
3589
|
-
class PluginError extends BunfigError {
|
|
3590
|
-
code = "PLUGIN_ERROR";
|
|
3591
|
-
constructor(pluginName, operation, cause) {
|
|
3592
|
-
super(`Plugin "${pluginName}" failed during ${operation}: ${cause.message}`, {
|
|
3593
|
-
pluginName,
|
|
3594
|
-
operation,
|
|
3595
|
-
originalError: cause.name,
|
|
3596
|
-
originalMessage: cause.message
|
|
3597
|
-
});
|
|
3598
|
-
this.cause = cause;
|
|
3599
|
-
}
|
|
3600
|
-
}
|
|
3601
|
-
var ErrorFactory = {
|
|
3602
|
-
configNotFound(configName, searchPaths, alias) {
|
|
3603
|
-
return new ConfigNotFoundError(configName, searchPaths, alias);
|
|
3604
|
-
},
|
|
3605
|
-
configLoad(configPath, cause, configName) {
|
|
3606
|
-
return new ConfigLoadError(configPath, cause, configName);
|
|
3607
|
-
},
|
|
3608
|
-
configValidation(configPath, errors, configName) {
|
|
3609
|
-
return new ConfigValidationError(configPath, errors, configName);
|
|
3610
|
-
},
|
|
3611
|
-
configMerge(sourcePath, targetPath, cause, configName) {
|
|
3612
|
-
return new ConfigMergeError(sourcePath, targetPath, cause, configName);
|
|
3613
|
-
},
|
|
3614
|
-
envVar(envKey, envValue, expectedType, configName) {
|
|
3615
|
-
return new EnvVarError(envKey, envValue, expectedType, configName);
|
|
3616
|
-
},
|
|
3617
|
-
fileSystem(operation, path, cause) {
|
|
3618
|
-
return new FileSystemError(operation, path, cause);
|
|
3619
|
-
},
|
|
3620
|
-
typeGeneration(configDir, outputPath, cause) {
|
|
3621
|
-
return new TypeGenerationError(configDir, outputPath, cause);
|
|
3622
|
-
},
|
|
3623
|
-
schemaValidation(schemaPath, errors, configName) {
|
|
3624
|
-
return new SchemaValidationError(schemaPath, errors, configName);
|
|
3625
|
-
},
|
|
3626
|
-
browserConfig(endpoint, status, statusText, configName) {
|
|
3627
|
-
return new BrowserConfigError(endpoint, status, statusText, configName);
|
|
3628
|
-
},
|
|
3629
|
-
plugin(pluginName, operation, cause) {
|
|
3630
|
-
return new PluginError(pluginName, operation, cause);
|
|
3631
|
-
}
|
|
3632
|
-
};
|
|
1571
|
+
var defaultLogDirectory;
|
|
1572
|
+
var defaultConfig;
|
|
1573
|
+
var config;
|
|
1574
|
+
var configReady;
|
|
1575
|
+
var terminalStyles;
|
|
1576
|
+
var styles;
|
|
1577
|
+
var red;
|
|
1578
|
+
var green;
|
|
1579
|
+
var yellow;
|
|
1580
|
+
var blue;
|
|
1581
|
+
var magenta;
|
|
1582
|
+
var cyan;
|
|
1583
|
+
var white;
|
|
1584
|
+
var gray;
|
|
1585
|
+
var bgRed;
|
|
1586
|
+
var bgYellow;
|
|
1587
|
+
var bgGray;
|
|
1588
|
+
var bold;
|
|
1589
|
+
var dim;
|
|
1590
|
+
var italic;
|
|
1591
|
+
var underline;
|
|
1592
|
+
var strikethrough;
|
|
1593
|
+
var reset;
|
|
1594
|
+
var defaultFingersCrossedConfig;
|
|
1595
|
+
var levelIcons;
|
|
1596
|
+
var logger;
|
|
1597
|
+
var init_src = __esm(() => {
|
|
1598
|
+
defaultLogDirectory = process.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
|
|
1599
|
+
defaultConfig = {
|
|
1600
|
+
level: "info",
|
|
1601
|
+
defaultName: "clarity",
|
|
1602
|
+
timestamp: true,
|
|
1603
|
+
colors: true,
|
|
1604
|
+
format: "text",
|
|
1605
|
+
maxLogSize: 10485760,
|
|
1606
|
+
logDatePattern: "YYYY-MM-DD",
|
|
1607
|
+
logDirectory: defaultLogDirectory,
|
|
1608
|
+
rotation: {
|
|
1609
|
+
frequency: "daily",
|
|
1610
|
+
maxSize: 10485760,
|
|
1611
|
+
maxFiles: 5,
|
|
1612
|
+
compress: false,
|
|
1613
|
+
rotateHour: 0,
|
|
1614
|
+
rotateMinute: 0,
|
|
1615
|
+
rotateDayOfWeek: 0,
|
|
1616
|
+
rotateDayOfMonth: 1,
|
|
1617
|
+
encrypt: false
|
|
1618
|
+
},
|
|
1619
|
+
verbose: false,
|
|
1620
|
+
writeToFile: false
|
|
1621
|
+
};
|
|
1622
|
+
config = { ...defaultConfig };
|
|
1623
|
+
configReady = (async () => {
|
|
1624
|
+
try {
|
|
1625
|
+
const { loadConfig: bunfigLoadConfig } = await Promise.resolve().then(() => (init_src2(), exports_src));
|
|
1626
|
+
const loadedConfig = await bunfigLoadConfig({
|
|
1627
|
+
name: "clarity",
|
|
1628
|
+
alias: "logging",
|
|
1629
|
+
defaultConfig,
|
|
1630
|
+
cwd: process.cwd()
|
|
1631
|
+
});
|
|
1632
|
+
if (loadedConfig)
|
|
1633
|
+
Object.assign(config, loadedConfig);
|
|
1634
|
+
} catch {}
|
|
1635
|
+
return config;
|
|
1636
|
+
})();
|
|
1637
|
+
terminalStyles = {
|
|
1638
|
+
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
1639
|
+
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
1640
|
+
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
1641
|
+
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
1642
|
+
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
1643
|
+
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
1644
|
+
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
1645
|
+
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
1646
|
+
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
1647
|
+
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
1648
|
+
bgGray: (text) => `\x1B[100m${text}\x1B[0m`,
|
|
1649
|
+
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
1650
|
+
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
1651
|
+
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
1652
|
+
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
1653
|
+
strikethrough: (text) => `\x1B[9m${text}\x1B[0m`,
|
|
1654
|
+
reset: "\x1B[0m"
|
|
1655
|
+
};
|
|
1656
|
+
styles = terminalStyles;
|
|
1657
|
+
red = terminalStyles.red;
|
|
1658
|
+
green = terminalStyles.green;
|
|
1659
|
+
yellow = terminalStyles.yellow;
|
|
1660
|
+
blue = terminalStyles.blue;
|
|
1661
|
+
magenta = terminalStyles.magenta;
|
|
1662
|
+
cyan = terminalStyles.cyan;
|
|
1663
|
+
white = terminalStyles.white;
|
|
1664
|
+
gray = terminalStyles.gray;
|
|
1665
|
+
bgRed = terminalStyles.bgRed;
|
|
1666
|
+
bgYellow = terminalStyles.bgYellow;
|
|
1667
|
+
bgGray = terminalStyles.bgGray;
|
|
1668
|
+
bold = terminalStyles.bold;
|
|
1669
|
+
dim = terminalStyles.dim;
|
|
1670
|
+
italic = terminalStyles.italic;
|
|
1671
|
+
underline = terminalStyles.underline;
|
|
1672
|
+
strikethrough = terminalStyles.strikethrough;
|
|
1673
|
+
reset = terminalStyles.reset;
|
|
1674
|
+
defaultFingersCrossedConfig = {
|
|
1675
|
+
activationLevel: "error",
|
|
1676
|
+
bufferSize: 50,
|
|
1677
|
+
flushOnDeactivation: true,
|
|
1678
|
+
stopBuffering: false
|
|
1679
|
+
};
|
|
1680
|
+
levelIcons = {
|
|
1681
|
+
debug: "\uD83D\uDD0D",
|
|
1682
|
+
info: blue("\u2139"),
|
|
1683
|
+
success: green("\u2713"),
|
|
1684
|
+
warning: bgYellow(white(bold(" WARN "))),
|
|
1685
|
+
error: bgRed(white(bold(" ERROR ")))
|
|
1686
|
+
};
|
|
1687
|
+
logger = new Logger("stacks");
|
|
1688
|
+
});
|
|
1689
|
+
var version = "0.15.9";
|
|
1690
|
+
var init_package = () => {};
|
|
3633
1691
|
async function withErrorRecovery(fn, options = {}) {
|
|
3634
1692
|
const {
|
|
3635
1693
|
maxRetries = 3,
|
|
@@ -3647,7 +1705,7 @@ async function withErrorRecovery(fn, options = {}) {
|
|
|
3647
1705
|
break;
|
|
3648
1706
|
}
|
|
3649
1707
|
if (retryDelay > 0) {
|
|
3650
|
-
await new Promise((
|
|
1708
|
+
await new Promise((resolve32) => setTimeout(resolve32, retryDelay));
|
|
3651
1709
|
}
|
|
3652
1710
|
}
|
|
3653
1711
|
}
|
|
@@ -3656,6 +1714,224 @@ async function withErrorRecovery(fn, options = {}) {
|
|
|
3656
1714
|
}
|
|
3657
1715
|
throw lastError instanceof Error ? lastError : new Error(`Unknown error: ${String(lastError)}`);
|
|
3658
1716
|
}
|
|
1717
|
+
function isBunfigError(error) {
|
|
1718
|
+
return error instanceof BunfigError;
|
|
1719
|
+
}
|
|
1720
|
+
function isConfigNotFoundError(error) {
|
|
1721
|
+
return error instanceof ConfigNotFoundError;
|
|
1722
|
+
}
|
|
1723
|
+
function isRetryableError(error) {
|
|
1724
|
+
if (isBunfigError(error)) {
|
|
1725
|
+
return error.code === "FILE_SYSTEM_ERROR" || error.code === "BROWSER_CONFIG_ERROR";
|
|
1726
|
+
}
|
|
1727
|
+
const retryableMessages = [
|
|
1728
|
+
"ENOENT",
|
|
1729
|
+
"EACCES",
|
|
1730
|
+
"EMFILE",
|
|
1731
|
+
"ENFILE",
|
|
1732
|
+
"EBUSY",
|
|
1733
|
+
"network",
|
|
1734
|
+
"timeout",
|
|
1735
|
+
"connection"
|
|
1736
|
+
];
|
|
1737
|
+
return retryableMessages.some((msg) => error.message.toLowerCase().includes(msg.toLowerCase()));
|
|
1738
|
+
}
|
|
1739
|
+
var BunfigError;
|
|
1740
|
+
var ConfigNotFoundError;
|
|
1741
|
+
var ConfigLoadError;
|
|
1742
|
+
var ConfigValidationError;
|
|
1743
|
+
var ConfigMergeError;
|
|
1744
|
+
var EnvVarError;
|
|
1745
|
+
var FileSystemError;
|
|
1746
|
+
var TypeGenerationError;
|
|
1747
|
+
var SchemaValidationError;
|
|
1748
|
+
var BrowserConfigError;
|
|
1749
|
+
var PluginError;
|
|
1750
|
+
var ErrorFactory;
|
|
1751
|
+
var init_errors = __esm(() => {
|
|
1752
|
+
BunfigError = class BunfigError2 extends Error {
|
|
1753
|
+
timestamp;
|
|
1754
|
+
context;
|
|
1755
|
+
constructor(message, context = {}) {
|
|
1756
|
+
super(message);
|
|
1757
|
+
this.name = this.constructor.name;
|
|
1758
|
+
this.timestamp = new Date;
|
|
1759
|
+
this.context = context;
|
|
1760
|
+
if (Error.captureStackTrace) {
|
|
1761
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
toJSON() {
|
|
1765
|
+
return {
|
|
1766
|
+
name: this.name,
|
|
1767
|
+
code: this.code,
|
|
1768
|
+
message: this.message,
|
|
1769
|
+
timestamp: this.timestamp.toISOString(),
|
|
1770
|
+
context: this.context,
|
|
1771
|
+
stack: this.stack
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
toString() {
|
|
1775
|
+
const contextStr = Object.keys(this.context).length > 0 ? ` (${Object.entries(this.context).map(([k, v]) => `${k}: ${v}`).join(", ")})` : "";
|
|
1776
|
+
return `${this.name} [${this.code}]: ${this.message}${contextStr}`;
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
ConfigNotFoundError = class ConfigNotFoundError2 extends BunfigError {
|
|
1780
|
+
code = "CONFIG_NOT_FOUND";
|
|
1781
|
+
constructor(configName, searchPaths, alias) {
|
|
1782
|
+
const aliasList = alias === undefined ? [] : Array.isArray(alias) ? alias.filter(Boolean) : [alias];
|
|
1783
|
+
let aliasStr = "";
|
|
1784
|
+
if (aliasList.length === 1)
|
|
1785
|
+
aliasStr = ` or alias "${aliasList[0]}"`;
|
|
1786
|
+
else if (aliasList.length > 1)
|
|
1787
|
+
aliasStr = ` or aliases ${aliasList.map((a) => `"${a}"`).join(", ")}`;
|
|
1788
|
+
super(`Configuration "${configName}"${aliasStr} not found`, {
|
|
1789
|
+
configName,
|
|
1790
|
+
alias,
|
|
1791
|
+
searchPaths,
|
|
1792
|
+
searchPathCount: searchPaths.length
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
ConfigLoadError = class ConfigLoadError2 extends BunfigError {
|
|
1797
|
+
code = "CONFIG_LOAD_ERROR";
|
|
1798
|
+
constructor(configPath, cause, configName) {
|
|
1799
|
+
super(`Failed to load configuration from "${configPath}": ${cause.message}`, {
|
|
1800
|
+
configPath,
|
|
1801
|
+
configName,
|
|
1802
|
+
originalError: cause.name,
|
|
1803
|
+
originalMessage: cause.message
|
|
1804
|
+
});
|
|
1805
|
+
this.cause = cause;
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
ConfigValidationError = class ConfigValidationError2 extends BunfigError {
|
|
1809
|
+
code = "CONFIG_VALIDATION_ERROR";
|
|
1810
|
+
constructor(configPath, validationErrors, configName) {
|
|
1811
|
+
super(`Configuration validation failed for "${configPath}"`, {
|
|
1812
|
+
configPath,
|
|
1813
|
+
configName,
|
|
1814
|
+
validationErrors,
|
|
1815
|
+
errorCount: validationErrors.length
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
};
|
|
1819
|
+
ConfigMergeError = class ConfigMergeError2 extends BunfigError {
|
|
1820
|
+
code = "CONFIG_MERGE_ERROR";
|
|
1821
|
+
constructor(sourcePath, targetPath, cause, configName) {
|
|
1822
|
+
super(`Failed to merge configuration from "${sourcePath}" with "${targetPath}": ${cause.message}`, {
|
|
1823
|
+
sourcePath,
|
|
1824
|
+
targetPath,
|
|
1825
|
+
configName,
|
|
1826
|
+
originalError: cause.name,
|
|
1827
|
+
originalMessage: cause.message
|
|
1828
|
+
});
|
|
1829
|
+
this.cause = cause;
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
EnvVarError = class EnvVarError2 extends BunfigError {
|
|
1833
|
+
code = "ENV_VAR_ERROR";
|
|
1834
|
+
constructor(envKey, envValue, expectedType, configName) {
|
|
1835
|
+
super(`Failed to parse environment variable "${envKey}" with value "${envValue}" as ${expectedType}`, {
|
|
1836
|
+
envKey,
|
|
1837
|
+
envValue,
|
|
1838
|
+
expectedType,
|
|
1839
|
+
configName
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
FileSystemError = class FileSystemError2 extends BunfigError {
|
|
1844
|
+
code = "FILE_SYSTEM_ERROR";
|
|
1845
|
+
constructor(operation, path, cause) {
|
|
1846
|
+
super(`File system ${operation} failed for "${path}": ${cause.message}`, {
|
|
1847
|
+
operation,
|
|
1848
|
+
path,
|
|
1849
|
+
originalError: cause.name,
|
|
1850
|
+
originalMessage: cause.message
|
|
1851
|
+
});
|
|
1852
|
+
this.cause = cause;
|
|
1853
|
+
}
|
|
1854
|
+
};
|
|
1855
|
+
TypeGenerationError = class TypeGenerationError2 extends BunfigError {
|
|
1856
|
+
code = "TYPE_GENERATION_ERROR";
|
|
1857
|
+
constructor(configDir, outputPath, cause) {
|
|
1858
|
+
super(`Failed to generate types from "${configDir}" to "${outputPath}": ${cause.message}`, {
|
|
1859
|
+
configDir,
|
|
1860
|
+
outputPath,
|
|
1861
|
+
originalError: cause.name,
|
|
1862
|
+
originalMessage: cause.message
|
|
1863
|
+
});
|
|
1864
|
+
this.cause = cause;
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
SchemaValidationError = class SchemaValidationError2 extends BunfigError {
|
|
1868
|
+
code = "SCHEMA_VALIDATION_ERROR";
|
|
1869
|
+
constructor(schemaPath, validationErrors, configName) {
|
|
1870
|
+
super(`Schema validation failed${configName ? ` for config "${configName}"` : ""}`, {
|
|
1871
|
+
schemaPath,
|
|
1872
|
+
configName,
|
|
1873
|
+
validationErrors,
|
|
1874
|
+
errorCount: validationErrors.length
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
};
|
|
1878
|
+
BrowserConfigError = class BrowserConfigError2 extends BunfigError {
|
|
1879
|
+
code = "BROWSER_CONFIG_ERROR";
|
|
1880
|
+
constructor(endpoint, status, statusText, configName) {
|
|
1881
|
+
super(`Failed to fetch configuration from "${endpoint}": ${status} ${statusText}`, {
|
|
1882
|
+
endpoint,
|
|
1883
|
+
status,
|
|
1884
|
+
statusText,
|
|
1885
|
+
configName
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
PluginError = class PluginError2 extends BunfigError {
|
|
1890
|
+
code = "PLUGIN_ERROR";
|
|
1891
|
+
constructor(pluginName, operation, cause) {
|
|
1892
|
+
super(`Plugin "${pluginName}" failed during ${operation}: ${cause.message}`, {
|
|
1893
|
+
pluginName,
|
|
1894
|
+
operation,
|
|
1895
|
+
originalError: cause.name,
|
|
1896
|
+
originalMessage: cause.message
|
|
1897
|
+
});
|
|
1898
|
+
this.cause = cause;
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
ErrorFactory = {
|
|
1902
|
+
configNotFound(configName, searchPaths, alias) {
|
|
1903
|
+
return new ConfigNotFoundError(configName, searchPaths, alias);
|
|
1904
|
+
},
|
|
1905
|
+
configLoad(configPath, cause, configName) {
|
|
1906
|
+
return new ConfigLoadError(configPath, cause, configName);
|
|
1907
|
+
},
|
|
1908
|
+
configValidation(configPath, errors, configName) {
|
|
1909
|
+
return new ConfigValidationError(configPath, errors, configName);
|
|
1910
|
+
},
|
|
1911
|
+
configMerge(sourcePath, targetPath, cause, configName) {
|
|
1912
|
+
return new ConfigMergeError(sourcePath, targetPath, cause, configName);
|
|
1913
|
+
},
|
|
1914
|
+
envVar(envKey, envValue, expectedType, configName) {
|
|
1915
|
+
return new EnvVarError(envKey, envValue, expectedType, configName);
|
|
1916
|
+
},
|
|
1917
|
+
fileSystem(operation, path, cause) {
|
|
1918
|
+
return new FileSystemError(operation, path, cause);
|
|
1919
|
+
},
|
|
1920
|
+
typeGeneration(configDir, outputPath, cause) {
|
|
1921
|
+
return new TypeGenerationError(configDir, outputPath, cause);
|
|
1922
|
+
},
|
|
1923
|
+
schemaValidation(schemaPath, errors, configName) {
|
|
1924
|
+
return new SchemaValidationError(schemaPath, errors, configName);
|
|
1925
|
+
},
|
|
1926
|
+
browserConfig(endpoint, status, statusText, configName) {
|
|
1927
|
+
return new BrowserConfigError(endpoint, status, statusText, configName);
|
|
1928
|
+
},
|
|
1929
|
+
plugin(pluginName, operation, cause) {
|
|
1930
|
+
return new PluginError(pluginName, operation, cause);
|
|
1931
|
+
}
|
|
1932
|
+
};
|
|
1933
|
+
});
|
|
1934
|
+
|
|
3659
1935
|
class EnvProcessor {
|
|
3660
1936
|
defaultParsers;
|
|
3661
1937
|
constructor() {
|
|
@@ -3705,7 +1981,7 @@ class EnvProcessor {
|
|
|
3705
1981
|
}
|
|
3706
1982
|
];
|
|
3707
1983
|
}
|
|
3708
|
-
async applyEnvironmentVariables(configName,
|
|
1984
|
+
async applyEnvironmentVariables(configName, config2, options = {}) {
|
|
3709
1985
|
const {
|
|
3710
1986
|
prefix,
|
|
3711
1987
|
useCamelCase = true,
|
|
@@ -3717,12 +1993,12 @@ class EnvProcessor {
|
|
|
3717
1993
|
const operation = async () => {
|
|
3718
1994
|
if (!configName) {
|
|
3719
1995
|
return {
|
|
3720
|
-
config:
|
|
1996
|
+
config: config2,
|
|
3721
1997
|
source: { type: "environment", priority: 50, timestamp: new Date }
|
|
3722
1998
|
};
|
|
3723
1999
|
}
|
|
3724
2000
|
const envPrefix = prefix || this.generateEnvPrefix(configName);
|
|
3725
|
-
const result = { ...
|
|
2001
|
+
const result = { ...config2 };
|
|
3726
2002
|
this.processObject(result, [], envPrefix, {
|
|
3727
2003
|
useCamelCase,
|
|
3728
2004
|
useBackwardCompatibility,
|
|
@@ -3761,10 +2037,10 @@ class EnvProcessor {
|
|
|
3761
2037
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3762
2038
|
this.processObject(value, envPath, envPrefix, options);
|
|
3763
2039
|
} else {
|
|
3764
|
-
const envValue =
|
|
2040
|
+
const envValue = process5.env[envKey] || (oldEnvKey ? process5.env[oldEnvKey] : undefined);
|
|
3765
2041
|
if (envValue !== undefined) {
|
|
3766
2042
|
if (options.verbose) {
|
|
3767
|
-
const _usedKey =
|
|
2043
|
+
const _usedKey = process5.env[envKey] ? envKey : oldEnvKey;
|
|
3768
2044
|
}
|
|
3769
2045
|
try {
|
|
3770
2046
|
obj[key] = this.parseEnvironmentValue(envValue, typeof value, envKey, options.customParsers, options.configName);
|
|
@@ -3800,7 +2076,7 @@ class EnvProcessor {
|
|
|
3800
2076
|
getEnvironmentVariables(prefix) {
|
|
3801
2077
|
const envVars = {};
|
|
3802
2078
|
const upperPrefix = prefix.toUpperCase();
|
|
3803
|
-
for (const [key, value] of Object.entries(
|
|
2079
|
+
for (const [key, value] of Object.entries(process5.env)) {
|
|
3804
2080
|
if (key.startsWith(upperPrefix) && value !== undefined) {
|
|
3805
2081
|
envVars[key] = value;
|
|
3806
2082
|
}
|
|
@@ -3824,11 +2100,11 @@ class EnvProcessor {
|
|
|
3824
2100
|
errors
|
|
3825
2101
|
};
|
|
3826
2102
|
}
|
|
3827
|
-
generateEnvVarDocs(configName,
|
|
2103
|
+
generateEnvVarDocs(configName, defaultConfig2, options = {}) {
|
|
3828
2104
|
const { prefix, format = "text" } = options;
|
|
3829
2105
|
const envPrefix = prefix || this.generateEnvPrefix(configName);
|
|
3830
2106
|
const envVars = [];
|
|
3831
|
-
this.extractEnvVarInfo(
|
|
2107
|
+
this.extractEnvVarInfo(defaultConfig2, [], envPrefix, envVars);
|
|
3832
2108
|
switch (format) {
|
|
3833
2109
|
case "markdown":
|
|
3834
2110
|
return this.formatAsMarkdown(envVars, configName);
|
|
@@ -3895,7 +2171,18 @@ class EnvProcessor {
|
|
|
3895
2171
|
return result;
|
|
3896
2172
|
}
|
|
3897
2173
|
}
|
|
3898
|
-
|
|
2174
|
+
var init_env_processor = __esm(() => {
|
|
2175
|
+
init_cache();
|
|
2176
|
+
init_errors();
|
|
2177
|
+
});
|
|
2178
|
+
function getEnvOrDefault(key, defaultValue) {
|
|
2179
|
+
const process6 = __require2("process");
|
|
2180
|
+
if (typeof process6 === "undefined" || !process6.env)
|
|
2181
|
+
return defaultValue;
|
|
2182
|
+
const envValue = process6.env[key];
|
|
2183
|
+
return envValue !== undefined ? envValue : defaultValue;
|
|
2184
|
+
}
|
|
2185
|
+
function deepMerge(target, source, options = {}) {
|
|
3899
2186
|
const visited = new WeakMap;
|
|
3900
2187
|
return deepMergeWithVisited(target, source, options, visited);
|
|
3901
2188
|
}
|
|
@@ -3917,7 +2204,7 @@ function deepMergeWithVisited(target, source, options, visited) {
|
|
|
3917
2204
|
if (Array.isArray(source) || Array.isArray(target)) {
|
|
3918
2205
|
return mergeArraysWithVisited(target, source, arrayMergeMode, visited);
|
|
3919
2206
|
}
|
|
3920
|
-
if (!
|
|
2207
|
+
if (!isObject(source) || !isObject(target)) {
|
|
3921
2208
|
return source;
|
|
3922
2209
|
}
|
|
3923
2210
|
return mergeObjectsWithVisited(target, source, options, visited);
|
|
@@ -3946,7 +2233,7 @@ function mergeArraysWithVisited(target, source, mode, visited) {
|
|
|
3946
2233
|
function concatArraysWithDedup(target, source) {
|
|
3947
2234
|
const result = [...source];
|
|
3948
2235
|
for (const item of target) {
|
|
3949
|
-
if (!result.some((existingItem) =>
|
|
2236
|
+
if (!result.some((existingItem) => deepEquals(existingItem, item))) {
|
|
3950
2237
|
result.push(item);
|
|
3951
2238
|
}
|
|
3952
2239
|
}
|
|
@@ -3957,7 +2244,7 @@ function smartMergeArraysWithVisited(target, source, visited) {
|
|
|
3957
2244
|
return target;
|
|
3958
2245
|
if (target.length === 0)
|
|
3959
2246
|
return source;
|
|
3960
|
-
if (
|
|
2247
|
+
if (isObject(source[0]) && isObject(target[0])) {
|
|
3961
2248
|
return mergeObjectArraysWithVisited(target, source, visited);
|
|
3962
2249
|
}
|
|
3963
2250
|
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
@@ -3974,7 +2261,7 @@ function smartMergeArraysWithVisited(target, source, visited) {
|
|
|
3974
2261
|
function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
3975
2262
|
const result = [...source];
|
|
3976
2263
|
for (const targetItem of target) {
|
|
3977
|
-
if (!
|
|
2264
|
+
if (!isObject(targetItem)) {
|
|
3978
2265
|
result.push(targetItem);
|
|
3979
2266
|
continue;
|
|
3980
2267
|
}
|
|
@@ -3982,7 +2269,7 @@ function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
|
3982
2269
|
let hasMatch = false;
|
|
3983
2270
|
for (const key of identifierKeys) {
|
|
3984
2271
|
if (key in targetItem) {
|
|
3985
|
-
const existingItem = result.find((item) =>
|
|
2272
|
+
const existingItem = result.find((item) => isObject(item) && (key in item) && item[key] === targetItem[key]);
|
|
3986
2273
|
if (existingItem) {
|
|
3987
2274
|
hasMatch = true;
|
|
3988
2275
|
break;
|
|
@@ -3997,11 +2284,11 @@ function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
|
3997
2284
|
}
|
|
3998
2285
|
function mergeObjectsWithVisited(target, source, options, visited) {
|
|
3999
2286
|
const sourceObj = source;
|
|
4000
|
-
if (
|
|
2287
|
+
if (isObject(sourceObj) && visited.has(sourceObj)) {
|
|
4001
2288
|
return visited.get(sourceObj);
|
|
4002
2289
|
}
|
|
4003
2290
|
const merged = { ...target };
|
|
4004
|
-
if (
|
|
2291
|
+
if (isObject(sourceObj)) {
|
|
4005
2292
|
visited.set(sourceObj, merged);
|
|
4006
2293
|
}
|
|
4007
2294
|
for (const key in sourceObj) {
|
|
@@ -4017,7 +2304,7 @@ function mergeObjectsWithVisited(target, source, options, visited) {
|
|
|
4017
2304
|
merged[key] = sourceValue;
|
|
4018
2305
|
continue;
|
|
4019
2306
|
}
|
|
4020
|
-
if (
|
|
2307
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
4021
2308
|
merged[key] = deepMergeWithVisited(targetValue, sourceValue, options, visited);
|
|
4022
2309
|
} else if (Array.isArray(sourceValue) || Array.isArray(targetValue)) {
|
|
4023
2310
|
merged[key] = mergeArraysWithVisited(targetValue, sourceValue, options.arrayMergeMode || "smart", visited);
|
|
@@ -4027,26 +2314,26 @@ function mergeObjectsWithVisited(target, source, options, visited) {
|
|
|
4027
2314
|
}
|
|
4028
2315
|
return merged;
|
|
4029
2316
|
}
|
|
4030
|
-
function
|
|
2317
|
+
function deepMergeWithArrayStrategy(target, source, strategy = "replace") {
|
|
4031
2318
|
const arrayMergeMode = strategy === "replace" ? "replace" : "smart";
|
|
4032
|
-
return
|
|
2319
|
+
return deepMerge(target, source, {
|
|
4033
2320
|
arrayMergeMode,
|
|
4034
2321
|
skipNullish: true
|
|
4035
2322
|
});
|
|
4036
2323
|
}
|
|
4037
|
-
function
|
|
2324
|
+
function deepEquals(a, b) {
|
|
4038
2325
|
if (a === b)
|
|
4039
2326
|
return true;
|
|
4040
2327
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
4041
2328
|
if (a.length !== b.length)
|
|
4042
2329
|
return false;
|
|
4043
2330
|
for (let i = 0;i < a.length; i++) {
|
|
4044
|
-
if (!
|
|
2331
|
+
if (!deepEquals(a[i], b[i]))
|
|
4045
2332
|
return false;
|
|
4046
2333
|
}
|
|
4047
2334
|
return true;
|
|
4048
2335
|
}
|
|
4049
|
-
if (
|
|
2336
|
+
if (isObject(a) && isObject(b)) {
|
|
4050
2337
|
const keysA = Object.keys(a);
|
|
4051
2338
|
const keysB = Object.keys(b);
|
|
4052
2339
|
if (keysA.length !== keysB.length)
|
|
@@ -4054,20 +2341,28 @@ function deepEquals3(a, b) {
|
|
|
4054
2341
|
for (const key of keysA) {
|
|
4055
2342
|
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
4056
2343
|
return false;
|
|
4057
|
-
if (!
|
|
2344
|
+
if (!deepEquals(a[key], b[key]))
|
|
4058
2345
|
return false;
|
|
4059
2346
|
}
|
|
4060
2347
|
return true;
|
|
4061
2348
|
}
|
|
4062
2349
|
return false;
|
|
4063
2350
|
}
|
|
4064
|
-
function
|
|
2351
|
+
function isObject(item) {
|
|
4065
2352
|
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
4066
2353
|
}
|
|
2354
|
+
var ArrayMergeStrategies;
|
|
2355
|
+
var init_utils = __esm(() => {
|
|
2356
|
+
ArrayMergeStrategies = {
|
|
2357
|
+
replace: "replace",
|
|
2358
|
+
concat: "concat",
|
|
2359
|
+
smart: "smart"
|
|
2360
|
+
};
|
|
2361
|
+
});
|
|
4067
2362
|
|
|
4068
2363
|
class ConfigFileLoader {
|
|
4069
2364
|
extensions = [".ts", ".js", ".mjs", ".cjs", ".json", ".mts", ".cts"];
|
|
4070
|
-
async loadFromPath(configPath,
|
|
2365
|
+
async loadFromPath(configPath, defaultConfig2, options = {}) {
|
|
4071
2366
|
const {
|
|
4072
2367
|
arrayStrategy = "replace",
|
|
4073
2368
|
useCache = true,
|
|
@@ -4085,7 +2380,7 @@ class ConfigFileLoader {
|
|
|
4085
2380
|
}
|
|
4086
2381
|
}
|
|
4087
2382
|
const loadOperation = async () => {
|
|
4088
|
-
if (!
|
|
2383
|
+
if (!existsSync3(configPath)) {
|
|
4089
2384
|
return null;
|
|
4090
2385
|
}
|
|
4091
2386
|
try {
|
|
@@ -4100,7 +2395,7 @@ class ConfigFileLoader {
|
|
|
4100
2395
|
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig)) {
|
|
4101
2396
|
throw new ConfigLoadError(configPath, new Error("Configuration must export a valid object"), "unknown");
|
|
4102
2397
|
}
|
|
4103
|
-
const mergedConfig =
|
|
2398
|
+
const mergedConfig = deepMergeWithArrayStrategy(defaultConfig2, loadedConfig, arrayStrategy);
|
|
4104
2399
|
const source = {
|
|
4105
2400
|
type: "file",
|
|
4106
2401
|
path: configPath,
|
|
@@ -4122,10 +2417,10 @@ class ConfigFileLoader {
|
|
|
4122
2417
|
}
|
|
4123
2418
|
return loadOperation();
|
|
4124
2419
|
}
|
|
4125
|
-
async tryLoadFromPaths(configPaths,
|
|
2420
|
+
async tryLoadFromPaths(configPaths, defaultConfig2, options = {}) {
|
|
4126
2421
|
for (const configPath of configPaths) {
|
|
4127
2422
|
try {
|
|
4128
|
-
const result = await this.loadFromPath(configPath,
|
|
2423
|
+
const result = await this.loadFromPath(configPath, defaultConfig2, options);
|
|
4129
2424
|
if (result) {
|
|
4130
2425
|
return result;
|
|
4131
2426
|
}
|
|
@@ -4145,7 +2440,7 @@ class ConfigFileLoader {
|
|
|
4145
2440
|
const paths = [];
|
|
4146
2441
|
for (const pattern of patterns) {
|
|
4147
2442
|
for (const ext of this.extensions) {
|
|
4148
|
-
paths.push(
|
|
2443
|
+
paths.push(resolve3(directory, `${pattern}${ext}`));
|
|
4149
2444
|
}
|
|
4150
2445
|
}
|
|
4151
2446
|
return paths;
|
|
@@ -4156,17 +2451,26 @@ class ConfigFileLoader {
|
|
|
4156
2451
|
if (configName) {
|
|
4157
2452
|
patterns.push(configName, `.${configName}.config`, `${configName}.config`, `.${configName}`);
|
|
4158
2453
|
}
|
|
4159
|
-
|
|
4160
|
-
|
|
2454
|
+
const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
|
|
2455
|
+
for (const a of aliases) {
|
|
2456
|
+
if (!a)
|
|
2457
|
+
continue;
|
|
2458
|
+
patterns.push(a, `.${a}.config`, `${a}.config`, `.${a}`);
|
|
4161
2459
|
if (configName) {
|
|
4162
|
-
patterns.push(`${configName}.${
|
|
2460
|
+
patterns.push(`${configName}.${a}.config`, `.${configName}.${a}.config`);
|
|
4163
2461
|
}
|
|
4164
2462
|
}
|
|
4165
|
-
|
|
2463
|
+
const seen = new Set;
|
|
2464
|
+
return patterns.filter((p) => {
|
|
2465
|
+
if (!p || seen.has(p))
|
|
2466
|
+
return false;
|
|
2467
|
+
seen.add(p);
|
|
2468
|
+
return true;
|
|
2469
|
+
});
|
|
4166
2470
|
}
|
|
4167
2471
|
checkFileAccess(filePath) {
|
|
4168
2472
|
return withErrorRecovery(async () => {
|
|
4169
|
-
return
|
|
2473
|
+
return existsSync3(filePath);
|
|
4170
2474
|
}, {
|
|
4171
2475
|
maxRetries: 2,
|
|
4172
2476
|
retryDelay: 100,
|
|
@@ -4175,14 +2479,14 @@ class ConfigFileLoader {
|
|
|
4175
2479
|
}
|
|
4176
2480
|
async discoverConfigFiles(directory, configName, alias) {
|
|
4177
2481
|
const discoveredFiles = [];
|
|
4178
|
-
if (!
|
|
2482
|
+
if (!existsSync3(directory)) {
|
|
4179
2483
|
return discoveredFiles;
|
|
4180
2484
|
}
|
|
4181
2485
|
if (configName || alias) {
|
|
4182
2486
|
const patterns = this.generateNamePatterns(configName || "", alias);
|
|
4183
2487
|
for (const pattern of patterns) {
|
|
4184
2488
|
for (const ext of this.extensions) {
|
|
4185
|
-
const filePath =
|
|
2489
|
+
const filePath = resolve3(directory, `${pattern}${ext}`);
|
|
4186
2490
|
if (await this.checkFileAccess(filePath)) {
|
|
4187
2491
|
discoveredFiles.push(filePath);
|
|
4188
2492
|
}
|
|
@@ -4190,11 +2494,11 @@ class ConfigFileLoader {
|
|
|
4190
2494
|
}
|
|
4191
2495
|
} else {
|
|
4192
2496
|
try {
|
|
4193
|
-
const { readdirSync:
|
|
4194
|
-
const files =
|
|
2497
|
+
const { readdirSync: readdirSync3 } = await import("fs");
|
|
2498
|
+
const files = readdirSync3(directory);
|
|
4195
2499
|
for (const file of files) {
|
|
4196
2500
|
if (this.looksLikeConfigFile(file)) {
|
|
4197
|
-
const filePath =
|
|
2501
|
+
const filePath = resolve3(directory, file);
|
|
4198
2502
|
if (await this.checkFileAccess(filePath)) {
|
|
4199
2503
|
discoveredFiles.push(filePath);
|
|
4200
2504
|
}
|
|
@@ -4217,23 +2521,23 @@ class ConfigFileLoader {
|
|
|
4217
2521
|
async validateConfigFile(filePath) {
|
|
4218
2522
|
const errors = [];
|
|
4219
2523
|
try {
|
|
4220
|
-
if (!
|
|
2524
|
+
if (!existsSync3(filePath)) {
|
|
4221
2525
|
errors.push("Configuration file does not exist");
|
|
4222
2526
|
return errors;
|
|
4223
2527
|
}
|
|
4224
2528
|
const imported = await import(filePath);
|
|
4225
|
-
const
|
|
4226
|
-
if (
|
|
2529
|
+
const config2 = imported.default || imported;
|
|
2530
|
+
if (config2 === undefined) {
|
|
4227
2531
|
errors.push("Configuration file must export a default value or named exports");
|
|
4228
|
-
} else if (typeof
|
|
2532
|
+
} else if (typeof config2 !== "object" || config2 === null) {
|
|
4229
2533
|
errors.push("Configuration must be an object");
|
|
4230
|
-
} else if (Array.isArray(
|
|
2534
|
+
} else if (Array.isArray(config2)) {
|
|
4231
2535
|
errors.push("Configuration cannot be an array at the root level");
|
|
4232
2536
|
}
|
|
4233
2537
|
if (filePath.endsWith(".json")) {
|
|
4234
2538
|
try {
|
|
4235
|
-
const { readFileSync } = await import("fs");
|
|
4236
|
-
const content =
|
|
2539
|
+
const { readFileSync: readFileSync2 } = await import("fs");
|
|
2540
|
+
const content = readFileSync2(filePath, "utf8");
|
|
4237
2541
|
JSON.parse(content);
|
|
4238
2542
|
} catch (jsonError) {
|
|
4239
2543
|
errors.push(`Invalid JSON syntax: ${jsonError}`);
|
|
@@ -4270,10 +2574,14 @@ class ConfigFileLoader {
|
|
|
4270
2574
|
return preloaded;
|
|
4271
2575
|
}
|
|
4272
2576
|
}
|
|
4273
|
-
var
|
|
2577
|
+
var init_file_loader = __esm(() => {
|
|
2578
|
+
init_cache();
|
|
2579
|
+
init_errors();
|
|
2580
|
+
init_utils();
|
|
2581
|
+
});
|
|
4274
2582
|
|
|
4275
2583
|
class ConfigValidator {
|
|
4276
|
-
async validateConfiguration(
|
|
2584
|
+
async validateConfiguration(config2, schema, options = {}) {
|
|
4277
2585
|
const {
|
|
4278
2586
|
stopOnFirstError = false,
|
|
4279
2587
|
validateRequired = true,
|
|
@@ -4295,11 +2603,11 @@ class ConfigValidator {
|
|
|
4295
2603
|
};
|
|
4296
2604
|
try {
|
|
4297
2605
|
if (typeof schema === "string") {
|
|
4298
|
-
return await this.validateWithSchemaFile(
|
|
2606
|
+
return await this.validateWithSchemaFile(config2, schema, resolvedOptions);
|
|
4299
2607
|
} else if (Array.isArray(schema)) {
|
|
4300
|
-
return this.validateWithRules(
|
|
2608
|
+
return this.validateWithRules(config2, [...schema, ...customRules], resolvedOptions);
|
|
4301
2609
|
} else {
|
|
4302
|
-
return this.validateWithJSONSchema(
|
|
2610
|
+
return this.validateWithJSONSchema(config2, schema, resolvedOptions);
|
|
4303
2611
|
}
|
|
4304
2612
|
} catch (error) {
|
|
4305
2613
|
errors.push({
|
|
@@ -4316,26 +2624,26 @@ class ConfigValidator {
|
|
|
4316
2624
|
}
|
|
4317
2625
|
return operation();
|
|
4318
2626
|
}
|
|
4319
|
-
async validateWithSchemaFile(
|
|
2627
|
+
async validateWithSchemaFile(config2, schemaPath, options) {
|
|
4320
2628
|
try {
|
|
4321
|
-
if (!
|
|
2629
|
+
if (!existsSync4(schemaPath)) {
|
|
4322
2630
|
throw new SchemaValidationError(schemaPath, [{ path: "", message: "Schema file does not exist" }]);
|
|
4323
2631
|
}
|
|
4324
2632
|
const schemaModule = await import(schemaPath);
|
|
4325
2633
|
const schema = schemaModule.default || schemaModule;
|
|
4326
2634
|
if (Array.isArray(schema)) {
|
|
4327
|
-
return this.validateWithRules(
|
|
2635
|
+
return this.validateWithRules(config2, schema, options);
|
|
4328
2636
|
} else {
|
|
4329
|
-
return this.validateWithJSONSchema(
|
|
2637
|
+
return this.validateWithJSONSchema(config2, schema, options);
|
|
4330
2638
|
}
|
|
4331
2639
|
} catch (error) {
|
|
4332
2640
|
throw new SchemaValidationError(schemaPath, [{ path: "", message: `Failed to load schema: ${error}` }]);
|
|
4333
2641
|
}
|
|
4334
2642
|
}
|
|
4335
|
-
validateWithJSONSchema(
|
|
2643
|
+
validateWithJSONSchema(config2, schema, options) {
|
|
4336
2644
|
const errors = [];
|
|
4337
2645
|
const warnings = [];
|
|
4338
|
-
this.validateObjectAgainstSchema(
|
|
2646
|
+
this.validateObjectAgainstSchema(config2, schema, "", errors, warnings, options);
|
|
4339
2647
|
return {
|
|
4340
2648
|
isValid: errors.length === 0,
|
|
4341
2649
|
errors,
|
|
@@ -4469,12 +2777,12 @@ class ConfigValidator {
|
|
|
4469
2777
|
}
|
|
4470
2778
|
}
|
|
4471
2779
|
}
|
|
4472
|
-
validateWithRules(
|
|
2780
|
+
validateWithRules(config2, rules, options) {
|
|
4473
2781
|
const errors = [];
|
|
4474
2782
|
const warnings = [];
|
|
4475
2783
|
for (const rule of rules) {
|
|
4476
2784
|
try {
|
|
4477
|
-
const value = this.getValueByPath(
|
|
2785
|
+
const value = this.getValueByPath(config2, rule.path);
|
|
4478
2786
|
const ruleErrors = this.validateWithRule(value, rule, rule.path);
|
|
4479
2787
|
errors.push(...ruleErrors);
|
|
4480
2788
|
if (options.stopOnFirstError && errors.length > 0) {
|
|
@@ -4639,9 +2947,22 @@ class ConfigValidator {
|
|
|
4639
2947
|
};
|
|
4640
2948
|
}
|
|
4641
2949
|
}
|
|
4642
|
-
var
|
|
4643
|
-
|
|
2950
|
+
var URL_PATTERN;
|
|
2951
|
+
var init_validator = __esm(() => {
|
|
2952
|
+
init_cache();
|
|
2953
|
+
init_errors();
|
|
2954
|
+
URL_PATTERN = /^https?:\/\//;
|
|
4644
2955
|
});
|
|
2956
|
+
function formatAliasSuffix(alias) {
|
|
2957
|
+
if (!alias)
|
|
2958
|
+
return "";
|
|
2959
|
+
const list = Array.isArray(alias) ? alias.filter(Boolean) : [alias];
|
|
2960
|
+
if (list.length === 0)
|
|
2961
|
+
return "";
|
|
2962
|
+
if (list.length === 1)
|
|
2963
|
+
return ` or alias "${list[0]}"`;
|
|
2964
|
+
return ` or aliases ${list.map((a) => `"${a}"`).join(", ")}`;
|
|
2965
|
+
}
|
|
4645
2966
|
|
|
4646
2967
|
class ConfigLoader {
|
|
4647
2968
|
fileLoader = new ConfigFileLoader;
|
|
@@ -4724,14 +3045,14 @@ class ConfigLoader {
|
|
|
4724
3045
|
performance2.onMetrics(metrics);
|
|
4725
3046
|
}
|
|
4726
3047
|
if (performance2.slowThreshold && metrics.duration > performance2.slowThreshold) {
|
|
4727
|
-
|
|
3048
|
+
log.warn(`Slow configuration loading detected: ${metrics.duration}ms for ${baseOptions.name}`);
|
|
4728
3049
|
}
|
|
4729
3050
|
result.metrics = metrics;
|
|
4730
3051
|
}
|
|
4731
3052
|
return result;
|
|
4732
3053
|
} catch (error) {
|
|
4733
3054
|
const duration = Date.now() - startTime;
|
|
4734
|
-
|
|
3055
|
+
log.error(`Configuration loading failed after ${duration}ms:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4735
3056
|
throw error;
|
|
4736
3057
|
}
|
|
4737
3058
|
}
|
|
@@ -4741,44 +3062,44 @@ class ConfigLoader {
|
|
|
4741
3062
|
alias,
|
|
4742
3063
|
cwd,
|
|
4743
3064
|
configDir,
|
|
4744
|
-
defaultConfig:
|
|
3065
|
+
defaultConfig: defaultConfig2,
|
|
4745
3066
|
checkEnv = true,
|
|
4746
3067
|
arrayStrategy = "replace",
|
|
4747
3068
|
verbose = false
|
|
4748
3069
|
} = options;
|
|
4749
|
-
const baseDir = cwd ||
|
|
3070
|
+
const baseDir = cwd || process7.cwd();
|
|
4750
3071
|
const searchPaths = [];
|
|
4751
|
-
const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir,
|
|
3072
|
+
const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig2, arrayStrategy, verbose, checkEnv, cacheOptions);
|
|
4752
3073
|
if (localResult) {
|
|
4753
3074
|
searchPaths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
|
|
4754
3075
|
return this.finalizeResult(localResult, searchPaths, checkEnv, name, verbose);
|
|
4755
3076
|
}
|
|
4756
|
-
const homeResult = await this.loadHomeConfiguration(name, alias,
|
|
3077
|
+
const homeResult = await this.loadHomeConfiguration(name, alias, defaultConfig2, arrayStrategy, verbose, checkEnv);
|
|
4757
3078
|
if (homeResult) {
|
|
4758
3079
|
searchPaths.push(...this.getHomeSearchPaths(name, alias));
|
|
4759
3080
|
return this.finalizeResult(homeResult, searchPaths, checkEnv, name, verbose);
|
|
4760
3081
|
}
|
|
4761
|
-
const packageResult = await this.loadPackageJsonConfiguration(name, alias, baseDir,
|
|
3082
|
+
const packageResult = await this.loadPackageJsonConfiguration(name, alias, baseDir, defaultConfig2, arrayStrategy, verbose, checkEnv);
|
|
4762
3083
|
if (packageResult) {
|
|
4763
|
-
searchPaths.push(
|
|
3084
|
+
searchPaths.push(resolve5(baseDir, "package.json"));
|
|
4764
3085
|
return this.finalizeResult(packageResult, searchPaths, checkEnv, name, verbose);
|
|
4765
3086
|
}
|
|
4766
3087
|
searchPaths.push(...this.getAllSearchPaths(name, alias, baseDir, configDir));
|
|
4767
3088
|
if (throwOnNotFound) {
|
|
4768
3089
|
throw ErrorFactory.configNotFound(name, searchPaths, alias);
|
|
4769
3090
|
}
|
|
4770
|
-
const envResult = await this.applyEnvironmentVariables(name,
|
|
3091
|
+
const envResult = await this.applyEnvironmentVariables(name, defaultConfig2, checkEnv, verbose);
|
|
4771
3092
|
return {
|
|
4772
3093
|
...envResult,
|
|
4773
|
-
warnings: [`No configuration file found for "${name}"${alias
|
|
3094
|
+
warnings: [`No configuration file found for "${name}"${formatAliasSuffix(alias)}, using defaults with environment variables`]
|
|
4774
3095
|
};
|
|
4775
3096
|
}
|
|
4776
|
-
async loadLocalConfiguration(name, alias, baseDir, configDir,
|
|
4777
|
-
const envDefaultConfig = checkEnv ?
|
|
3097
|
+
async loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig2, arrayStrategy, verbose, checkEnv, cacheOptions) {
|
|
3098
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4778
3099
|
const searchDirectories = this.getLocalDirectories(baseDir, configDir);
|
|
4779
3100
|
for (const directory of searchDirectories) {
|
|
4780
3101
|
if (verbose) {
|
|
4781
|
-
|
|
3102
|
+
log.info(`Searching for configuration in: ${directory}`);
|
|
4782
3103
|
}
|
|
4783
3104
|
const configPaths = this.fileLoader.generateConfigPaths(name, directory, alias);
|
|
4784
3105
|
const result = await this.fileLoader.tryLoadFromPaths(configPaths, envDefaultConfig, {
|
|
@@ -4789,56 +3110,72 @@ class ConfigLoader {
|
|
|
4789
3110
|
});
|
|
4790
3111
|
if (result) {
|
|
4791
3112
|
if (verbose) {
|
|
4792
|
-
|
|
3113
|
+
log.success(`Configuration loaded from: ${result.source.path}`);
|
|
4793
3114
|
}
|
|
4794
3115
|
return result;
|
|
4795
3116
|
}
|
|
4796
3117
|
}
|
|
4797
3118
|
return null;
|
|
4798
3119
|
}
|
|
4799
|
-
async loadHomeConfiguration(name, alias,
|
|
3120
|
+
async loadHomeConfiguration(name, alias, defaultConfig2, arrayStrategy, verbose, checkEnv) {
|
|
4800
3121
|
if (!name)
|
|
4801
3122
|
return null;
|
|
4802
|
-
const envDefaultConfig = checkEnv ?
|
|
3123
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4803
3124
|
const homeDirectories = [
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
3125
|
+
resolve5(homedir(), ".config", name),
|
|
3126
|
+
resolve5(homedir(), ".config"),
|
|
3127
|
+
homedir()
|
|
4807
3128
|
];
|
|
4808
3129
|
for (const directory of homeDirectories) {
|
|
4809
3130
|
if (verbose) {
|
|
4810
|
-
|
|
3131
|
+
log.info(`Checking home directory: ${directory}`);
|
|
4811
3132
|
}
|
|
4812
3133
|
const configPaths = this.fileLoader.generateConfigPaths(name, directory, alias);
|
|
4813
3134
|
const result = await this.fileLoader.tryLoadFromPaths(configPaths, envDefaultConfig, { arrayStrategy, verbose });
|
|
4814
3135
|
if (result) {
|
|
4815
3136
|
if (verbose) {
|
|
4816
|
-
|
|
3137
|
+
log.success(`Configuration loaded from home directory: ${result.source.path}`);
|
|
4817
3138
|
}
|
|
4818
3139
|
return result;
|
|
4819
3140
|
}
|
|
4820
3141
|
}
|
|
4821
3142
|
return null;
|
|
4822
3143
|
}
|
|
4823
|
-
async loadPackageJsonConfiguration(name, alias, baseDir,
|
|
4824
|
-
const envDefaultConfig = checkEnv ?
|
|
3144
|
+
async loadPackageJsonConfiguration(name, alias, baseDir, defaultConfig2, arrayStrategy, verbose, checkEnv) {
|
|
3145
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4825
3146
|
try {
|
|
4826
|
-
const pkgPath =
|
|
4827
|
-
if (!
|
|
3147
|
+
const pkgPath = resolve5(baseDir, "package.json");
|
|
3148
|
+
if (!existsSync5(pkgPath)) {
|
|
3149
|
+
return null;
|
|
3150
|
+
}
|
|
3151
|
+
let pkg = {};
|
|
3152
|
+
try {
|
|
3153
|
+
pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
3154
|
+
} catch (parseError) {
|
|
3155
|
+
if (verbose) {
|
|
3156
|
+
log.warn(`Failed to parse package.json:`, [parseError instanceof Error ? parseError : new Error(String(parseError))]);
|
|
3157
|
+
}
|
|
4828
3158
|
return null;
|
|
4829
3159
|
}
|
|
4830
|
-
const pkg = await import(pkgPath);
|
|
4831
3160
|
let pkgConfig = pkg[name];
|
|
4832
3161
|
let usedName = name;
|
|
4833
3162
|
if (!pkgConfig && alias) {
|
|
4834
|
-
|
|
4835
|
-
|
|
3163
|
+
const aliases = Array.isArray(alias) ? alias : [alias];
|
|
3164
|
+
for (const a of aliases) {
|
|
3165
|
+
if (!a)
|
|
3166
|
+
continue;
|
|
3167
|
+
if (pkg[a]) {
|
|
3168
|
+
pkgConfig = pkg[a];
|
|
3169
|
+
usedName = a;
|
|
3170
|
+
break;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
4836
3173
|
}
|
|
4837
3174
|
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
4838
3175
|
if (verbose) {
|
|
4839
|
-
|
|
3176
|
+
log.success(`Configuration loaded from package.json: ${usedName}`);
|
|
4840
3177
|
}
|
|
4841
|
-
const mergedConfig =
|
|
3178
|
+
const mergedConfig = deepMergeWithArrayStrategy(envDefaultConfig, pkgConfig, arrayStrategy);
|
|
4842
3179
|
return {
|
|
4843
3180
|
config: mergedConfig,
|
|
4844
3181
|
source: {
|
|
@@ -4851,15 +3188,15 @@ class ConfigLoader {
|
|
|
4851
3188
|
}
|
|
4852
3189
|
} catch (error) {
|
|
4853
3190
|
if (verbose) {
|
|
4854
|
-
|
|
3191
|
+
log.warn(`Failed to load package.json:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4855
3192
|
}
|
|
4856
3193
|
}
|
|
4857
3194
|
return null;
|
|
4858
3195
|
}
|
|
4859
|
-
async applyEnvironmentVariables(name,
|
|
4860
|
-
if (!checkEnv || !name || typeof
|
|
3196
|
+
async applyEnvironmentVariables(name, config2, checkEnv, verbose) {
|
|
3197
|
+
if (!checkEnv || !name || typeof config2 !== "object" || config2 === null || Array.isArray(config2)) {
|
|
4861
3198
|
return {
|
|
4862
|
-
config:
|
|
3199
|
+
config: config2,
|
|
4863
3200
|
source: {
|
|
4864
3201
|
type: "default",
|
|
4865
3202
|
priority: 10,
|
|
@@ -4867,7 +3204,7 @@ class ConfigLoader {
|
|
|
4867
3204
|
}
|
|
4868
3205
|
};
|
|
4869
3206
|
}
|
|
4870
|
-
const processedConfig =
|
|
3207
|
+
const processedConfig = applyEnvVarsToConfig(name, config2, verbose);
|
|
4871
3208
|
return {
|
|
4872
3209
|
config: processedConfig,
|
|
4873
3210
|
source: {
|
|
@@ -4884,16 +3221,16 @@ class ConfigLoader {
|
|
|
4884
3221
|
path: result.source.path
|
|
4885
3222
|
};
|
|
4886
3223
|
}
|
|
4887
|
-
async validateConfiguration(
|
|
3224
|
+
async validateConfiguration(config2, schema, customValidator, configName) {
|
|
4888
3225
|
const errors = [];
|
|
4889
3226
|
if (customValidator) {
|
|
4890
|
-
const customErrors = customValidator(
|
|
3227
|
+
const customErrors = customValidator(config2);
|
|
4891
3228
|
if (customErrors) {
|
|
4892
3229
|
errors.push(...customErrors);
|
|
4893
3230
|
}
|
|
4894
3231
|
}
|
|
4895
3232
|
if (schema) {
|
|
4896
|
-
const validationResult = await this.validator.validateConfiguration(
|
|
3233
|
+
const validationResult = await this.validator.validateConfiguration(config2, schema);
|
|
4897
3234
|
if (!validationResult.isValid) {
|
|
4898
3235
|
errors.push(...validationResult.errors.map((e) => e.path ? `${e.path}: ${e.message}` : e.message));
|
|
4899
3236
|
}
|
|
@@ -4913,8 +3250,10 @@ class ConfigLoader {
|
|
|
4913
3250
|
}
|
|
4914
3251
|
generateCacheKey(configName, options) {
|
|
4915
3252
|
const keyParts = [configName];
|
|
4916
|
-
if (options.alias)
|
|
4917
|
-
|
|
3253
|
+
if (options.alias) {
|
|
3254
|
+
const aliasKey = Array.isArray(options.alias) ? options.alias.join(",") : options.alias;
|
|
3255
|
+
keyParts.push(`alias:${aliasKey}`);
|
|
3256
|
+
}
|
|
4918
3257
|
if (options.cwd)
|
|
4919
3258
|
keyParts.push(`cwd:${options.cwd}`);
|
|
4920
3259
|
if (options.configDir)
|
|
@@ -4926,16 +3265,16 @@ class ConfigLoader {
|
|
|
4926
3265
|
getLocalDirectories(baseDir, configDir) {
|
|
4927
3266
|
return Array.from(new Set([
|
|
4928
3267
|
baseDir,
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
configDir ?
|
|
3268
|
+
resolve5(baseDir, "config"),
|
|
3269
|
+
resolve5(baseDir, ".config"),
|
|
3270
|
+
configDir ? resolve5(baseDir, configDir) : undefined
|
|
4932
3271
|
].filter(Boolean)));
|
|
4933
3272
|
}
|
|
4934
3273
|
getAllSearchPaths(name, alias, baseDir, configDir) {
|
|
4935
3274
|
const paths = [];
|
|
4936
3275
|
paths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
|
|
4937
3276
|
paths.push(...this.getHomeSearchPaths(name, alias));
|
|
4938
|
-
paths.push(
|
|
3277
|
+
paths.push(resolve5(baseDir, "package.json"));
|
|
4939
3278
|
return paths;
|
|
4940
3279
|
}
|
|
4941
3280
|
getLocalSearchPaths(name, alias, baseDir, configDir) {
|
|
@@ -4950,9 +3289,9 @@ class ConfigLoader {
|
|
|
4950
3289
|
if (!name)
|
|
4951
3290
|
return [];
|
|
4952
3291
|
const homeDirectories = [
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
3292
|
+
resolve5(homedir(), ".config", name),
|
|
3293
|
+
resolve5(homedir(), ".config"),
|
|
3294
|
+
homedir()
|
|
4956
3295
|
];
|
|
4957
3296
|
const paths = [];
|
|
4958
3297
|
for (const directory of homeDirectories) {
|
|
@@ -4964,9 +3303,20 @@ class ConfigLoader {
|
|
|
4964
3303
|
return this.loadConfig(options);
|
|
4965
3304
|
}
|
|
4966
3305
|
}
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
const
|
|
3306
|
+
function shouldHandleConfigLoadErrorGracefully(error) {
|
|
3307
|
+
const isPermissionError = error.message.includes("EACCES") || error.message.includes("EPERM") || error.message.includes("permission denied");
|
|
3308
|
+
const isSyntaxError = !isPermissionError && (error.message.includes("syntax") || error.message.includes("Expected") || error.message.includes("Unexpected") || error.message.includes("BuildMessage"));
|
|
3309
|
+
const isStructureError = error.message.includes("Configuration must export a valid object") || error.message.includes("Configuration file is empty and exports nothing");
|
|
3310
|
+
return isSyntaxError || isStructureError;
|
|
3311
|
+
}
|
|
3312
|
+
async function loadConfigWithResult(options) {
|
|
3313
|
+
return globalConfigLoader.loadConfig({
|
|
3314
|
+
...options,
|
|
3315
|
+
__strictErrorHandling: true
|
|
3316
|
+
});
|
|
3317
|
+
}
|
|
3318
|
+
async function loadConfig(options) {
|
|
3319
|
+
const defaultConfig2 = "defaultConfig" in options && options.defaultConfig !== undefined ? options.defaultConfig : {};
|
|
4970
3320
|
const isEnhanced = "cache" in options || "performance" in options || "schema" in options || "validate" in options;
|
|
4971
3321
|
try {
|
|
4972
3322
|
let result;
|
|
@@ -4975,34 +3325,85 @@ async function loadConfig5(options) {
|
|
|
4975
3325
|
} else {
|
|
4976
3326
|
result = await globalConfigLoader.loadConfig({
|
|
4977
3327
|
...options,
|
|
4978
|
-
defaultConfig:
|
|
3328
|
+
defaultConfig: defaultConfig2,
|
|
4979
3329
|
cache: { enabled: true },
|
|
4980
3330
|
performance: { enabled: false }
|
|
4981
3331
|
});
|
|
4982
3332
|
}
|
|
4983
|
-
return result?.config ??
|
|
3333
|
+
return result?.config ?? defaultConfig2;
|
|
4984
3334
|
} catch (error) {
|
|
4985
3335
|
const errorName = error instanceof Error ? error.name : "UnknownError";
|
|
4986
3336
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4987
3337
|
const isConfigError = errorName === "ConfigNotFoundError" || errorName === "ConfigLoadError" || errorName === "ConfigValidationError" || errorMessage.includes("config");
|
|
4988
3338
|
if (!isConfigError && options.verbose) {
|
|
4989
|
-
|
|
3339
|
+
log.warn(`Unexpected error loading config, using defaults:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4990
3340
|
}
|
|
4991
|
-
const configOptions = isEnhanced ? { ...options, defaultConfig:
|
|
3341
|
+
const configOptions = isEnhanced ? { ...options, defaultConfig: defaultConfig2 } : {
|
|
4992
3342
|
...options,
|
|
4993
|
-
defaultConfig:
|
|
3343
|
+
defaultConfig: defaultConfig2,
|
|
4994
3344
|
cache: { enabled: true },
|
|
4995
3345
|
performance: { enabled: false }
|
|
4996
3346
|
};
|
|
4997
3347
|
const shouldCheckEnv = "checkEnv" in options ? options.checkEnv !== false : true;
|
|
4998
3348
|
if (shouldCheckEnv) {
|
|
4999
|
-
const envResult = await globalConfigLoader.applyEnvironmentVariables(configOptions.name || "",
|
|
5000
|
-
return envResult?.config ??
|
|
3349
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(configOptions.name || "", defaultConfig2, true, configOptions.verbose || false);
|
|
3350
|
+
return envResult?.config ?? defaultConfig2;
|
|
3351
|
+
}
|
|
3352
|
+
return defaultConfig2;
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
async function config2(nameOrOptions = { defaultConfig: {} }) {
|
|
3356
|
+
if (typeof nameOrOptions === "string") {
|
|
3357
|
+
const { cwd } = await import("process");
|
|
3358
|
+
try {
|
|
3359
|
+
const result = await globalConfigLoader.loadConfig({
|
|
3360
|
+
name: nameOrOptions,
|
|
3361
|
+
cwd: cwd(),
|
|
3362
|
+
generatedDir: "./generated",
|
|
3363
|
+
configDir: "./config",
|
|
3364
|
+
defaultConfig: {},
|
|
3365
|
+
checkEnv: true,
|
|
3366
|
+
arrayStrategy: "replace"
|
|
3367
|
+
});
|
|
3368
|
+
return result.config;
|
|
3369
|
+
} catch (error) {
|
|
3370
|
+
if (error instanceof Error && (error.name === "ConfigNotFoundError" || error.name === "ConfigLoadError" && shouldHandleConfigLoadErrorGracefully(error))) {
|
|
3371
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(nameOrOptions, {}, true, false);
|
|
3372
|
+
return envResult.config;
|
|
3373
|
+
}
|
|
3374
|
+
throw error;
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
try {
|
|
3378
|
+
const result = await globalConfigLoader.loadConfig({
|
|
3379
|
+
...nameOrOptions,
|
|
3380
|
+
cwd: nameOrOptions.cwd || process7.cwd(),
|
|
3381
|
+
cache: { enabled: true },
|
|
3382
|
+
performance: { enabled: false }
|
|
3383
|
+
});
|
|
3384
|
+
return result.config;
|
|
3385
|
+
} catch (error) {
|
|
3386
|
+
if (error instanceof Error && (error.name === "ConfigNotFoundError" || error.name === "ConfigLoadError" && shouldHandleConfigLoadErrorGracefully(error))) {
|
|
3387
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(nameOrOptions.name || "", nameOrOptions.defaultConfig || {}, nameOrOptions.checkEnv !== false, nameOrOptions.verbose || false);
|
|
3388
|
+
return envResult.config;
|
|
5001
3389
|
}
|
|
5002
|
-
|
|
3390
|
+
throw error;
|
|
5003
3391
|
}
|
|
5004
3392
|
}
|
|
5005
|
-
function
|
|
3393
|
+
async function tryLoadConfig(configPath, defaultConfig2, arrayStrategy = "replace") {
|
|
3394
|
+
const fileLoader = new ConfigFileLoader;
|
|
3395
|
+
try {
|
|
3396
|
+
const result = await fileLoader.loadFromPath(configPath, defaultConfig2, {
|
|
3397
|
+
arrayStrategy,
|
|
3398
|
+
useCache: false,
|
|
3399
|
+
trackPerformance: false
|
|
3400
|
+
});
|
|
3401
|
+
return result ? result.config : null;
|
|
3402
|
+
} catch {
|
|
3403
|
+
return null;
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
function applyEnvVarsToConfig(name, config3, verbose = false) {
|
|
5006
3407
|
const _envProcessor = new EnvProcessor;
|
|
5007
3408
|
const envPrefix = name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
5008
3409
|
function processConfigLevel(obj, path = []) {
|
|
@@ -5017,7 +3418,7 @@ function applyEnvVarsToConfig2(name, config4, verbose = false) {
|
|
|
5017
3418
|
let envValue;
|
|
5018
3419
|
let usedKey;
|
|
5019
3420
|
for (const envKey of envKeys) {
|
|
5020
|
-
envValue =
|
|
3421
|
+
envValue = process7.env[envKey];
|
|
5021
3422
|
if (envValue !== undefined) {
|
|
5022
3423
|
usedKey = envKey;
|
|
5023
3424
|
break;
|
|
@@ -5047,29 +3448,218 @@ function applyEnvVarsToConfig2(name, config4, verbose = false) {
|
|
|
5047
3448
|
}
|
|
5048
3449
|
return result;
|
|
5049
3450
|
}
|
|
5050
|
-
return processConfigLevel(
|
|
3451
|
+
return processConfigLevel(config3);
|
|
3452
|
+
}
|
|
3453
|
+
function generateConfigTypes(options) {
|
|
3454
|
+
const configDir = resolve5(process7.cwd(), options.configDir);
|
|
3455
|
+
const generatedDir = resolve5(process7.cwd(), options.generatedDir);
|
|
3456
|
+
const outputFile = resolve5(generatedDir, "config-types.ts");
|
|
3457
|
+
if (!existsSync5(dirname(outputFile)))
|
|
3458
|
+
mkdirSync(dirname(outputFile), { recursive: true, mode: 511 });
|
|
3459
|
+
const files = existsSync5(configDir) ? readdirSync(configDir).map((file) => file.replace(/\.(ts|js|mjs|cjs|mts|cts|json)$/, "")).sort() : [];
|
|
3460
|
+
const content = `// Generated by bunfig v${version}
|
|
3461
|
+
export type ConfigNames = ${files.length ? `'${files.join("' | '")}'` : "string"}
|
|
3462
|
+
`;
|
|
3463
|
+
writeFileSync2(outputFile, content, { mode: 438 });
|
|
3464
|
+
}
|
|
3465
|
+
function createLibraryConfig(options) {
|
|
3466
|
+
let configCache = null;
|
|
3467
|
+
let loadPromise = null;
|
|
3468
|
+
const startLoading = () => {
|
|
3469
|
+
if (!loadPromise) {
|
|
3470
|
+
loadPromise = loadConfig(options).then((loadedConfig) => {
|
|
3471
|
+
configCache = loadedConfig;
|
|
3472
|
+
return loadedConfig;
|
|
3473
|
+
}, (error) => {
|
|
3474
|
+
const defaultConfig3 = "defaultConfig" in options ? options.defaultConfig : {};
|
|
3475
|
+
configCache = defaultConfig3;
|
|
3476
|
+
const verbose = "verbose" in options && options.verbose;
|
|
3477
|
+
if (verbose) {
|
|
3478
|
+
log.warn(`Config loading failed, using defaults:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
3479
|
+
}
|
|
3480
|
+
return defaultConfig3;
|
|
3481
|
+
});
|
|
3482
|
+
}
|
|
3483
|
+
return loadPromise;
|
|
3484
|
+
};
|
|
3485
|
+
const defaultConfig2 = "defaultConfig" in options ? options.defaultConfig : {};
|
|
3486
|
+
configCache = defaultConfig2;
|
|
3487
|
+
startLoading();
|
|
3488
|
+
return new Proxy({}, {
|
|
3489
|
+
get(target, prop) {
|
|
3490
|
+
if (configCache) {
|
|
3491
|
+
return configCache[prop];
|
|
3492
|
+
}
|
|
3493
|
+
const value = defaultConfig2[prop];
|
|
3494
|
+
startLoading();
|
|
3495
|
+
return value;
|
|
3496
|
+
},
|
|
3497
|
+
has(target, prop) {
|
|
3498
|
+
return prop in (configCache || defaultConfig2);
|
|
3499
|
+
},
|
|
3500
|
+
ownKeys() {
|
|
3501
|
+
return Object.keys(configCache || defaultConfig2);
|
|
3502
|
+
},
|
|
3503
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
3504
|
+
return Object.getOwnPropertyDescriptor(configCache || defaultConfig2, prop);
|
|
3505
|
+
},
|
|
3506
|
+
set(target, prop, value) {
|
|
3507
|
+
if (!configCache) {
|
|
3508
|
+
configCache = { ...defaultConfig2 };
|
|
3509
|
+
}
|
|
3510
|
+
configCache[prop] = value;
|
|
3511
|
+
return true;
|
|
3512
|
+
}
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
var log;
|
|
3516
|
+
var globalConfigLoader;
|
|
3517
|
+
var defaultConfigDir;
|
|
3518
|
+
var defaultGeneratedDir;
|
|
3519
|
+
var init_config = __esm(() => {
|
|
3520
|
+
init_src();
|
|
3521
|
+
init_package();
|
|
3522
|
+
init_cache();
|
|
3523
|
+
init_errors();
|
|
3524
|
+
init_env_processor();
|
|
3525
|
+
init_file_loader();
|
|
3526
|
+
init_validator();
|
|
3527
|
+
init_utils();
|
|
3528
|
+
log = new Logger("bunfig", {
|
|
3529
|
+
showTags: true
|
|
3530
|
+
});
|
|
3531
|
+
globalConfigLoader = new ConfigLoader;
|
|
3532
|
+
defaultConfigDir = resolve5(process7.cwd(), "config");
|
|
3533
|
+
defaultGeneratedDir = resolve5(process7.cwd(), "src/generated");
|
|
3534
|
+
});
|
|
3535
|
+
function bunfigPlugin(options) {
|
|
3536
|
+
const configDir = resolve6(process8.cwd(), options?.configDir || "./config");
|
|
3537
|
+
function readConfigSelection() {
|
|
3538
|
+
if (!existsSync6(configDir))
|
|
3539
|
+
return [];
|
|
3540
|
+
const allowed = new Set([".ts", ".js", ".mjs", ".cjs", ".mts", ".cts", ".json"]);
|
|
3541
|
+
const priority = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs", ".json"];
|
|
3542
|
+
const entries = readdirSync2(configDir).filter((file) => allowed.has(extname(file))).map((file) => ({ base: file.replace(/\.(?:ts|js|mjs|cjs|mts|cts|json)$/i, ""), file }));
|
|
3543
|
+
const bestByBase = new Map;
|
|
3544
|
+
for (const { base, file } of entries) {
|
|
3545
|
+
const ext = extname(file).toLowerCase();
|
|
3546
|
+
const current = bestByBase.get(base);
|
|
3547
|
+
if (!current) {
|
|
3548
|
+
bestByBase.set(base, file);
|
|
3549
|
+
continue;
|
|
3550
|
+
}
|
|
3551
|
+
const currExt = extname(current).toLowerCase();
|
|
3552
|
+
if (priority.indexOf(ext) < priority.indexOf(currExt)) {
|
|
3553
|
+
bestByBase.set(base, file);
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
return Array.from(bestByBase.entries()).map(([base, file]) => ({ base, file })).sort((a, b) => a.base.localeCompare(b.base));
|
|
3557
|
+
}
|
|
3558
|
+
function generateModuleSource() {
|
|
3559
|
+
const selections = readConfigSelection();
|
|
3560
|
+
const names = selections.map((s) => s.base);
|
|
3561
|
+
const union = names.length ? names.map((n) => `'${n}'`).join(" | ") : "string";
|
|
3562
|
+
const byName = selections.length ? `{
|
|
3563
|
+
${selections.map((sel) => {
|
|
3564
|
+
const abs = resolve6(configDir, sel.file).replace(/\\/g, "/");
|
|
3565
|
+
return ` '${sel.base}': typeof import('${abs}').default`;
|
|
3566
|
+
}).join(`,
|
|
3567
|
+
`)}
|
|
3568
|
+
}` : "Record<string, any>";
|
|
3569
|
+
const source = `export type ConfigNames = ${union}
|
|
3570
|
+
export type ConfigByName = ${byName}
|
|
3571
|
+
export type Config<N extends ConfigNames> = N extends keyof ConfigByName ? ConfigByName[N] : unknown
|
|
3572
|
+
export type ConfigOf = Config
|
|
3573
|
+
`;
|
|
3574
|
+
return source;
|
|
3575
|
+
}
|
|
3576
|
+
return {
|
|
3577
|
+
name: "bunfig-plugin",
|
|
3578
|
+
setup(builder) {
|
|
3579
|
+
builder.onResolve({ filter: /^virtual:bunfig-types$/ }, (args) => {
|
|
3580
|
+
return { path: args.path, namespace: "bunfig-virtual" };
|
|
3581
|
+
});
|
|
3582
|
+
builder.onLoad({ filter: /^virtual:bunfig-types$/, namespace: "bunfig-virtual" }, () => {
|
|
3583
|
+
const contents = generateModuleSource();
|
|
3584
|
+
return { contents, loader: "ts" };
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
};
|
|
5051
3588
|
}
|
|
5052
|
-
var
|
|
5053
|
-
var
|
|
3589
|
+
var init_plugin = () => {};
|
|
3590
|
+
var exports_src = {};
|
|
3591
|
+
__export(exports_src, {
|
|
3592
|
+
withErrorRecovery: () => withErrorRecovery,
|
|
3593
|
+
tryLoadConfig: () => tryLoadConfig,
|
|
3594
|
+
loadConfigWithResult: () => loadConfigWithResult,
|
|
3595
|
+
loadConfig: () => loadConfig,
|
|
3596
|
+
isRetryableError: () => isRetryableError,
|
|
3597
|
+
isConfigNotFoundError: () => isConfigNotFoundError,
|
|
3598
|
+
isBunfigError: () => isBunfigError,
|
|
3599
|
+
globalPerformanceMonitor: () => globalPerformanceMonitor,
|
|
3600
|
+
globalCache: () => globalCache,
|
|
3601
|
+
getEnvOrDefault: () => getEnvOrDefault,
|
|
3602
|
+
generateConfigTypes: () => generateConfigTypes,
|
|
3603
|
+
defaultGeneratedDir: () => defaultGeneratedDir,
|
|
3604
|
+
defaultConfigDir: () => defaultConfigDir,
|
|
3605
|
+
deepMergeWithArrayStrategy: () => deepMergeWithArrayStrategy,
|
|
3606
|
+
deepMerge: () => deepMerge,
|
|
3607
|
+
createLibraryConfig: () => createLibraryConfig,
|
|
3608
|
+
config: () => config2,
|
|
3609
|
+
bunfigPlugin: () => bunfigPlugin,
|
|
3610
|
+
applyEnvVarsToConfig: () => applyEnvVarsToConfig,
|
|
3611
|
+
TypeGenerationError: () => TypeGenerationError,
|
|
3612
|
+
SchemaValidationError: () => SchemaValidationError,
|
|
3613
|
+
PluginError: () => PluginError,
|
|
3614
|
+
PerformanceMonitor: () => PerformanceMonitor,
|
|
3615
|
+
FileSystemError: () => FileSystemError,
|
|
3616
|
+
ErrorFactory: () => ErrorFactory,
|
|
3617
|
+
EnvVarError: () => EnvVarError,
|
|
3618
|
+
EnvProcessor: () => EnvProcessor,
|
|
3619
|
+
ConfigValidator: () => ConfigValidator,
|
|
3620
|
+
ConfigValidationError: () => ConfigValidationError,
|
|
3621
|
+
ConfigNotFoundError: () => ConfigNotFoundError,
|
|
3622
|
+
ConfigMergeError: () => ConfigMergeError,
|
|
3623
|
+
ConfigLoader: () => ConfigLoader,
|
|
3624
|
+
ConfigLoadError: () => ConfigLoadError,
|
|
3625
|
+
ConfigFileLoader: () => ConfigFileLoader,
|
|
3626
|
+
ConfigCache: () => ConfigCache,
|
|
3627
|
+
CacheUtils: () => CacheUtils,
|
|
3628
|
+
BunfigError: () => BunfigError,
|
|
3629
|
+
BrowserConfigError: () => BrowserConfigError,
|
|
3630
|
+
ArrayMergeStrategies: () => ArrayMergeStrategies
|
|
3631
|
+
});
|
|
3632
|
+
var init_src2 = __esm(() => {
|
|
3633
|
+
init_config();
|
|
3634
|
+
init_errors();
|
|
3635
|
+
init_cache();
|
|
3636
|
+
init_errors();
|
|
3637
|
+
init_plugin();
|
|
3638
|
+
init_env_processor();
|
|
3639
|
+
init_file_loader();
|
|
3640
|
+
init_validator();
|
|
3641
|
+
init_utils();
|
|
3642
|
+
});
|
|
3643
|
+
init_src2();
|
|
5054
3644
|
|
|
5055
3645
|
// src/config.ts
|
|
5056
|
-
var
|
|
3646
|
+
var defaultConfig2 = {
|
|
5057
3647
|
verbose: true
|
|
5058
3648
|
};
|
|
5059
3649
|
var _config = null;
|
|
5060
3650
|
async function getConfig() {
|
|
5061
3651
|
if (!_config) {
|
|
5062
|
-
_config = await
|
|
3652
|
+
_config = await loadConfig({
|
|
5063
3653
|
name: "development",
|
|
5064
3654
|
alias: "dx",
|
|
5065
|
-
defaultConfig:
|
|
3655
|
+
defaultConfig: defaultConfig2
|
|
5066
3656
|
});
|
|
5067
3657
|
}
|
|
5068
3658
|
return _config;
|
|
5069
3659
|
}
|
|
5070
|
-
var config3 =
|
|
3660
|
+
var config3 = defaultConfig2;
|
|
5071
3661
|
export {
|
|
5072
3662
|
getConfig,
|
|
5073
|
-
|
|
3663
|
+
defaultConfig2 as defaultConfig,
|
|
5074
3664
|
config3 as config
|
|
5075
3665
|
};
|