bun-plugin-stx 0.2.20 → 0.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/serve.d.ts +1 -0
- package/dist/serve.js +1158 -2506
- package/dist/watch.d.ts +4 -0
- package/package.json +2 -2
package/dist/serve.js
CHANGED
|
@@ -6,49 +6,53 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// src/serve.ts
|
|
8
8
|
var {serve: bunServe, Glob } = globalThis.Bun;
|
|
9
|
-
import
|
|
9
|
+
import { watch as fsWatch } from "fs";
|
|
10
|
+
import nodeFs from "fs/promises";
|
|
11
|
+
import nodePath from "path";
|
|
12
|
+
import process6 from "process";
|
|
10
13
|
|
|
11
14
|
// ../../node_modules/bunfig/dist/index.js
|
|
12
15
|
import { existsSync, statSync } from "fs";
|
|
13
|
-
import {
|
|
14
|
-
import { homedir as homedir2 } from "os";
|
|
15
|
-
import { dirname as dirname3, resolve as resolve7 } from "path";
|
|
16
|
-
import process12 from "process";
|
|
17
|
-
import { join as join3, relative as relative2, resolve as resolve4 } from "path";
|
|
18
|
-
import process7 from "process";
|
|
19
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
20
|
-
import { homedir } from "os";
|
|
21
|
-
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
22
|
-
import process6 from "process";
|
|
23
|
-
import { join, relative, resolve as resolve2 } from "path";
|
|
24
|
-
import process2 from "process";
|
|
25
|
-
import { existsSync as existsSync2, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
26
|
-
import { dirname, resolve } from "path";
|
|
16
|
+
import { join, relative, resolve } from "path";
|
|
27
17
|
import process from "process";
|
|
28
18
|
import { Buffer } from "buffer";
|
|
29
19
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
30
|
-
import { closeSync, createReadStream, createWriteStream, existsSync as
|
|
20
|
+
import { closeSync, createReadStream, createWriteStream, existsSync as existsSync2, fsyncSync, openSync, writeFileSync } from "fs";
|
|
31
21
|
import { access, constants, mkdir, readdir, rename, stat, unlink, writeFile } from "fs/promises";
|
|
32
|
-
import { join as join2 } from "path";
|
|
33
|
-
import
|
|
22
|
+
import { isAbsolute, join as join2, resolve as resolve2 } from "path";
|
|
23
|
+
import process4 from "process";
|
|
34
24
|
import { pipeline } from "stream/promises";
|
|
35
25
|
import { createGzip } from "zlib";
|
|
36
|
-
import process4 from "process";
|
|
37
26
|
import process3 from "process";
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import
|
|
44
|
-
import {
|
|
45
|
-
import {
|
|
46
|
-
import
|
|
47
|
-
import
|
|
27
|
+
import process2 from "process";
|
|
28
|
+
import process5 from "process";
|
|
29
|
+
import { existsSync as existsSync3 } from "fs";
|
|
30
|
+
import { resolve as resolve3 } from "path";
|
|
31
|
+
import { existsSync as existsSync4 } from "fs";
|
|
32
|
+
import { existsSync as existsSync5, mkdirSync, readdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
33
|
+
import { homedir } from "os";
|
|
34
|
+
import { dirname, resolve as resolve5 } from "path";
|
|
35
|
+
import process7 from "process";
|
|
36
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
|
|
37
|
+
import { extname, resolve as resolve6 } from "path";
|
|
48
38
|
import process8 from "process";
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
39
|
+
var __defProp = Object.defineProperty;
|
|
40
|
+
var __returnValue = (v) => v;
|
|
41
|
+
function __exportSetter(name, newValue) {
|
|
42
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
43
|
+
}
|
|
44
|
+
var __export = (target, all) => {
|
|
45
|
+
for (var name in all)
|
|
46
|
+
__defProp(target, name, {
|
|
47
|
+
get: all[name],
|
|
48
|
+
enumerable: true,
|
|
49
|
+
configurable: true,
|
|
50
|
+
set: __exportSetter.bind(all, name)
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
54
|
+
var __require2 = import.meta.require;
|
|
55
|
+
|
|
52
56
|
class ConfigCache {
|
|
53
57
|
cache = new Map;
|
|
54
58
|
totalHits = 0;
|
|
@@ -287,254 +291,62 @@ class PerformanceMonitor {
|
|
|
287
291
|
return this.metrics.filter((m) => m.duration > threshold);
|
|
288
292
|
}
|
|
289
293
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return source;
|
|
295
|
-
}
|
|
296
|
-
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) {
|
|
297
|
-
return { a: null, b: 2, c: undefined };
|
|
298
|
-
}
|
|
299
|
-
if (source === null || source === undefined) {
|
|
300
|
-
return target;
|
|
301
|
-
}
|
|
302
|
-
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
303
|
-
return source;
|
|
304
|
-
}
|
|
305
|
-
if (Array.isArray(source) && Array.isArray(target)) {
|
|
306
|
-
if (isObject(target) && "arr" in target && Array.isArray(target.arr) && isObject(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
307
|
-
return source;
|
|
308
|
-
}
|
|
309
|
-
if (source.length > 0 && target.length > 0 && isObject(source[0]) && isObject(target[0])) {
|
|
310
|
-
const result = [...source];
|
|
311
|
-
for (const targetItem of target) {
|
|
312
|
-
if (isObject(targetItem) && "name" in targetItem) {
|
|
313
|
-
const existingItem = result.find((item) => isObject(item) && ("name" in item) && item.name === targetItem.name);
|
|
314
|
-
if (!existingItem) {
|
|
315
|
-
result.push(targetItem);
|
|
316
|
-
}
|
|
317
|
-
} else if (isObject(targetItem) && "path" in targetItem) {
|
|
318
|
-
const existingItem = result.find((item) => isObject(item) && ("path" in item) && item.path === targetItem.path);
|
|
319
|
-
if (!existingItem) {
|
|
320
|
-
result.push(targetItem);
|
|
321
|
-
}
|
|
322
|
-
} else if (!result.some((item) => deepEquals(item, targetItem))) {
|
|
323
|
-
result.push(targetItem);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return result;
|
|
327
|
-
}
|
|
328
|
-
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
329
|
-
const result = [...source];
|
|
330
|
-
for (const item of target) {
|
|
331
|
-
if (!result.includes(item)) {
|
|
332
|
-
result.push(item);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return result;
|
|
336
|
-
}
|
|
337
|
-
return source;
|
|
338
|
-
}
|
|
339
|
-
if (!isObject(source) || !isObject(target)) {
|
|
340
|
-
return source;
|
|
341
|
-
}
|
|
342
|
-
const merged = { ...target };
|
|
343
|
-
for (const key in source) {
|
|
344
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
345
|
-
const sourceValue = source[key];
|
|
346
|
-
if (sourceValue === null || sourceValue === undefined) {
|
|
347
|
-
continue;
|
|
348
|
-
} else if (isObject(sourceValue) && isObject(merged[key])) {
|
|
349
|
-
merged[key] = deepMerge(merged[key], sourceValue);
|
|
350
|
-
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
351
|
-
if (sourceValue.length > 0 && merged[key].length > 0 && isObject(sourceValue[0]) && isObject(merged[key][0])) {
|
|
352
|
-
const result = [...sourceValue];
|
|
353
|
-
for (const targetItem of merged[key]) {
|
|
354
|
-
if (isObject(targetItem) && "name" in targetItem) {
|
|
355
|
-
const existingItem = result.find((item) => isObject(item) && ("name" in item) && item.name === targetItem.name);
|
|
356
|
-
if (!existingItem) {
|
|
357
|
-
result.push(targetItem);
|
|
358
|
-
}
|
|
359
|
-
} else if (isObject(targetItem) && "path" in targetItem) {
|
|
360
|
-
const existingItem = result.find((item) => isObject(item) && ("path" in item) && item.path === targetItem.path);
|
|
361
|
-
if (!existingItem) {
|
|
362
|
-
result.push(targetItem);
|
|
363
|
-
}
|
|
364
|
-
} else if (!result.some((item) => deepEquals(item, targetItem))) {
|
|
365
|
-
result.push(targetItem);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
merged[key] = result;
|
|
369
|
-
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
370
|
-
const result = [...sourceValue];
|
|
371
|
-
for (const item of merged[key]) {
|
|
372
|
-
if (!result.includes(item)) {
|
|
373
|
-
result.push(item);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
merged[key] = result;
|
|
377
|
-
} else {
|
|
378
|
-
merged[key] = sourceValue;
|
|
379
|
-
}
|
|
380
|
-
} else {
|
|
381
|
-
merged[key] = sourceValue;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
return merged;
|
|
386
|
-
}
|
|
387
|
-
function deepEquals(a, b) {
|
|
388
|
-
if (a === b)
|
|
389
|
-
return true;
|
|
390
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
391
|
-
if (a.length !== b.length)
|
|
392
|
-
return false;
|
|
393
|
-
for (let i = 0;i < a.length; i++) {
|
|
394
|
-
if (!deepEquals(a[i], b[i]))
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
if (isObject(a) && isObject(b)) {
|
|
400
|
-
const keysA = Object.keys(a);
|
|
401
|
-
const keysB = Object.keys(b);
|
|
402
|
-
if (keysA.length !== keysB.length)
|
|
403
|
-
return false;
|
|
404
|
-
for (const key of keysA) {
|
|
405
|
-
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
406
|
-
return false;
|
|
407
|
-
if (!deepEquals(a[key], b[key]))
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
function isObject(item) {
|
|
415
|
-
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
294
|
+
function createKey(configName, options = {}) {
|
|
295
|
+
const sortedKeys = Object.keys(options).sort();
|
|
296
|
+
const optionsStr = sortedKeys.map((key) => `${key}:${options[key]}`).join("|");
|
|
297
|
+
return optionsStr ? `${configName}:${optionsStr}` : configName;
|
|
416
298
|
}
|
|
417
|
-
|
|
418
|
-
if (!existsSync2(configPath))
|
|
419
|
-
return null;
|
|
299
|
+
function isEquivalent(a, b) {
|
|
420
300
|
try {
|
|
421
|
-
|
|
422
|
-
const loadedConfig = importedConfig.default || importedConfig;
|
|
423
|
-
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
424
|
-
return null;
|
|
425
|
-
try {
|
|
426
|
-
return deepMerge(defaultConfig, loadedConfig);
|
|
427
|
-
} catch {
|
|
428
|
-
return null;
|
|
429
|
-
}
|
|
301
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
430
302
|
} catch {
|
|
431
|
-
return
|
|
303
|
+
return a === b;
|
|
432
304
|
}
|
|
433
305
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
defaultConfig
|
|
438
|
-
}) {
|
|
439
|
-
const baseDir = cwd || process.cwd();
|
|
440
|
-
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
441
|
-
const configPaths = [
|
|
442
|
-
`${name}.config`,
|
|
443
|
-
`.${name}.config`,
|
|
444
|
-
name,
|
|
445
|
-
`.${name}`
|
|
446
|
-
];
|
|
447
|
-
for (const configPath of configPaths) {
|
|
448
|
-
for (const ext of extensions) {
|
|
449
|
-
const fullPath = resolve(baseDir, `${configPath}${ext}`);
|
|
450
|
-
const config2 = await tryLoadConfig(fullPath, defaultConfig);
|
|
451
|
-
if (config2 !== null) {
|
|
452
|
-
return config2;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
try {
|
|
457
|
-
const pkgPath = resolve(baseDir, "package.json");
|
|
458
|
-
if (existsSync2(pkgPath)) {
|
|
459
|
-
const pkg = await import(pkgPath);
|
|
460
|
-
const pkgConfig = pkg[name];
|
|
461
|
-
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
462
|
-
try {
|
|
463
|
-
return deepMerge(defaultConfig, pkgConfig);
|
|
464
|
-
} catch {}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
} catch {}
|
|
468
|
-
return defaultConfig;
|
|
306
|
+
function estimateMemoryUsage(cache) {
|
|
307
|
+
const stats = cache.getStats();
|
|
308
|
+
return stats.size * 2;
|
|
469
309
|
}
|
|
470
|
-
var
|
|
471
|
-
var
|
|
310
|
+
var globalCache;
|
|
311
|
+
var globalPerformanceMonitor;
|
|
312
|
+
var CacheUtils;
|
|
313
|
+
var init_cache = __esm(() => {
|
|
314
|
+
globalCache = new ConfigCache;
|
|
315
|
+
globalPerformanceMonitor = new PerformanceMonitor;
|
|
316
|
+
CacheUtils = {
|
|
317
|
+
createKey,
|
|
318
|
+
isEquivalent,
|
|
319
|
+
estimateMemoryUsage
|
|
320
|
+
};
|
|
321
|
+
});
|
|
472
322
|
function getProjectRoot(filePath, options = {}) {
|
|
473
|
-
let path =
|
|
323
|
+
let path = process.cwd();
|
|
474
324
|
while (path.includes("storage"))
|
|
475
|
-
path =
|
|
476
|
-
const finalPath =
|
|
325
|
+
path = resolve(path, "..");
|
|
326
|
+
const finalPath = resolve(path, filePath || "");
|
|
477
327
|
if (options?.relative)
|
|
478
|
-
return relative(
|
|
328
|
+
return relative(process.cwd(), finalPath);
|
|
479
329
|
return finalPath;
|
|
480
330
|
}
|
|
481
|
-
var defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
|
|
482
|
-
var defaultConfig = {
|
|
483
|
-
level: "info",
|
|
484
|
-
defaultName: "clarity",
|
|
485
|
-
timestamp: true,
|
|
486
|
-
colors: true,
|
|
487
|
-
format: "text",
|
|
488
|
-
maxLogSize: 10485760,
|
|
489
|
-
logDatePattern: "YYYY-MM-DD",
|
|
490
|
-
logDirectory: defaultLogDirectory,
|
|
491
|
-
rotation: {
|
|
492
|
-
frequency: "daily",
|
|
493
|
-
maxSize: 10485760,
|
|
494
|
-
maxFiles: 5,
|
|
495
|
-
compress: false,
|
|
496
|
-
rotateHour: 0,
|
|
497
|
-
rotateMinute: 0,
|
|
498
|
-
rotateDayOfWeek: 0,
|
|
499
|
-
rotateDayOfMonth: 1,
|
|
500
|
-
encrypt: false
|
|
501
|
-
},
|
|
502
|
-
verbose: false
|
|
503
|
-
};
|
|
504
|
-
async function loadConfig2() {
|
|
505
|
-
try {
|
|
506
|
-
const loadedConfig = await loadConfig({
|
|
507
|
-
name: "clarity",
|
|
508
|
-
defaultConfig,
|
|
509
|
-
cwd: process2.cwd(),
|
|
510
|
-
endpoint: "",
|
|
511
|
-
headers: {}
|
|
512
|
-
});
|
|
513
|
-
return { ...defaultConfig, ...loadedConfig };
|
|
514
|
-
} catch {
|
|
515
|
-
return defaultConfig;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
var config = await loadConfig2();
|
|
519
331
|
function isBrowserProcess() {
|
|
520
|
-
if (
|
|
332
|
+
if (process2.env.NODE_ENV === "test" || process2.env.BUN_ENV === "test") {
|
|
521
333
|
return false;
|
|
522
334
|
}
|
|
523
335
|
return typeof window !== "undefined";
|
|
524
336
|
}
|
|
525
337
|
async function isServerProcess() {
|
|
526
|
-
if (
|
|
338
|
+
if (process2.env.NODE_ENV === "test" || process2.env.BUN_ENV === "test") {
|
|
527
339
|
return true;
|
|
528
340
|
}
|
|
529
341
|
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
530
342
|
return true;
|
|
531
343
|
}
|
|
532
|
-
if (typeof
|
|
533
|
-
const type =
|
|
344
|
+
if (typeof process2 !== "undefined") {
|
|
345
|
+
const type = process2.type;
|
|
534
346
|
if (type === "renderer" || type === "worker") {
|
|
535
347
|
return false;
|
|
536
348
|
}
|
|
537
|
-
return !!(
|
|
349
|
+
return !!(process2.versions && (process2.versions.node || process2.versions.bun));
|
|
538
350
|
}
|
|
539
351
|
return false;
|
|
540
352
|
}
|
|
@@ -555,17 +367,17 @@ class JsonFormatter {
|
|
|
555
367
|
if (isServer) {
|
|
556
368
|
const { hostname } = await import("os");
|
|
557
369
|
return {
|
|
558
|
-
pid:
|
|
370
|
+
pid: process3.pid,
|
|
559
371
|
hostname: hostname(),
|
|
560
|
-
environment:
|
|
561
|
-
platform:
|
|
562
|
-
version:
|
|
372
|
+
environment: process3.env.NODE_ENV || "development",
|
|
373
|
+
platform: process3.platform,
|
|
374
|
+
version: process3.version
|
|
563
375
|
};
|
|
564
376
|
}
|
|
565
377
|
return {
|
|
566
378
|
userAgent: navigator.userAgent,
|
|
567
379
|
hostname: window.location.hostname || "browser",
|
|
568
|
-
environment:
|
|
380
|
+
environment: process3.env.NODE_ENV || process3.env.BUN_ENV || "development",
|
|
569
381
|
viewport: {
|
|
570
382
|
width: window.innerWidth,
|
|
571
383
|
height: window.innerHeight
|
|
@@ -574,64 +386,12 @@ class JsonFormatter {
|
|
|
574
386
|
};
|
|
575
387
|
}
|
|
576
388
|
}
|
|
577
|
-
var terminalStyles = {
|
|
578
|
-
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
579
|
-
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
580
|
-
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
581
|
-
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
582
|
-
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
583
|
-
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
584
|
-
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
585
|
-
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
586
|
-
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
587
|
-
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
588
|
-
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
589
|
-
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
590
|
-
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
591
|
-
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
592
|
-
reset: "\x1B[0m"
|
|
593
|
-
};
|
|
594
|
-
var styles = terminalStyles;
|
|
595
|
-
var red = terminalStyles.red;
|
|
596
|
-
var green = terminalStyles.green;
|
|
597
|
-
var yellow = terminalStyles.yellow;
|
|
598
|
-
var blue = terminalStyles.blue;
|
|
599
|
-
var magenta = terminalStyles.magenta;
|
|
600
|
-
var cyan = terminalStyles.cyan;
|
|
601
|
-
var white = terminalStyles.white;
|
|
602
|
-
var gray = terminalStyles.gray;
|
|
603
|
-
var bgRed = terminalStyles.bgRed;
|
|
604
|
-
var bgYellow = terminalStyles.bgYellow;
|
|
605
|
-
var bold = terminalStyles.bold;
|
|
606
|
-
var dim = terminalStyles.dim;
|
|
607
|
-
var italic = terminalStyles.italic;
|
|
608
|
-
var underline = terminalStyles.underline;
|
|
609
|
-
var reset = terminalStyles.reset;
|
|
610
|
-
var defaultFingersCrossedConfig = {
|
|
611
|
-
activationLevel: "error",
|
|
612
|
-
bufferSize: 50,
|
|
613
|
-
flushOnDeactivation: true,
|
|
614
|
-
stopBuffering: false
|
|
615
|
-
};
|
|
616
|
-
var levelIcons = {
|
|
617
|
-
debug: "\uD83D\uDD0D",
|
|
618
|
-
info: blue("\u2139"),
|
|
619
|
-
success: green("\u2713"),
|
|
620
|
-
warning: bgYellow(white(bold(" WARN "))),
|
|
621
|
-
error: bgRed(white(bold(" ERROR ")))
|
|
622
|
-
};
|
|
623
389
|
|
|
624
390
|
class Logger {
|
|
625
391
|
name;
|
|
626
392
|
fileLocks = new Map;
|
|
627
393
|
currentKeyId = null;
|
|
628
394
|
keys = new Map;
|
|
629
|
-
config;
|
|
630
|
-
options;
|
|
631
|
-
formatter;
|
|
632
|
-
timers = new Set;
|
|
633
|
-
subLoggers = new Set;
|
|
634
|
-
fingersCrossedBuffer = [];
|
|
635
395
|
fingersCrossedConfig;
|
|
636
396
|
fingersCrossedActive = false;
|
|
637
397
|
currentLogFile;
|
|
@@ -646,6 +406,12 @@ class Logger {
|
|
|
646
406
|
tagFormat;
|
|
647
407
|
timestampPosition;
|
|
648
408
|
environment;
|
|
409
|
+
config;
|
|
410
|
+
options;
|
|
411
|
+
formatter;
|
|
412
|
+
timers = new Set;
|
|
413
|
+
subLoggers = new Set;
|
|
414
|
+
fingersCrossedBuffer = [];
|
|
649
415
|
ANSI_PATTERN = /\u001B\[.*?m/g;
|
|
650
416
|
activeProgressBar = null;
|
|
651
417
|
constructor(name, options = {}) {
|
|
@@ -657,7 +423,7 @@ class Logger {
|
|
|
657
423
|
this.fancy = options.fancy ?? true;
|
|
658
424
|
this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
|
|
659
425
|
this.timestampPosition = options.timestampPosition ?? "right";
|
|
660
|
-
this.environment = options.environment ??
|
|
426
|
+
this.environment = options.environment ?? process4.env.APP_ENV ?? "local";
|
|
661
427
|
this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
|
|
662
428
|
const configOptions = { ...options };
|
|
663
429
|
const hasTimestamp = options.timestamp !== undefined;
|
|
@@ -667,7 +433,8 @@ class Logger {
|
|
|
667
433
|
this.config = {
|
|
668
434
|
...this.config,
|
|
669
435
|
...configOptions,
|
|
670
|
-
timestamp: hasTimestamp || this.config.timestamp
|
|
436
|
+
timestamp: hasTimestamp || this.config.timestamp,
|
|
437
|
+
level: this.options.level ?? "info"
|
|
671
438
|
};
|
|
672
439
|
this.currentLogFile = this.generateLogFilename();
|
|
673
440
|
this.encryptionKeys = new Map;
|
|
@@ -684,6 +451,19 @@ class Logger {
|
|
|
684
451
|
this.setupKeyRotation();
|
|
685
452
|
}
|
|
686
453
|
}
|
|
454
|
+
shouldActivateFingersCrossed(level) {
|
|
455
|
+
if (!this.fingersCrossedConfig)
|
|
456
|
+
return false;
|
|
457
|
+
const levels = {
|
|
458
|
+
debug: 0,
|
|
459
|
+
info: 1,
|
|
460
|
+
success: 2,
|
|
461
|
+
warning: 3,
|
|
462
|
+
error: 4
|
|
463
|
+
};
|
|
464
|
+
const activation = this.fingersCrossedConfig.activationLevel ?? "error";
|
|
465
|
+
return levels[level] >= levels[activation];
|
|
466
|
+
}
|
|
687
467
|
initializeFingersCrossedConfig(options) {
|
|
688
468
|
if (!options.fingersCrossedEnabled && options.fingersCrossed) {
|
|
689
469
|
return {
|
|
@@ -712,6 +492,7 @@ class Logger {
|
|
|
712
492
|
fingersCrossed: {},
|
|
713
493
|
enabled: true,
|
|
714
494
|
showTags: false,
|
|
495
|
+
showIcons: true,
|
|
715
496
|
formatter: undefined
|
|
716
497
|
};
|
|
717
498
|
const mergedOptions = {
|
|
@@ -723,6 +504,9 @@ class Logger {
|
|
|
723
504
|
}
|
|
724
505
|
return mergedOptions;
|
|
725
506
|
}
|
|
507
|
+
shouldWriteToFile() {
|
|
508
|
+
return !isBrowserProcess() && this.config.writeToFile === true;
|
|
509
|
+
}
|
|
726
510
|
async writeToFile(data) {
|
|
727
511
|
const cancelled = false;
|
|
728
512
|
const operationPromise = (async () => {
|
|
@@ -756,11 +540,11 @@ class Logger {
|
|
|
756
540
|
throw new Error("Operation cancelled: Logger was destroyed");
|
|
757
541
|
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
|
|
758
542
|
try {
|
|
759
|
-
if (!
|
|
543
|
+
if (!existsSync2(this.currentLogFile)) {
|
|
760
544
|
await writeFile(this.currentLogFile, "", { mode: 420 });
|
|
761
545
|
}
|
|
762
546
|
fd = openSync(this.currentLogFile, "a", 420);
|
|
763
|
-
|
|
547
|
+
writeFileSync(fd, dataToWrite, { flag: "a" });
|
|
764
548
|
fsyncSync(fd);
|
|
765
549
|
if (fd !== undefined) {
|
|
766
550
|
closeSync(fd);
|
|
@@ -838,6 +622,8 @@ class Logger {
|
|
|
838
622
|
setupRotation() {
|
|
839
623
|
if (isBrowserProcess())
|
|
840
624
|
return;
|
|
625
|
+
if (!this.shouldWriteToFile())
|
|
626
|
+
return;
|
|
841
627
|
if (typeof this.config.rotation === "boolean")
|
|
842
628
|
return;
|
|
843
629
|
const config2 = this.config.rotation;
|
|
@@ -922,13 +708,18 @@ class Logger {
|
|
|
922
708
|
const { key } = this.getCurrentKey();
|
|
923
709
|
const iv = randomBytes(16);
|
|
924
710
|
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
711
|
+
const input = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf8");
|
|
712
|
+
const part1 = cipher.update(input);
|
|
713
|
+
const part2 = cipher.final();
|
|
714
|
+
const totalCipherLen = part1.length + part2.length;
|
|
929
715
|
const authTag = cipher.getAuthTag();
|
|
716
|
+
const out = Buffer.allocUnsafe(16 + totalCipherLen + 16);
|
|
717
|
+
iv.copy(out, 0);
|
|
718
|
+
part1.copy(out, 16);
|
|
719
|
+
part2.copy(out, 16 + part1.length);
|
|
720
|
+
authTag.copy(out, 16 + totalCipherLen);
|
|
930
721
|
return {
|
|
931
|
-
encrypted:
|
|
722
|
+
encrypted: out,
|
|
932
723
|
iv
|
|
933
724
|
};
|
|
934
725
|
}
|
|
@@ -963,6 +754,8 @@ class Logger {
|
|
|
963
754
|
async rotateLog() {
|
|
964
755
|
if (isBrowserProcess())
|
|
965
756
|
return;
|
|
757
|
+
if (!this.shouldWriteToFile())
|
|
758
|
+
return;
|
|
966
759
|
const stats = await stat(this.currentLogFile).catch(() => null);
|
|
967
760
|
if (!stats)
|
|
968
761
|
return;
|
|
@@ -1035,42 +828,19 @@ class Logger {
|
|
|
1035
828
|
this.isActivated = true;
|
|
1036
829
|
for (const entry of this.logBuffer) {
|
|
1037
830
|
const formattedBufferedEntry = await this.formatter.format(entry);
|
|
1038
|
-
|
|
831
|
+
if (this.shouldWriteToFile())
|
|
832
|
+
await this.writeToFile(formattedBufferedEntry);
|
|
1039
833
|
console.log(formattedBufferedEntry);
|
|
1040
834
|
}
|
|
1041
835
|
if (this.fingersCrossedConfig.stopBuffering)
|
|
1042
836
|
this.logBuffer = [];
|
|
1043
837
|
}
|
|
1044
838
|
if (this.isActivated) {
|
|
1045
|
-
|
|
839
|
+
if (this.shouldWriteToFile())
|
|
840
|
+
await this.writeToFile(formattedEntry);
|
|
1046
841
|
console.log(formattedEntry);
|
|
1047
|
-
} else {
|
|
1048
|
-
if (this.logBuffer.length >= this.fingersCrossedConfig.bufferSize)
|
|
1049
|
-
this.logBuffer.shift();
|
|
1050
|
-
const entry = {
|
|
1051
|
-
timestamp: new Date,
|
|
1052
|
-
level,
|
|
1053
|
-
message: formattedEntry,
|
|
1054
|
-
name: this.name
|
|
1055
|
-
};
|
|
1056
|
-
this.logBuffer.push(entry);
|
|
1057
842
|
}
|
|
1058
843
|
}
|
|
1059
|
-
shouldActivateFingersCrossed(level) {
|
|
1060
|
-
if (!this.fingersCrossedConfig)
|
|
1061
|
-
return false;
|
|
1062
|
-
return this.getLevelValue(level) >= this.getLevelValue(this.fingersCrossedConfig.activationLevel);
|
|
1063
|
-
}
|
|
1064
|
-
getLevelValue(level) {
|
|
1065
|
-
const levels = {
|
|
1066
|
-
debug: 0,
|
|
1067
|
-
info: 1,
|
|
1068
|
-
success: 2,
|
|
1069
|
-
warning: 3,
|
|
1070
|
-
error: 4
|
|
1071
|
-
};
|
|
1072
|
-
return levels[level];
|
|
1073
|
-
}
|
|
1074
844
|
shouldLog(level) {
|
|
1075
845
|
if (!this.enabled)
|
|
1076
846
|
return false;
|
|
@@ -1092,7 +862,7 @@ class Logger {
|
|
|
1092
862
|
}
|
|
1093
863
|
return Promise.resolve();
|
|
1094
864
|
}));
|
|
1095
|
-
if (
|
|
865
|
+
if (existsSync2(this.currentLogFile)) {
|
|
1096
866
|
try {
|
|
1097
867
|
const fd = openSync(this.currentLogFile, "r+");
|
|
1098
868
|
fsyncSync(fd);
|
|
@@ -1150,7 +920,17 @@ class Logger {
|
|
|
1150
920
|
return `[${date.toISOString()}]`;
|
|
1151
921
|
}
|
|
1152
922
|
formatConsoleTimestamp(date) {
|
|
1153
|
-
return this.
|
|
923
|
+
return this.shouldStyleConsole() ? styles.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
|
|
924
|
+
}
|
|
925
|
+
shouldStyleConsole() {
|
|
926
|
+
if (!this.fancy || isBrowserProcess())
|
|
927
|
+
return false;
|
|
928
|
+
const noColor = typeof process4.env.NO_COLOR !== "undefined";
|
|
929
|
+
const forceColorDisabled = process4.env.FORCE_COLOR === "0";
|
|
930
|
+
if (noColor || forceColorDisabled)
|
|
931
|
+
return false;
|
|
932
|
+
const hasTTY = typeof process4.stderr !== "undefined" && process4.stderr.isTTY || typeof process4.stdout !== "undefined" && process4.stdout.isTTY;
|
|
933
|
+
return !!hasTTY;
|
|
1154
934
|
}
|
|
1155
935
|
formatConsoleMessage(parts) {
|
|
1156
936
|
const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
|
|
@@ -1170,7 +950,7 @@ class Logger {
|
|
|
1170
950
|
components.push(message);
|
|
1171
951
|
return components.join(" ");
|
|
1172
952
|
}
|
|
1173
|
-
const terminalWidth =
|
|
953
|
+
const terminalWidth = process4.stdout.columns || 120;
|
|
1174
954
|
let mainPart = "";
|
|
1175
955
|
if (level === "warning" || level === "error") {
|
|
1176
956
|
mainPart = `${icon} ${message}`;
|
|
@@ -1220,7 +1000,79 @@ class Logger {
|
|
|
1220
1000
|
}
|
|
1221
1001
|
return formattedMessage;
|
|
1222
1002
|
}
|
|
1003
|
+
formatMarkdown(input) {
|
|
1004
|
+
if (!input)
|
|
1005
|
+
return input;
|
|
1006
|
+
let out = input;
|
|
1007
|
+
out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => {
|
|
1008
|
+
const label = styles.underline(styles.blue(text));
|
|
1009
|
+
const absFile = this.toAbsoluteFilePath(url);
|
|
1010
|
+
if (absFile && this.shouldStyleConsole() && this.supportsHyperlinks()) {
|
|
1011
|
+
const href = `file://${encodeURI(absFile)}`;
|
|
1012
|
+
const OSC = "\x1B]8;;";
|
|
1013
|
+
const ST = "\x1B\\";
|
|
1014
|
+
return `${OSC}${href}${ST}${label}${OSC}${ST}`;
|
|
1015
|
+
}
|
|
1016
|
+
if (this.shouldStyleConsole() && this.supportsHyperlinks()) {
|
|
1017
|
+
const OSC = "\x1B]8;;";
|
|
1018
|
+
const ST = "\x1B\\";
|
|
1019
|
+
return `${OSC}${url}${ST}${label}${OSC}${ST}`;
|
|
1020
|
+
}
|
|
1021
|
+
return label;
|
|
1022
|
+
});
|
|
1023
|
+
out = out.replace(/`([^`]+)`/g, (_, m) => styles.bgGray(m));
|
|
1024
|
+
out = out.replace(/\*\*([^*]+)\*\*/g, (_, m) => styles.bold(m));
|
|
1025
|
+
out = out.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, m) => styles.italic(m));
|
|
1026
|
+
out = out.replace(/(?<!_)_([^_]+)_(?!_)/g, (_, m) => styles.italic(m));
|
|
1027
|
+
out = out.replace(/~([^~]+)~/g, (_, m) => styles.strikethrough(m));
|
|
1028
|
+
return out;
|
|
1029
|
+
}
|
|
1030
|
+
supportsHyperlinks() {
|
|
1031
|
+
if (isBrowserProcess())
|
|
1032
|
+
return false;
|
|
1033
|
+
const env = process4.env;
|
|
1034
|
+
if (!env)
|
|
1035
|
+
return false;
|
|
1036
|
+
if (env.TERM_PROGRAM === "iTerm.app" || env.TERM_PROGRAM === "vscode" || env.TERM_PROGRAM === "WezTerm")
|
|
1037
|
+
return true;
|
|
1038
|
+
if (env.WT_SESSION)
|
|
1039
|
+
return true;
|
|
1040
|
+
if (env.TERM === "xterm-kitty")
|
|
1041
|
+
return true;
|
|
1042
|
+
const vte = env.VTE_VERSION ? Number.parseInt(env.VTE_VERSION, 10) : 0;
|
|
1043
|
+
if (!Number.isNaN(vte) && vte >= 5000)
|
|
1044
|
+
return true;
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
toAbsoluteFilePath(input) {
|
|
1048
|
+
try {
|
|
1049
|
+
let p = input;
|
|
1050
|
+
if (p.startsWith("file://")) {
|
|
1051
|
+
p = p.replace(/^file:\/\//, "");
|
|
1052
|
+
}
|
|
1053
|
+
if (p.startsWith("~")) {
|
|
1054
|
+
const home = process4.env.HOME || "";
|
|
1055
|
+
if (home)
|
|
1056
|
+
p = p.replace(/^~(?=$|\/)/, home);
|
|
1057
|
+
}
|
|
1058
|
+
if (isAbsolute(p) || p.startsWith("./") || p.startsWith("../")) {
|
|
1059
|
+
p = resolve2(p);
|
|
1060
|
+
} else {
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
return existsSync2(p) ? p : null;
|
|
1064
|
+
} catch {
|
|
1065
|
+
return null;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
buildOutputTexts(input) {
|
|
1069
|
+
const consoleText = this.shouldStyleConsole() ? this.formatMarkdown(input) : input;
|
|
1070
|
+
const fileText = input.replace(this.ANSI_PATTERN, "");
|
|
1071
|
+
return { consoleText, fileText };
|
|
1072
|
+
}
|
|
1223
1073
|
async log(level, message, ...args) {
|
|
1074
|
+
if (!this.shouldLog(level))
|
|
1075
|
+
return;
|
|
1224
1076
|
const timestamp = new Date;
|
|
1225
1077
|
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1226
1078
|
const fileTime = this.formatFileTimestamp(timestamp);
|
|
@@ -1232,8 +1084,9 @@ class Logger {
|
|
|
1232
1084
|
} else {
|
|
1233
1085
|
formattedMessage = this.formatMessage(message, args);
|
|
1234
1086
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1087
|
+
const { consoleText: baseConsoleText, fileText } = this.buildOutputTexts(formattedMessage);
|
|
1088
|
+
if (this.shouldStyleConsole()) {
|
|
1089
|
+
const icon = this.options.showIcons === false ? "" : levelIcons[level];
|
|
1237
1090
|
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1238
1091
|
let consoleMessage;
|
|
1239
1092
|
switch (level) {
|
|
@@ -1242,7 +1095,7 @@ class Logger {
|
|
|
1242
1095
|
timestamp: consoleTime,
|
|
1243
1096
|
icon,
|
|
1244
1097
|
tag,
|
|
1245
|
-
message: styles.gray(
|
|
1098
|
+
message: styles.gray(baseConsoleText),
|
|
1246
1099
|
level
|
|
1247
1100
|
});
|
|
1248
1101
|
console.error(consoleMessage);
|
|
@@ -1252,17 +1105,17 @@ class Logger {
|
|
|
1252
1105
|
timestamp: consoleTime,
|
|
1253
1106
|
icon,
|
|
1254
1107
|
tag,
|
|
1255
|
-
message:
|
|
1108
|
+
message: baseConsoleText,
|
|
1256
1109
|
level
|
|
1257
1110
|
});
|
|
1258
|
-
console.
|
|
1111
|
+
console.warn(consoleMessage);
|
|
1259
1112
|
break;
|
|
1260
1113
|
case "success":
|
|
1261
1114
|
consoleMessage = this.formatConsoleMessage({
|
|
1262
1115
|
timestamp: consoleTime,
|
|
1263
1116
|
icon,
|
|
1264
1117
|
tag,
|
|
1265
|
-
message: styles.green(
|
|
1118
|
+
message: styles.green(baseConsoleText),
|
|
1266
1119
|
level
|
|
1267
1120
|
});
|
|
1268
1121
|
console.error(consoleMessage);
|
|
@@ -1272,7 +1125,7 @@ class Logger {
|
|
|
1272
1125
|
timestamp: consoleTime,
|
|
1273
1126
|
icon,
|
|
1274
1127
|
tag,
|
|
1275
|
-
message:
|
|
1128
|
+
message: baseConsoleText,
|
|
1276
1129
|
level
|
|
1277
1130
|
});
|
|
1278
1131
|
console.warn(consoleMessage);
|
|
@@ -1282,7 +1135,7 @@ class Logger {
|
|
|
1282
1135
|
timestamp: consoleTime,
|
|
1283
1136
|
icon,
|
|
1284
1137
|
tag,
|
|
1285
|
-
message:
|
|
1138
|
+
message: baseConsoleText,
|
|
1286
1139
|
level
|
|
1287
1140
|
});
|
|
1288
1141
|
console.error(consoleMessage);
|
|
@@ -1308,1731 +1161,6 @@ class Logger {
|
|
|
1308
1161
|
console.error(errorStack);
|
|
1309
1162
|
}
|
|
1310
1163
|
}
|
|
1311
|
-
if (!this.shouldLog(level))
|
|
1312
|
-
return;
|
|
1313
|
-
let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}
|
|
1314
|
-
`;
|
|
1315
|
-
if (errorStack) {
|
|
1316
|
-
logEntry += `${errorStack}
|
|
1317
|
-
`;
|
|
1318
|
-
}
|
|
1319
|
-
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
1320
|
-
await this.writeToFile(logEntry);
|
|
1321
|
-
}
|
|
1322
|
-
time(label) {
|
|
1323
|
-
const start = performance.now();
|
|
1324
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1325
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1326
|
-
const consoleTime = this.formatConsoleTimestamp(new Date);
|
|
1327
|
-
console.error(this.formatConsoleMessage({
|
|
1328
|
-
timestamp: consoleTime,
|
|
1329
|
-
icon: styles.blue("\u25D0"),
|
|
1330
|
-
tag,
|
|
1331
|
-
message: `${styles.cyan(label)}...`
|
|
1332
|
-
}));
|
|
1333
|
-
}
|
|
1334
|
-
return async (metadata) => {
|
|
1335
|
-
if (!this.enabled)
|
|
1336
|
-
return;
|
|
1337
|
-
const end = performance.now();
|
|
1338
|
-
const elapsed = Math.round(end - start);
|
|
1339
|
-
const completionMessage = `${label} completed in ${elapsed}ms`;
|
|
1340
|
-
const timestamp = new Date;
|
|
1341
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1342
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
1343
|
-
let logEntry = `${fileTime} ${this.environment}.INFO: ${completionMessage}`;
|
|
1344
|
-
if (metadata) {
|
|
1345
|
-
logEntry += ` ${JSON.stringify(metadata)}`;
|
|
1346
|
-
}
|
|
1347
|
-
logEntry += `
|
|
1348
|
-
`;
|
|
1349
|
-
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
1350
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1351
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1352
|
-
console.error(this.formatConsoleMessage({
|
|
1353
|
-
timestamp: consoleTime,
|
|
1354
|
-
icon: styles.green("\u2713"),
|
|
1355
|
-
tag,
|
|
1356
|
-
message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
|
|
1357
|
-
}));
|
|
1358
|
-
} else if (!isBrowserProcess()) {
|
|
1359
|
-
console.error(logEntry.trim());
|
|
1360
|
-
}
|
|
1361
|
-
await this.writeToFile(logEntry);
|
|
1362
|
-
};
|
|
1363
|
-
}
|
|
1364
|
-
async debug(message, ...args) {
|
|
1365
|
-
await this.log("debug", message, ...args);
|
|
1366
|
-
}
|
|
1367
|
-
async info(message, ...args) {
|
|
1368
|
-
await this.log("info", message, ...args);
|
|
1369
|
-
}
|
|
1370
|
-
async success(message, ...args) {
|
|
1371
|
-
await this.log("success", message, ...args);
|
|
1372
|
-
}
|
|
1373
|
-
async warn(message, ...args) {
|
|
1374
|
-
await this.log("warning", message, ...args);
|
|
1375
|
-
}
|
|
1376
|
-
async error(message, ...args) {
|
|
1377
|
-
await this.log("error", message, ...args);
|
|
1378
|
-
}
|
|
1379
|
-
validateEncryptionConfig() {
|
|
1380
|
-
if (!this.config.rotation)
|
|
1381
|
-
return false;
|
|
1382
|
-
if (typeof this.config.rotation === "boolean")
|
|
1383
|
-
return false;
|
|
1384
|
-
const rotation = this.config.rotation;
|
|
1385
|
-
const { encrypt } = rotation;
|
|
1386
|
-
return !!encrypt;
|
|
1387
|
-
}
|
|
1388
|
-
async only(fn) {
|
|
1389
|
-
if (!this.enabled)
|
|
1390
|
-
return;
|
|
1391
|
-
return await fn();
|
|
1392
|
-
}
|
|
1393
|
-
isEnabled() {
|
|
1394
|
-
return this.enabled;
|
|
1395
|
-
}
|
|
1396
|
-
setEnabled(enabled) {
|
|
1397
|
-
this.enabled = enabled;
|
|
1398
|
-
}
|
|
1399
|
-
extend(namespace) {
|
|
1400
|
-
const childName = `${this.name}:${namespace}`;
|
|
1401
|
-
const childLogger = new Logger(childName, {
|
|
1402
|
-
...this.options,
|
|
1403
|
-
logDirectory: this.config.logDirectory,
|
|
1404
|
-
level: this.config.level,
|
|
1405
|
-
format: this.config.format,
|
|
1406
|
-
rotation: typeof this.config.rotation === "boolean" ? undefined : this.config.rotation,
|
|
1407
|
-
timestamp: typeof this.config.timestamp === "boolean" ? undefined : this.config.timestamp
|
|
1408
|
-
});
|
|
1409
|
-
this.subLoggers.add(childLogger);
|
|
1410
|
-
return childLogger;
|
|
1411
|
-
}
|
|
1412
|
-
createReadStream() {
|
|
1413
|
-
if (isBrowserProcess())
|
|
1414
|
-
throw new Error("createReadStream is not supported in browser environments");
|
|
1415
|
-
if (!existsSync22(this.currentLogFile))
|
|
1416
|
-
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
1417
|
-
return createReadStream(this.currentLogFile, { encoding: "utf8" });
|
|
1418
|
-
}
|
|
1419
|
-
async decrypt(data) {
|
|
1420
|
-
if (!this.validateEncryptionConfig())
|
|
1421
|
-
throw new Error("Encryption is not configured");
|
|
1422
|
-
const encryptionConfig = this.config.rotation;
|
|
1423
|
-
if (!encryptionConfig.encrypt || typeof encryptionConfig.encrypt === "boolean")
|
|
1424
|
-
throw new Error("Invalid encryption configuration");
|
|
1425
|
-
if (!this.currentKeyId || !this.keys.has(this.currentKeyId))
|
|
1426
|
-
throw new Error("No valid encryption key available");
|
|
1427
|
-
const key = this.keys.get(this.currentKeyId);
|
|
1428
|
-
try {
|
|
1429
|
-
const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
|
|
1430
|
-
const iv = encryptedData.slice(0, 16);
|
|
1431
|
-
const authTag = encryptedData.slice(-16);
|
|
1432
|
-
const ciphertext = encryptedData.slice(16, -16);
|
|
1433
|
-
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
1434
|
-
decipher.setAuthTag(authTag);
|
|
1435
|
-
const decrypted = Buffer.concat([
|
|
1436
|
-
decipher.update(ciphertext),
|
|
1437
|
-
decipher.final()
|
|
1438
|
-
]);
|
|
1439
|
-
return decrypted.toString("utf8");
|
|
1440
|
-
} catch (err) {
|
|
1441
|
-
throw new Error(`Decryption failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1442
|
-
}
|
|
1443
|
-
}
|
|
1444
|
-
getLevel() {
|
|
1445
|
-
return this.config.level;
|
|
1446
|
-
}
|
|
1447
|
-
getLogDirectory() {
|
|
1448
|
-
return this.config.logDirectory;
|
|
1449
|
-
}
|
|
1450
|
-
getFormat() {
|
|
1451
|
-
return this.config.format;
|
|
1452
|
-
}
|
|
1453
|
-
getRotationConfig() {
|
|
1454
|
-
return this.config.rotation;
|
|
1455
|
-
}
|
|
1456
|
-
isBrowserMode() {
|
|
1457
|
-
return isBrowserProcess();
|
|
1458
|
-
}
|
|
1459
|
-
isServerMode() {
|
|
1460
|
-
return !isBrowserProcess();
|
|
1461
|
-
}
|
|
1462
|
-
setTestEncryptionKey(keyId, key) {
|
|
1463
|
-
this.currentKeyId = keyId;
|
|
1464
|
-
this.keys.set(keyId, key);
|
|
1465
|
-
}
|
|
1466
|
-
getTestCurrentKey() {
|
|
1467
|
-
if (!this.currentKeyId || !this.keys.has(this.currentKeyId)) {
|
|
1468
|
-
return null;
|
|
1469
|
-
}
|
|
1470
|
-
return {
|
|
1471
|
-
id: this.currentKeyId,
|
|
1472
|
-
key: this.keys.get(this.currentKeyId)
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
|
-
getConfig() {
|
|
1476
|
-
return this.config;
|
|
1477
|
-
}
|
|
1478
|
-
async box(message) {
|
|
1479
|
-
if (!this.enabled)
|
|
1480
|
-
return;
|
|
1481
|
-
const timestamp = new Date;
|
|
1482
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
1483
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
1484
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1485
|
-
const lines = message.split(`
|
|
1486
|
-
`);
|
|
1487
|
-
const width = Math.max(...lines.map((line) => line.length)) + 2;
|
|
1488
|
-
const top = `\u250C${"\u2500".repeat(width)}\u2510`;
|
|
1489
|
-
const bottom = `\u2514${"\u2500".repeat(width)}\u2518`;
|
|
1490
|
-
const boxedLines = lines.map((line) => {
|
|
1491
|
-
const padding = " ".repeat(width - line.length - 2);
|
|
1492
|
-
return `\u2502 ${line}${padding} \u2502`;
|
|
1493
|
-
});
|
|
1494
|
-
if (this.options.showTags !== false && this.name) {
|
|
1495
|
-
console.error(this.formatConsoleMessage({
|
|
1496
|
-
timestamp: consoleTime,
|
|
1497
|
-
message: styles.gray(this.formatTag(this.name)),
|
|
1498
|
-
showTimestamp: false
|
|
1499
|
-
}));
|
|
1500
|
-
}
|
|
1501
|
-
console.error(this.formatConsoleMessage({
|
|
1502
|
-
timestamp: consoleTime,
|
|
1503
|
-
message: styles.cyan(top)
|
|
1504
|
-
}));
|
|
1505
|
-
boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
|
|
1506
|
-
timestamp: consoleTime,
|
|
1507
|
-
message: styles.cyan(line),
|
|
1508
|
-
showTimestamp: false
|
|
1509
|
-
})));
|
|
1510
|
-
console.error(this.formatConsoleMessage({
|
|
1511
|
-
timestamp: consoleTime,
|
|
1512
|
-
message: styles.cyan(bottom),
|
|
1513
|
-
showTimestamp: false
|
|
1514
|
-
}));
|
|
1515
|
-
} else if (!isBrowserProcess()) {
|
|
1516
|
-
console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
|
|
1517
|
-
}
|
|
1518
|
-
const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
|
|
1519
|
-
`.replace(this.ANSI_PATTERN, "");
|
|
1520
|
-
await this.writeToFile(logEntry);
|
|
1521
|
-
}
|
|
1522
|
-
async prompt(message) {
|
|
1523
|
-
if (isBrowserProcess()) {
|
|
1524
|
-
return Promise.resolve(true);
|
|
1525
|
-
}
|
|
1526
|
-
return new Promise((resolve32) => {
|
|
1527
|
-
console.error(`${styles.cyan("?")} ${message} (y/n) `);
|
|
1528
|
-
const onData = (data) => {
|
|
1529
|
-
const input = data.toString().trim().toLowerCase();
|
|
1530
|
-
process5.stdin.removeListener("data", onData);
|
|
1531
|
-
try {
|
|
1532
|
-
if (typeof process5.stdin.setRawMode === "function") {
|
|
1533
|
-
process5.stdin.setRawMode(false);
|
|
1534
|
-
}
|
|
1535
|
-
} catch {}
|
|
1536
|
-
process5.stdin.pause();
|
|
1537
|
-
console.error("");
|
|
1538
|
-
resolve32(input === "y" || input === "yes");
|
|
1539
|
-
};
|
|
1540
|
-
try {
|
|
1541
|
-
if (typeof process5.stdin.setRawMode === "function") {
|
|
1542
|
-
process5.stdin.setRawMode(true);
|
|
1543
|
-
}
|
|
1544
|
-
} catch {}
|
|
1545
|
-
process5.stdin.resume();
|
|
1546
|
-
process5.stdin.once("data", onData);
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
|
-
setFancy(enabled) {
|
|
1550
|
-
this.fancy = enabled;
|
|
1551
|
-
}
|
|
1552
|
-
isFancy() {
|
|
1553
|
-
return this.fancy;
|
|
1554
|
-
}
|
|
1555
|
-
pause() {
|
|
1556
|
-
this.enabled = false;
|
|
1557
|
-
}
|
|
1558
|
-
resume() {
|
|
1559
|
-
this.enabled = true;
|
|
1560
|
-
}
|
|
1561
|
-
async start(message, ...args) {
|
|
1562
|
-
if (!this.enabled)
|
|
1563
|
-
return;
|
|
1564
|
-
let formattedMessage = message;
|
|
1565
|
-
if (args && args.length > 0) {
|
|
1566
|
-
const formatRegex = /%([sdijfo%])/g;
|
|
1567
|
-
let argIndex = 0;
|
|
1568
|
-
formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
1569
|
-
if (type === "%")
|
|
1570
|
-
return "%";
|
|
1571
|
-
if (argIndex >= args.length)
|
|
1572
|
-
return match;
|
|
1573
|
-
const arg = args[argIndex++];
|
|
1574
|
-
switch (type) {
|
|
1575
|
-
case "s":
|
|
1576
|
-
return String(arg);
|
|
1577
|
-
case "d":
|
|
1578
|
-
case "i":
|
|
1579
|
-
return Number(arg).toString();
|
|
1580
|
-
case "j":
|
|
1581
|
-
case "o":
|
|
1582
|
-
return JSON.stringify(arg, null, 2);
|
|
1583
|
-
default:
|
|
1584
|
-
return match;
|
|
1585
|
-
}
|
|
1586
|
-
});
|
|
1587
|
-
if (argIndex < args.length) {
|
|
1588
|
-
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
if (this.fancy && !isBrowserProcess()) {
|
|
1592
|
-
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1593
|
-
const spinnerChar = styles.blue("\u25D0");
|
|
1594
|
-
console.error(`${spinnerChar} ${tag} ${styles.cyan(formattedMessage)}`);
|
|
1595
|
-
}
|
|
1596
|
-
const timestamp = new Date;
|
|
1597
|
-
const formattedDate = timestamp.toISOString();
|
|
1598
|
-
const logEntry = `[${formattedDate}] ${this.environment}.INFO: [START] ${formattedMessage}
|
|
1599
|
-
`.replace(this.ANSI_PATTERN, "");
|
|
1600
|
-
await this.writeToFile(logEntry);
|
|
1601
|
-
}
|
|
1602
|
-
progress(total, initialMessage = "") {
|
|
1603
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || total <= 0) {
|
|
1604
|
-
return {
|
|
1605
|
-
update: () => {},
|
|
1606
|
-
finish: () => {},
|
|
1607
|
-
interrupt: () => {}
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1610
|
-
if (this.activeProgressBar) {
|
|
1611
|
-
console.warn("Warning: Another progress bar is already active. Finishing the previous one.");
|
|
1612
|
-
this.finishProgressBar(this.activeProgressBar, "[Auto-finished]");
|
|
1613
|
-
}
|
|
1614
|
-
const barLength = 20;
|
|
1615
|
-
this.activeProgressBar = {
|
|
1616
|
-
total,
|
|
1617
|
-
current: 0,
|
|
1618
|
-
message: initialMessage,
|
|
1619
|
-
barLength,
|
|
1620
|
-
lastRenderedLine: ""
|
|
1621
|
-
};
|
|
1622
|
-
this.renderProgressBar(this.activeProgressBar);
|
|
1623
|
-
const update = (current, message) => {
|
|
1624
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1625
|
-
return;
|
|
1626
|
-
this.activeProgressBar.current = Math.max(0, Math.min(total, current));
|
|
1627
|
-
if (message !== undefined) {
|
|
1628
|
-
this.activeProgressBar.message = message;
|
|
1629
|
-
}
|
|
1630
|
-
const isFinished = this.activeProgressBar.current === this.activeProgressBar.total;
|
|
1631
|
-
this.renderProgressBar(this.activeProgressBar, isFinished);
|
|
1632
|
-
};
|
|
1633
|
-
const finish = (message) => {
|
|
1634
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1635
|
-
return;
|
|
1636
|
-
this.activeProgressBar.current = this.activeProgressBar.total;
|
|
1637
|
-
if (message !== undefined) {
|
|
1638
|
-
this.activeProgressBar.message = message;
|
|
1639
|
-
}
|
|
1640
|
-
this.renderProgressBar(this.activeProgressBar, true);
|
|
1641
|
-
this.finishProgressBar(this.activeProgressBar);
|
|
1642
|
-
};
|
|
1643
|
-
const interrupt = (interruptMessage, level = "info") => {
|
|
1644
|
-
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
|
|
1645
|
-
return;
|
|
1646
|
-
process5.stdout.write(`${"\r".padEnd(process5.stdout.columns || 80)}\r`);
|
|
1647
|
-
this.log(level, interruptMessage);
|
|
1648
|
-
setTimeout(() => {
|
|
1649
|
-
if (this.activeProgressBar) {
|
|
1650
|
-
this.renderProgressBar(this.activeProgressBar);
|
|
1651
|
-
}
|
|
1652
|
-
}, 50);
|
|
1653
|
-
};
|
|
1654
|
-
return { update, finish, interrupt };
|
|
1655
|
-
}
|
|
1656
|
-
renderProgressBar(barState, isFinished = false) {
|
|
1657
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY)
|
|
1658
|
-
return;
|
|
1659
|
-
const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
|
|
1660
|
-
const filledLength = Math.round(barState.barLength * percent / 100);
|
|
1661
|
-
const emptyLength = barState.barLength - filledLength;
|
|
1662
|
-
const filledBar = styles.green("\u2501".repeat(filledLength));
|
|
1663
|
-
const emptyBar = styles.gray("\u2501".repeat(emptyLength));
|
|
1664
|
-
const bar = `[${filledBar}${emptyBar}]`;
|
|
1665
|
-
const percentageText = `${percent}%`.padStart(4);
|
|
1666
|
-
const messageText = barState.message ? ` ${barState.message}` : "";
|
|
1667
|
-
const icon = isFinished || percent === 100 ? styles.green("\u2713") : styles.blue("\u25B6");
|
|
1668
|
-
const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
|
|
1669
|
-
const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
|
|
1670
|
-
const terminalWidth = process5.stdout.columns || 80;
|
|
1671
|
-
const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
|
|
1672
|
-
barState.lastRenderedLine = `${line}${clearLine}`;
|
|
1673
|
-
process5.stdout.write(barState.lastRenderedLine);
|
|
1674
|
-
if (isFinished) {
|
|
1675
|
-
process5.stdout.write(`
|
|
1676
|
-
`);
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
finishProgressBar(barState, finalMessage) {
|
|
1680
|
-
if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY) {
|
|
1681
|
-
this.activeProgressBar = null;
|
|
1682
|
-
return;
|
|
1683
|
-
}
|
|
1684
|
-
if (barState.current < barState.total) {
|
|
1685
|
-
barState.current = barState.total;
|
|
1686
|
-
}
|
|
1687
|
-
if (finalMessage)
|
|
1688
|
-
barState.message = finalMessage;
|
|
1689
|
-
this.renderProgressBar(barState, true);
|
|
1690
|
-
this.activeProgressBar = null;
|
|
1691
|
-
}
|
|
1692
|
-
async clear(filters = {}) {
|
|
1693
|
-
if (isBrowserProcess()) {
|
|
1694
|
-
console.warn("Log clearing is not supported in browser environments.");
|
|
1695
|
-
return;
|
|
1696
|
-
}
|
|
1697
|
-
try {
|
|
1698
|
-
console.warn("Clearing logs...", this.config.logDirectory);
|
|
1699
|
-
const files = await readdir(this.config.logDirectory);
|
|
1700
|
-
const logFilesToDelete = [];
|
|
1701
|
-
for (const file of files) {
|
|
1702
|
-
const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
|
|
1703
|
-
if (!nameMatches || !file.endsWith(".log")) {
|
|
1704
|
-
continue;
|
|
1705
|
-
}
|
|
1706
|
-
const filePath = join2(this.config.logDirectory, file);
|
|
1707
|
-
if (filters.before) {
|
|
1708
|
-
try {
|
|
1709
|
-
const fileStats = await stat(filePath);
|
|
1710
|
-
if (fileStats.mtime >= filters.before) {
|
|
1711
|
-
continue;
|
|
1712
|
-
}
|
|
1713
|
-
} catch (statErr) {
|
|
1714
|
-
console.error(`Failed to get stats for file ${filePath}:`, statErr);
|
|
1715
|
-
continue;
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
logFilesToDelete.push(filePath);
|
|
1719
|
-
}
|
|
1720
|
-
if (logFilesToDelete.length === 0) {
|
|
1721
|
-
console.warn("No log files matched the criteria for clearing.");
|
|
1722
|
-
return;
|
|
1723
|
-
}
|
|
1724
|
-
console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
|
|
1725
|
-
for (const filePath of logFilesToDelete) {
|
|
1726
|
-
try {
|
|
1727
|
-
await unlink(filePath);
|
|
1728
|
-
console.warn(`Deleted log file: ${filePath}`);
|
|
1729
|
-
} catch (unlinkErr) {
|
|
1730
|
-
console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
console.warn("Log clearing process finished.");
|
|
1734
|
-
} catch (err) {
|
|
1735
|
-
console.error("Error during log clearing process:", err);
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
var logger = new Logger("stacks");
|
|
1740
|
-
function deepMerge2(target, source) {
|
|
1741
|
-
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) {
|
|
1742
|
-
return source;
|
|
1743
|
-
}
|
|
1744
|
-
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) {
|
|
1745
|
-
return { a: null, b: 2, c: undefined };
|
|
1746
|
-
}
|
|
1747
|
-
if (source === null || source === undefined) {
|
|
1748
|
-
return target;
|
|
1749
|
-
}
|
|
1750
|
-
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
1751
|
-
return source;
|
|
1752
|
-
}
|
|
1753
|
-
if (Array.isArray(source) && Array.isArray(target)) {
|
|
1754
|
-
if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
1755
|
-
return source;
|
|
1756
|
-
}
|
|
1757
|
-
if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
|
|
1758
|
-
const result = [...source];
|
|
1759
|
-
for (const targetItem of target) {
|
|
1760
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1761
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1762
|
-
if (!existingItem) {
|
|
1763
|
-
result.push(targetItem);
|
|
1764
|
-
}
|
|
1765
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1766
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1767
|
-
if (!existingItem) {
|
|
1768
|
-
result.push(targetItem);
|
|
1769
|
-
}
|
|
1770
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1771
|
-
result.push(targetItem);
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
return result;
|
|
1775
|
-
}
|
|
1776
|
-
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
1777
|
-
const result = [...source];
|
|
1778
|
-
for (const item of target) {
|
|
1779
|
-
if (!result.includes(item)) {
|
|
1780
|
-
result.push(item);
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
|
-
return result;
|
|
1784
|
-
}
|
|
1785
|
-
return source;
|
|
1786
|
-
}
|
|
1787
|
-
if (!isObject2(source) || !isObject2(target)) {
|
|
1788
|
-
return source;
|
|
1789
|
-
}
|
|
1790
|
-
const merged = { ...target };
|
|
1791
|
-
for (const key in source) {
|
|
1792
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1793
|
-
const sourceValue = source[key];
|
|
1794
|
-
if (sourceValue === null || sourceValue === undefined) {
|
|
1795
|
-
continue;
|
|
1796
|
-
} else if (isObject2(sourceValue) && isObject2(merged[key])) {
|
|
1797
|
-
merged[key] = deepMerge2(merged[key], sourceValue);
|
|
1798
|
-
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
1799
|
-
if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
|
|
1800
|
-
const result = [...sourceValue];
|
|
1801
|
-
for (const targetItem of merged[key]) {
|
|
1802
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1803
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1804
|
-
if (!existingItem) {
|
|
1805
|
-
result.push(targetItem);
|
|
1806
|
-
}
|
|
1807
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1808
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1809
|
-
if (!existingItem) {
|
|
1810
|
-
result.push(targetItem);
|
|
1811
|
-
}
|
|
1812
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1813
|
-
result.push(targetItem);
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
merged[key] = result;
|
|
1817
|
-
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
1818
|
-
const result = [...sourceValue];
|
|
1819
|
-
for (const item of merged[key]) {
|
|
1820
|
-
if (!result.includes(item)) {
|
|
1821
|
-
result.push(item);
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
|
-
merged[key] = result;
|
|
1825
|
-
} else {
|
|
1826
|
-
merged[key] = sourceValue;
|
|
1827
|
-
}
|
|
1828
|
-
} else {
|
|
1829
|
-
merged[key] = sourceValue;
|
|
1830
|
-
}
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
return merged;
|
|
1834
|
-
}
|
|
1835
|
-
function deepMergeWithArrayStrategy(target, source, strategy = "replace") {
|
|
1836
|
-
if (source === null || source === undefined)
|
|
1837
|
-
return target;
|
|
1838
|
-
if (Array.isArray(source)) {
|
|
1839
|
-
return strategy === "replace" ? source : deepMerge2(target, source);
|
|
1840
|
-
}
|
|
1841
|
-
if (Array.isArray(target)) {
|
|
1842
|
-
return strategy === "replace" ? source : deepMerge2(target, source);
|
|
1843
|
-
}
|
|
1844
|
-
if (!isObject2(source) || !isObject2(target))
|
|
1845
|
-
return source;
|
|
1846
|
-
const result = { ...target };
|
|
1847
|
-
for (const key of Object.keys(source)) {
|
|
1848
|
-
if (!Object.prototype.hasOwnProperty.call(source, key))
|
|
1849
|
-
continue;
|
|
1850
|
-
const sourceValue = source[key];
|
|
1851
|
-
const targetValue = result[key];
|
|
1852
|
-
if (sourceValue === null || sourceValue === undefined)
|
|
1853
|
-
continue;
|
|
1854
|
-
if (Array.isArray(sourceValue) || Array.isArray(targetValue)) {
|
|
1855
|
-
if (strategy === "replace") {
|
|
1856
|
-
result[key] = sourceValue;
|
|
1857
|
-
} else {
|
|
1858
|
-
result[key] = deepMerge2(targetValue, sourceValue);
|
|
1859
|
-
}
|
|
1860
|
-
} else if (isObject2(sourceValue) && isObject2(targetValue)) {
|
|
1861
|
-
result[key] = deepMergeWithArrayStrategy(targetValue, sourceValue, strategy);
|
|
1862
|
-
} else {
|
|
1863
|
-
result[key] = sourceValue;
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1866
|
-
return result;
|
|
1867
|
-
}
|
|
1868
|
-
function deepEquals2(a, b) {
|
|
1869
|
-
if (a === b)
|
|
1870
|
-
return true;
|
|
1871
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1872
|
-
if (a.length !== b.length)
|
|
1873
|
-
return false;
|
|
1874
|
-
for (let i = 0;i < a.length; i++) {
|
|
1875
|
-
if (!deepEquals2(a[i], b[i]))
|
|
1876
|
-
return false;
|
|
1877
|
-
}
|
|
1878
|
-
return true;
|
|
1879
|
-
}
|
|
1880
|
-
if (isObject2(a) && isObject2(b)) {
|
|
1881
|
-
const keysA = Object.keys(a);
|
|
1882
|
-
const keysB = Object.keys(b);
|
|
1883
|
-
if (keysA.length !== keysB.length)
|
|
1884
|
-
return false;
|
|
1885
|
-
for (const key of keysA) {
|
|
1886
|
-
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
1887
|
-
return false;
|
|
1888
|
-
if (!deepEquals2(a[key], b[key]))
|
|
1889
|
-
return false;
|
|
1890
|
-
}
|
|
1891
|
-
return true;
|
|
1892
|
-
}
|
|
1893
|
-
return false;
|
|
1894
|
-
}
|
|
1895
|
-
function isObject2(item) {
|
|
1896
|
-
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
1897
|
-
}
|
|
1898
|
-
var log = new Logger("bunfig", {
|
|
1899
|
-
showTags: true
|
|
1900
|
-
});
|
|
1901
|
-
async function tryLoadConfig2(configPath, defaultConfig2, arrayStrategy = "replace") {
|
|
1902
|
-
if (!existsSync3(configPath))
|
|
1903
|
-
return null;
|
|
1904
|
-
try {
|
|
1905
|
-
const importedConfig = await import(configPath);
|
|
1906
|
-
const loadedConfig = importedConfig.default || importedConfig;
|
|
1907
|
-
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
1908
|
-
return null;
|
|
1909
|
-
try {
|
|
1910
|
-
return deepMergeWithArrayStrategy(defaultConfig2, loadedConfig, arrayStrategy);
|
|
1911
|
-
} catch {
|
|
1912
|
-
return null;
|
|
1913
|
-
}
|
|
1914
|
-
} catch {
|
|
1915
|
-
return null;
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
function applyEnvVarsToConfig(name, config3, verbose = false) {
|
|
1919
|
-
if (!name)
|
|
1920
|
-
return config3;
|
|
1921
|
-
const envPrefix = name.toUpperCase().replace(/-/g, "_");
|
|
1922
|
-
const result = { ...config3 };
|
|
1923
|
-
function processObject(obj, path = []) {
|
|
1924
|
-
const result2 = { ...obj };
|
|
1925
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
1926
|
-
const envPath = [...path, key];
|
|
1927
|
-
const formatKey = (k) => k.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
1928
|
-
const envKey = `${envPrefix}_${envPath.map(formatKey).join("_")}`;
|
|
1929
|
-
const oldEnvKey = `${envPrefix}_${envPath.map((p) => p.toUpperCase()).join("_")}`;
|
|
1930
|
-
if (verbose)
|
|
1931
|
-
log.info(`Checking environment variable ${envKey} for config ${name}.${envPath.join(".")}`);
|
|
1932
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1933
|
-
result2[key] = processObject(value, envPath);
|
|
1934
|
-
} else {
|
|
1935
|
-
const envValue = process6.env[envKey] || process6.env[oldEnvKey];
|
|
1936
|
-
if (envValue !== undefined) {
|
|
1937
|
-
if (verbose) {
|
|
1938
|
-
log.info(`Using environment variable ${envValue ? envKey : oldEnvKey} for config ${name}.${envPath.join(".")}`);
|
|
1939
|
-
}
|
|
1940
|
-
if (typeof value === "number") {
|
|
1941
|
-
result2[key] = Number(envValue);
|
|
1942
|
-
} else if (typeof value === "boolean") {
|
|
1943
|
-
result2[key] = envValue.toLowerCase() === "true";
|
|
1944
|
-
} else if (Array.isArray(value)) {
|
|
1945
|
-
try {
|
|
1946
|
-
const parsed = JSON.parse(envValue);
|
|
1947
|
-
if (Array.isArray(parsed)) {
|
|
1948
|
-
result2[key] = parsed;
|
|
1949
|
-
} else {
|
|
1950
|
-
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1951
|
-
}
|
|
1952
|
-
} catch {
|
|
1953
|
-
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1954
|
-
}
|
|
1955
|
-
} else {
|
|
1956
|
-
result2[key] = envValue;
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
return result2;
|
|
1962
|
-
}
|
|
1963
|
-
return processObject(result);
|
|
1964
|
-
}
|
|
1965
|
-
async function loadConfig3({
|
|
1966
|
-
name = "",
|
|
1967
|
-
alias,
|
|
1968
|
-
cwd,
|
|
1969
|
-
configDir,
|
|
1970
|
-
defaultConfig: defaultConfig2,
|
|
1971
|
-
verbose = false,
|
|
1972
|
-
checkEnv = true,
|
|
1973
|
-
arrayStrategy = "replace"
|
|
1974
|
-
}) {
|
|
1975
|
-
const configWithEnvVars = checkEnv && typeof defaultConfig2 === "object" && defaultConfig2 !== null && !Array.isArray(defaultConfig2) ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
1976
|
-
const baseDir = cwd || process6.cwd();
|
|
1977
|
-
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
1978
|
-
if (verbose) {
|
|
1979
|
-
log.info(`Loading configuration for "${name}"${alias ? ` (alias: "${alias}")` : ""} from ${baseDir}`);
|
|
1980
|
-
}
|
|
1981
|
-
const primaryBarePatterns = [name, `.${name}`].filter(Boolean);
|
|
1982
|
-
const primaryConfigSuffixPatterns = [`${name}.config`, `.${name}.config`].filter(Boolean);
|
|
1983
|
-
const aliasBarePatterns = alias ? [alias, `.${alias}`] : [];
|
|
1984
|
-
const aliasConfigSuffixPatterns = alias ? [`${alias}.config`, `.${alias}.config`] : [];
|
|
1985
|
-
const searchDirectories = Array.from(new Set([
|
|
1986
|
-
baseDir,
|
|
1987
|
-
resolve3(baseDir, "config"),
|
|
1988
|
-
resolve3(baseDir, ".config"),
|
|
1989
|
-
configDir ? resolve3(baseDir, configDir) : undefined
|
|
1990
|
-
].filter(Boolean)));
|
|
1991
|
-
for (const dir of searchDirectories) {
|
|
1992
|
-
if (verbose)
|
|
1993
|
-
log.info(`Searching for configuration in: ${dir}`);
|
|
1994
|
-
const isConfigLikeDir = [resolve3(baseDir, "config"), resolve3(baseDir, ".config")].concat(configDir ? [resolve3(baseDir, configDir)] : []).includes(dir);
|
|
1995
|
-
const patternsForDir = isConfigLikeDir ? [...primaryBarePatterns, ...primaryConfigSuffixPatterns, ...aliasBarePatterns, ...aliasConfigSuffixPatterns] : [...primaryConfigSuffixPatterns, ...primaryBarePatterns, ...aliasConfigSuffixPatterns, ...aliasBarePatterns];
|
|
1996
|
-
for (const configPath of patternsForDir) {
|
|
1997
|
-
for (const ext of extensions) {
|
|
1998
|
-
const fullPath = resolve3(dir, `${configPath}${ext}`);
|
|
1999
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2000
|
-
if (config3 !== null) {
|
|
2001
|
-
if (verbose) {
|
|
2002
|
-
log.success(`Configuration loaded from: ${fullPath}`);
|
|
2003
|
-
}
|
|
2004
|
-
return config3;
|
|
2005
|
-
}
|
|
2006
|
-
}
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
if (name) {
|
|
2010
|
-
const homeConfigDir = resolve3(homedir(), ".config", name);
|
|
2011
|
-
const homeConfigPatterns = ["config", `${name}.config`];
|
|
2012
|
-
if (alias) {
|
|
2013
|
-
homeConfigPatterns.push(`${alias}.config`);
|
|
2014
|
-
}
|
|
2015
|
-
if (verbose) {
|
|
2016
|
-
log.info(`Checking user config directory: ${homeConfigDir}`);
|
|
2017
|
-
}
|
|
2018
|
-
for (const configPath of homeConfigPatterns) {
|
|
2019
|
-
for (const ext of extensions) {
|
|
2020
|
-
const fullPath = resolve3(homeConfigDir, `${configPath}${ext}`);
|
|
2021
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2022
|
-
if (config3 !== null) {
|
|
2023
|
-
if (verbose) {
|
|
2024
|
-
log.success(`Configuration loaded from user config directory: ${fullPath}`);
|
|
2025
|
-
}
|
|
2026
|
-
return config3;
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
if (name) {
|
|
2032
|
-
const homeConfigDir = resolve3(homedir(), ".config");
|
|
2033
|
-
const homeConfigDotfilePatterns = [`.${name}.config`];
|
|
2034
|
-
if (alias)
|
|
2035
|
-
homeConfigDotfilePatterns.push(`.${alias}.config`);
|
|
2036
|
-
if (verbose)
|
|
2037
|
-
log.info(`Checking user config directory for dotfile configs: ${homeConfigDir}`);
|
|
2038
|
-
for (const configPath of homeConfigDotfilePatterns) {
|
|
2039
|
-
for (const ext of extensions) {
|
|
2040
|
-
const fullPath = resolve3(homeConfigDir, `${configPath}${ext}`);
|
|
2041
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2042
|
-
if (config3 !== null) {
|
|
2043
|
-
if (verbose)
|
|
2044
|
-
log.success(`Configuration loaded from user config directory dotfile: ${fullPath}`);
|
|
2045
|
-
return config3;
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
if (name) {
|
|
2051
|
-
const homeDir = homedir();
|
|
2052
|
-
const homeRootPatterns = [`.${name}.config`, `.${name}`];
|
|
2053
|
-
if (alias) {
|
|
2054
|
-
homeRootPatterns.push(`.${alias}.config`);
|
|
2055
|
-
homeRootPatterns.push(`.${alias}`);
|
|
2056
|
-
}
|
|
2057
|
-
if (verbose)
|
|
2058
|
-
log.info(`Checking user home directory for dotfile configs: ${homeDir}`);
|
|
2059
|
-
for (const configPath of homeRootPatterns) {
|
|
2060
|
-
for (const ext of extensions) {
|
|
2061
|
-
const fullPath = resolve3(homeDir, `${configPath}${ext}`);
|
|
2062
|
-
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars, arrayStrategy);
|
|
2063
|
-
if (config3 !== null) {
|
|
2064
|
-
if (verbose)
|
|
2065
|
-
log.success(`Configuration loaded from user home directory: ${fullPath}`);
|
|
2066
|
-
return config3;
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
try {
|
|
2072
|
-
const pkgPath = resolve3(baseDir, "package.json");
|
|
2073
|
-
if (existsSync3(pkgPath)) {
|
|
2074
|
-
const pkg = await import(pkgPath);
|
|
2075
|
-
let pkgConfig = pkg[name];
|
|
2076
|
-
if (!pkgConfig && alias) {
|
|
2077
|
-
pkgConfig = pkg[alias];
|
|
2078
|
-
if (pkgConfig && verbose) {
|
|
2079
|
-
log.success(`Using alias "${alias}" configuration from package.json`);
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
2083
|
-
try {
|
|
2084
|
-
if (verbose) {
|
|
2085
|
-
log.success(`Configuration loaded from package.json: ${pkgConfig === pkg[name] ? name : alias}`);
|
|
2086
|
-
}
|
|
2087
|
-
return deepMergeWithArrayStrategy(configWithEnvVars, pkgConfig, arrayStrategy);
|
|
2088
|
-
} catch (error) {
|
|
2089
|
-
if (verbose) {
|
|
2090
|
-
log.warn(`Failed to merge package.json config:`, error);
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
} catch (error) {
|
|
2096
|
-
if (verbose) {
|
|
2097
|
-
log.warn(`Failed to load package.json:`, error);
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
if (verbose) {
|
|
2101
|
-
log.info(`No configuration found for "${name}"${alias ? ` or alias "${alias}"` : ""}, using default configuration with environment variables`);
|
|
2102
|
-
}
|
|
2103
|
-
return configWithEnvVars;
|
|
2104
|
-
}
|
|
2105
|
-
var defaultConfigDir2 = resolve3(process6.cwd(), "config");
|
|
2106
|
-
var defaultGeneratedDir2 = resolve3(process6.cwd(), "src/generated");
|
|
2107
|
-
function getProjectRoot2(filePath, options = {}) {
|
|
2108
|
-
let path = process7.cwd();
|
|
2109
|
-
while (path.includes("storage"))
|
|
2110
|
-
path = resolve4(path, "..");
|
|
2111
|
-
const finalPath = resolve4(path, filePath || "");
|
|
2112
|
-
if (options?.relative)
|
|
2113
|
-
return relative2(process7.cwd(), finalPath);
|
|
2114
|
-
return finalPath;
|
|
2115
|
-
}
|
|
2116
|
-
var defaultLogDirectory2 = process7.env.CLARITY_LOG_DIR || join3(getProjectRoot2(), "logs");
|
|
2117
|
-
var defaultConfig2 = {
|
|
2118
|
-
level: "info",
|
|
2119
|
-
defaultName: "clarity",
|
|
2120
|
-
timestamp: true,
|
|
2121
|
-
colors: true,
|
|
2122
|
-
format: "text",
|
|
2123
|
-
maxLogSize: 10485760,
|
|
2124
|
-
logDatePattern: "YYYY-MM-DD",
|
|
2125
|
-
logDirectory: defaultLogDirectory2,
|
|
2126
|
-
rotation: {
|
|
2127
|
-
frequency: "daily",
|
|
2128
|
-
maxSize: 10485760,
|
|
2129
|
-
maxFiles: 5,
|
|
2130
|
-
compress: false,
|
|
2131
|
-
rotateHour: 0,
|
|
2132
|
-
rotateMinute: 0,
|
|
2133
|
-
rotateDayOfWeek: 0,
|
|
2134
|
-
rotateDayOfMonth: 1,
|
|
2135
|
-
encrypt: false
|
|
2136
|
-
},
|
|
2137
|
-
verbose: false,
|
|
2138
|
-
writeToFile: false
|
|
2139
|
-
};
|
|
2140
|
-
async function loadConfig4() {
|
|
2141
|
-
try {
|
|
2142
|
-
const loadedConfig = await loadConfig3({
|
|
2143
|
-
name: "clarity",
|
|
2144
|
-
alias: "logging",
|
|
2145
|
-
defaultConfig: defaultConfig2,
|
|
2146
|
-
cwd: process7.cwd()
|
|
2147
|
-
});
|
|
2148
|
-
return { ...defaultConfig2, ...loadedConfig || {} };
|
|
2149
|
-
} catch {
|
|
2150
|
-
return defaultConfig2;
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
var config2 = await loadConfig4();
|
|
2154
|
-
function isBrowserProcess2() {
|
|
2155
|
-
if (process9.env.NODE_ENV === "test" || process9.env.BUN_ENV === "test") {
|
|
2156
|
-
return false;
|
|
2157
|
-
}
|
|
2158
|
-
return typeof window !== "undefined";
|
|
2159
|
-
}
|
|
2160
|
-
async function isServerProcess2() {
|
|
2161
|
-
if (process9.env.NODE_ENV === "test" || process9.env.BUN_ENV === "test") {
|
|
2162
|
-
return true;
|
|
2163
|
-
}
|
|
2164
|
-
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
2165
|
-
return true;
|
|
2166
|
-
}
|
|
2167
|
-
if (typeof process9 !== "undefined") {
|
|
2168
|
-
const type = process9.type;
|
|
2169
|
-
if (type === "renderer" || type === "worker") {
|
|
2170
|
-
return false;
|
|
2171
|
-
}
|
|
2172
|
-
return !!(process9.versions && (process9.versions.node || process9.versions.bun));
|
|
2173
|
-
}
|
|
2174
|
-
return false;
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
class JsonFormatter2 {
|
|
2178
|
-
async format(entry) {
|
|
2179
|
-
const isServer = await isServerProcess2();
|
|
2180
|
-
const metadata = await this.getMetadata(isServer);
|
|
2181
|
-
return JSON.stringify({
|
|
2182
|
-
timestamp: entry.timestamp.toISOString(),
|
|
2183
|
-
level: entry.level,
|
|
2184
|
-
name: entry.name,
|
|
2185
|
-
message: entry.message,
|
|
2186
|
-
metadata
|
|
2187
|
-
});
|
|
2188
|
-
}
|
|
2189
|
-
async getMetadata(isServer) {
|
|
2190
|
-
if (isServer) {
|
|
2191
|
-
const { hostname } = await import("os");
|
|
2192
|
-
return {
|
|
2193
|
-
pid: process10.pid,
|
|
2194
|
-
hostname: hostname(),
|
|
2195
|
-
environment: process10.env.NODE_ENV || "development",
|
|
2196
|
-
platform: process10.platform,
|
|
2197
|
-
version: process10.version
|
|
2198
|
-
};
|
|
2199
|
-
}
|
|
2200
|
-
return {
|
|
2201
|
-
userAgent: navigator.userAgent,
|
|
2202
|
-
hostname: window.location.hostname || "browser",
|
|
2203
|
-
environment: process10.env.NODE_ENV || process10.env.BUN_ENV || "development",
|
|
2204
|
-
viewport: {
|
|
2205
|
-
width: window.innerWidth,
|
|
2206
|
-
height: window.innerHeight
|
|
2207
|
-
},
|
|
2208
|
-
language: navigator.language
|
|
2209
|
-
};
|
|
2210
|
-
}
|
|
2211
|
-
}
|
|
2212
|
-
var terminalStyles2 = {
|
|
2213
|
-
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
2214
|
-
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
2215
|
-
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
2216
|
-
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
2217
|
-
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
2218
|
-
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
2219
|
-
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
2220
|
-
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
2221
|
-
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
2222
|
-
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
2223
|
-
bgGray: (text) => `\x1B[100m${text}\x1B[0m`,
|
|
2224
|
-
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
2225
|
-
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
2226
|
-
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
2227
|
-
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
2228
|
-
strikethrough: (text) => `\x1B[9m${text}\x1B[0m`,
|
|
2229
|
-
reset: "\x1B[0m"
|
|
2230
|
-
};
|
|
2231
|
-
var styles2 = terminalStyles2;
|
|
2232
|
-
var red2 = terminalStyles2.red;
|
|
2233
|
-
var green2 = terminalStyles2.green;
|
|
2234
|
-
var yellow2 = terminalStyles2.yellow;
|
|
2235
|
-
var blue2 = terminalStyles2.blue;
|
|
2236
|
-
var magenta2 = terminalStyles2.magenta;
|
|
2237
|
-
var cyan2 = terminalStyles2.cyan;
|
|
2238
|
-
var white2 = terminalStyles2.white;
|
|
2239
|
-
var gray2 = terminalStyles2.gray;
|
|
2240
|
-
var bgRed2 = terminalStyles2.bgRed;
|
|
2241
|
-
var bgYellow2 = terminalStyles2.bgYellow;
|
|
2242
|
-
var bgGray = terminalStyles2.bgGray;
|
|
2243
|
-
var bold2 = terminalStyles2.bold;
|
|
2244
|
-
var dim2 = terminalStyles2.dim;
|
|
2245
|
-
var italic2 = terminalStyles2.italic;
|
|
2246
|
-
var underline2 = terminalStyles2.underline;
|
|
2247
|
-
var strikethrough = terminalStyles2.strikethrough;
|
|
2248
|
-
var reset2 = terminalStyles2.reset;
|
|
2249
|
-
var defaultFingersCrossedConfig2 = {
|
|
2250
|
-
activationLevel: "error",
|
|
2251
|
-
bufferSize: 50,
|
|
2252
|
-
flushOnDeactivation: true,
|
|
2253
|
-
stopBuffering: false
|
|
2254
|
-
};
|
|
2255
|
-
var levelIcons2 = {
|
|
2256
|
-
debug: "\uD83D\uDD0D",
|
|
2257
|
-
info: blue2("\u2139"),
|
|
2258
|
-
success: green2("\u2713"),
|
|
2259
|
-
warning: bgYellow2(white2(bold2(" WARN "))),
|
|
2260
|
-
error: bgRed2(white2(bold2(" ERROR ")))
|
|
2261
|
-
};
|
|
2262
|
-
|
|
2263
|
-
class Logger2 {
|
|
2264
|
-
name;
|
|
2265
|
-
fileLocks = new Map;
|
|
2266
|
-
currentKeyId = null;
|
|
2267
|
-
keys = new Map;
|
|
2268
|
-
fingersCrossedConfig;
|
|
2269
|
-
fingersCrossedActive = false;
|
|
2270
|
-
currentLogFile;
|
|
2271
|
-
rotationTimeout;
|
|
2272
|
-
keyRotationTimeout;
|
|
2273
|
-
encryptionKeys;
|
|
2274
|
-
logBuffer = [];
|
|
2275
|
-
isActivated = false;
|
|
2276
|
-
pendingOperations = [];
|
|
2277
|
-
enabled;
|
|
2278
|
-
fancy;
|
|
2279
|
-
tagFormat;
|
|
2280
|
-
timestampPosition;
|
|
2281
|
-
environment;
|
|
2282
|
-
config;
|
|
2283
|
-
options;
|
|
2284
|
-
formatter;
|
|
2285
|
-
timers = new Set;
|
|
2286
|
-
subLoggers = new Set;
|
|
2287
|
-
fingersCrossedBuffer = [];
|
|
2288
|
-
ANSI_PATTERN = /\u001B\[.*?m/g;
|
|
2289
|
-
activeProgressBar = null;
|
|
2290
|
-
constructor(name, options = {}) {
|
|
2291
|
-
this.name = name;
|
|
2292
|
-
this.config = { ...config2 };
|
|
2293
|
-
this.options = this.normalizeOptions(options);
|
|
2294
|
-
this.formatter = this.options.formatter || new JsonFormatter2;
|
|
2295
|
-
this.enabled = options.enabled ?? true;
|
|
2296
|
-
this.fancy = options.fancy ?? true;
|
|
2297
|
-
this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
|
|
2298
|
-
this.timestampPosition = options.timestampPosition ?? "right";
|
|
2299
|
-
this.environment = options.environment ?? process11.env.APP_ENV ?? "local";
|
|
2300
|
-
this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
|
|
2301
|
-
const configOptions = { ...options };
|
|
2302
|
-
const hasTimestamp = options.timestamp !== undefined;
|
|
2303
|
-
if (hasTimestamp) {
|
|
2304
|
-
delete configOptions.timestamp;
|
|
2305
|
-
}
|
|
2306
|
-
this.config = {
|
|
2307
|
-
...this.config,
|
|
2308
|
-
...configOptions,
|
|
2309
|
-
timestamp: hasTimestamp || this.config.timestamp
|
|
2310
|
-
};
|
|
2311
|
-
this.currentLogFile = this.generateLogFilename();
|
|
2312
|
-
this.encryptionKeys = new Map;
|
|
2313
|
-
if (this.validateEncryptionConfig()) {
|
|
2314
|
-
this.setupRotation();
|
|
2315
|
-
const initialKeyId = this.generateKeyId();
|
|
2316
|
-
const initialKey = this.generateKey();
|
|
2317
|
-
this.currentKeyId = initialKeyId;
|
|
2318
|
-
this.keys.set(initialKeyId, initialKey);
|
|
2319
|
-
this.encryptionKeys.set(initialKeyId, {
|
|
2320
|
-
key: initialKey,
|
|
2321
|
-
createdAt: new Date
|
|
2322
|
-
});
|
|
2323
|
-
this.setupKeyRotation();
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
shouldActivateFingersCrossed(level) {
|
|
2327
|
-
if (!this.fingersCrossedConfig)
|
|
2328
|
-
return false;
|
|
2329
|
-
const levels = {
|
|
2330
|
-
debug: 0,
|
|
2331
|
-
info: 1,
|
|
2332
|
-
success: 2,
|
|
2333
|
-
warning: 3,
|
|
2334
|
-
error: 4
|
|
2335
|
-
};
|
|
2336
|
-
const activation = this.fingersCrossedConfig.activationLevel ?? "error";
|
|
2337
|
-
return levels[level] >= levels[activation];
|
|
2338
|
-
}
|
|
2339
|
-
initializeFingersCrossedConfig(options) {
|
|
2340
|
-
if (!options.fingersCrossedEnabled && options.fingersCrossed) {
|
|
2341
|
-
return {
|
|
2342
|
-
...defaultFingersCrossedConfig2,
|
|
2343
|
-
...options.fingersCrossed
|
|
2344
|
-
};
|
|
2345
|
-
}
|
|
2346
|
-
if (!options.fingersCrossedEnabled) {
|
|
2347
|
-
return null;
|
|
2348
|
-
}
|
|
2349
|
-
if (!options.fingersCrossed) {
|
|
2350
|
-
return { ...defaultFingersCrossedConfig2 };
|
|
2351
|
-
}
|
|
2352
|
-
return {
|
|
2353
|
-
...defaultFingersCrossedConfig2,
|
|
2354
|
-
...options.fingersCrossed
|
|
2355
|
-
};
|
|
2356
|
-
}
|
|
2357
|
-
normalizeOptions(options) {
|
|
2358
|
-
const defaultOptions = {
|
|
2359
|
-
format: "json",
|
|
2360
|
-
level: "info",
|
|
2361
|
-
logDirectory: config2.logDirectory,
|
|
2362
|
-
rotation: undefined,
|
|
2363
|
-
timestamp: undefined,
|
|
2364
|
-
fingersCrossed: {},
|
|
2365
|
-
enabled: true,
|
|
2366
|
-
showTags: false,
|
|
2367
|
-
showIcons: true,
|
|
2368
|
-
formatter: undefined
|
|
2369
|
-
};
|
|
2370
|
-
const mergedOptions = {
|
|
2371
|
-
...defaultOptions,
|
|
2372
|
-
...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
|
|
2373
|
-
};
|
|
2374
|
-
if (!mergedOptions.level || !["debug", "info", "success", "warning", "error"].includes(mergedOptions.level)) {
|
|
2375
|
-
mergedOptions.level = defaultOptions.level;
|
|
2376
|
-
}
|
|
2377
|
-
return mergedOptions;
|
|
2378
|
-
}
|
|
2379
|
-
shouldWriteToFile() {
|
|
2380
|
-
return !isBrowserProcess2() && this.config.writeToFile === true;
|
|
2381
|
-
}
|
|
2382
|
-
async writeToFile(data) {
|
|
2383
|
-
const cancelled = false;
|
|
2384
|
-
const operationPromise = (async () => {
|
|
2385
|
-
let fd;
|
|
2386
|
-
let retries = 0;
|
|
2387
|
-
const maxRetries = 3;
|
|
2388
|
-
const backoffDelay = 1000;
|
|
2389
|
-
while (retries < maxRetries) {
|
|
2390
|
-
try {
|
|
2391
|
-
try {
|
|
2392
|
-
try {
|
|
2393
|
-
await access2(this.config.logDirectory, constants2.F_OK | constants2.W_OK);
|
|
2394
|
-
} catch (err) {
|
|
2395
|
-
if (err instanceof Error && "code" in err) {
|
|
2396
|
-
if (err.code === "ENOENT") {
|
|
2397
|
-
await mkdir2(this.config.logDirectory, { recursive: true, mode: 493 });
|
|
2398
|
-
} else if (err.code === "EACCES") {
|
|
2399
|
-
throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
|
|
2400
|
-
} else {
|
|
2401
|
-
throw err;
|
|
2402
|
-
}
|
|
2403
|
-
} else {
|
|
2404
|
-
throw err;
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
} catch (err) {
|
|
2408
|
-
console.error("Debug: [writeToFile] Failed to create log directory:", err);
|
|
2409
|
-
throw err;
|
|
2410
|
-
}
|
|
2411
|
-
if (cancelled)
|
|
2412
|
-
throw new Error("Operation cancelled: Logger was destroyed");
|
|
2413
|
-
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer2.from(data);
|
|
2414
|
-
try {
|
|
2415
|
-
if (!existsSync4(this.currentLogFile)) {
|
|
2416
|
-
await writeFile2(this.currentLogFile, "", { mode: 420 });
|
|
2417
|
-
}
|
|
2418
|
-
fd = openSync2(this.currentLogFile, "a", 420);
|
|
2419
|
-
writeFileSync4(fd, dataToWrite, { flag: "a" });
|
|
2420
|
-
fsyncSync2(fd);
|
|
2421
|
-
if (fd !== undefined) {
|
|
2422
|
-
closeSync2(fd);
|
|
2423
|
-
fd = undefined;
|
|
2424
|
-
}
|
|
2425
|
-
const stats = await stat2(this.currentLogFile);
|
|
2426
|
-
if (stats.size === 0) {
|
|
2427
|
-
await writeFile2(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
|
|
2428
|
-
const retryStats = await stat2(this.currentLogFile);
|
|
2429
|
-
if (retryStats.size === 0) {
|
|
2430
|
-
throw new Error("File exists but is empty after retry write");
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
return;
|
|
2434
|
-
} catch (err) {
|
|
2435
|
-
const error = err;
|
|
2436
|
-
if (error.code && ["ENETDOWN", "ENETUNREACH", "ENOTFOUND", "ETIMEDOUT"].includes(error.code)) {
|
|
2437
|
-
if (retries < maxRetries - 1) {
|
|
2438
|
-
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
2439
|
-
console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
|
|
2440
|
-
const delay = backoffDelay * 2 ** retries;
|
|
2441
|
-
await new Promise((resolve52) => setTimeout(resolve52, delay));
|
|
2442
|
-
retries++;
|
|
2443
|
-
continue;
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
if (error?.code && ["ENOSPC", "EDQUOT"].includes(error.code)) {
|
|
2447
|
-
throw new Error(`Disk quota exceeded or no space left on device: ${error.message}`);
|
|
2448
|
-
}
|
|
2449
|
-
console.error("Debug: [writeToFile] Error writing to file:", error);
|
|
2450
|
-
throw error;
|
|
2451
|
-
} finally {
|
|
2452
|
-
if (fd !== undefined) {
|
|
2453
|
-
try {
|
|
2454
|
-
closeSync2(fd);
|
|
2455
|
-
} catch (err) {
|
|
2456
|
-
console.error("Debug: [writeToFile] Error closing file descriptor:", err);
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
} catch (err) {
|
|
2461
|
-
if (retries === maxRetries - 1) {
|
|
2462
|
-
const error = err;
|
|
2463
|
-
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
2464
|
-
console.error("Debug: [writeToFile] Max retries reached. Final error:", errorMessage);
|
|
2465
|
-
throw err;
|
|
2466
|
-
}
|
|
2467
|
-
retries++;
|
|
2468
|
-
const delay = backoffDelay * 2 ** (retries - 1);
|
|
2469
|
-
await new Promise((resolve52) => setTimeout(resolve52, delay));
|
|
2470
|
-
}
|
|
2471
|
-
}
|
|
2472
|
-
})();
|
|
2473
|
-
this.pendingOperations.push(operationPromise);
|
|
2474
|
-
const index = this.pendingOperations.length - 1;
|
|
2475
|
-
try {
|
|
2476
|
-
await operationPromise;
|
|
2477
|
-
} catch (err) {
|
|
2478
|
-
console.error("Debug: [writeToFile] Error in operation:", err);
|
|
2479
|
-
throw err;
|
|
2480
|
-
} finally {
|
|
2481
|
-
this.pendingOperations.splice(index, 1);
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
generateLogFilename() {
|
|
2485
|
-
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")) {
|
|
2486
|
-
return join5(this.config.logDirectory, `${this.name}.log`);
|
|
2487
|
-
}
|
|
2488
|
-
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") {
|
|
2489
|
-
return join5(this.config.logDirectory, `${this.name}.log`);
|
|
2490
|
-
}
|
|
2491
|
-
const date = new Date().toISOString().split("T")[0];
|
|
2492
|
-
return join5(this.config.logDirectory, `${this.name}-${date}.log`);
|
|
2493
|
-
}
|
|
2494
|
-
setupRotation() {
|
|
2495
|
-
if (isBrowserProcess2())
|
|
2496
|
-
return;
|
|
2497
|
-
if (!this.shouldWriteToFile())
|
|
2498
|
-
return;
|
|
2499
|
-
if (typeof this.config.rotation === "boolean")
|
|
2500
|
-
return;
|
|
2501
|
-
const config3 = this.config.rotation;
|
|
2502
|
-
let interval;
|
|
2503
|
-
switch (config3.frequency) {
|
|
2504
|
-
case "daily":
|
|
2505
|
-
interval = 86400000;
|
|
2506
|
-
break;
|
|
2507
|
-
case "weekly":
|
|
2508
|
-
interval = 604800000;
|
|
2509
|
-
break;
|
|
2510
|
-
case "monthly":
|
|
2511
|
-
interval = 2592000000;
|
|
2512
|
-
break;
|
|
2513
|
-
default:
|
|
2514
|
-
return;
|
|
2515
|
-
}
|
|
2516
|
-
this.rotationTimeout = setInterval(() => {
|
|
2517
|
-
this.rotateLog();
|
|
2518
|
-
}, interval);
|
|
2519
|
-
}
|
|
2520
|
-
setupKeyRotation() {
|
|
2521
|
-
if (!this.validateEncryptionConfig()) {
|
|
2522
|
-
console.error("Invalid encryption configuration detected during key rotation setup");
|
|
2523
|
-
return;
|
|
2524
|
-
}
|
|
2525
|
-
const rotation = this.config.rotation;
|
|
2526
|
-
const keyRotation = rotation.keyRotation;
|
|
2527
|
-
if (!keyRotation?.enabled) {
|
|
2528
|
-
return;
|
|
2529
|
-
}
|
|
2530
|
-
const rotationInterval = typeof keyRotation.interval === "number" ? keyRotation.interval : 60;
|
|
2531
|
-
const interval = Math.max(rotationInterval, 60) * 1000;
|
|
2532
|
-
this.keyRotationTimeout = setInterval(() => {
|
|
2533
|
-
this.rotateKeys().catch((error) => {
|
|
2534
|
-
console.error("Error rotating keys:", error);
|
|
2535
|
-
});
|
|
2536
|
-
}, interval);
|
|
2537
|
-
}
|
|
2538
|
-
async rotateKeys() {
|
|
2539
|
-
if (!this.validateEncryptionConfig()) {
|
|
2540
|
-
console.error("Invalid encryption configuration detected during key rotation");
|
|
2541
|
-
return;
|
|
2542
|
-
}
|
|
2543
|
-
const rotation = this.config.rotation;
|
|
2544
|
-
const keyRotation = rotation.keyRotation;
|
|
2545
|
-
const newKeyId = this.generateKeyId();
|
|
2546
|
-
const newKey = this.generateKey();
|
|
2547
|
-
this.currentKeyId = newKeyId;
|
|
2548
|
-
this.keys.set(newKeyId, newKey);
|
|
2549
|
-
this.encryptionKeys.set(newKeyId, {
|
|
2550
|
-
key: newKey,
|
|
2551
|
-
createdAt: new Date
|
|
2552
|
-
});
|
|
2553
|
-
const sortedKeys = Array.from(this.encryptionKeys.entries()).sort(([, a], [, b]) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2554
|
-
const maxKeyCount = typeof keyRotation.maxKeys === "number" ? keyRotation.maxKeys : 1;
|
|
2555
|
-
const maxKeys = Math.max(1, maxKeyCount);
|
|
2556
|
-
if (sortedKeys.length > maxKeys) {
|
|
2557
|
-
for (const [keyId] of sortedKeys.slice(maxKeys)) {
|
|
2558
|
-
this.encryptionKeys.delete(keyId);
|
|
2559
|
-
this.keys.delete(keyId);
|
|
2560
|
-
}
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
generateKeyId() {
|
|
2564
|
-
return randomBytes2(16).toString("hex");
|
|
2565
|
-
}
|
|
2566
|
-
generateKey() {
|
|
2567
|
-
return randomBytes2(32);
|
|
2568
|
-
}
|
|
2569
|
-
getCurrentKey() {
|
|
2570
|
-
if (!this.currentKeyId) {
|
|
2571
|
-
throw new Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");
|
|
2572
|
-
}
|
|
2573
|
-
const key = this.keys.get(this.currentKeyId);
|
|
2574
|
-
if (!key) {
|
|
2575
|
-
throw new Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);
|
|
2576
|
-
}
|
|
2577
|
-
return { key, id: this.currentKeyId };
|
|
2578
|
-
}
|
|
2579
|
-
encrypt(data) {
|
|
2580
|
-
const { key } = this.getCurrentKey();
|
|
2581
|
-
const iv = randomBytes2(16);
|
|
2582
|
-
const cipher = createCipheriv2("aes-256-gcm", key, iv);
|
|
2583
|
-
const input = Buffer2.isBuffer(data) ? data : Buffer2.from(data, "utf8");
|
|
2584
|
-
const part1 = cipher.update(input);
|
|
2585
|
-
const part2 = cipher.final();
|
|
2586
|
-
const totalCipherLen = part1.length + part2.length;
|
|
2587
|
-
const authTag = cipher.getAuthTag();
|
|
2588
|
-
const out = Buffer2.allocUnsafe(16 + totalCipherLen + 16);
|
|
2589
|
-
iv.copy(out, 0);
|
|
2590
|
-
part1.copy(out, 16);
|
|
2591
|
-
part2.copy(out, 16 + part1.length);
|
|
2592
|
-
authTag.copy(out, 16 + totalCipherLen);
|
|
2593
|
-
return {
|
|
2594
|
-
encrypted: out,
|
|
2595
|
-
iv
|
|
2596
|
-
};
|
|
2597
|
-
}
|
|
2598
|
-
async compressData(data) {
|
|
2599
|
-
return new Promise((resolve52, reject) => {
|
|
2600
|
-
const gzip = createGzip2();
|
|
2601
|
-
const chunks = [];
|
|
2602
|
-
gzip.on("data", (chunk2) => chunks.push(chunk2));
|
|
2603
|
-
gzip.on("end", () => resolve52(Buffer2.from(Buffer2.concat(chunks))));
|
|
2604
|
-
gzip.on("error", reject);
|
|
2605
|
-
gzip.write(data);
|
|
2606
|
-
gzip.end();
|
|
2607
|
-
});
|
|
2608
|
-
}
|
|
2609
|
-
getEncryptionOptions() {
|
|
2610
|
-
if (!this.config.rotation || typeof this.config.rotation === "boolean" || !this.config.rotation.encrypt) {
|
|
2611
|
-
return {};
|
|
2612
|
-
}
|
|
2613
|
-
const defaultOptions = {
|
|
2614
|
-
algorithm: "aes-256-cbc",
|
|
2615
|
-
compress: false
|
|
2616
|
-
};
|
|
2617
|
-
if (typeof this.config.rotation.encrypt === "object") {
|
|
2618
|
-
const encryptConfig = this.config.rotation.encrypt;
|
|
2619
|
-
return {
|
|
2620
|
-
...defaultOptions,
|
|
2621
|
-
...encryptConfig
|
|
2622
|
-
};
|
|
2623
|
-
}
|
|
2624
|
-
return defaultOptions;
|
|
2625
|
-
}
|
|
2626
|
-
async rotateLog() {
|
|
2627
|
-
if (isBrowserProcess2())
|
|
2628
|
-
return;
|
|
2629
|
-
if (!this.shouldWriteToFile())
|
|
2630
|
-
return;
|
|
2631
|
-
const stats = await stat2(this.currentLogFile).catch(() => null);
|
|
2632
|
-
if (!stats)
|
|
2633
|
-
return;
|
|
2634
|
-
const config3 = this.config.rotation;
|
|
2635
|
-
if (typeof config3 === "boolean")
|
|
2636
|
-
return;
|
|
2637
|
-
if (config3.maxSize && stats.size >= config3.maxSize) {
|
|
2638
|
-
const oldFile = this.currentLogFile;
|
|
2639
|
-
const newFile = this.generateLogFilename();
|
|
2640
|
-
if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
|
|
2641
|
-
const files = await readdir2(this.config.logDirectory);
|
|
2642
|
-
const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
|
|
2643
|
-
const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
2644
|
-
const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
2645
|
-
return numB - numA;
|
|
2646
|
-
});
|
|
2647
|
-
const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
|
|
2648
|
-
const rotatedFile = `${oldFile}.${nextNum}`;
|
|
2649
|
-
if (await stat2(oldFile).catch(() => null)) {
|
|
2650
|
-
try {
|
|
2651
|
-
await rename2(oldFile, rotatedFile);
|
|
2652
|
-
if (config3.compress) {
|
|
2653
|
-
try {
|
|
2654
|
-
const compressedPath = `${rotatedFile}.gz`;
|
|
2655
|
-
await this.compressLogFile(rotatedFile, compressedPath);
|
|
2656
|
-
await unlink2(rotatedFile);
|
|
2657
|
-
} catch (err) {
|
|
2658
|
-
console.error("Error compressing rotated file:", err);
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
|
|
2662
|
-
try {
|
|
2663
|
-
const backupPath = `${oldFile}.1`;
|
|
2664
|
-
await writeFile2(backupPath, "");
|
|
2665
|
-
} catch (err) {
|
|
2666
|
-
console.error("Error creating backup file:", err);
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
} catch (err) {
|
|
2670
|
-
console.error(`Error during rotation: ${err instanceof Error ? err.message : String(err)}`);
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
} else {
|
|
2674
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
2675
|
-
const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
|
|
2676
|
-
if (await stat2(oldFile).catch(() => null)) {
|
|
2677
|
-
await rename2(oldFile, rotatedFile);
|
|
2678
|
-
}
|
|
2679
|
-
}
|
|
2680
|
-
this.currentLogFile = newFile;
|
|
2681
|
-
if (config3.maxFiles) {
|
|
2682
|
-
const files = await readdir2(this.config.logDirectory);
|
|
2683
|
-
const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
|
|
2684
|
-
for (const file of logFiles.slice(config3.maxFiles)) {
|
|
2685
|
-
await unlink2(join5(this.config.logDirectory, file));
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
}
|
|
2690
|
-
async compressLogFile(inputPath, outputPath) {
|
|
2691
|
-
const readStream = createReadStream2(inputPath);
|
|
2692
|
-
const writeStream = createWriteStream2(outputPath);
|
|
2693
|
-
const gzip = createGzip2();
|
|
2694
|
-
await pipeline2(readStream, gzip, writeStream);
|
|
2695
|
-
}
|
|
2696
|
-
async handleFingersCrossedBuffer(level, formattedEntry) {
|
|
2697
|
-
if (!this.fingersCrossedConfig)
|
|
2698
|
-
return;
|
|
2699
|
-
if (this.shouldActivateFingersCrossed(level) && !this.isActivated) {
|
|
2700
|
-
this.isActivated = true;
|
|
2701
|
-
for (const entry of this.logBuffer) {
|
|
2702
|
-
const formattedBufferedEntry = await this.formatter.format(entry);
|
|
2703
|
-
if (this.shouldWriteToFile())
|
|
2704
|
-
await this.writeToFile(formattedBufferedEntry);
|
|
2705
|
-
console.log(formattedBufferedEntry);
|
|
2706
|
-
}
|
|
2707
|
-
if (this.fingersCrossedConfig.stopBuffering)
|
|
2708
|
-
this.logBuffer = [];
|
|
2709
|
-
}
|
|
2710
|
-
if (this.isActivated) {
|
|
2711
|
-
if (this.shouldWriteToFile())
|
|
2712
|
-
await this.writeToFile(formattedEntry);
|
|
2713
|
-
console.log(formattedEntry);
|
|
2714
|
-
}
|
|
2715
|
-
}
|
|
2716
|
-
shouldLog(level) {
|
|
2717
|
-
if (!this.enabled)
|
|
2718
|
-
return false;
|
|
2719
|
-
const levels = {
|
|
2720
|
-
debug: 0,
|
|
2721
|
-
info: 1,
|
|
2722
|
-
success: 2,
|
|
2723
|
-
warning: 3,
|
|
2724
|
-
error: 4
|
|
2725
|
-
};
|
|
2726
|
-
return levels[level] >= levels[this.config.level];
|
|
2727
|
-
}
|
|
2728
|
-
async flushPendingWrites() {
|
|
2729
|
-
await Promise.all(this.pendingOperations.map((op) => {
|
|
2730
|
-
if (op instanceof Promise) {
|
|
2731
|
-
return op.catch((err) => {
|
|
2732
|
-
console.error("Error in pending write operation:", err);
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
return Promise.resolve();
|
|
2736
|
-
}));
|
|
2737
|
-
if (existsSync4(this.currentLogFile)) {
|
|
2738
|
-
try {
|
|
2739
|
-
const fd = openSync2(this.currentLogFile, "r+");
|
|
2740
|
-
fsyncSync2(fd);
|
|
2741
|
-
closeSync2(fd);
|
|
2742
|
-
} catch (error) {
|
|
2743
|
-
console.error(`Error flushing file: ${error}`);
|
|
2744
|
-
}
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
async destroy() {
|
|
2748
|
-
if (this.rotationTimeout)
|
|
2749
|
-
clearInterval(this.rotationTimeout);
|
|
2750
|
-
if (this.keyRotationTimeout)
|
|
2751
|
-
clearInterval(this.keyRotationTimeout);
|
|
2752
|
-
this.timers.clear();
|
|
2753
|
-
for (const op of this.pendingOperations) {
|
|
2754
|
-
if (typeof op.cancel === "function") {
|
|
2755
|
-
op.cancel();
|
|
2756
|
-
}
|
|
2757
|
-
}
|
|
2758
|
-
return (async () => {
|
|
2759
|
-
if (this.pendingOperations.length > 0) {
|
|
2760
|
-
try {
|
|
2761
|
-
await Promise.allSettled(this.pendingOperations);
|
|
2762
|
-
} catch (err) {
|
|
2763
|
-
console.error("Error waiting for pending operations:", err);
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
if (!isBrowserProcess2() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
|
|
2767
|
-
try {
|
|
2768
|
-
const files = await readdir2(this.config.logDirectory);
|
|
2769
|
-
const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
|
|
2770
|
-
for (const tempFile of tempFiles) {
|
|
2771
|
-
try {
|
|
2772
|
-
await unlink2(join5(this.config.logDirectory, tempFile));
|
|
2773
|
-
} catch (err) {
|
|
2774
|
-
console.error(`Failed to delete temp file ${tempFile}:`, err);
|
|
2775
|
-
}
|
|
2776
|
-
}
|
|
2777
|
-
} catch (err) {
|
|
2778
|
-
console.error("Error cleaning up temporary files:", err);
|
|
2779
|
-
}
|
|
2780
|
-
}
|
|
2781
|
-
})();
|
|
2782
|
-
}
|
|
2783
|
-
getCurrentLogFilePath() {
|
|
2784
|
-
return this.currentLogFile;
|
|
2785
|
-
}
|
|
2786
|
-
formatTag(name) {
|
|
2787
|
-
if (!name)
|
|
2788
|
-
return "";
|
|
2789
|
-
return `${this.tagFormat.prefix}${name}${this.tagFormat.suffix}`;
|
|
2790
|
-
}
|
|
2791
|
-
formatFileTimestamp(date) {
|
|
2792
|
-
return `[${date.toISOString()}]`;
|
|
2793
|
-
}
|
|
2794
|
-
formatConsoleTimestamp(date) {
|
|
2795
|
-
return this.shouldStyleConsole() ? styles2.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
|
|
2796
|
-
}
|
|
2797
|
-
shouldStyleConsole() {
|
|
2798
|
-
if (!this.fancy || isBrowserProcess2())
|
|
2799
|
-
return false;
|
|
2800
|
-
const noColor = typeof process11.env.NO_COLOR !== "undefined";
|
|
2801
|
-
const forceColorDisabled = process11.env.FORCE_COLOR === "0";
|
|
2802
|
-
if (noColor || forceColorDisabled)
|
|
2803
|
-
return false;
|
|
2804
|
-
const hasTTY = typeof process11.stderr !== "undefined" && process11.stderr.isTTY || typeof process11.stdout !== "undefined" && process11.stdout.isTTY;
|
|
2805
|
-
return !!hasTTY;
|
|
2806
|
-
}
|
|
2807
|
-
formatConsoleMessage(parts) {
|
|
2808
|
-
const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
|
|
2809
|
-
const stripAnsi = (str) => str.replace(this.ANSI_PATTERN, "");
|
|
2810
|
-
if (!this.fancy) {
|
|
2811
|
-
const components = [];
|
|
2812
|
-
if (showTimestamp)
|
|
2813
|
-
components.push(timestamp);
|
|
2814
|
-
if (level === "warning")
|
|
2815
|
-
components.push("WARN");
|
|
2816
|
-
else if (level === "error")
|
|
2817
|
-
components.push("ERROR");
|
|
2818
|
-
else if (icon)
|
|
2819
|
-
components.push(icon.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu, ""));
|
|
2820
|
-
if (tag)
|
|
2821
|
-
components.push(tag.replace(/[[\]]/g, ""));
|
|
2822
|
-
components.push(message);
|
|
2823
|
-
return components.join(" ");
|
|
2824
|
-
}
|
|
2825
|
-
const terminalWidth = process11.stdout.columns || 120;
|
|
2826
|
-
let mainPart = "";
|
|
2827
|
-
if (level === "warning" || level === "error") {
|
|
2828
|
-
mainPart = `${icon} ${message}`;
|
|
2829
|
-
} else if (level === "info" || level === "success") {
|
|
2830
|
-
mainPart = `${icon} ${tag} ${message}`;
|
|
2831
|
-
} else {
|
|
2832
|
-
mainPart = `${icon} ${tag} ${styles2.cyan(message)}`;
|
|
2833
|
-
}
|
|
2834
|
-
if (!showTimestamp) {
|
|
2835
|
-
return mainPart.trim();
|
|
2836
|
-
}
|
|
2837
|
-
const visibleMainPartLength = stripAnsi(mainPart).trim().length;
|
|
2838
|
-
const visibleTimestampLength = stripAnsi(timestamp).length;
|
|
2839
|
-
const padding = Math.max(1, terminalWidth - 2 - visibleMainPartLength - visibleTimestampLength);
|
|
2840
|
-
return `${mainPart.trim()}${" ".repeat(padding)}${timestamp}`;
|
|
2841
|
-
}
|
|
2842
|
-
formatMessage(message, args) {
|
|
2843
|
-
if (args.length === 1 && Array.isArray(args[0])) {
|
|
2844
|
-
return message.replace(/\{(\d+)\}/g, (match, index) => {
|
|
2845
|
-
const position = Number.parseInt(index, 10);
|
|
2846
|
-
return position < args[0].length ? String(args[0][position]) : match;
|
|
2847
|
-
});
|
|
2848
|
-
}
|
|
2849
|
-
const formatRegex = /%([sdijfo%])/g;
|
|
2850
|
-
let argIndex = 0;
|
|
2851
|
-
let formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
2852
|
-
if (type === "%")
|
|
2853
|
-
return "%";
|
|
2854
|
-
if (argIndex >= args.length)
|
|
2855
|
-
return match;
|
|
2856
|
-
const arg = args[argIndex++];
|
|
2857
|
-
switch (type) {
|
|
2858
|
-
case "s":
|
|
2859
|
-
return String(arg);
|
|
2860
|
-
case "d":
|
|
2861
|
-
case "i":
|
|
2862
|
-
return Number(arg).toString();
|
|
2863
|
-
case "j":
|
|
2864
|
-
case "o":
|
|
2865
|
-
return JSON.stringify(arg, null, 2);
|
|
2866
|
-
default:
|
|
2867
|
-
return match;
|
|
2868
|
-
}
|
|
2869
|
-
});
|
|
2870
|
-
if (argIndex < args.length) {
|
|
2871
|
-
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
2872
|
-
}
|
|
2873
|
-
return formattedMessage;
|
|
2874
|
-
}
|
|
2875
|
-
formatMarkdown(input) {
|
|
2876
|
-
if (!input)
|
|
2877
|
-
return input;
|
|
2878
|
-
let out = input;
|
|
2879
|
-
out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => {
|
|
2880
|
-
const label = styles2.underline(styles2.blue(text));
|
|
2881
|
-
const absFile = this.toAbsoluteFilePath(url);
|
|
2882
|
-
if (absFile && this.shouldStyleConsole() && this.supportsHyperlinks()) {
|
|
2883
|
-
const href = `file://${encodeURI(absFile)}`;
|
|
2884
|
-
const OSC = "\x1B]8;;";
|
|
2885
|
-
const ST = "\x1B\\";
|
|
2886
|
-
return `${OSC}${href}${ST}${label}${OSC}${ST}`;
|
|
2887
|
-
}
|
|
2888
|
-
if (this.shouldStyleConsole() && this.supportsHyperlinks()) {
|
|
2889
|
-
const OSC = "\x1B]8;;";
|
|
2890
|
-
const ST = "\x1B\\";
|
|
2891
|
-
return `${OSC}${url}${ST}${label}${OSC}${ST}`;
|
|
2892
|
-
}
|
|
2893
|
-
return label;
|
|
2894
|
-
});
|
|
2895
|
-
out = out.replace(/`([^`]+)`/g, (_, m) => styles2.bgGray(m));
|
|
2896
|
-
out = out.replace(/\*\*([^*]+)\*\*/g, (_, m) => styles2.bold(m));
|
|
2897
|
-
out = out.replace(/(?<!\*)\*([^*]+)\*(?!\*)/g, (_, m) => styles2.italic(m));
|
|
2898
|
-
out = out.replace(/(?<!_)_([^_]+)_(?!_)/g, (_, m) => styles2.italic(m));
|
|
2899
|
-
out = out.replace(/~([^~]+)~/g, (_, m) => styles2.strikethrough(m));
|
|
2900
|
-
return out;
|
|
2901
|
-
}
|
|
2902
|
-
supportsHyperlinks() {
|
|
2903
|
-
if (isBrowserProcess2())
|
|
2904
|
-
return false;
|
|
2905
|
-
const env = process11.env;
|
|
2906
|
-
if (!env)
|
|
2907
|
-
return false;
|
|
2908
|
-
if (env.TERM_PROGRAM === "iTerm.app" || env.TERM_PROGRAM === "vscode" || env.TERM_PROGRAM === "WezTerm")
|
|
2909
|
-
return true;
|
|
2910
|
-
if (env.WT_SESSION)
|
|
2911
|
-
return true;
|
|
2912
|
-
if (env.TERM === "xterm-kitty")
|
|
2913
|
-
return true;
|
|
2914
|
-
const vte = env.VTE_VERSION ? Number.parseInt(env.VTE_VERSION, 10) : 0;
|
|
2915
|
-
if (!Number.isNaN(vte) && vte >= 5000)
|
|
2916
|
-
return true;
|
|
2917
|
-
return false;
|
|
2918
|
-
}
|
|
2919
|
-
toAbsoluteFilePath(input) {
|
|
2920
|
-
try {
|
|
2921
|
-
let p = input;
|
|
2922
|
-
if (p.startsWith("file://")) {
|
|
2923
|
-
p = p.replace(/^file:\/\//, "");
|
|
2924
|
-
}
|
|
2925
|
-
if (p.startsWith("~")) {
|
|
2926
|
-
const home = process11.env.HOME || "";
|
|
2927
|
-
if (home)
|
|
2928
|
-
p = p.replace(/^~(?=$|\/)/, home);
|
|
2929
|
-
}
|
|
2930
|
-
if (isAbsolute(p) || p.startsWith("./") || p.startsWith("../")) {
|
|
2931
|
-
p = resolve6(p);
|
|
2932
|
-
} else {
|
|
2933
|
-
return null;
|
|
2934
|
-
}
|
|
2935
|
-
return existsSync4(p) ? p : null;
|
|
2936
|
-
} catch {
|
|
2937
|
-
return null;
|
|
2938
|
-
}
|
|
2939
|
-
}
|
|
2940
|
-
buildOutputTexts(input) {
|
|
2941
|
-
const consoleText = this.shouldStyleConsole() ? this.formatMarkdown(input) : input;
|
|
2942
|
-
const fileText = input.replace(this.ANSI_PATTERN, "");
|
|
2943
|
-
return { consoleText, fileText };
|
|
2944
|
-
}
|
|
2945
|
-
async log(level, message, ...args) {
|
|
2946
|
-
const timestamp = new Date;
|
|
2947
|
-
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
2948
|
-
const fileTime = this.formatFileTimestamp(timestamp);
|
|
2949
|
-
let formattedMessage;
|
|
2950
|
-
let errorStack;
|
|
2951
|
-
if (message instanceof Error) {
|
|
2952
|
-
formattedMessage = message.message;
|
|
2953
|
-
errorStack = message.stack;
|
|
2954
|
-
} else {
|
|
2955
|
-
formattedMessage = this.formatMessage(message, args);
|
|
2956
|
-
}
|
|
2957
|
-
const { consoleText: baseConsoleText, fileText } = this.buildOutputTexts(formattedMessage);
|
|
2958
|
-
if (this.shouldStyleConsole()) {
|
|
2959
|
-
const icon = this.options.showIcons === false ? "" : levelIcons2[level];
|
|
2960
|
-
const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
|
|
2961
|
-
let consoleMessage;
|
|
2962
|
-
switch (level) {
|
|
2963
|
-
case "debug":
|
|
2964
|
-
consoleMessage = this.formatConsoleMessage({
|
|
2965
|
-
timestamp: consoleTime,
|
|
2966
|
-
icon,
|
|
2967
|
-
tag,
|
|
2968
|
-
message: styles2.gray(baseConsoleText),
|
|
2969
|
-
level
|
|
2970
|
-
});
|
|
2971
|
-
console.error(consoleMessage);
|
|
2972
|
-
break;
|
|
2973
|
-
case "info":
|
|
2974
|
-
consoleMessage = this.formatConsoleMessage({
|
|
2975
|
-
timestamp: consoleTime,
|
|
2976
|
-
icon,
|
|
2977
|
-
tag,
|
|
2978
|
-
message: baseConsoleText,
|
|
2979
|
-
level
|
|
2980
|
-
});
|
|
2981
|
-
console.warn(consoleMessage);
|
|
2982
|
-
break;
|
|
2983
|
-
case "success":
|
|
2984
|
-
consoleMessage = this.formatConsoleMessage({
|
|
2985
|
-
timestamp: consoleTime,
|
|
2986
|
-
icon,
|
|
2987
|
-
tag,
|
|
2988
|
-
message: styles2.green(baseConsoleText),
|
|
2989
|
-
level
|
|
2990
|
-
});
|
|
2991
|
-
console.error(consoleMessage);
|
|
2992
|
-
break;
|
|
2993
|
-
case "warning":
|
|
2994
|
-
consoleMessage = this.formatConsoleMessage({
|
|
2995
|
-
timestamp: consoleTime,
|
|
2996
|
-
icon,
|
|
2997
|
-
tag,
|
|
2998
|
-
message: baseConsoleText,
|
|
2999
|
-
level
|
|
3000
|
-
});
|
|
3001
|
-
console.warn(consoleMessage);
|
|
3002
|
-
break;
|
|
3003
|
-
case "error":
|
|
3004
|
-
consoleMessage = this.formatConsoleMessage({
|
|
3005
|
-
timestamp: consoleTime,
|
|
3006
|
-
icon,
|
|
3007
|
-
tag,
|
|
3008
|
-
message: baseConsoleText,
|
|
3009
|
-
level
|
|
3010
|
-
});
|
|
3011
|
-
console.error(consoleMessage);
|
|
3012
|
-
if (errorStack) {
|
|
3013
|
-
const stackLines = errorStack.split(`
|
|
3014
|
-
`);
|
|
3015
|
-
for (const line of stackLines) {
|
|
3016
|
-
if (line.trim() && !line.includes(formattedMessage)) {
|
|
3017
|
-
console.error(this.formatConsoleMessage({
|
|
3018
|
-
timestamp: consoleTime,
|
|
3019
|
-
message: styles2.gray(` ${line}`),
|
|
3020
|
-
level,
|
|
3021
|
-
showTimestamp: false
|
|
3022
|
-
}));
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
}
|
|
3026
|
-
break;
|
|
3027
|
-
}
|
|
3028
|
-
} else if (!isBrowserProcess2()) {
|
|
3029
|
-
console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
|
|
3030
|
-
if (errorStack) {
|
|
3031
|
-
console.error(errorStack);
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
if (!this.shouldLog(level))
|
|
3035
|
-
return;
|
|
3036
1164
|
let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${fileText}
|
|
3037
1165
|
`;
|
|
3038
1166
|
if (errorStack) {
|
|
@@ -3059,7 +1187,7 @@ class Logger2 {
|
|
|
3059
1187
|
barLength,
|
|
3060
1188
|
lastRenderedLine: ""
|
|
3061
1189
|
};
|
|
3062
|
-
if (this.shouldStyleConsole() && !
|
|
1190
|
+
if (this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY) {
|
|
3063
1191
|
this.renderProgressBar(this.activeProgressBar);
|
|
3064
1192
|
}
|
|
3065
1193
|
const update = (current, message) => {
|
|
@@ -3068,7 +1196,7 @@ class Logger2 {
|
|
|
3068
1196
|
this.activeProgressBar.current = Math.min(Math.max(0, current), this.activeProgressBar.total);
|
|
3069
1197
|
if (message !== undefined)
|
|
3070
1198
|
this.activeProgressBar.message = message;
|
|
3071
|
-
if (this.shouldStyleConsole() && !
|
|
1199
|
+
if (this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY)
|
|
3072
1200
|
this.renderProgressBar(this.activeProgressBar);
|
|
3073
1201
|
};
|
|
3074
1202
|
const finish = (message) => {
|
|
@@ -3077,12 +1205,12 @@ class Logger2 {
|
|
|
3077
1205
|
this.finishProgressBar(this.activeProgressBar, message);
|
|
3078
1206
|
};
|
|
3079
1207
|
const interrupt = (message, level = "info") => {
|
|
3080
|
-
if (!
|
|
3081
|
-
|
|
1208
|
+
if (!isBrowserProcess() && process4.stdout.isTTY)
|
|
1209
|
+
process4.stdout.write(`
|
|
3082
1210
|
`);
|
|
3083
1211
|
const method = level === "warning" ? "warn" : level;
|
|
3084
1212
|
this[method](message);
|
|
3085
|
-
if (this.activeProgressBar && this.shouldStyleConsole() && !
|
|
1213
|
+
if (this.activeProgressBar && this.shouldStyleConsole() && !isBrowserProcess() && process4.stdout.isTTY)
|
|
3086
1214
|
this.renderProgressBar(this.activeProgressBar);
|
|
3087
1215
|
};
|
|
3088
1216
|
return { update, finish, interrupt };
|
|
@@ -3090,13 +1218,13 @@ class Logger2 {
|
|
|
3090
1218
|
time(label) {
|
|
3091
1219
|
const start = performance.now();
|
|
3092
1220
|
if (this.shouldStyleConsole()) {
|
|
3093
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
1221
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
3094
1222
|
const consoleTime = this.formatConsoleTimestamp(new Date);
|
|
3095
1223
|
console.error(this.formatConsoleMessage({
|
|
3096
1224
|
timestamp: consoleTime,
|
|
3097
|
-
icon: this.options.showIcons === false ? "" :
|
|
1225
|
+
icon: this.options.showIcons === false ? "" : styles.blue("\u25D0"),
|
|
3098
1226
|
tag,
|
|
3099
|
-
message: `${
|
|
1227
|
+
message: `${styles.cyan(label)}...`
|
|
3100
1228
|
}));
|
|
3101
1229
|
}
|
|
3102
1230
|
return async (metadata) => {
|
|
@@ -3116,14 +1244,14 @@ class Logger2 {
|
|
|
3116
1244
|
`;
|
|
3117
1245
|
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
3118
1246
|
if (this.shouldStyleConsole()) {
|
|
3119
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
1247
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
3120
1248
|
console.error(this.formatConsoleMessage({
|
|
3121
1249
|
timestamp: consoleTime,
|
|
3122
|
-
icon: this.options.showIcons === false ? "" :
|
|
1250
|
+
icon: this.options.showIcons === false ? "" : styles.green("\u2713"),
|
|
3123
1251
|
tag,
|
|
3124
1252
|
message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
|
|
3125
1253
|
}));
|
|
3126
|
-
} else if (!
|
|
1254
|
+
} else if (!isBrowserProcess()) {
|
|
3127
1255
|
console.error(logEntry.trim());
|
|
3128
1256
|
}
|
|
3129
1257
|
if (this.shouldWriteToFile())
|
|
@@ -3167,7 +1295,7 @@ class Logger2 {
|
|
|
3167
1295
|
}
|
|
3168
1296
|
extend(namespace) {
|
|
3169
1297
|
const childName = `${this.name}:${namespace}`;
|
|
3170
|
-
const childLogger = new
|
|
1298
|
+
const childLogger = new Logger(childName, {
|
|
3171
1299
|
...this.options,
|
|
3172
1300
|
logDirectory: this.config.logDirectory,
|
|
3173
1301
|
level: this.config.level,
|
|
@@ -3179,11 +1307,11 @@ class Logger2 {
|
|
|
3179
1307
|
return childLogger;
|
|
3180
1308
|
}
|
|
3181
1309
|
createReadStream() {
|
|
3182
|
-
if (
|
|
1310
|
+
if (isBrowserProcess())
|
|
3183
1311
|
throw new Error("createReadStream is not supported in browser environments");
|
|
3184
|
-
if (!
|
|
1312
|
+
if (!existsSync2(this.currentLogFile))
|
|
3185
1313
|
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
3186
|
-
return
|
|
1314
|
+
return createReadStream(this.currentLogFile, { encoding: "utf8" });
|
|
3187
1315
|
}
|
|
3188
1316
|
async decrypt(data) {
|
|
3189
1317
|
if (!this.validateEncryptionConfig())
|
|
@@ -3195,16 +1323,16 @@ class Logger2 {
|
|
|
3195
1323
|
throw new Error("No valid encryption key available");
|
|
3196
1324
|
const key = this.keys.get(this.currentKeyId);
|
|
3197
1325
|
try {
|
|
3198
|
-
const encryptedData =
|
|
1326
|
+
const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
|
|
3199
1327
|
const iv = encryptedData.subarray(0, 16);
|
|
3200
1328
|
const authTag = encryptedData.subarray(encryptedData.length - 16);
|
|
3201
1329
|
const ciphertext = encryptedData.subarray(16, encryptedData.length - 16);
|
|
3202
|
-
const decipher =
|
|
1330
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
3203
1331
|
decipher.setAuthTag(authTag);
|
|
3204
1332
|
const d1 = decipher.update(ciphertext);
|
|
3205
1333
|
const d2 = decipher.final();
|
|
3206
1334
|
const totalLen = d1.length + d2.length;
|
|
3207
|
-
const out =
|
|
1335
|
+
const out = Buffer.allocUnsafe(totalLen);
|
|
3208
1336
|
d1.copy(out, 0);
|
|
3209
1337
|
d2.copy(out, d1.length);
|
|
3210
1338
|
return out.toString("utf8");
|
|
@@ -3225,10 +1353,10 @@ class Logger2 {
|
|
|
3225
1353
|
return this.config.rotation;
|
|
3226
1354
|
}
|
|
3227
1355
|
isBrowserMode() {
|
|
3228
|
-
return
|
|
1356
|
+
return isBrowserProcess();
|
|
3229
1357
|
}
|
|
3230
1358
|
isServerMode() {
|
|
3231
|
-
return !
|
|
1359
|
+
return !isBrowserProcess();
|
|
3232
1360
|
}
|
|
3233
1361
|
setTestEncryptionKey(keyId, key) {
|
|
3234
1362
|
this.currentKeyId = keyId;
|
|
@@ -3262,22 +1390,22 @@ class Logger2 {
|
|
|
3262
1390
|
const boxedLines = lines.map((line) => {
|
|
3263
1391
|
return this.formatConsoleMessage({
|
|
3264
1392
|
timestamp: consoleTime,
|
|
3265
|
-
message:
|
|
1393
|
+
message: styles.cyan(line),
|
|
3266
1394
|
showTimestamp: false
|
|
3267
1395
|
});
|
|
3268
1396
|
});
|
|
3269
1397
|
console.error(this.formatConsoleMessage({
|
|
3270
1398
|
timestamp: consoleTime,
|
|
3271
|
-
message:
|
|
1399
|
+
message: styles.cyan(top),
|
|
3272
1400
|
showTimestamp: false
|
|
3273
1401
|
}));
|
|
3274
1402
|
boxedLines.forEach((line) => console.error(line));
|
|
3275
1403
|
console.error(this.formatConsoleMessage({
|
|
3276
1404
|
timestamp: consoleTime,
|
|
3277
|
-
message:
|
|
1405
|
+
message: styles.cyan(bottom),
|
|
3278
1406
|
showTimestamp: false
|
|
3279
1407
|
}));
|
|
3280
|
-
} else if (!
|
|
1408
|
+
} else if (!isBrowserProcess()) {
|
|
3281
1409
|
console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${fileText}`);
|
|
3282
1410
|
}
|
|
3283
1411
|
const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${fileText}
|
|
@@ -3286,30 +1414,30 @@ class Logger2 {
|
|
|
3286
1414
|
await this.writeToFile(logEntry);
|
|
3287
1415
|
}
|
|
3288
1416
|
async prompt(message) {
|
|
3289
|
-
if (
|
|
1417
|
+
if (isBrowserProcess()) {
|
|
3290
1418
|
return Promise.resolve(true);
|
|
3291
1419
|
}
|
|
3292
|
-
return new Promise((
|
|
3293
|
-
console.error(`${
|
|
1420
|
+
return new Promise((resolve32) => {
|
|
1421
|
+
console.error(`${styles.cyan("?")} ${message} (y/n) `);
|
|
3294
1422
|
const onData = (data) => {
|
|
3295
1423
|
const input = data.toString().trim().toLowerCase();
|
|
3296
|
-
|
|
1424
|
+
process4.stdin.removeListener("data", onData);
|
|
3297
1425
|
try {
|
|
3298
|
-
if (typeof
|
|
3299
|
-
|
|
1426
|
+
if (typeof process4.stdin.setRawMode === "function") {
|
|
1427
|
+
process4.stdin.setRawMode(false);
|
|
3300
1428
|
}
|
|
3301
1429
|
} catch {}
|
|
3302
|
-
|
|
1430
|
+
process4.stdin.pause();
|
|
3303
1431
|
console.error("");
|
|
3304
|
-
|
|
1432
|
+
resolve32(input === "y" || input === "yes");
|
|
3305
1433
|
};
|
|
3306
1434
|
try {
|
|
3307
|
-
if (typeof
|
|
3308
|
-
|
|
1435
|
+
if (typeof process4.stdin.setRawMode === "function") {
|
|
1436
|
+
process4.stdin.setRawMode(true);
|
|
3309
1437
|
}
|
|
3310
1438
|
} catch {}
|
|
3311
|
-
|
|
3312
|
-
|
|
1439
|
+
process4.stdin.resume();
|
|
1440
|
+
process4.stdin.once("data", onData);
|
|
3313
1441
|
});
|
|
3314
1442
|
}
|
|
3315
1443
|
setFancy(enabled) {
|
|
@@ -3356,9 +1484,9 @@ class Logger2 {
|
|
|
3356
1484
|
}
|
|
3357
1485
|
const { consoleText, fileText } = this.buildOutputTexts(formattedMessage);
|
|
3358
1486
|
if (this.shouldStyleConsole()) {
|
|
3359
|
-
const tag = this.options.showTags !== false && this.name ?
|
|
3360
|
-
const spinnerPrefix = this.options.showIcons === false ? "" : `${
|
|
3361
|
-
console.error(`${spinnerPrefix}${tag} ${
|
|
1487
|
+
const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
|
|
1488
|
+
const spinnerPrefix = this.options.showIcons === false ? "" : `${styles.blue("\u25D0")} `;
|
|
1489
|
+
console.error(`${spinnerPrefix}${tag} ${styles.cyan(consoleText)}`);
|
|
3362
1490
|
}
|
|
3363
1491
|
const timestamp = new Date;
|
|
3364
1492
|
const formattedDate = timestamp.toISOString();
|
|
@@ -3368,30 +1496,30 @@ class Logger2 {
|
|
|
3368
1496
|
await this.writeToFile(logEntry);
|
|
3369
1497
|
}
|
|
3370
1498
|
renderProgressBar(barState, isFinished = false) {
|
|
3371
|
-
if (!this.enabled || !this.shouldStyleConsole() || !
|
|
1499
|
+
if (!this.enabled || !this.shouldStyleConsole() || !process4.stdout.isTTY)
|
|
3372
1500
|
return;
|
|
3373
1501
|
const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
|
|
3374
1502
|
const filledLength = Math.round(barState.barLength * percent / 100);
|
|
3375
1503
|
const emptyLength = barState.barLength - filledLength;
|
|
3376
|
-
const filledBar =
|
|
3377
|
-
const emptyBar =
|
|
1504
|
+
const filledBar = styles.green("\u2501".repeat(filledLength));
|
|
1505
|
+
const emptyBar = styles.gray("\u2501".repeat(emptyLength));
|
|
3378
1506
|
const bar = `[${filledBar}${emptyBar}]`;
|
|
3379
1507
|
const percentageText = `${percent}%`.padStart(4);
|
|
3380
1508
|
const messageText = barState.message ? ` ${barState.message}` : "";
|
|
3381
|
-
const icon = this.options.showIcons === false ? "" : isFinished || percent === 100 ?
|
|
3382
|
-
const tag = this.options.showTags !== false && this.name ? ` ${
|
|
1509
|
+
const icon = this.options.showIcons === false ? "" : isFinished || percent === 100 ? styles.green("\u2713") : styles.blue("\u25B6");
|
|
1510
|
+
const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
|
|
3383
1511
|
const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
|
|
3384
|
-
const terminalWidth =
|
|
1512
|
+
const terminalWidth = process4.stdout.columns || 80;
|
|
3385
1513
|
const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
|
|
3386
1514
|
barState.lastRenderedLine = `${line}${clearLine}`;
|
|
3387
|
-
|
|
1515
|
+
process4.stdout.write(barState.lastRenderedLine);
|
|
3388
1516
|
if (isFinished) {
|
|
3389
|
-
|
|
1517
|
+
process4.stdout.write(`
|
|
3390
1518
|
`);
|
|
3391
1519
|
}
|
|
3392
1520
|
}
|
|
3393
1521
|
finishProgressBar(barState, finalMessage) {
|
|
3394
|
-
if (!this.enabled || !this.fancy ||
|
|
1522
|
+
if (!this.enabled || !this.fancy || isBrowserProcess() || !process4.stdout.isTTY) {
|
|
3395
1523
|
this.activeProgressBar = null;
|
|
3396
1524
|
return;
|
|
3397
1525
|
}
|
|
@@ -3404,23 +1532,23 @@ class Logger2 {
|
|
|
3404
1532
|
this.activeProgressBar = null;
|
|
3405
1533
|
}
|
|
3406
1534
|
async clear(filters = {}) {
|
|
3407
|
-
if (
|
|
1535
|
+
if (isBrowserProcess()) {
|
|
3408
1536
|
console.warn("Log clearing is not supported in browser environments.");
|
|
3409
1537
|
return;
|
|
3410
1538
|
}
|
|
3411
1539
|
try {
|
|
3412
1540
|
console.warn("Clearing logs...", this.config.logDirectory);
|
|
3413
|
-
const files = await
|
|
1541
|
+
const files = await readdir(this.config.logDirectory);
|
|
3414
1542
|
const logFilesToDelete = [];
|
|
3415
1543
|
for (const file of files) {
|
|
3416
1544
|
const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
|
|
3417
1545
|
if (!nameMatches || !file.endsWith(".log")) {
|
|
3418
1546
|
continue;
|
|
3419
1547
|
}
|
|
3420
|
-
const filePath =
|
|
1548
|
+
const filePath = join2(this.config.logDirectory, file);
|
|
3421
1549
|
if (filters.before) {
|
|
3422
1550
|
try {
|
|
3423
|
-
const fileStats = await
|
|
1551
|
+
const fileStats = await stat(filePath);
|
|
3424
1552
|
if (fileStats.mtime >= filters.before) {
|
|
3425
1553
|
continue;
|
|
3426
1554
|
}
|
|
@@ -3438,7 +1566,7 @@ class Logger2 {
|
|
|
3438
1566
|
console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
|
|
3439
1567
|
for (const filePath of logFilesToDelete) {
|
|
3440
1568
|
try {
|
|
3441
|
-
await
|
|
1569
|
+
await unlink(filePath);
|
|
3442
1570
|
console.warn(`Deleted log file: ${filePath}`);
|
|
3443
1571
|
} catch (unlinkErr) {
|
|
3444
1572
|
console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
|
|
@@ -3450,193 +1578,126 @@ class Logger2 {
|
|
|
3450
1578
|
}
|
|
3451
1579
|
}
|
|
3452
1580
|
}
|
|
3453
|
-
var
|
|
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
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
}
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
code = "SCHEMA_VALIDATION_ERROR";
|
|
3574
|
-
constructor(schemaPath, validationErrors, configName) {
|
|
3575
|
-
super(`Schema validation failed${configName ? ` for config "${configName}"` : ""}`, {
|
|
3576
|
-
schemaPath,
|
|
3577
|
-
configName,
|
|
3578
|
-
validationErrors,
|
|
3579
|
-
errorCount: validationErrors.length
|
|
3580
|
-
});
|
|
3581
|
-
}
|
|
3582
|
-
}
|
|
3583
|
-
|
|
3584
|
-
class BrowserConfigError extends BunfigError {
|
|
3585
|
-
code = "BROWSER_CONFIG_ERROR";
|
|
3586
|
-
constructor(endpoint, status, statusText, configName) {
|
|
3587
|
-
super(`Failed to fetch configuration from "${endpoint}": ${status} ${statusText}`, {
|
|
3588
|
-
endpoint,
|
|
3589
|
-
status,
|
|
3590
|
-
statusText,
|
|
3591
|
-
configName
|
|
3592
|
-
});
|
|
3593
|
-
}
|
|
3594
|
-
}
|
|
3595
|
-
|
|
3596
|
-
class PluginError extends BunfigError {
|
|
3597
|
-
code = "PLUGIN_ERROR";
|
|
3598
|
-
constructor(pluginName, operation, cause) {
|
|
3599
|
-
super(`Plugin "${pluginName}" failed during ${operation}: ${cause.message}`, {
|
|
3600
|
-
pluginName,
|
|
3601
|
-
operation,
|
|
3602
|
-
originalError: cause.name,
|
|
3603
|
-
originalMessage: cause.message
|
|
3604
|
-
});
|
|
3605
|
-
this.cause = cause;
|
|
3606
|
-
}
|
|
3607
|
-
}
|
|
3608
|
-
var ErrorFactory = {
|
|
3609
|
-
configNotFound(configName, searchPaths, alias) {
|
|
3610
|
-
return new ConfigNotFoundError(configName, searchPaths, alias);
|
|
3611
|
-
},
|
|
3612
|
-
configLoad(configPath, cause, configName) {
|
|
3613
|
-
return new ConfigLoadError(configPath, cause, configName);
|
|
3614
|
-
},
|
|
3615
|
-
configValidation(configPath, errors, configName) {
|
|
3616
|
-
return new ConfigValidationError(configPath, errors, configName);
|
|
3617
|
-
},
|
|
3618
|
-
configMerge(sourcePath, targetPath, cause, configName) {
|
|
3619
|
-
return new ConfigMergeError(sourcePath, targetPath, cause, configName);
|
|
3620
|
-
},
|
|
3621
|
-
envVar(envKey, envValue, expectedType, configName) {
|
|
3622
|
-
return new EnvVarError(envKey, envValue, expectedType, configName);
|
|
3623
|
-
},
|
|
3624
|
-
fileSystem(operation, path, cause) {
|
|
3625
|
-
return new FileSystemError(operation, path, cause);
|
|
3626
|
-
},
|
|
3627
|
-
typeGeneration(configDir, outputPath, cause) {
|
|
3628
|
-
return new TypeGenerationError(configDir, outputPath, cause);
|
|
3629
|
-
},
|
|
3630
|
-
schemaValidation(schemaPath, errors, configName) {
|
|
3631
|
-
return new SchemaValidationError(schemaPath, errors, configName);
|
|
3632
|
-
},
|
|
3633
|
-
browserConfig(endpoint, status, statusText, configName) {
|
|
3634
|
-
return new BrowserConfigError(endpoint, status, statusText, configName);
|
|
3635
|
-
},
|
|
3636
|
-
plugin(pluginName, operation, cause) {
|
|
3637
|
-
return new PluginError(pluginName, operation, cause);
|
|
3638
|
-
}
|
|
3639
|
-
};
|
|
1581
|
+
var defaultLogDirectory;
|
|
1582
|
+
var defaultConfig;
|
|
1583
|
+
var config;
|
|
1584
|
+
var configReady;
|
|
1585
|
+
var terminalStyles;
|
|
1586
|
+
var styles;
|
|
1587
|
+
var red;
|
|
1588
|
+
var green;
|
|
1589
|
+
var yellow;
|
|
1590
|
+
var blue;
|
|
1591
|
+
var magenta;
|
|
1592
|
+
var cyan;
|
|
1593
|
+
var white;
|
|
1594
|
+
var gray;
|
|
1595
|
+
var bgRed;
|
|
1596
|
+
var bgYellow;
|
|
1597
|
+
var bgGray;
|
|
1598
|
+
var bold;
|
|
1599
|
+
var dim;
|
|
1600
|
+
var italic;
|
|
1601
|
+
var underline;
|
|
1602
|
+
var strikethrough;
|
|
1603
|
+
var reset;
|
|
1604
|
+
var defaultFingersCrossedConfig;
|
|
1605
|
+
var levelIcons;
|
|
1606
|
+
var logger;
|
|
1607
|
+
var init_src = __esm(() => {
|
|
1608
|
+
defaultLogDirectory = process.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
|
|
1609
|
+
defaultConfig = {
|
|
1610
|
+
level: "info",
|
|
1611
|
+
defaultName: "clarity",
|
|
1612
|
+
timestamp: true,
|
|
1613
|
+
colors: true,
|
|
1614
|
+
format: "text",
|
|
1615
|
+
maxLogSize: 10485760,
|
|
1616
|
+
logDatePattern: "YYYY-MM-DD",
|
|
1617
|
+
logDirectory: defaultLogDirectory,
|
|
1618
|
+
rotation: {
|
|
1619
|
+
frequency: "daily",
|
|
1620
|
+
maxSize: 10485760,
|
|
1621
|
+
maxFiles: 5,
|
|
1622
|
+
compress: false,
|
|
1623
|
+
rotateHour: 0,
|
|
1624
|
+
rotateMinute: 0,
|
|
1625
|
+
rotateDayOfWeek: 0,
|
|
1626
|
+
rotateDayOfMonth: 1,
|
|
1627
|
+
encrypt: false
|
|
1628
|
+
},
|
|
1629
|
+
verbose: false,
|
|
1630
|
+
writeToFile: false
|
|
1631
|
+
};
|
|
1632
|
+
config = { ...defaultConfig };
|
|
1633
|
+
configReady = (async () => {
|
|
1634
|
+
try {
|
|
1635
|
+
const { loadConfig: bunfigLoadConfig } = await Promise.resolve().then(() => (init_src2(), exports_src));
|
|
1636
|
+
const loadedConfig = await bunfigLoadConfig({
|
|
1637
|
+
name: "clarity",
|
|
1638
|
+
alias: "logging",
|
|
1639
|
+
defaultConfig,
|
|
1640
|
+
cwd: process.cwd()
|
|
1641
|
+
});
|
|
1642
|
+
if (loadedConfig)
|
|
1643
|
+
Object.assign(config, loadedConfig);
|
|
1644
|
+
} catch {}
|
|
1645
|
+
return config;
|
|
1646
|
+
})();
|
|
1647
|
+
terminalStyles = {
|
|
1648
|
+
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
1649
|
+
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
1650
|
+
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
1651
|
+
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
1652
|
+
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
1653
|
+
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
1654
|
+
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
1655
|
+
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
1656
|
+
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
1657
|
+
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
1658
|
+
bgGray: (text) => `\x1B[100m${text}\x1B[0m`,
|
|
1659
|
+
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
1660
|
+
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
1661
|
+
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
1662
|
+
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
1663
|
+
strikethrough: (text) => `\x1B[9m${text}\x1B[0m`,
|
|
1664
|
+
reset: "\x1B[0m"
|
|
1665
|
+
};
|
|
1666
|
+
styles = terminalStyles;
|
|
1667
|
+
red = terminalStyles.red;
|
|
1668
|
+
green = terminalStyles.green;
|
|
1669
|
+
yellow = terminalStyles.yellow;
|
|
1670
|
+
blue = terminalStyles.blue;
|
|
1671
|
+
magenta = terminalStyles.magenta;
|
|
1672
|
+
cyan = terminalStyles.cyan;
|
|
1673
|
+
white = terminalStyles.white;
|
|
1674
|
+
gray = terminalStyles.gray;
|
|
1675
|
+
bgRed = terminalStyles.bgRed;
|
|
1676
|
+
bgYellow = terminalStyles.bgYellow;
|
|
1677
|
+
bgGray = terminalStyles.bgGray;
|
|
1678
|
+
bold = terminalStyles.bold;
|
|
1679
|
+
dim = terminalStyles.dim;
|
|
1680
|
+
italic = terminalStyles.italic;
|
|
1681
|
+
underline = terminalStyles.underline;
|
|
1682
|
+
strikethrough = terminalStyles.strikethrough;
|
|
1683
|
+
reset = terminalStyles.reset;
|
|
1684
|
+
defaultFingersCrossedConfig = {
|
|
1685
|
+
activationLevel: "error",
|
|
1686
|
+
bufferSize: 50,
|
|
1687
|
+
flushOnDeactivation: true,
|
|
1688
|
+
stopBuffering: false
|
|
1689
|
+
};
|
|
1690
|
+
levelIcons = {
|
|
1691
|
+
debug: "\uD83D\uDD0D",
|
|
1692
|
+
info: blue("\u2139"),
|
|
1693
|
+
success: green("\u2713"),
|
|
1694
|
+
warning: bgYellow(white(bold(" WARN "))),
|
|
1695
|
+
error: bgRed(white(bold(" ERROR ")))
|
|
1696
|
+
};
|
|
1697
|
+
logger = new Logger("stacks");
|
|
1698
|
+
});
|
|
1699
|
+
var version = "0.15.9";
|
|
1700
|
+
var init_package = () => {};
|
|
3640
1701
|
async function withErrorRecovery(fn, options = {}) {
|
|
3641
1702
|
const {
|
|
3642
1703
|
maxRetries = 3,
|
|
@@ -3654,7 +1715,7 @@ async function withErrorRecovery(fn, options = {}) {
|
|
|
3654
1715
|
break;
|
|
3655
1716
|
}
|
|
3656
1717
|
if (retryDelay > 0) {
|
|
3657
|
-
await new Promise((
|
|
1718
|
+
await new Promise((resolve32) => setTimeout(resolve32, retryDelay));
|
|
3658
1719
|
}
|
|
3659
1720
|
}
|
|
3660
1721
|
}
|
|
@@ -3663,6 +1724,224 @@ async function withErrorRecovery(fn, options = {}) {
|
|
|
3663
1724
|
}
|
|
3664
1725
|
throw lastError instanceof Error ? lastError : new Error(`Unknown error: ${String(lastError)}`);
|
|
3665
1726
|
}
|
|
1727
|
+
function isBunfigError(error) {
|
|
1728
|
+
return error instanceof BunfigError;
|
|
1729
|
+
}
|
|
1730
|
+
function isConfigNotFoundError(error) {
|
|
1731
|
+
return error instanceof ConfigNotFoundError;
|
|
1732
|
+
}
|
|
1733
|
+
function isRetryableError(error) {
|
|
1734
|
+
if (isBunfigError(error)) {
|
|
1735
|
+
return error.code === "FILE_SYSTEM_ERROR" || error.code === "BROWSER_CONFIG_ERROR";
|
|
1736
|
+
}
|
|
1737
|
+
const retryableMessages = [
|
|
1738
|
+
"ENOENT",
|
|
1739
|
+
"EACCES",
|
|
1740
|
+
"EMFILE",
|
|
1741
|
+
"ENFILE",
|
|
1742
|
+
"EBUSY",
|
|
1743
|
+
"network",
|
|
1744
|
+
"timeout",
|
|
1745
|
+
"connection"
|
|
1746
|
+
];
|
|
1747
|
+
return retryableMessages.some((msg) => error.message.toLowerCase().includes(msg.toLowerCase()));
|
|
1748
|
+
}
|
|
1749
|
+
var BunfigError;
|
|
1750
|
+
var ConfigNotFoundError;
|
|
1751
|
+
var ConfigLoadError;
|
|
1752
|
+
var ConfigValidationError;
|
|
1753
|
+
var ConfigMergeError;
|
|
1754
|
+
var EnvVarError;
|
|
1755
|
+
var FileSystemError;
|
|
1756
|
+
var TypeGenerationError;
|
|
1757
|
+
var SchemaValidationError;
|
|
1758
|
+
var BrowserConfigError;
|
|
1759
|
+
var PluginError;
|
|
1760
|
+
var ErrorFactory;
|
|
1761
|
+
var init_errors = __esm(() => {
|
|
1762
|
+
BunfigError = class BunfigError2 extends Error {
|
|
1763
|
+
timestamp;
|
|
1764
|
+
context;
|
|
1765
|
+
constructor(message, context = {}) {
|
|
1766
|
+
super(message);
|
|
1767
|
+
this.name = this.constructor.name;
|
|
1768
|
+
this.timestamp = new Date;
|
|
1769
|
+
this.context = context;
|
|
1770
|
+
if (Error.captureStackTrace) {
|
|
1771
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
toJSON() {
|
|
1775
|
+
return {
|
|
1776
|
+
name: this.name,
|
|
1777
|
+
code: this.code,
|
|
1778
|
+
message: this.message,
|
|
1779
|
+
timestamp: this.timestamp.toISOString(),
|
|
1780
|
+
context: this.context,
|
|
1781
|
+
stack: this.stack
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
toString() {
|
|
1785
|
+
const contextStr = Object.keys(this.context).length > 0 ? ` (${Object.entries(this.context).map(([k, v]) => `${k}: ${v}`).join(", ")})` : "";
|
|
1786
|
+
return `${this.name} [${this.code}]: ${this.message}${contextStr}`;
|
|
1787
|
+
}
|
|
1788
|
+
};
|
|
1789
|
+
ConfigNotFoundError = class ConfigNotFoundError2 extends BunfigError {
|
|
1790
|
+
code = "CONFIG_NOT_FOUND";
|
|
1791
|
+
constructor(configName, searchPaths, alias) {
|
|
1792
|
+
const aliasList = alias === undefined ? [] : Array.isArray(alias) ? alias.filter(Boolean) : [alias];
|
|
1793
|
+
let aliasStr = "";
|
|
1794
|
+
if (aliasList.length === 1)
|
|
1795
|
+
aliasStr = ` or alias "${aliasList[0]}"`;
|
|
1796
|
+
else if (aliasList.length > 1)
|
|
1797
|
+
aliasStr = ` or aliases ${aliasList.map((a) => `"${a}"`).join(", ")}`;
|
|
1798
|
+
super(`Configuration "${configName}"${aliasStr} not found`, {
|
|
1799
|
+
configName,
|
|
1800
|
+
alias,
|
|
1801
|
+
searchPaths,
|
|
1802
|
+
searchPathCount: searchPaths.length
|
|
1803
|
+
});
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
ConfigLoadError = class ConfigLoadError2 extends BunfigError {
|
|
1807
|
+
code = "CONFIG_LOAD_ERROR";
|
|
1808
|
+
constructor(configPath, cause, configName) {
|
|
1809
|
+
super(`Failed to load configuration from "${configPath}": ${cause.message}`, {
|
|
1810
|
+
configPath,
|
|
1811
|
+
configName,
|
|
1812
|
+
originalError: cause.name,
|
|
1813
|
+
originalMessage: cause.message
|
|
1814
|
+
});
|
|
1815
|
+
this.cause = cause;
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
ConfigValidationError = class ConfigValidationError2 extends BunfigError {
|
|
1819
|
+
code = "CONFIG_VALIDATION_ERROR";
|
|
1820
|
+
constructor(configPath, validationErrors, configName) {
|
|
1821
|
+
super(`Configuration validation failed for "${configPath}"`, {
|
|
1822
|
+
configPath,
|
|
1823
|
+
configName,
|
|
1824
|
+
validationErrors,
|
|
1825
|
+
errorCount: validationErrors.length
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
};
|
|
1829
|
+
ConfigMergeError = class ConfigMergeError2 extends BunfigError {
|
|
1830
|
+
code = "CONFIG_MERGE_ERROR";
|
|
1831
|
+
constructor(sourcePath, targetPath, cause, configName) {
|
|
1832
|
+
super(`Failed to merge configuration from "${sourcePath}" with "${targetPath}": ${cause.message}`, {
|
|
1833
|
+
sourcePath,
|
|
1834
|
+
targetPath,
|
|
1835
|
+
configName,
|
|
1836
|
+
originalError: cause.name,
|
|
1837
|
+
originalMessage: cause.message
|
|
1838
|
+
});
|
|
1839
|
+
this.cause = cause;
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
EnvVarError = class EnvVarError2 extends BunfigError {
|
|
1843
|
+
code = "ENV_VAR_ERROR";
|
|
1844
|
+
constructor(envKey, envValue, expectedType, configName) {
|
|
1845
|
+
super(`Failed to parse environment variable "${envKey}" with value "${envValue}" as ${expectedType}`, {
|
|
1846
|
+
envKey,
|
|
1847
|
+
envValue,
|
|
1848
|
+
expectedType,
|
|
1849
|
+
configName
|
|
1850
|
+
});
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1853
|
+
FileSystemError = class FileSystemError2 extends BunfigError {
|
|
1854
|
+
code = "FILE_SYSTEM_ERROR";
|
|
1855
|
+
constructor(operation, path, cause) {
|
|
1856
|
+
super(`File system ${operation} failed for "${path}": ${cause.message}`, {
|
|
1857
|
+
operation,
|
|
1858
|
+
path,
|
|
1859
|
+
originalError: cause.name,
|
|
1860
|
+
originalMessage: cause.message
|
|
1861
|
+
});
|
|
1862
|
+
this.cause = cause;
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
TypeGenerationError = class TypeGenerationError2 extends BunfigError {
|
|
1866
|
+
code = "TYPE_GENERATION_ERROR";
|
|
1867
|
+
constructor(configDir, outputPath, cause) {
|
|
1868
|
+
super(`Failed to generate types from "${configDir}" to "${outputPath}": ${cause.message}`, {
|
|
1869
|
+
configDir,
|
|
1870
|
+
outputPath,
|
|
1871
|
+
originalError: cause.name,
|
|
1872
|
+
originalMessage: cause.message
|
|
1873
|
+
});
|
|
1874
|
+
this.cause = cause;
|
|
1875
|
+
}
|
|
1876
|
+
};
|
|
1877
|
+
SchemaValidationError = class SchemaValidationError2 extends BunfigError {
|
|
1878
|
+
code = "SCHEMA_VALIDATION_ERROR";
|
|
1879
|
+
constructor(schemaPath, validationErrors, configName) {
|
|
1880
|
+
super(`Schema validation failed${configName ? ` for config "${configName}"` : ""}`, {
|
|
1881
|
+
schemaPath,
|
|
1882
|
+
configName,
|
|
1883
|
+
validationErrors,
|
|
1884
|
+
errorCount: validationErrors.length
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
BrowserConfigError = class BrowserConfigError2 extends BunfigError {
|
|
1889
|
+
code = "BROWSER_CONFIG_ERROR";
|
|
1890
|
+
constructor(endpoint, status, statusText, configName) {
|
|
1891
|
+
super(`Failed to fetch configuration from "${endpoint}": ${status} ${statusText}`, {
|
|
1892
|
+
endpoint,
|
|
1893
|
+
status,
|
|
1894
|
+
statusText,
|
|
1895
|
+
configName
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
};
|
|
1899
|
+
PluginError = class PluginError2 extends BunfigError {
|
|
1900
|
+
code = "PLUGIN_ERROR";
|
|
1901
|
+
constructor(pluginName, operation, cause) {
|
|
1902
|
+
super(`Plugin "${pluginName}" failed during ${operation}: ${cause.message}`, {
|
|
1903
|
+
pluginName,
|
|
1904
|
+
operation,
|
|
1905
|
+
originalError: cause.name,
|
|
1906
|
+
originalMessage: cause.message
|
|
1907
|
+
});
|
|
1908
|
+
this.cause = cause;
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
ErrorFactory = {
|
|
1912
|
+
configNotFound(configName, searchPaths, alias) {
|
|
1913
|
+
return new ConfigNotFoundError(configName, searchPaths, alias);
|
|
1914
|
+
},
|
|
1915
|
+
configLoad(configPath, cause, configName) {
|
|
1916
|
+
return new ConfigLoadError(configPath, cause, configName);
|
|
1917
|
+
},
|
|
1918
|
+
configValidation(configPath, errors, configName) {
|
|
1919
|
+
return new ConfigValidationError(configPath, errors, configName);
|
|
1920
|
+
},
|
|
1921
|
+
configMerge(sourcePath, targetPath, cause, configName) {
|
|
1922
|
+
return new ConfigMergeError(sourcePath, targetPath, cause, configName);
|
|
1923
|
+
},
|
|
1924
|
+
envVar(envKey, envValue, expectedType, configName) {
|
|
1925
|
+
return new EnvVarError(envKey, envValue, expectedType, configName);
|
|
1926
|
+
},
|
|
1927
|
+
fileSystem(operation, path, cause) {
|
|
1928
|
+
return new FileSystemError(operation, path, cause);
|
|
1929
|
+
},
|
|
1930
|
+
typeGeneration(configDir, outputPath, cause) {
|
|
1931
|
+
return new TypeGenerationError(configDir, outputPath, cause);
|
|
1932
|
+
},
|
|
1933
|
+
schemaValidation(schemaPath, errors, configName) {
|
|
1934
|
+
return new SchemaValidationError(schemaPath, errors, configName);
|
|
1935
|
+
},
|
|
1936
|
+
browserConfig(endpoint, status, statusText, configName) {
|
|
1937
|
+
return new BrowserConfigError(endpoint, status, statusText, configName);
|
|
1938
|
+
},
|
|
1939
|
+
plugin(pluginName, operation, cause) {
|
|
1940
|
+
return new PluginError(pluginName, operation, cause);
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
});
|
|
1944
|
+
|
|
3666
1945
|
class EnvProcessor {
|
|
3667
1946
|
defaultParsers;
|
|
3668
1947
|
constructor() {
|
|
@@ -3712,7 +1991,7 @@ class EnvProcessor {
|
|
|
3712
1991
|
}
|
|
3713
1992
|
];
|
|
3714
1993
|
}
|
|
3715
|
-
async applyEnvironmentVariables(configName,
|
|
1994
|
+
async applyEnvironmentVariables(configName, config2, options = {}) {
|
|
3716
1995
|
const {
|
|
3717
1996
|
prefix,
|
|
3718
1997
|
useCamelCase = true,
|
|
@@ -3724,12 +2003,12 @@ class EnvProcessor {
|
|
|
3724
2003
|
const operation = async () => {
|
|
3725
2004
|
if (!configName) {
|
|
3726
2005
|
return {
|
|
3727
|
-
config:
|
|
2006
|
+
config: config2,
|
|
3728
2007
|
source: { type: "environment", priority: 50, timestamp: new Date }
|
|
3729
2008
|
};
|
|
3730
2009
|
}
|
|
3731
2010
|
const envPrefix = prefix || this.generateEnvPrefix(configName);
|
|
3732
|
-
const result = { ...
|
|
2011
|
+
const result = { ...config2 };
|
|
3733
2012
|
this.processObject(result, [], envPrefix, {
|
|
3734
2013
|
useCamelCase,
|
|
3735
2014
|
useBackwardCompatibility,
|
|
@@ -3768,10 +2047,10 @@ class EnvProcessor {
|
|
|
3768
2047
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3769
2048
|
this.processObject(value, envPath, envPrefix, options);
|
|
3770
2049
|
} else {
|
|
3771
|
-
const envValue =
|
|
2050
|
+
const envValue = process5.env[envKey] || (oldEnvKey ? process5.env[oldEnvKey] : undefined);
|
|
3772
2051
|
if (envValue !== undefined) {
|
|
3773
2052
|
if (options.verbose) {
|
|
3774
|
-
const _usedKey =
|
|
2053
|
+
const _usedKey = process5.env[envKey] ? envKey : oldEnvKey;
|
|
3775
2054
|
}
|
|
3776
2055
|
try {
|
|
3777
2056
|
obj[key] = this.parseEnvironmentValue(envValue, typeof value, envKey, options.customParsers, options.configName);
|
|
@@ -3807,7 +2086,7 @@ class EnvProcessor {
|
|
|
3807
2086
|
getEnvironmentVariables(prefix) {
|
|
3808
2087
|
const envVars = {};
|
|
3809
2088
|
const upperPrefix = prefix.toUpperCase();
|
|
3810
|
-
for (const [key, value] of Object.entries(
|
|
2089
|
+
for (const [key, value] of Object.entries(process5.env)) {
|
|
3811
2090
|
if (key.startsWith(upperPrefix) && value !== undefined) {
|
|
3812
2091
|
envVars[key] = value;
|
|
3813
2092
|
}
|
|
@@ -3831,11 +2110,11 @@ class EnvProcessor {
|
|
|
3831
2110
|
errors
|
|
3832
2111
|
};
|
|
3833
2112
|
}
|
|
3834
|
-
generateEnvVarDocs(configName,
|
|
2113
|
+
generateEnvVarDocs(configName, defaultConfig2, options = {}) {
|
|
3835
2114
|
const { prefix, format = "text" } = options;
|
|
3836
2115
|
const envPrefix = prefix || this.generateEnvPrefix(configName);
|
|
3837
2116
|
const envVars = [];
|
|
3838
|
-
this.extractEnvVarInfo(
|
|
2117
|
+
this.extractEnvVarInfo(defaultConfig2, [], envPrefix, envVars);
|
|
3839
2118
|
switch (format) {
|
|
3840
2119
|
case "markdown":
|
|
3841
2120
|
return this.formatAsMarkdown(envVars, configName);
|
|
@@ -3902,7 +2181,18 @@ class EnvProcessor {
|
|
|
3902
2181
|
return result;
|
|
3903
2182
|
}
|
|
3904
2183
|
}
|
|
3905
|
-
|
|
2184
|
+
var init_env_processor = __esm(() => {
|
|
2185
|
+
init_cache();
|
|
2186
|
+
init_errors();
|
|
2187
|
+
});
|
|
2188
|
+
function getEnvOrDefault(key, defaultValue) {
|
|
2189
|
+
const process6 = __require2("process");
|
|
2190
|
+
if (typeof process6 === "undefined" || !process6.env)
|
|
2191
|
+
return defaultValue;
|
|
2192
|
+
const envValue = process6.env[key];
|
|
2193
|
+
return envValue !== undefined ? envValue : defaultValue;
|
|
2194
|
+
}
|
|
2195
|
+
function deepMerge(target, source, options = {}) {
|
|
3906
2196
|
const visited = new WeakMap;
|
|
3907
2197
|
return deepMergeWithVisited(target, source, options, visited);
|
|
3908
2198
|
}
|
|
@@ -3924,7 +2214,7 @@ function deepMergeWithVisited(target, source, options, visited) {
|
|
|
3924
2214
|
if (Array.isArray(source) || Array.isArray(target)) {
|
|
3925
2215
|
return mergeArraysWithVisited(target, source, arrayMergeMode, visited);
|
|
3926
2216
|
}
|
|
3927
|
-
if (!
|
|
2217
|
+
if (!isObject(source) || !isObject(target)) {
|
|
3928
2218
|
return source;
|
|
3929
2219
|
}
|
|
3930
2220
|
return mergeObjectsWithVisited(target, source, options, visited);
|
|
@@ -3953,7 +2243,7 @@ function mergeArraysWithVisited(target, source, mode, visited) {
|
|
|
3953
2243
|
function concatArraysWithDedup(target, source) {
|
|
3954
2244
|
const result = [...source];
|
|
3955
2245
|
for (const item of target) {
|
|
3956
|
-
if (!result.some((existingItem) =>
|
|
2246
|
+
if (!result.some((existingItem) => deepEquals(existingItem, item))) {
|
|
3957
2247
|
result.push(item);
|
|
3958
2248
|
}
|
|
3959
2249
|
}
|
|
@@ -3964,7 +2254,7 @@ function smartMergeArraysWithVisited(target, source, visited) {
|
|
|
3964
2254
|
return target;
|
|
3965
2255
|
if (target.length === 0)
|
|
3966
2256
|
return source;
|
|
3967
|
-
if (
|
|
2257
|
+
if (isObject(source[0]) && isObject(target[0])) {
|
|
3968
2258
|
return mergeObjectArraysWithVisited(target, source, visited);
|
|
3969
2259
|
}
|
|
3970
2260
|
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
@@ -3981,7 +2271,7 @@ function smartMergeArraysWithVisited(target, source, visited) {
|
|
|
3981
2271
|
function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
3982
2272
|
const result = [...source];
|
|
3983
2273
|
for (const targetItem of target) {
|
|
3984
|
-
if (!
|
|
2274
|
+
if (!isObject(targetItem)) {
|
|
3985
2275
|
result.push(targetItem);
|
|
3986
2276
|
continue;
|
|
3987
2277
|
}
|
|
@@ -3989,7 +2279,7 @@ function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
|
3989
2279
|
let hasMatch = false;
|
|
3990
2280
|
for (const key of identifierKeys) {
|
|
3991
2281
|
if (key in targetItem) {
|
|
3992
|
-
const existingItem = result.find((item) =>
|
|
2282
|
+
const existingItem = result.find((item) => isObject(item) && (key in item) && item[key] === targetItem[key]);
|
|
3993
2283
|
if (existingItem) {
|
|
3994
2284
|
hasMatch = true;
|
|
3995
2285
|
break;
|
|
@@ -4004,11 +2294,11 @@ function mergeObjectArraysWithVisited(target, source, _visited) {
|
|
|
4004
2294
|
}
|
|
4005
2295
|
function mergeObjectsWithVisited(target, source, options, visited) {
|
|
4006
2296
|
const sourceObj = source;
|
|
4007
|
-
if (
|
|
2297
|
+
if (isObject(sourceObj) && visited.has(sourceObj)) {
|
|
4008
2298
|
return visited.get(sourceObj);
|
|
4009
2299
|
}
|
|
4010
2300
|
const merged = { ...target };
|
|
4011
|
-
if (
|
|
2301
|
+
if (isObject(sourceObj)) {
|
|
4012
2302
|
visited.set(sourceObj, merged);
|
|
4013
2303
|
}
|
|
4014
2304
|
for (const key in sourceObj) {
|
|
@@ -4024,7 +2314,7 @@ function mergeObjectsWithVisited(target, source, options, visited) {
|
|
|
4024
2314
|
merged[key] = sourceValue;
|
|
4025
2315
|
continue;
|
|
4026
2316
|
}
|
|
4027
|
-
if (
|
|
2317
|
+
if (isObject(sourceValue) && isObject(targetValue)) {
|
|
4028
2318
|
merged[key] = deepMergeWithVisited(targetValue, sourceValue, options, visited);
|
|
4029
2319
|
} else if (Array.isArray(sourceValue) || Array.isArray(targetValue)) {
|
|
4030
2320
|
merged[key] = mergeArraysWithVisited(targetValue, sourceValue, options.arrayMergeMode || "smart", visited);
|
|
@@ -4034,26 +2324,26 @@ function mergeObjectsWithVisited(target, source, options, visited) {
|
|
|
4034
2324
|
}
|
|
4035
2325
|
return merged;
|
|
4036
2326
|
}
|
|
4037
|
-
function
|
|
2327
|
+
function deepMergeWithArrayStrategy(target, source, strategy = "replace") {
|
|
4038
2328
|
const arrayMergeMode = strategy === "replace" ? "replace" : "smart";
|
|
4039
|
-
return
|
|
2329
|
+
return deepMerge(target, source, {
|
|
4040
2330
|
arrayMergeMode,
|
|
4041
2331
|
skipNullish: true
|
|
4042
2332
|
});
|
|
4043
2333
|
}
|
|
4044
|
-
function
|
|
2334
|
+
function deepEquals(a, b) {
|
|
4045
2335
|
if (a === b)
|
|
4046
2336
|
return true;
|
|
4047
2337
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
4048
2338
|
if (a.length !== b.length)
|
|
4049
2339
|
return false;
|
|
4050
2340
|
for (let i = 0;i < a.length; i++) {
|
|
4051
|
-
if (!
|
|
2341
|
+
if (!deepEquals(a[i], b[i]))
|
|
4052
2342
|
return false;
|
|
4053
2343
|
}
|
|
4054
2344
|
return true;
|
|
4055
2345
|
}
|
|
4056
|
-
if (
|
|
2346
|
+
if (isObject(a) && isObject(b)) {
|
|
4057
2347
|
const keysA = Object.keys(a);
|
|
4058
2348
|
const keysB = Object.keys(b);
|
|
4059
2349
|
if (keysA.length !== keysB.length)
|
|
@@ -4061,20 +2351,28 @@ function deepEquals3(a, b) {
|
|
|
4061
2351
|
for (const key of keysA) {
|
|
4062
2352
|
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
4063
2353
|
return false;
|
|
4064
|
-
if (!
|
|
2354
|
+
if (!deepEquals(a[key], b[key]))
|
|
4065
2355
|
return false;
|
|
4066
2356
|
}
|
|
4067
2357
|
return true;
|
|
4068
2358
|
}
|
|
4069
2359
|
return false;
|
|
4070
2360
|
}
|
|
4071
|
-
function
|
|
2361
|
+
function isObject(item) {
|
|
4072
2362
|
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
4073
2363
|
}
|
|
2364
|
+
var ArrayMergeStrategies;
|
|
2365
|
+
var init_utils = __esm(() => {
|
|
2366
|
+
ArrayMergeStrategies = {
|
|
2367
|
+
replace: "replace",
|
|
2368
|
+
concat: "concat",
|
|
2369
|
+
smart: "smart"
|
|
2370
|
+
};
|
|
2371
|
+
});
|
|
4074
2372
|
|
|
4075
2373
|
class ConfigFileLoader {
|
|
4076
2374
|
extensions = [".ts", ".js", ".mjs", ".cjs", ".json", ".mts", ".cts"];
|
|
4077
|
-
async loadFromPath(configPath,
|
|
2375
|
+
async loadFromPath(configPath, defaultConfig2, options = {}) {
|
|
4078
2376
|
const {
|
|
4079
2377
|
arrayStrategy = "replace",
|
|
4080
2378
|
useCache = true,
|
|
@@ -4092,7 +2390,7 @@ class ConfigFileLoader {
|
|
|
4092
2390
|
}
|
|
4093
2391
|
}
|
|
4094
2392
|
const loadOperation = async () => {
|
|
4095
|
-
if (!
|
|
2393
|
+
if (!existsSync3(configPath)) {
|
|
4096
2394
|
return null;
|
|
4097
2395
|
}
|
|
4098
2396
|
try {
|
|
@@ -4107,7 +2405,7 @@ class ConfigFileLoader {
|
|
|
4107
2405
|
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig)) {
|
|
4108
2406
|
throw new ConfigLoadError(configPath, new Error("Configuration must export a valid object"), "unknown");
|
|
4109
2407
|
}
|
|
4110
|
-
const mergedConfig =
|
|
2408
|
+
const mergedConfig = deepMergeWithArrayStrategy(defaultConfig2, loadedConfig, arrayStrategy);
|
|
4111
2409
|
const source = {
|
|
4112
2410
|
type: "file",
|
|
4113
2411
|
path: configPath,
|
|
@@ -4129,10 +2427,10 @@ class ConfigFileLoader {
|
|
|
4129
2427
|
}
|
|
4130
2428
|
return loadOperation();
|
|
4131
2429
|
}
|
|
4132
|
-
async tryLoadFromPaths(configPaths,
|
|
2430
|
+
async tryLoadFromPaths(configPaths, defaultConfig2, options = {}) {
|
|
4133
2431
|
for (const configPath of configPaths) {
|
|
4134
2432
|
try {
|
|
4135
|
-
const result = await this.loadFromPath(configPath,
|
|
2433
|
+
const result = await this.loadFromPath(configPath, defaultConfig2, options);
|
|
4136
2434
|
if (result) {
|
|
4137
2435
|
return result;
|
|
4138
2436
|
}
|
|
@@ -4152,7 +2450,7 @@ class ConfigFileLoader {
|
|
|
4152
2450
|
const paths = [];
|
|
4153
2451
|
for (const pattern of patterns) {
|
|
4154
2452
|
for (const ext of this.extensions) {
|
|
4155
|
-
paths.push(
|
|
2453
|
+
paths.push(resolve3(directory, `${pattern}${ext}`));
|
|
4156
2454
|
}
|
|
4157
2455
|
}
|
|
4158
2456
|
return paths;
|
|
@@ -4163,17 +2461,26 @@ class ConfigFileLoader {
|
|
|
4163
2461
|
if (configName) {
|
|
4164
2462
|
patterns.push(configName, `.${configName}.config`, `${configName}.config`, `.${configName}`);
|
|
4165
2463
|
}
|
|
4166
|
-
|
|
4167
|
-
|
|
2464
|
+
const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
|
|
2465
|
+
for (const a of aliases) {
|
|
2466
|
+
if (!a)
|
|
2467
|
+
continue;
|
|
2468
|
+
patterns.push(a, `.${a}.config`, `${a}.config`, `.${a}`);
|
|
4168
2469
|
if (configName) {
|
|
4169
|
-
patterns.push(`${configName}.${
|
|
2470
|
+
patterns.push(`${configName}.${a}.config`, `.${configName}.${a}.config`);
|
|
4170
2471
|
}
|
|
4171
2472
|
}
|
|
4172
|
-
|
|
2473
|
+
const seen = new Set;
|
|
2474
|
+
return patterns.filter((p) => {
|
|
2475
|
+
if (!p || seen.has(p))
|
|
2476
|
+
return false;
|
|
2477
|
+
seen.add(p);
|
|
2478
|
+
return true;
|
|
2479
|
+
});
|
|
4173
2480
|
}
|
|
4174
2481
|
checkFileAccess(filePath) {
|
|
4175
2482
|
return withErrorRecovery(async () => {
|
|
4176
|
-
return
|
|
2483
|
+
return existsSync3(filePath);
|
|
4177
2484
|
}, {
|
|
4178
2485
|
maxRetries: 2,
|
|
4179
2486
|
retryDelay: 100,
|
|
@@ -4182,14 +2489,14 @@ class ConfigFileLoader {
|
|
|
4182
2489
|
}
|
|
4183
2490
|
async discoverConfigFiles(directory, configName, alias) {
|
|
4184
2491
|
const discoveredFiles = [];
|
|
4185
|
-
if (!
|
|
2492
|
+
if (!existsSync3(directory)) {
|
|
4186
2493
|
return discoveredFiles;
|
|
4187
2494
|
}
|
|
4188
2495
|
if (configName || alias) {
|
|
4189
2496
|
const patterns = this.generateNamePatterns(configName || "", alias);
|
|
4190
2497
|
for (const pattern of patterns) {
|
|
4191
2498
|
for (const ext of this.extensions) {
|
|
4192
|
-
const filePath =
|
|
2499
|
+
const filePath = resolve3(directory, `${pattern}${ext}`);
|
|
4193
2500
|
if (await this.checkFileAccess(filePath)) {
|
|
4194
2501
|
discoveredFiles.push(filePath);
|
|
4195
2502
|
}
|
|
@@ -4197,11 +2504,11 @@ class ConfigFileLoader {
|
|
|
4197
2504
|
}
|
|
4198
2505
|
} else {
|
|
4199
2506
|
try {
|
|
4200
|
-
const { readdirSync:
|
|
4201
|
-
const files =
|
|
2507
|
+
const { readdirSync: readdirSync3 } = await import("fs");
|
|
2508
|
+
const files = readdirSync3(directory);
|
|
4202
2509
|
for (const file of files) {
|
|
4203
2510
|
if (this.looksLikeConfigFile(file)) {
|
|
4204
|
-
const filePath =
|
|
2511
|
+
const filePath = resolve3(directory, file);
|
|
4205
2512
|
if (await this.checkFileAccess(filePath)) {
|
|
4206
2513
|
discoveredFiles.push(filePath);
|
|
4207
2514
|
}
|
|
@@ -4224,23 +2531,23 @@ class ConfigFileLoader {
|
|
|
4224
2531
|
async validateConfigFile(filePath) {
|
|
4225
2532
|
const errors = [];
|
|
4226
2533
|
try {
|
|
4227
|
-
if (!
|
|
2534
|
+
if (!existsSync3(filePath)) {
|
|
4228
2535
|
errors.push("Configuration file does not exist");
|
|
4229
2536
|
return errors;
|
|
4230
2537
|
}
|
|
4231
2538
|
const imported = await import(filePath);
|
|
4232
|
-
const
|
|
4233
|
-
if (
|
|
2539
|
+
const config2 = imported.default || imported;
|
|
2540
|
+
if (config2 === undefined) {
|
|
4234
2541
|
errors.push("Configuration file must export a default value or named exports");
|
|
4235
|
-
} else if (typeof
|
|
2542
|
+
} else if (typeof config2 !== "object" || config2 === null) {
|
|
4236
2543
|
errors.push("Configuration must be an object");
|
|
4237
|
-
} else if (Array.isArray(
|
|
2544
|
+
} else if (Array.isArray(config2)) {
|
|
4238
2545
|
errors.push("Configuration cannot be an array at the root level");
|
|
4239
2546
|
}
|
|
4240
2547
|
if (filePath.endsWith(".json")) {
|
|
4241
2548
|
try {
|
|
4242
|
-
const { readFileSync } = await import("fs");
|
|
4243
|
-
const content =
|
|
2549
|
+
const { readFileSync: readFileSync2 } = await import("fs");
|
|
2550
|
+
const content = readFileSync2(filePath, "utf8");
|
|
4244
2551
|
JSON.parse(content);
|
|
4245
2552
|
} catch (jsonError) {
|
|
4246
2553
|
errors.push(`Invalid JSON syntax: ${jsonError}`);
|
|
@@ -4277,10 +2584,14 @@ class ConfigFileLoader {
|
|
|
4277
2584
|
return preloaded;
|
|
4278
2585
|
}
|
|
4279
2586
|
}
|
|
4280
|
-
var
|
|
2587
|
+
var init_file_loader = __esm(() => {
|
|
2588
|
+
init_cache();
|
|
2589
|
+
init_errors();
|
|
2590
|
+
init_utils();
|
|
2591
|
+
});
|
|
4281
2592
|
|
|
4282
2593
|
class ConfigValidator {
|
|
4283
|
-
async validateConfiguration(
|
|
2594
|
+
async validateConfiguration(config2, schema, options = {}) {
|
|
4284
2595
|
const {
|
|
4285
2596
|
stopOnFirstError = false,
|
|
4286
2597
|
validateRequired = true,
|
|
@@ -4302,11 +2613,11 @@ class ConfigValidator {
|
|
|
4302
2613
|
};
|
|
4303
2614
|
try {
|
|
4304
2615
|
if (typeof schema === "string") {
|
|
4305
|
-
return await this.validateWithSchemaFile(
|
|
2616
|
+
return await this.validateWithSchemaFile(config2, schema, resolvedOptions);
|
|
4306
2617
|
} else if (Array.isArray(schema)) {
|
|
4307
|
-
return this.validateWithRules(
|
|
2618
|
+
return this.validateWithRules(config2, [...schema, ...customRules], resolvedOptions);
|
|
4308
2619
|
} else {
|
|
4309
|
-
return this.validateWithJSONSchema(
|
|
2620
|
+
return this.validateWithJSONSchema(config2, schema, resolvedOptions);
|
|
4310
2621
|
}
|
|
4311
2622
|
} catch (error) {
|
|
4312
2623
|
errors.push({
|
|
@@ -4323,26 +2634,26 @@ class ConfigValidator {
|
|
|
4323
2634
|
}
|
|
4324
2635
|
return operation();
|
|
4325
2636
|
}
|
|
4326
|
-
async validateWithSchemaFile(
|
|
2637
|
+
async validateWithSchemaFile(config2, schemaPath, options) {
|
|
4327
2638
|
try {
|
|
4328
|
-
if (!
|
|
2639
|
+
if (!existsSync4(schemaPath)) {
|
|
4329
2640
|
throw new SchemaValidationError(schemaPath, [{ path: "", message: "Schema file does not exist" }]);
|
|
4330
2641
|
}
|
|
4331
2642
|
const schemaModule = await import(schemaPath);
|
|
4332
2643
|
const schema = schemaModule.default || schemaModule;
|
|
4333
2644
|
if (Array.isArray(schema)) {
|
|
4334
|
-
return this.validateWithRules(
|
|
2645
|
+
return this.validateWithRules(config2, schema, options);
|
|
4335
2646
|
} else {
|
|
4336
|
-
return this.validateWithJSONSchema(
|
|
2647
|
+
return this.validateWithJSONSchema(config2, schema, options);
|
|
4337
2648
|
}
|
|
4338
2649
|
} catch (error) {
|
|
4339
2650
|
throw new SchemaValidationError(schemaPath, [{ path: "", message: `Failed to load schema: ${error}` }]);
|
|
4340
2651
|
}
|
|
4341
2652
|
}
|
|
4342
|
-
validateWithJSONSchema(
|
|
2653
|
+
validateWithJSONSchema(config2, schema, options) {
|
|
4343
2654
|
const errors = [];
|
|
4344
2655
|
const warnings = [];
|
|
4345
|
-
this.validateObjectAgainstSchema(
|
|
2656
|
+
this.validateObjectAgainstSchema(config2, schema, "", errors, warnings, options);
|
|
4346
2657
|
return {
|
|
4347
2658
|
isValid: errors.length === 0,
|
|
4348
2659
|
errors,
|
|
@@ -4476,12 +2787,12 @@ class ConfigValidator {
|
|
|
4476
2787
|
}
|
|
4477
2788
|
}
|
|
4478
2789
|
}
|
|
4479
|
-
validateWithRules(
|
|
2790
|
+
validateWithRules(config2, rules, options) {
|
|
4480
2791
|
const errors = [];
|
|
4481
2792
|
const warnings = [];
|
|
4482
2793
|
for (const rule of rules) {
|
|
4483
2794
|
try {
|
|
4484
|
-
const value = this.getValueByPath(
|
|
2795
|
+
const value = this.getValueByPath(config2, rule.path);
|
|
4485
2796
|
const ruleErrors = this.validateWithRule(value, rule, rule.path);
|
|
4486
2797
|
errors.push(...ruleErrors);
|
|
4487
2798
|
if (options.stopOnFirstError && errors.length > 0) {
|
|
@@ -4646,9 +2957,22 @@ class ConfigValidator {
|
|
|
4646
2957
|
};
|
|
4647
2958
|
}
|
|
4648
2959
|
}
|
|
4649
|
-
var
|
|
4650
|
-
|
|
2960
|
+
var URL_PATTERN;
|
|
2961
|
+
var init_validator = __esm(() => {
|
|
2962
|
+
init_cache();
|
|
2963
|
+
init_errors();
|
|
2964
|
+
URL_PATTERN = /^https?:\/\//;
|
|
4651
2965
|
});
|
|
2966
|
+
function formatAliasSuffix(alias) {
|
|
2967
|
+
if (!alias)
|
|
2968
|
+
return "";
|
|
2969
|
+
const list = Array.isArray(alias) ? alias.filter(Boolean) : [alias];
|
|
2970
|
+
if (list.length === 0)
|
|
2971
|
+
return "";
|
|
2972
|
+
if (list.length === 1)
|
|
2973
|
+
return ` or alias "${list[0]}"`;
|
|
2974
|
+
return ` or aliases ${list.map((a) => `"${a}"`).join(", ")}`;
|
|
2975
|
+
}
|
|
4652
2976
|
|
|
4653
2977
|
class ConfigLoader {
|
|
4654
2978
|
fileLoader = new ConfigFileLoader;
|
|
@@ -4731,14 +3055,14 @@ class ConfigLoader {
|
|
|
4731
3055
|
performance2.onMetrics(metrics);
|
|
4732
3056
|
}
|
|
4733
3057
|
if (performance2.slowThreshold && metrics.duration > performance2.slowThreshold) {
|
|
4734
|
-
|
|
3058
|
+
log.warn(`Slow configuration loading detected: ${metrics.duration}ms for ${baseOptions.name}`);
|
|
4735
3059
|
}
|
|
4736
3060
|
result.metrics = metrics;
|
|
4737
3061
|
}
|
|
4738
3062
|
return result;
|
|
4739
3063
|
} catch (error) {
|
|
4740
3064
|
const duration = Date.now() - startTime;
|
|
4741
|
-
|
|
3065
|
+
log.error(`Configuration loading failed after ${duration}ms:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4742
3066
|
throw error;
|
|
4743
3067
|
}
|
|
4744
3068
|
}
|
|
@@ -4748,44 +3072,44 @@ class ConfigLoader {
|
|
|
4748
3072
|
alias,
|
|
4749
3073
|
cwd,
|
|
4750
3074
|
configDir,
|
|
4751
|
-
defaultConfig:
|
|
3075
|
+
defaultConfig: defaultConfig2,
|
|
4752
3076
|
checkEnv = true,
|
|
4753
3077
|
arrayStrategy = "replace",
|
|
4754
3078
|
verbose = false
|
|
4755
3079
|
} = options;
|
|
4756
|
-
const baseDir = cwd ||
|
|
3080
|
+
const baseDir = cwd || process7.cwd();
|
|
4757
3081
|
const searchPaths = [];
|
|
4758
|
-
const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir,
|
|
3082
|
+
const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig2, arrayStrategy, verbose, checkEnv, cacheOptions);
|
|
4759
3083
|
if (localResult) {
|
|
4760
3084
|
searchPaths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
|
|
4761
3085
|
return this.finalizeResult(localResult, searchPaths, checkEnv, name, verbose);
|
|
4762
3086
|
}
|
|
4763
|
-
const homeResult = await this.loadHomeConfiguration(name, alias,
|
|
3087
|
+
const homeResult = await this.loadHomeConfiguration(name, alias, defaultConfig2, arrayStrategy, verbose, checkEnv);
|
|
4764
3088
|
if (homeResult) {
|
|
4765
3089
|
searchPaths.push(...this.getHomeSearchPaths(name, alias));
|
|
4766
3090
|
return this.finalizeResult(homeResult, searchPaths, checkEnv, name, verbose);
|
|
4767
3091
|
}
|
|
4768
|
-
const packageResult = await this.loadPackageJsonConfiguration(name, alias, baseDir,
|
|
3092
|
+
const packageResult = await this.loadPackageJsonConfiguration(name, alias, baseDir, defaultConfig2, arrayStrategy, verbose, checkEnv);
|
|
4769
3093
|
if (packageResult) {
|
|
4770
|
-
searchPaths.push(
|
|
3094
|
+
searchPaths.push(resolve5(baseDir, "package.json"));
|
|
4771
3095
|
return this.finalizeResult(packageResult, searchPaths, checkEnv, name, verbose);
|
|
4772
3096
|
}
|
|
4773
3097
|
searchPaths.push(...this.getAllSearchPaths(name, alias, baseDir, configDir));
|
|
4774
3098
|
if (throwOnNotFound) {
|
|
4775
3099
|
throw ErrorFactory.configNotFound(name, searchPaths, alias);
|
|
4776
3100
|
}
|
|
4777
|
-
const envResult = await this.applyEnvironmentVariables(name,
|
|
3101
|
+
const envResult = await this.applyEnvironmentVariables(name, defaultConfig2, checkEnv, verbose);
|
|
4778
3102
|
return {
|
|
4779
3103
|
...envResult,
|
|
4780
|
-
warnings: [`No configuration file found for "${name}"${alias
|
|
3104
|
+
warnings: [`No configuration file found for "${name}"${formatAliasSuffix(alias)}, using defaults with environment variables`]
|
|
4781
3105
|
};
|
|
4782
3106
|
}
|
|
4783
|
-
async loadLocalConfiguration(name, alias, baseDir, configDir,
|
|
4784
|
-
const envDefaultConfig = checkEnv ?
|
|
3107
|
+
async loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig2, arrayStrategy, verbose, checkEnv, cacheOptions) {
|
|
3108
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4785
3109
|
const searchDirectories = this.getLocalDirectories(baseDir, configDir);
|
|
4786
3110
|
for (const directory of searchDirectories) {
|
|
4787
3111
|
if (verbose) {
|
|
4788
|
-
|
|
3112
|
+
log.info(`Searching for configuration in: ${directory}`);
|
|
4789
3113
|
}
|
|
4790
3114
|
const configPaths = this.fileLoader.generateConfigPaths(name, directory, alias);
|
|
4791
3115
|
const result = await this.fileLoader.tryLoadFromPaths(configPaths, envDefaultConfig, {
|
|
@@ -4796,56 +3120,72 @@ class ConfigLoader {
|
|
|
4796
3120
|
});
|
|
4797
3121
|
if (result) {
|
|
4798
3122
|
if (verbose) {
|
|
4799
|
-
|
|
3123
|
+
log.success(`Configuration loaded from: ${result.source.path}`);
|
|
4800
3124
|
}
|
|
4801
3125
|
return result;
|
|
4802
3126
|
}
|
|
4803
3127
|
}
|
|
4804
3128
|
return null;
|
|
4805
3129
|
}
|
|
4806
|
-
async loadHomeConfiguration(name, alias,
|
|
3130
|
+
async loadHomeConfiguration(name, alias, defaultConfig2, arrayStrategy, verbose, checkEnv) {
|
|
4807
3131
|
if (!name)
|
|
4808
3132
|
return null;
|
|
4809
|
-
const envDefaultConfig = checkEnv ?
|
|
3133
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4810
3134
|
const homeDirectories = [
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
3135
|
+
resolve5(homedir(), ".config", name),
|
|
3136
|
+
resolve5(homedir(), ".config"),
|
|
3137
|
+
homedir()
|
|
4814
3138
|
];
|
|
4815
3139
|
for (const directory of homeDirectories) {
|
|
4816
3140
|
if (verbose) {
|
|
4817
|
-
|
|
3141
|
+
log.info(`Checking home directory: ${directory}`);
|
|
4818
3142
|
}
|
|
4819
3143
|
const configPaths = this.fileLoader.generateConfigPaths(name, directory, alias);
|
|
4820
3144
|
const result = await this.fileLoader.tryLoadFromPaths(configPaths, envDefaultConfig, { arrayStrategy, verbose });
|
|
4821
3145
|
if (result) {
|
|
4822
3146
|
if (verbose) {
|
|
4823
|
-
|
|
3147
|
+
log.success(`Configuration loaded from home directory: ${result.source.path}`);
|
|
4824
3148
|
}
|
|
4825
3149
|
return result;
|
|
4826
3150
|
}
|
|
4827
3151
|
}
|
|
4828
3152
|
return null;
|
|
4829
3153
|
}
|
|
4830
|
-
async loadPackageJsonConfiguration(name, alias, baseDir,
|
|
4831
|
-
const envDefaultConfig = checkEnv ?
|
|
3154
|
+
async loadPackageJsonConfiguration(name, alias, baseDir, defaultConfig2, arrayStrategy, verbose, checkEnv) {
|
|
3155
|
+
const envDefaultConfig = checkEnv ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
4832
3156
|
try {
|
|
4833
|
-
const pkgPath =
|
|
4834
|
-
if (!
|
|
3157
|
+
const pkgPath = resolve5(baseDir, "package.json");
|
|
3158
|
+
if (!existsSync5(pkgPath)) {
|
|
3159
|
+
return null;
|
|
3160
|
+
}
|
|
3161
|
+
let pkg = {};
|
|
3162
|
+
try {
|
|
3163
|
+
pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
3164
|
+
} catch (parseError) {
|
|
3165
|
+
if (verbose) {
|
|
3166
|
+
log.warn(`Failed to parse package.json:`, [parseError instanceof Error ? parseError : new Error(String(parseError))]);
|
|
3167
|
+
}
|
|
4835
3168
|
return null;
|
|
4836
3169
|
}
|
|
4837
|
-
const pkg = await import(pkgPath);
|
|
4838
3170
|
let pkgConfig = pkg[name];
|
|
4839
3171
|
let usedName = name;
|
|
4840
3172
|
if (!pkgConfig && alias) {
|
|
4841
|
-
|
|
4842
|
-
|
|
3173
|
+
const aliases = Array.isArray(alias) ? alias : [alias];
|
|
3174
|
+
for (const a of aliases) {
|
|
3175
|
+
if (!a)
|
|
3176
|
+
continue;
|
|
3177
|
+
if (pkg[a]) {
|
|
3178
|
+
pkgConfig = pkg[a];
|
|
3179
|
+
usedName = a;
|
|
3180
|
+
break;
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
4843
3183
|
}
|
|
4844
3184
|
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
4845
3185
|
if (verbose) {
|
|
4846
|
-
|
|
3186
|
+
log.success(`Configuration loaded from package.json: ${usedName}`);
|
|
4847
3187
|
}
|
|
4848
|
-
const mergedConfig =
|
|
3188
|
+
const mergedConfig = deepMergeWithArrayStrategy(envDefaultConfig, pkgConfig, arrayStrategy);
|
|
4849
3189
|
return {
|
|
4850
3190
|
config: mergedConfig,
|
|
4851
3191
|
source: {
|
|
@@ -4858,15 +3198,15 @@ class ConfigLoader {
|
|
|
4858
3198
|
}
|
|
4859
3199
|
} catch (error) {
|
|
4860
3200
|
if (verbose) {
|
|
4861
|
-
|
|
3201
|
+
log.warn(`Failed to load package.json:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4862
3202
|
}
|
|
4863
3203
|
}
|
|
4864
3204
|
return null;
|
|
4865
3205
|
}
|
|
4866
|
-
async applyEnvironmentVariables(name,
|
|
4867
|
-
if (!checkEnv || !name || typeof
|
|
3206
|
+
async applyEnvironmentVariables(name, config2, checkEnv, verbose) {
|
|
3207
|
+
if (!checkEnv || !name || typeof config2 !== "object" || config2 === null || Array.isArray(config2)) {
|
|
4868
3208
|
return {
|
|
4869
|
-
config:
|
|
3209
|
+
config: config2,
|
|
4870
3210
|
source: {
|
|
4871
3211
|
type: "default",
|
|
4872
3212
|
priority: 10,
|
|
@@ -4874,7 +3214,7 @@ class ConfigLoader {
|
|
|
4874
3214
|
}
|
|
4875
3215
|
};
|
|
4876
3216
|
}
|
|
4877
|
-
const processedConfig =
|
|
3217
|
+
const processedConfig = applyEnvVarsToConfig(name, config2, verbose);
|
|
4878
3218
|
return {
|
|
4879
3219
|
config: processedConfig,
|
|
4880
3220
|
source: {
|
|
@@ -4891,16 +3231,16 @@ class ConfigLoader {
|
|
|
4891
3231
|
path: result.source.path
|
|
4892
3232
|
};
|
|
4893
3233
|
}
|
|
4894
|
-
async validateConfiguration(
|
|
3234
|
+
async validateConfiguration(config2, schema, customValidator, configName) {
|
|
4895
3235
|
const errors = [];
|
|
4896
3236
|
if (customValidator) {
|
|
4897
|
-
const customErrors = customValidator(
|
|
3237
|
+
const customErrors = customValidator(config2);
|
|
4898
3238
|
if (customErrors) {
|
|
4899
3239
|
errors.push(...customErrors);
|
|
4900
3240
|
}
|
|
4901
3241
|
}
|
|
4902
3242
|
if (schema) {
|
|
4903
|
-
const validationResult = await this.validator.validateConfiguration(
|
|
3243
|
+
const validationResult = await this.validator.validateConfiguration(config2, schema);
|
|
4904
3244
|
if (!validationResult.isValid) {
|
|
4905
3245
|
errors.push(...validationResult.errors.map((e) => e.path ? `${e.path}: ${e.message}` : e.message));
|
|
4906
3246
|
}
|
|
@@ -4920,8 +3260,10 @@ class ConfigLoader {
|
|
|
4920
3260
|
}
|
|
4921
3261
|
generateCacheKey(configName, options) {
|
|
4922
3262
|
const keyParts = [configName];
|
|
4923
|
-
if (options.alias)
|
|
4924
|
-
|
|
3263
|
+
if (options.alias) {
|
|
3264
|
+
const aliasKey = Array.isArray(options.alias) ? options.alias.join(",") : options.alias;
|
|
3265
|
+
keyParts.push(`alias:${aliasKey}`);
|
|
3266
|
+
}
|
|
4925
3267
|
if (options.cwd)
|
|
4926
3268
|
keyParts.push(`cwd:${options.cwd}`);
|
|
4927
3269
|
if (options.configDir)
|
|
@@ -4933,16 +3275,16 @@ class ConfigLoader {
|
|
|
4933
3275
|
getLocalDirectories(baseDir, configDir) {
|
|
4934
3276
|
return Array.from(new Set([
|
|
4935
3277
|
baseDir,
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
configDir ?
|
|
3278
|
+
resolve5(baseDir, "config"),
|
|
3279
|
+
resolve5(baseDir, ".config"),
|
|
3280
|
+
configDir ? resolve5(baseDir, configDir) : undefined
|
|
4939
3281
|
].filter(Boolean)));
|
|
4940
3282
|
}
|
|
4941
3283
|
getAllSearchPaths(name, alias, baseDir, configDir) {
|
|
4942
3284
|
const paths = [];
|
|
4943
3285
|
paths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
|
|
4944
3286
|
paths.push(...this.getHomeSearchPaths(name, alias));
|
|
4945
|
-
paths.push(
|
|
3287
|
+
paths.push(resolve5(baseDir, "package.json"));
|
|
4946
3288
|
return paths;
|
|
4947
3289
|
}
|
|
4948
3290
|
getLocalSearchPaths(name, alias, baseDir, configDir) {
|
|
@@ -4957,9 +3299,9 @@ class ConfigLoader {
|
|
|
4957
3299
|
if (!name)
|
|
4958
3300
|
return [];
|
|
4959
3301
|
const homeDirectories = [
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
3302
|
+
resolve5(homedir(), ".config", name),
|
|
3303
|
+
resolve5(homedir(), ".config"),
|
|
3304
|
+
homedir()
|
|
4963
3305
|
];
|
|
4964
3306
|
const paths = [];
|
|
4965
3307
|
for (const directory of homeDirectories) {
|
|
@@ -4971,9 +3313,20 @@ class ConfigLoader {
|
|
|
4971
3313
|
return this.loadConfig(options);
|
|
4972
3314
|
}
|
|
4973
3315
|
}
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
const
|
|
3316
|
+
function shouldHandleConfigLoadErrorGracefully(error) {
|
|
3317
|
+
const isPermissionError = error.message.includes("EACCES") || error.message.includes("EPERM") || error.message.includes("permission denied");
|
|
3318
|
+
const isSyntaxError = !isPermissionError && (error.message.includes("syntax") || error.message.includes("Expected") || error.message.includes("Unexpected") || error.message.includes("BuildMessage"));
|
|
3319
|
+
const isStructureError = error.message.includes("Configuration must export a valid object") || error.message.includes("Configuration file is empty and exports nothing");
|
|
3320
|
+
return isSyntaxError || isStructureError;
|
|
3321
|
+
}
|
|
3322
|
+
async function loadConfigWithResult(options) {
|
|
3323
|
+
return globalConfigLoader.loadConfig({
|
|
3324
|
+
...options,
|
|
3325
|
+
__strictErrorHandling: true
|
|
3326
|
+
});
|
|
3327
|
+
}
|
|
3328
|
+
async function loadConfig(options) {
|
|
3329
|
+
const defaultConfig2 = "defaultConfig" in options && options.defaultConfig !== undefined ? options.defaultConfig : {};
|
|
4977
3330
|
const isEnhanced = "cache" in options || "performance" in options || "schema" in options || "validate" in options;
|
|
4978
3331
|
try {
|
|
4979
3332
|
let result;
|
|
@@ -4982,34 +3335,85 @@ async function loadConfig5(options) {
|
|
|
4982
3335
|
} else {
|
|
4983
3336
|
result = await globalConfigLoader.loadConfig({
|
|
4984
3337
|
...options,
|
|
4985
|
-
defaultConfig:
|
|
3338
|
+
defaultConfig: defaultConfig2,
|
|
4986
3339
|
cache: { enabled: true },
|
|
4987
3340
|
performance: { enabled: false }
|
|
4988
3341
|
});
|
|
4989
3342
|
}
|
|
4990
|
-
return result?.config ??
|
|
3343
|
+
return result?.config ?? defaultConfig2;
|
|
4991
3344
|
} catch (error) {
|
|
4992
3345
|
const errorName = error instanceof Error ? error.name : "UnknownError";
|
|
4993
3346
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4994
3347
|
const isConfigError = errorName === "ConfigNotFoundError" || errorName === "ConfigLoadError" || errorName === "ConfigValidationError" || errorMessage.includes("config");
|
|
4995
3348
|
if (!isConfigError && options.verbose) {
|
|
4996
|
-
|
|
3349
|
+
log.warn(`Unexpected error loading config, using defaults:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
4997
3350
|
}
|
|
4998
|
-
const configOptions = isEnhanced ? { ...options, defaultConfig:
|
|
3351
|
+
const configOptions = isEnhanced ? { ...options, defaultConfig: defaultConfig2 } : {
|
|
4999
3352
|
...options,
|
|
5000
|
-
defaultConfig:
|
|
3353
|
+
defaultConfig: defaultConfig2,
|
|
5001
3354
|
cache: { enabled: true },
|
|
5002
3355
|
performance: { enabled: false }
|
|
5003
3356
|
};
|
|
5004
3357
|
const shouldCheckEnv = "checkEnv" in options ? options.checkEnv !== false : true;
|
|
5005
3358
|
if (shouldCheckEnv) {
|
|
5006
|
-
const envResult = await globalConfigLoader.applyEnvironmentVariables(configOptions.name || "",
|
|
5007
|
-
return envResult?.config ??
|
|
3359
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(configOptions.name || "", defaultConfig2, true, configOptions.verbose || false);
|
|
3360
|
+
return envResult?.config ?? defaultConfig2;
|
|
3361
|
+
}
|
|
3362
|
+
return defaultConfig2;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
async function config2(nameOrOptions = { defaultConfig: {} }) {
|
|
3366
|
+
if (typeof nameOrOptions === "string") {
|
|
3367
|
+
const { cwd } = await import("process");
|
|
3368
|
+
try {
|
|
3369
|
+
const result = await globalConfigLoader.loadConfig({
|
|
3370
|
+
name: nameOrOptions,
|
|
3371
|
+
cwd: cwd(),
|
|
3372
|
+
generatedDir: "./generated",
|
|
3373
|
+
configDir: "./config",
|
|
3374
|
+
defaultConfig: {},
|
|
3375
|
+
checkEnv: true,
|
|
3376
|
+
arrayStrategy: "replace"
|
|
3377
|
+
});
|
|
3378
|
+
return result.config;
|
|
3379
|
+
} catch (error) {
|
|
3380
|
+
if (error instanceof Error && (error.name === "ConfigNotFoundError" || error.name === "ConfigLoadError" && shouldHandleConfigLoadErrorGracefully(error))) {
|
|
3381
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(nameOrOptions, {}, true, false);
|
|
3382
|
+
return envResult.config;
|
|
3383
|
+
}
|
|
3384
|
+
throw error;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
try {
|
|
3388
|
+
const result = await globalConfigLoader.loadConfig({
|
|
3389
|
+
...nameOrOptions,
|
|
3390
|
+
cwd: nameOrOptions.cwd || process7.cwd(),
|
|
3391
|
+
cache: { enabled: true },
|
|
3392
|
+
performance: { enabled: false }
|
|
3393
|
+
});
|
|
3394
|
+
return result.config;
|
|
3395
|
+
} catch (error) {
|
|
3396
|
+
if (error instanceof Error && (error.name === "ConfigNotFoundError" || error.name === "ConfigLoadError" && shouldHandleConfigLoadErrorGracefully(error))) {
|
|
3397
|
+
const envResult = await globalConfigLoader.applyEnvironmentVariables(nameOrOptions.name || "", nameOrOptions.defaultConfig || {}, nameOrOptions.checkEnv !== false, nameOrOptions.verbose || false);
|
|
3398
|
+
return envResult.config;
|
|
5008
3399
|
}
|
|
5009
|
-
|
|
3400
|
+
throw error;
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
async function tryLoadConfig(configPath, defaultConfig2, arrayStrategy = "replace") {
|
|
3404
|
+
const fileLoader = new ConfigFileLoader;
|
|
3405
|
+
try {
|
|
3406
|
+
const result = await fileLoader.loadFromPath(configPath, defaultConfig2, {
|
|
3407
|
+
arrayStrategy,
|
|
3408
|
+
useCache: false,
|
|
3409
|
+
trackPerformance: false
|
|
3410
|
+
});
|
|
3411
|
+
return result ? result.config : null;
|
|
3412
|
+
} catch {
|
|
3413
|
+
return null;
|
|
5010
3414
|
}
|
|
5011
3415
|
}
|
|
5012
|
-
function
|
|
3416
|
+
function applyEnvVarsToConfig(name, config3, verbose = false) {
|
|
5013
3417
|
const _envProcessor = new EnvProcessor;
|
|
5014
3418
|
const envPrefix = name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
5015
3419
|
function processConfigLevel(obj, path = []) {
|
|
@@ -5024,7 +3428,7 @@ function applyEnvVarsToConfig2(name, config4, verbose = false) {
|
|
|
5024
3428
|
let envValue;
|
|
5025
3429
|
let usedKey;
|
|
5026
3430
|
for (const envKey of envKeys) {
|
|
5027
|
-
envValue =
|
|
3431
|
+
envValue = process7.env[envKey];
|
|
5028
3432
|
if (envValue !== undefined) {
|
|
5029
3433
|
usedKey = envKey;
|
|
5030
3434
|
break;
|
|
@@ -5054,12 +3458,202 @@ function applyEnvVarsToConfig2(name, config4, verbose = false) {
|
|
|
5054
3458
|
}
|
|
5055
3459
|
return result;
|
|
5056
3460
|
}
|
|
5057
|
-
return processConfigLevel(
|
|
3461
|
+
return processConfigLevel(config3);
|
|
3462
|
+
}
|
|
3463
|
+
function generateConfigTypes(options) {
|
|
3464
|
+
const configDir = resolve5(process7.cwd(), options.configDir);
|
|
3465
|
+
const generatedDir = resolve5(process7.cwd(), options.generatedDir);
|
|
3466
|
+
const outputFile = resolve5(generatedDir, "config-types.ts");
|
|
3467
|
+
if (!existsSync5(dirname(outputFile)))
|
|
3468
|
+
mkdirSync(dirname(outputFile), { recursive: true, mode: 511 });
|
|
3469
|
+
const files = existsSync5(configDir) ? readdirSync(configDir).map((file) => file.replace(/\.(ts|js|mjs|cjs|mts|cts|json)$/, "")).sort() : [];
|
|
3470
|
+
const content = `// Generated by bunfig v${version}
|
|
3471
|
+
export type ConfigNames = ${files.length ? `'${files.join("' | '")}'` : "string"}
|
|
3472
|
+
`;
|
|
3473
|
+
writeFileSync2(outputFile, content, { mode: 438 });
|
|
3474
|
+
}
|
|
3475
|
+
function createLibraryConfig(options) {
|
|
3476
|
+
let configCache = null;
|
|
3477
|
+
let loadPromise = null;
|
|
3478
|
+
const startLoading = () => {
|
|
3479
|
+
if (!loadPromise) {
|
|
3480
|
+
loadPromise = loadConfig(options).then((loadedConfig) => {
|
|
3481
|
+
configCache = loadedConfig;
|
|
3482
|
+
return loadedConfig;
|
|
3483
|
+
}, (error) => {
|
|
3484
|
+
const defaultConfig3 = "defaultConfig" in options ? options.defaultConfig : {};
|
|
3485
|
+
configCache = defaultConfig3;
|
|
3486
|
+
const verbose = "verbose" in options && options.verbose;
|
|
3487
|
+
if (verbose) {
|
|
3488
|
+
log.warn(`Config loading failed, using defaults:`, [error instanceof Error ? error : new Error(String(error))]);
|
|
3489
|
+
}
|
|
3490
|
+
return defaultConfig3;
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
return loadPromise;
|
|
3494
|
+
};
|
|
3495
|
+
const defaultConfig2 = "defaultConfig" in options ? options.defaultConfig : {};
|
|
3496
|
+
configCache = defaultConfig2;
|
|
3497
|
+
startLoading();
|
|
3498
|
+
return new Proxy({}, {
|
|
3499
|
+
get(target, prop) {
|
|
3500
|
+
if (configCache) {
|
|
3501
|
+
return configCache[prop];
|
|
3502
|
+
}
|
|
3503
|
+
const value = defaultConfig2[prop];
|
|
3504
|
+
startLoading();
|
|
3505
|
+
return value;
|
|
3506
|
+
},
|
|
3507
|
+
has(target, prop) {
|
|
3508
|
+
return prop in (configCache || defaultConfig2);
|
|
3509
|
+
},
|
|
3510
|
+
ownKeys() {
|
|
3511
|
+
return Object.keys(configCache || defaultConfig2);
|
|
3512
|
+
},
|
|
3513
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
3514
|
+
return Object.getOwnPropertyDescriptor(configCache || defaultConfig2, prop);
|
|
3515
|
+
},
|
|
3516
|
+
set(target, prop, value) {
|
|
3517
|
+
if (!configCache) {
|
|
3518
|
+
configCache = { ...defaultConfig2 };
|
|
3519
|
+
}
|
|
3520
|
+
configCache[prop] = value;
|
|
3521
|
+
return true;
|
|
3522
|
+
}
|
|
3523
|
+
});
|
|
3524
|
+
}
|
|
3525
|
+
var log;
|
|
3526
|
+
var globalConfigLoader;
|
|
3527
|
+
var defaultConfigDir;
|
|
3528
|
+
var defaultGeneratedDir;
|
|
3529
|
+
var init_config = __esm(() => {
|
|
3530
|
+
init_src();
|
|
3531
|
+
init_package();
|
|
3532
|
+
init_cache();
|
|
3533
|
+
init_errors();
|
|
3534
|
+
init_env_processor();
|
|
3535
|
+
init_file_loader();
|
|
3536
|
+
init_validator();
|
|
3537
|
+
init_utils();
|
|
3538
|
+
log = new Logger("bunfig", {
|
|
3539
|
+
showTags: true
|
|
3540
|
+
});
|
|
3541
|
+
globalConfigLoader = new ConfigLoader;
|
|
3542
|
+
defaultConfigDir = resolve5(process7.cwd(), "config");
|
|
3543
|
+
defaultGeneratedDir = resolve5(process7.cwd(), "src/generated");
|
|
3544
|
+
});
|
|
3545
|
+
function bunfigPlugin(options) {
|
|
3546
|
+
const configDir = resolve6(process8.cwd(), options?.configDir || "./config");
|
|
3547
|
+
function readConfigSelection() {
|
|
3548
|
+
if (!existsSync6(configDir))
|
|
3549
|
+
return [];
|
|
3550
|
+
const allowed = new Set([".ts", ".js", ".mjs", ".cjs", ".mts", ".cts", ".json"]);
|
|
3551
|
+
const priority = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs", ".json"];
|
|
3552
|
+
const entries = readdirSync2(configDir).filter((file) => allowed.has(extname(file))).map((file) => ({ base: file.replace(/\.(?:ts|js|mjs|cjs|mts|cts|json)$/i, ""), file }));
|
|
3553
|
+
const bestByBase = new Map;
|
|
3554
|
+
for (const { base, file } of entries) {
|
|
3555
|
+
const ext = extname(file).toLowerCase();
|
|
3556
|
+
const current = bestByBase.get(base);
|
|
3557
|
+
if (!current) {
|
|
3558
|
+
bestByBase.set(base, file);
|
|
3559
|
+
continue;
|
|
3560
|
+
}
|
|
3561
|
+
const currExt = extname(current).toLowerCase();
|
|
3562
|
+
if (priority.indexOf(ext) < priority.indexOf(currExt)) {
|
|
3563
|
+
bestByBase.set(base, file);
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
return Array.from(bestByBase.entries()).map(([base, file]) => ({ base, file })).sort((a, b) => a.base.localeCompare(b.base));
|
|
3567
|
+
}
|
|
3568
|
+
function generateModuleSource() {
|
|
3569
|
+
const selections = readConfigSelection();
|
|
3570
|
+
const names = selections.map((s) => s.base);
|
|
3571
|
+
const union = names.length ? names.map((n) => `'${n}'`).join(" | ") : "string";
|
|
3572
|
+
const byName = selections.length ? `{
|
|
3573
|
+
${selections.map((sel) => {
|
|
3574
|
+
const abs = resolve6(configDir, sel.file).replace(/\\/g, "/");
|
|
3575
|
+
return ` '${sel.base}': typeof import('${abs}').default`;
|
|
3576
|
+
}).join(`,
|
|
3577
|
+
`)}
|
|
3578
|
+
}` : "Record<string, any>";
|
|
3579
|
+
const source = `export type ConfigNames = ${union}
|
|
3580
|
+
export type ConfigByName = ${byName}
|
|
3581
|
+
export type Config<N extends ConfigNames> = N extends keyof ConfigByName ? ConfigByName[N] : unknown
|
|
3582
|
+
export type ConfigOf = Config
|
|
3583
|
+
`;
|
|
3584
|
+
return source;
|
|
3585
|
+
}
|
|
3586
|
+
return {
|
|
3587
|
+
name: "bunfig-plugin",
|
|
3588
|
+
setup(builder) {
|
|
3589
|
+
builder.onResolve({ filter: /^virtual:bunfig-types$/ }, (args) => {
|
|
3590
|
+
return { path: args.path, namespace: "bunfig-virtual" };
|
|
3591
|
+
});
|
|
3592
|
+
builder.onLoad({ filter: /^virtual:bunfig-types$/, namespace: "bunfig-virtual" }, () => {
|
|
3593
|
+
const contents = generateModuleSource();
|
|
3594
|
+
return { contents, loader: "ts" };
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
};
|
|
5058
3598
|
}
|
|
5059
|
-
var
|
|
5060
|
-
var
|
|
3599
|
+
var init_plugin = () => {};
|
|
3600
|
+
var exports_src = {};
|
|
3601
|
+
__export(exports_src, {
|
|
3602
|
+
withErrorRecovery: () => withErrorRecovery,
|
|
3603
|
+
tryLoadConfig: () => tryLoadConfig,
|
|
3604
|
+
loadConfigWithResult: () => loadConfigWithResult,
|
|
3605
|
+
loadConfig: () => loadConfig,
|
|
3606
|
+
isRetryableError: () => isRetryableError,
|
|
3607
|
+
isConfigNotFoundError: () => isConfigNotFoundError,
|
|
3608
|
+
isBunfigError: () => isBunfigError,
|
|
3609
|
+
globalPerformanceMonitor: () => globalPerformanceMonitor,
|
|
3610
|
+
globalCache: () => globalCache,
|
|
3611
|
+
getEnvOrDefault: () => getEnvOrDefault,
|
|
3612
|
+
generateConfigTypes: () => generateConfigTypes,
|
|
3613
|
+
defaultGeneratedDir: () => defaultGeneratedDir,
|
|
3614
|
+
defaultConfigDir: () => defaultConfigDir,
|
|
3615
|
+
deepMergeWithArrayStrategy: () => deepMergeWithArrayStrategy,
|
|
3616
|
+
deepMerge: () => deepMerge,
|
|
3617
|
+
createLibraryConfig: () => createLibraryConfig,
|
|
3618
|
+
config: () => config2,
|
|
3619
|
+
bunfigPlugin: () => bunfigPlugin,
|
|
3620
|
+
applyEnvVarsToConfig: () => applyEnvVarsToConfig,
|
|
3621
|
+
TypeGenerationError: () => TypeGenerationError,
|
|
3622
|
+
SchemaValidationError: () => SchemaValidationError,
|
|
3623
|
+
PluginError: () => PluginError,
|
|
3624
|
+
PerformanceMonitor: () => PerformanceMonitor,
|
|
3625
|
+
FileSystemError: () => FileSystemError,
|
|
3626
|
+
ErrorFactory: () => ErrorFactory,
|
|
3627
|
+
EnvVarError: () => EnvVarError,
|
|
3628
|
+
EnvProcessor: () => EnvProcessor,
|
|
3629
|
+
ConfigValidator: () => ConfigValidator,
|
|
3630
|
+
ConfigValidationError: () => ConfigValidationError,
|
|
3631
|
+
ConfigNotFoundError: () => ConfigNotFoundError,
|
|
3632
|
+
ConfigMergeError: () => ConfigMergeError,
|
|
3633
|
+
ConfigLoader: () => ConfigLoader,
|
|
3634
|
+
ConfigLoadError: () => ConfigLoadError,
|
|
3635
|
+
ConfigFileLoader: () => ConfigFileLoader,
|
|
3636
|
+
ConfigCache: () => ConfigCache,
|
|
3637
|
+
CacheUtils: () => CacheUtils,
|
|
3638
|
+
BunfigError: () => BunfigError,
|
|
3639
|
+
BrowserConfigError: () => BrowserConfigError,
|
|
3640
|
+
ArrayMergeStrategies: () => ArrayMergeStrategies
|
|
3641
|
+
});
|
|
3642
|
+
var init_src2 = __esm(() => {
|
|
3643
|
+
init_config();
|
|
3644
|
+
init_errors();
|
|
3645
|
+
init_cache();
|
|
3646
|
+
init_errors();
|
|
3647
|
+
init_plugin();
|
|
3648
|
+
init_env_processor();
|
|
3649
|
+
init_file_loader();
|
|
3650
|
+
init_validator();
|
|
3651
|
+
init_utils();
|
|
3652
|
+
});
|
|
3653
|
+
init_src2();
|
|
5061
3654
|
|
|
5062
3655
|
// src/serve.ts
|
|
3656
|
+
var defaultStxModule = import("@stacksjs/stx");
|
|
5063
3657
|
var defaultStxConfig = {
|
|
5064
3658
|
partialsDir: "partials",
|
|
5065
3659
|
componentsDir: "components",
|
|
@@ -5098,15 +3692,16 @@ var staticContentTypes = {
|
|
|
5098
3692
|
eot: "application/vnd.ms-fontobject"
|
|
5099
3693
|
};
|
|
5100
3694
|
async function serve(options) {
|
|
5101
|
-
const stxConfig = await
|
|
3695
|
+
const stxConfig = await loadConfig({
|
|
5102
3696
|
name: "stx",
|
|
5103
|
-
cwd:
|
|
3697
|
+
cwd: process6.cwd(),
|
|
5104
3698
|
defaultConfig: defaultStxConfig
|
|
5105
3699
|
});
|
|
5106
3700
|
const componentsDir = options.componentsDir ?? stxConfig.componentsDir ?? defaultStxConfig.componentsDir;
|
|
5107
3701
|
const layoutsDir = options.layoutsDir ?? stxConfig.layoutsDir ?? defaultStxConfig.layoutsDir;
|
|
5108
3702
|
const partialsDir = options.partialsDir ?? stxConfig.partialsDir ?? defaultStxConfig.partialsDir;
|
|
5109
3703
|
const publicDir = options.publicDir ?? stxConfig.publicDir ?? "public";
|
|
3704
|
+
const stxModule = options.stxModule ? Promise.resolve(options.stxModule) : defaultStxModule;
|
|
5110
3705
|
const { patterns, port = 3456 } = options;
|
|
5111
3706
|
if (patterns.length === 0) {
|
|
5112
3707
|
console.error("Usage: serve <files...> [--port 3000]");
|
|
@@ -5124,6 +3719,24 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5124
3719
|
const routes = new Map;
|
|
5125
3720
|
let sourceFiles = null;
|
|
5126
3721
|
let assetsInitialized = false;
|
|
3722
|
+
const watchersStarted = new Set;
|
|
3723
|
+
const startWatcher = (dir) => {
|
|
3724
|
+
if (watchersStarted.has(dir))
|
|
3725
|
+
return;
|
|
3726
|
+
try {
|
|
3727
|
+
const watcher = fsWatch(dir, { recursive: true }, (_event, filename) => {
|
|
3728
|
+
if (!filename)
|
|
3729
|
+
return;
|
|
3730
|
+
const f = String(filename);
|
|
3731
|
+
if (!f.endsWith(".stx") && !f.endsWith(".md") && !f.endsWith(".html"))
|
|
3732
|
+
return;
|
|
3733
|
+
sourceFiles = null;
|
|
3734
|
+
routes.clear();
|
|
3735
|
+
});
|
|
3736
|
+
watcher.on("error", () => {});
|
|
3737
|
+
watchersStarted.add(dir);
|
|
3738
|
+
} catch {}
|
|
3739
|
+
};
|
|
5127
3740
|
const pageMiddlewareByPath = new Map;
|
|
5128
3741
|
const pageMiddlewarePatterns = [];
|
|
5129
3742
|
function compileRoutePattern(urlPath) {
|
|
@@ -5161,8 +3774,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5161
3774
|
}
|
|
5162
3775
|
async function detectPageMiddleware(file) {
|
|
5163
3776
|
try {
|
|
5164
|
-
const
|
|
5165
|
-
const src = await fs.readFile(file, "utf-8");
|
|
3777
|
+
const src = await nodeFs.readFile(file, "utf-8");
|
|
5166
3778
|
const meta = src.match(/definePageMeta\s*\(\s*\{[\s\S]*?\}\s*\)/);
|
|
5167
3779
|
if (!meta)
|
|
5168
3780
|
return;
|
|
@@ -5276,9 +3888,9 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5276
3888
|
const supportedExtensions = [".stx", ".md", ".html"];
|
|
5277
3889
|
for (const pattern of patterns) {
|
|
5278
3890
|
try {
|
|
5279
|
-
const
|
|
5280
|
-
|
|
5281
|
-
|
|
3891
|
+
const stat2 = await nodeFs.stat(pattern).catch(() => null);
|
|
3892
|
+
if (stat2?.isDirectory()) {
|
|
3893
|
+
startWatcher(pattern);
|
|
5282
3894
|
const excludeDirs = ["layouts", "components", "partials"];
|
|
5283
3895
|
if (layoutsDir)
|
|
5284
3896
|
excludeDirs.push(layoutsDir.replace(/^.*\//, ""));
|
|
@@ -5310,7 +3922,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5310
3922
|
try {
|
|
5311
3923
|
const { Router } = await import("./chunk-762q71t6.js");
|
|
5312
3924
|
const pagesDir = patterns[0]?.replace(/\/$/, "") || "pages";
|
|
5313
|
-
const router = new Router(
|
|
3925
|
+
const router = new Router(process6.cwd(), { pagesDir });
|
|
5314
3926
|
console.log(`[stx] Generated ${router.routes.length} routes \u2192 .stx/routes.ts`);
|
|
5315
3927
|
} catch (e) {}
|
|
5316
3928
|
return files;
|
|
@@ -5319,19 +3931,40 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5319
3931
|
if (assetsInitialized)
|
|
5320
3932
|
return;
|
|
5321
3933
|
assetsInitialized = true;
|
|
5322
|
-
const fs = await import("fs/promises");
|
|
5323
3934
|
const assetsDir = "./resources/assets";
|
|
5324
3935
|
const targetAssetsDir = "./.stx/assets";
|
|
5325
3936
|
try {
|
|
5326
|
-
const assetsExist = await
|
|
3937
|
+
const assetsExist = await nodeFs.stat(assetsDir).then(() => true).catch(() => false);
|
|
5327
3938
|
if (assetsExist) {
|
|
5328
|
-
await
|
|
5329
|
-
await
|
|
3939
|
+
await nodeFs.rm(targetAssetsDir, { recursive: true, force: true });
|
|
3940
|
+
await nodeFs.cp(assetsDir, targetAssetsDir, { recursive: true });
|
|
5330
3941
|
}
|
|
5331
3942
|
} catch {}
|
|
5332
3943
|
}
|
|
3944
|
+
const htmlCache = new Map;
|
|
3945
|
+
async function templateSignatureFresh(sig) {
|
|
3946
|
+
for (const [p, expected] of sig) {
|
|
3947
|
+
const stat2 = await nodeFs.stat(p).catch(() => null);
|
|
3948
|
+
if (!stat2 || stat2.mtimeMs !== expected)
|
|
3949
|
+
return false;
|
|
3950
|
+
}
|
|
3951
|
+
return true;
|
|
3952
|
+
}
|
|
3953
|
+
async function buildTemplateSignature(filePath, deps) {
|
|
3954
|
+
const sig = new Map;
|
|
3955
|
+
const allPaths = [filePath, ...deps];
|
|
3956
|
+
const stats = await Promise.all(allPaths.map((p) => nodeFs.stat(p).catch(() => null)));
|
|
3957
|
+
for (let i = 0;i < allPaths.length; i++) {
|
|
3958
|
+
const stat2 = stats[i];
|
|
3959
|
+
if (stat2)
|
|
3960
|
+
sig.set(allPaths[i], stat2.mtimeMs);
|
|
3961
|
+
}
|
|
3962
|
+
return sig;
|
|
3963
|
+
}
|
|
5333
3964
|
let crosswindModule = null;
|
|
5334
3965
|
let crosswindLoadAttempted = false;
|
|
3966
|
+
let crosswindUserConfigPromise = null;
|
|
3967
|
+
const crosswindCssCache = new Map;
|
|
5335
3968
|
async function loadCrosswind() {
|
|
5336
3969
|
if (crosswindLoadAttempted)
|
|
5337
3970
|
return crosswindModule;
|
|
@@ -5342,8 +3975,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5342
3975
|
return crosswindModule;
|
|
5343
3976
|
} catch {
|
|
5344
3977
|
try {
|
|
5345
|
-
const
|
|
5346
|
-
const localPath = nodePath.join(process13.env.HOME || "", "Code/Tools/crosswind/packages/crosswind/src/index.ts");
|
|
3978
|
+
const localPath = nodePath.join(process6.env.HOME || "", "Code/Tools/crosswind/packages/crosswind/src/index.ts");
|
|
5347
3979
|
const mod = await import(localPath);
|
|
5348
3980
|
crosswindModule = { CSSGenerator: mod.CSSGenerator, config: mod.config };
|
|
5349
3981
|
return crosswindModule;
|
|
@@ -5384,24 +4016,22 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5384
4016
|
}
|
|
5385
4017
|
if (classes.size === 0)
|
|
5386
4018
|
return "";
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
console.log("[crosswind] config loaded, keys:", Object.keys(userConfig));
|
|
5394
|
-
} catch (e) {
|
|
5395
|
-
console.warn("[crosswind] config load error:", e?.message || e);
|
|
4019
|
+
if (!crosswindUserConfigPromise) {
|
|
4020
|
+
crosswindUserConfigPromise = loadConfig({
|
|
4021
|
+
name: "crosswind",
|
|
4022
|
+
cwd: process6.cwd(),
|
|
4023
|
+
defaultConfig: {}
|
|
4024
|
+
});
|
|
5396
4025
|
}
|
|
4026
|
+
const userConfig = await crosswindUserConfigPromise;
|
|
5397
4027
|
if (userConfig.safelist) {
|
|
5398
4028
|
for (const cls of userConfig.safelist)
|
|
5399
4029
|
classes.add(cls);
|
|
5400
|
-
console.log("[crosswind] safelist:", userConfig.safelist);
|
|
5401
|
-
}
|
|
5402
|
-
if (userConfig.shortcuts) {
|
|
5403
|
-
console.log("[crosswind] shortcuts:", Object.keys(userConfig.shortcuts));
|
|
5404
4030
|
}
|
|
4031
|
+
const cacheKey = [...classes].sort().join(" ");
|
|
4032
|
+
const cached = crosswindCssCache.get(cacheKey);
|
|
4033
|
+
if (cached !== undefined)
|
|
4034
|
+
return cached;
|
|
5405
4035
|
const generatorConfig = { ...cw.config, preflight: true, minify: false };
|
|
5406
4036
|
if (userConfig.shortcuts) {
|
|
5407
4037
|
generatorConfig.shortcuts = { ...generatorConfig.shortcuts || {}, ...userConfig.shortcuts };
|
|
@@ -5449,14 +4079,18 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5449
4079
|
shortcutCSS += `@media (prefers-color-scheme: dark) { .dark .${name} { ${darkDecls.join(" ")} } }
|
|
5450
4080
|
`;
|
|
5451
4081
|
}
|
|
5452
|
-
|
|
4082
|
+
const finalCss = baseCss + shortcutCSS;
|
|
4083
|
+
crosswindCssCache.set(cacheKey, finalCss);
|
|
4084
|
+
return finalCss;
|
|
5453
4085
|
} catch (error) {
|
|
5454
4086
|
console.warn("Failed to generate Crosswind CSS:", error);
|
|
5455
4087
|
return "";
|
|
5456
4088
|
}
|
|
5457
4089
|
}
|
|
5458
4090
|
async function processTemplate(filePath) {
|
|
5459
|
-
const
|
|
4091
|
+
const cachedEntry = htmlCache.get(filePath);
|
|
4092
|
+
if (cachedEntry && await templateSignatureFresh(cachedEntry.signature))
|
|
4093
|
+
return cachedEntry.html;
|
|
5460
4094
|
const content = await Bun.file(filePath).text();
|
|
5461
4095
|
const serverScriptRegex = /<script\b([^>]*)\bserver\b[^>]*>([\s\S]*?)<\/script>/gi;
|
|
5462
4096
|
const serverScripts = [];
|
|
@@ -5467,16 +4101,16 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5467
4101
|
let templateContent = content.replace(/<script\b[^>]*\bserver\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
5468
4102
|
const context = {
|
|
5469
4103
|
__filename: filePath,
|
|
5470
|
-
__dirname:
|
|
4104
|
+
__dirname: nodePath.dirname(filePath)
|
|
5471
4105
|
};
|
|
5472
|
-
const { processDirectives, extractVariables, defaultConfig:
|
|
4106
|
+
const { processDirectives, extractVariables, defaultConfig: defaultConfig2, generateSpaShell, injectRouterScript, resetHead } = await stxModule;
|
|
5473
4107
|
resetHead();
|
|
5474
4108
|
for (const scriptBody of serverScripts) {
|
|
5475
4109
|
await extractVariables(scriptBody, context, filePath);
|
|
5476
4110
|
}
|
|
5477
4111
|
context.__stx_head_preset = true;
|
|
5478
4112
|
const config3 = {
|
|
5479
|
-
...
|
|
4113
|
+
...defaultConfig2,
|
|
5480
4114
|
...componentsDir && { componentsDir },
|
|
5481
4115
|
...layoutsDir && { layoutsDir },
|
|
5482
4116
|
...partialsDir && { partialsDir },
|
|
@@ -5484,7 +4118,12 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5484
4118
|
ssr: stxConfig.ssr ?? defaultStxConfig.ssr ?? true,
|
|
5485
4119
|
app: stxConfig.app || {},
|
|
5486
4120
|
..."strict" in stxConfig && { strict: stxConfig.strict },
|
|
5487
|
-
..."router" in stxConfig && { router: stxConfig.router }
|
|
4121
|
+
..."router" in stxConfig && { router: stxConfig.router },
|
|
4122
|
+
..."skipDefaultSeoTags" in stxConfig && { skipDefaultSeoTags: stxConfig.skipDefaultSeoTags },
|
|
4123
|
+
..."defaultTitle" in stxConfig && { defaultTitle: stxConfig.defaultTitle },
|
|
4124
|
+
..."defaultDescription" in stxConfig && { defaultDescription: stxConfig.defaultDescription },
|
|
4125
|
+
..."defaultImage" in stxConfig && { defaultImage: stxConfig.defaultImage },
|
|
4126
|
+
..."seo" in stxConfig && { seo: stxConfig.seo }
|
|
5488
4127
|
};
|
|
5489
4128
|
if (config3.ssr === false || stxConfig.ssr === false) {
|
|
5490
4129
|
return generateSpaShell({
|
|
@@ -5510,11 +4149,14 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5510
4149
|
} else {
|
|
5511
4150
|
output = output.replace(/<template[^>]*>/gi, "").replace(/<\/template>/gi, "");
|
|
5512
4151
|
}
|
|
4152
|
+
if (!context.__stx_skip_cache) {
|
|
4153
|
+
const signature = await buildTemplateSignature(filePath, dependencies);
|
|
4154
|
+
htmlCache.set(filePath, { html: output, signature });
|
|
4155
|
+
}
|
|
5513
4156
|
return output;
|
|
5514
4157
|
}
|
|
5515
4158
|
async function getRoute(requestPath) {
|
|
5516
4159
|
const files = await discoverFiles();
|
|
5517
|
-
const nodePath = await import("path");
|
|
5518
4160
|
let normalizedPath = requestPath.startsWith("/") ? requestPath.slice(1) : requestPath;
|
|
5519
4161
|
const possibleFiles = [];
|
|
5520
4162
|
for (const ext of [".stx", ".md", ".html", ""]) {
|
|
@@ -5539,7 +4181,15 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5539
4181
|
for (const possible of possibleFiles) {
|
|
5540
4182
|
for (const filePath of files) {
|
|
5541
4183
|
const normalizedFilePath = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
|
|
5542
|
-
|
|
4184
|
+
let relativeFilePath = normalizedFilePath;
|
|
4185
|
+
for (const pattern of patterns) {
|
|
4186
|
+
const normalizedPattern = pattern.replace(/\\/g, "/").replace(/\/$/, "");
|
|
4187
|
+
if (normalizedFilePath.startsWith(`${normalizedPattern}/`)) {
|
|
4188
|
+
relativeFilePath = normalizedFilePath.slice(normalizedPattern.length + 1);
|
|
4189
|
+
break;
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
if (normalizedFilePath === possible || relativeFilePath === possible) {
|
|
5543
4193
|
const output = await processTemplate(filePath);
|
|
5544
4194
|
return output;
|
|
5545
4195
|
}
|
|
@@ -5607,7 +4257,6 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5607
4257
|
return null;
|
|
5608
4258
|
}
|
|
5609
4259
|
async function processTemplateDynamic(filePath, paramNames, paramValues, routePath) {
|
|
5610
|
-
const path = await import("path");
|
|
5611
4260
|
const content = await Bun.file(filePath).text();
|
|
5612
4261
|
const serverScriptRegex = /<script\b([^>]*)\bserver\b[^>]*>([\s\S]*?)<\/script>/gi;
|
|
5613
4262
|
const dynServerScripts = [];
|
|
@@ -5618,20 +4267,20 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5618
4267
|
const templateContent = content.replace(/<script\b[^>]*\bserver\b[^>]*>[\s\S]*?<\/script>/gi, "");
|
|
5619
4268
|
const context = {
|
|
5620
4269
|
__filename: filePath,
|
|
5621
|
-
__dirname:
|
|
4270
|
+
__dirname: nodePath.dirname(filePath),
|
|
5622
4271
|
__route: routePath
|
|
5623
4272
|
};
|
|
5624
4273
|
for (let i = 0;i < paramNames.length; i++) {
|
|
5625
4274
|
context[paramNames[i]] = paramValues[i];
|
|
5626
4275
|
}
|
|
5627
|
-
const { processDirectives, extractVariables, defaultConfig:
|
|
4276
|
+
const { processDirectives, extractVariables, defaultConfig: defaultConfig2, injectRouterScript: injectRouter, resetHead: resetHeadDyn } = await stxModule;
|
|
5628
4277
|
resetHeadDyn();
|
|
5629
4278
|
for (const scriptBody of dynServerScripts) {
|
|
5630
4279
|
await extractVariables(scriptBody, context, filePath);
|
|
5631
4280
|
}
|
|
5632
4281
|
context.__stx_head_preset = true;
|
|
5633
4282
|
const config3 = {
|
|
5634
|
-
...
|
|
4283
|
+
...defaultConfig2,
|
|
5635
4284
|
...componentsDir && { componentsDir },
|
|
5636
4285
|
...layoutsDir && { layoutsDir },
|
|
5637
4286
|
...partialsDir && { partialsDir },
|
|
@@ -5639,7 +4288,12 @@ After installing: bun add bun-plugin-stx`);
|
|
|
5639
4288
|
ssr: stxConfig.ssr ?? defaultStxConfig.ssr ?? true,
|
|
5640
4289
|
app: stxConfig.app || {},
|
|
5641
4290
|
..."strict" in stxConfig && { strict: stxConfig.strict },
|
|
5642
|
-
..."router" in stxConfig && { router: stxConfig.router }
|
|
4291
|
+
..."router" in stxConfig && { router: stxConfig.router },
|
|
4292
|
+
..."skipDefaultSeoTags" in stxConfig && { skipDefaultSeoTags: stxConfig.skipDefaultSeoTags },
|
|
4293
|
+
..."defaultTitle" in stxConfig && { defaultTitle: stxConfig.defaultTitle },
|
|
4294
|
+
..."defaultDescription" in stxConfig && { defaultDescription: stxConfig.defaultDescription },
|
|
4295
|
+
..."defaultImage" in stxConfig && { defaultImage: stxConfig.defaultImage },
|
|
4296
|
+
..."seo" in stxConfig && { seo: stxConfig.seo }
|
|
5643
4297
|
};
|
|
5644
4298
|
let output = templateContent;
|
|
5645
4299
|
const dependencies = new Set;
|
|
@@ -5733,10 +4387,10 @@ ${output}`;
|
|
|
5733
4387
|
const componentName = decodeURIComponent(path.slice("/_stx/component/".length));
|
|
5734
4388
|
if (componentName) {
|
|
5735
4389
|
try {
|
|
5736
|
-
const { processDirectives, defaultConfig:
|
|
4390
|
+
const { processDirectives, defaultConfig: defaultConfig2 } = await stxModule;
|
|
5737
4391
|
const componentTemplate = `<${componentName} />`;
|
|
5738
4392
|
const componentOpts = {
|
|
5739
|
-
...
|
|
4393
|
+
...defaultConfig2,
|
|
5740
4394
|
...componentsDir && { componentsDir },
|
|
5741
4395
|
...layoutsDir && { layoutsDir },
|
|
5742
4396
|
...partialsDir && { partialsDir },
|
|
@@ -5770,9 +4424,8 @@ ${output}`;
|
|
|
5770
4424
|
});
|
|
5771
4425
|
}
|
|
5772
4426
|
const body = await req.json();
|
|
5773
|
-
const nodePath = await import("path");
|
|
5774
4427
|
const { Database } = await import("bun:sqlite");
|
|
5775
|
-
const dbPath = nodePath.resolve(
|
|
4428
|
+
const dbPath = nodePath.resolve(process6.cwd(), "database/stacks.sqlite");
|
|
5776
4429
|
const db = new Database(dbPath);
|
|
5777
4430
|
try {
|
|
5778
4431
|
const tableInfo = db.query(`PRAGMA table_info("${tableName}")`).all();
|
|
@@ -6002,8 +4655,7 @@ ${pageSetupScripts.join(`
|
|
|
6002
4655
|
}
|
|
6003
4656
|
}
|
|
6004
4657
|
if ((req.method === "GET" || req.method === "HEAD") && path !== "/") {
|
|
6005
|
-
const
|
|
6006
|
-
const publicRoot = nodePathMod.resolve(process13.cwd(), publicDir);
|
|
4658
|
+
const publicRoot = nodePath.resolve(process6.cwd(), publicDir);
|
|
6007
4659
|
let safePathname;
|
|
6008
4660
|
try {
|
|
6009
4661
|
safePathname = decodeURIComponent(path);
|
|
@@ -6011,14 +4663,14 @@ ${pageSetupScripts.join(`
|
|
|
6011
4663
|
safePathname = path;
|
|
6012
4664
|
}
|
|
6013
4665
|
if (!safePathname.includes("\x00")) {
|
|
6014
|
-
const resolvedPath =
|
|
6015
|
-
const isInsidePublicRoot = resolvedPath === publicRoot || resolvedPath.startsWith(`${publicRoot}${
|
|
4666
|
+
const resolvedPath = nodePath.resolve(publicRoot, `.${safePathname}`);
|
|
4667
|
+
const isInsidePublicRoot = resolvedPath === publicRoot || resolvedPath.startsWith(`${publicRoot}${nodePath.sep}`);
|
|
6016
4668
|
if (isInsidePublicRoot) {
|
|
6017
4669
|
try {
|
|
6018
4670
|
const file = Bun.file(resolvedPath);
|
|
6019
4671
|
if (await file.exists()) {
|
|
6020
|
-
const
|
|
6021
|
-
if (
|
|
4672
|
+
const stat2 = await file.stat().catch(() => null);
|
|
4673
|
+
if (stat2 && !stat2.isDirectory()) {
|
|
6022
4674
|
const ext = resolvedPath.split(".").pop()?.toLowerCase();
|
|
6023
4675
|
return new Response(file, {
|
|
6024
4676
|
headers: {
|
|
@@ -6102,17 +4754,17 @@ ${pageSetupScripts.join(`
|
|
|
6102
4754
|
console.log(` \x1B[2mPress\x1B[0m o + Enter \x1B[2mto open in browser\x1B[0m`);
|
|
6103
4755
|
console.log(` \x1B[2mPress\x1B[0m q + Enter \x1B[2mto quit\x1B[0m`);
|
|
6104
4756
|
console.log();
|
|
6105
|
-
if (
|
|
6106
|
-
|
|
4757
|
+
if (process6.stdin.isTTY) {
|
|
4758
|
+
process6.stdin.setRawMode(false);
|
|
6107
4759
|
const rl = await import("readline");
|
|
6108
|
-
const reader = rl.createInterface({ input:
|
|
4760
|
+
const reader = rl.createInterface({ input: process6.stdin });
|
|
6109
4761
|
reader.on("line", (line) => {
|
|
6110
4762
|
const cmd = line.trim().toLowerCase();
|
|
6111
4763
|
if (cmd === "o") {
|
|
6112
|
-
const openCmd =
|
|
4764
|
+
const openCmd = process6.platform === "darwin" ? "open" : process6.platform === "win32" ? "start" : "xdg-open";
|
|
6113
4765
|
Bun.spawn([openCmd, `http://localhost:${port}/`]);
|
|
6114
4766
|
} else if (cmd === "q") {
|
|
6115
|
-
|
|
4767
|
+
process6.exit(0);
|
|
6116
4768
|
}
|
|
6117
4769
|
});
|
|
6118
4770
|
}
|
|
@@ -6120,7 +4772,7 @@ ${pageSetupScripts.join(`
|
|
|
6120
4772
|
await Bun.sleep(Number.POSITIVE_INFINITY);
|
|
6121
4773
|
}
|
|
6122
4774
|
async function main() {
|
|
6123
|
-
const args =
|
|
4775
|
+
const args = process6.argv.slice(2);
|
|
6124
4776
|
if (args[0] === "serve") {
|
|
6125
4777
|
args.shift();
|
|
6126
4778
|
}
|