bun-git-hooks 0.2.14 → 0.2.16

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/index.js CHANGED
@@ -18,27 +18,12 @@ var __toESM = (mod, isNodeMode, target) => {
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
20
  // src/config.ts
21
- import process7 from "node:process";
21
+ import process2 from "node:process";
22
22
 
23
23
  // node_modules/bunfig/dist/index.js
24
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
25
- import { dirname as dirname2, resolve as resolve3 } from "path";
26
- import process6 from "process";
27
- import { join, relative, resolve as resolve2 } from "path";
28
- import process2 from "process";
29
24
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
30
25
  import { dirname, resolve } from "path";
31
26
  import process from "process";
32
- import { Buffer } from "buffer";
33
- import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
34
- import { closeSync, createReadStream, createWriteStream, existsSync as existsSync2, fsyncSync, openSync, writeFileSync as writeFileSync2 } from "fs";
35
- import { access, constants, mkdir, readdir, rename, stat, unlink, writeFile } from "fs/promises";
36
- import { join as join2 } from "path";
37
- import process5 from "process";
38
- import { pipeline } from "stream/promises";
39
- import { createGzip } from "zlib";
40
- import process4 from "process";
41
- import process3 from "process";
42
27
  function deepMerge(target, source) {
43
28
  if (Array.isArray(source) && Array.isArray(target) && source.length === 2 && target.length === 2 && isObject(source[0]) && "id" in source[0] && source[0].id === 3 && isObject(source[1]) && "id" in source[1] && source[1].id === 4) {
44
29
  return source;
@@ -198,2978 +183,77 @@ async function loadConfig({
198
183
  for (const ext of extensions) {
199
184
  const fullPath = resolve(baseDir, `${configPath}${ext}`);
200
185
  const config2 = await tryLoadConfig(fullPath, defaultConfig);
201
- if (config2 !== null)
186
+ if (config2 !== null) {
202
187
  return config2;
188
+ }
203
189
  }
204
190
  }
205
- console.error("Failed to load client config from any expected location");
191
+ try {
192
+ const pkgPath = resolve(baseDir, "package.json");
193
+ if (existsSync(pkgPath)) {
194
+ const pkg = await import(pkgPath);
195
+ const pkgConfig = pkg[name];
196
+ if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
197
+ try {
198
+ return deepMerge(defaultConfig, pkgConfig);
199
+ } catch {}
200
+ }
201
+ }
202
+ } catch {}
206
203
  return defaultConfig;
207
204
  }
208
205
  var defaultConfigDir = resolve(process.cwd(), "config");
209
206
  var defaultGeneratedDir = resolve(process.cwd(), "src/generated");
210
- function getProjectRoot(filePath, options = {}) {
211
- let path = process2.cwd();
212
- while (path.includes("storage"))
213
- path = resolve2(path, "..");
214
- const finalPath = resolve2(path, filePath || "");
215
- if (options?.relative)
216
- return relative(process2.cwd(), finalPath);
217
- return finalPath;
218
- }
219
- var defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
220
- var defaultConfig = {
221
- level: "info",
222
- defaultName: "clarity",
223
- timestamp: true,
224
- colors: true,
225
- format: "text",
226
- maxLogSize: 10485760,
227
- logDatePattern: "YYYY-MM-DD",
228
- logDirectory: defaultLogDirectory,
229
- rotation: {
230
- frequency: "daily",
231
- maxSize: 10485760,
232
- maxFiles: 5,
233
- compress: false,
234
- rotateHour: 0,
235
- rotateMinute: 0,
236
- rotateDayOfWeek: 0,
237
- rotateDayOfMonth: 1,
238
- encrypt: false
239
- },
240
- verbose: false
241
- };
242
- async function loadConfig2() {
243
- try {
244
- const loadedConfig = await loadConfig({
245
- name: "clarity",
246
- defaultConfig,
247
- cwd: process2.cwd(),
248
- endpoint: "",
249
- headers: {}
250
- });
251
- return { ...defaultConfig, ...loadedConfig };
252
- } catch {
253
- return defaultConfig;
254
- }
255
- }
256
- var config = await loadConfig2();
257
- function isBrowserProcess() {
258
- if (process3.env.NODE_ENV === "test" || process3.env.BUN_ENV === "test") {
259
- return false;
260
- }
261
- return typeof window !== "undefined";
262
- }
263
- async function isServerProcess() {
264
- if (process3.env.NODE_ENV === "test" || process3.env.BUN_ENV === "test") {
265
- return true;
266
- }
267
- if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
268
- return true;
269
- }
270
- if (typeof process3 !== "undefined") {
271
- const type = process3.type;
272
- if (type === "renderer" || type === "worker") {
273
- return false;
274
- }
275
- return !!(process3.versions && (process3.versions.node || process3.versions.bun));
276
- }
277
- return false;
278
- }
279
-
280
- class JsonFormatter {
281
- async format(entry) {
282
- const isServer = await isServerProcess();
283
- const metadata = await this.getMetadata(isServer);
284
- return JSON.stringify({
285
- timestamp: entry.timestamp.toISOString(),
286
- level: entry.level,
287
- name: entry.name,
288
- message: entry.message,
289
- metadata
290
- });
291
- }
292
- async getMetadata(isServer) {
293
- if (isServer) {
294
- const { hostname } = await import("os");
295
- return {
296
- pid: process4.pid,
297
- hostname: hostname(),
298
- environment: process4.env.NODE_ENV || "development",
299
- platform: process4.platform,
300
- version: process4.version
301
- };
302
- }
303
- return {
304
- userAgent: navigator.userAgent,
305
- hostname: window.location.hostname || "browser",
306
- environment: process4.env.NODE_ENV || process4.env.BUN_ENV || "development",
307
- viewport: {
308
- width: window.innerWidth,
309
- height: window.innerHeight
310
- },
311
- language: navigator.language
312
- };
313
- }
314
- }
315
- var terminalStyles = {
316
- red: (text) => `\x1B[31m${text}\x1B[0m`,
317
- green: (text) => `\x1B[32m${text}\x1B[0m`,
318
- yellow: (text) => `\x1B[33m${text}\x1B[0m`,
319
- blue: (text) => `\x1B[34m${text}\x1B[0m`,
320
- magenta: (text) => `\x1B[35m${text}\x1B[0m`,
321
- cyan: (text) => `\x1B[36m${text}\x1B[0m`,
322
- white: (text) => `\x1B[37m${text}\x1B[0m`,
323
- gray: (text) => `\x1B[90m${text}\x1B[0m`,
324
- bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
325
- bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
326
- bold: (text) => `\x1B[1m${text}\x1B[0m`,
327
- dim: (text) => `\x1B[2m${text}\x1B[0m`,
328
- italic: (text) => `\x1B[3m${text}\x1B[0m`,
329
- underline: (text) => `\x1B[4m${text}\x1B[0m`,
330
- reset: "\x1B[0m"
331
- };
332
- var styles = terminalStyles;
333
- var red = terminalStyles.red;
334
- var green = terminalStyles.green;
335
- var yellow = terminalStyles.yellow;
336
- var blue = terminalStyles.blue;
337
- var magenta = terminalStyles.magenta;
338
- var cyan = terminalStyles.cyan;
339
- var white = terminalStyles.white;
340
- var gray = terminalStyles.gray;
341
- var bgRed = terminalStyles.bgRed;
342
- var bgYellow = terminalStyles.bgYellow;
343
- var bold = terminalStyles.bold;
344
- var dim = terminalStyles.dim;
345
- var italic = terminalStyles.italic;
346
- var underline = terminalStyles.underline;
347
- var reset = terminalStyles.reset;
348
- var defaultFingersCrossedConfig = {
349
- activationLevel: "error",
350
- bufferSize: 50,
351
- flushOnDeactivation: true,
352
- stopBuffering: false
353
- };
354
- var levelIcons = {
355
- debug: "\uD83D\uDD0D",
356
- info: blue("ℹ"),
357
- success: green("✓"),
358
- warning: bgYellow(white(bold(" WARN "))),
359
- error: bgRed(white(bold(" ERROR ")))
360
- };
361
207
 
362
- class Logger {
363
- name;
364
- fileLocks = new Map;
365
- currentKeyId = null;
366
- keys = new Map;
367
- config;
368
- options;
369
- formatter;
370
- timers = new Set;
371
- subLoggers = new Set;
372
- fingersCrossedBuffer = [];
373
- fingersCrossedConfig;
374
- fingersCrossedActive = false;
375
- currentLogFile;
376
- rotationTimeout;
377
- keyRotationTimeout;
378
- encryptionKeys;
379
- logBuffer = [];
380
- isActivated = false;
381
- pendingOperations = [];
382
- enabled;
383
- fancy;
384
- tagFormat;
385
- timestampPosition;
386
- environment;
387
- ANSI_PATTERN = /\u001B\[.*?m/g;
388
- activeProgressBar = null;
389
- constructor(name, options = {}) {
390
- this.name = name;
391
- this.config = { ...config };
392
- this.options = this.normalizeOptions(options);
393
- this.formatter = this.options.formatter || new JsonFormatter;
394
- this.enabled = options.enabled ?? true;
395
- this.fancy = options.fancy ?? true;
396
- this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
397
- this.timestampPosition = options.timestampPosition ?? "right";
398
- this.environment = options.environment ?? process5.env.APP_ENV ?? "local";
399
- this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
400
- const configOptions = { ...options };
401
- const hasTimestamp = options.timestamp !== undefined;
402
- if (hasTimestamp) {
403
- delete configOptions.timestamp;
404
- }
405
- this.config = {
406
- ...this.config,
407
- ...configOptions,
408
- timestamp: hasTimestamp || this.config.timestamp
409
- };
410
- if (!this.config.logDirectory) {
411
- this.config.logDirectory = config.logDirectory;
412
- }
413
- if (!isBrowserProcess()) {
414
- mkdir(this.config.logDirectory, { recursive: true, mode: 493 }).catch((err) => console.error("Failed to create log directory:", err));
415
- }
416
- this.currentLogFile = this.generateLogFilename();
417
- this.encryptionKeys = new Map;
418
- if (this.validateEncryptionConfig()) {
419
- this.setupRotation();
420
- const initialKeyId = this.generateKeyId();
421
- const initialKey = this.generateKey();
422
- this.currentKeyId = initialKeyId;
423
- this.keys.set(initialKeyId, initialKey);
424
- this.encryptionKeys.set(initialKeyId, {
425
- key: initialKey,
426
- createdAt: new Date
427
- });
428
- this.setupKeyRotation();
429
- }
430
- }
431
- initializeFingersCrossedConfig(options) {
432
- if (!options.fingersCrossedEnabled && options.fingersCrossed) {
433
- return {
434
- ...defaultFingersCrossedConfig,
435
- ...options.fingersCrossed
436
- };
437
- }
438
- if (!options.fingersCrossedEnabled) {
439
- return null;
440
- }
441
- if (!options.fingersCrossed) {
442
- return { ...defaultFingersCrossedConfig };
208
+ // git-hooks.config.ts
209
+ var config = {
210
+ "pre-commit": {
211
+ "staged-lint": {
212
+ "**/*.{js,ts}": [
213
+ "bunx --bun eslint --max-warnings=0",
214
+ "bunx --bun tsc --noEmit"
215
+ ]
443
216
  }
444
- return {
445
- ...defaultFingersCrossedConfig,
446
- ...options.fingersCrossed
447
- };
448
- }
449
- normalizeOptions(options) {
450
- const defaultOptions = {
451
- format: "json",
452
- level: "info",
453
- logDirectory: config.logDirectory,
454
- rotation: undefined,
455
- timestamp: undefined,
456
- fingersCrossed: {},
457
- enabled: true,
458
- showTags: false,
459
- formatter: undefined
460
- };
461
- const mergedOptions = {
462
- ...defaultOptions,
463
- ...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
464
- };
465
- if (!mergedOptions.level || !["debug", "info", "success", "warning", "error"].includes(mergedOptions.level)) {
466
- mergedOptions.level = defaultOptions.level;
467
- }
468
- return mergedOptions;
469
- }
470
- async writeToFile(data) {
471
- const cancelled = false;
472
- const operationPromise = (async () => {
473
- let fd;
474
- let retries = 0;
475
- const maxRetries = 3;
476
- const backoffDelay = 1000;
477
- while (retries < maxRetries) {
478
- try {
479
- try {
480
- try {
481
- await access(this.config.logDirectory, constants.F_OK | constants.W_OK);
482
- } catch (err) {
483
- if (err instanceof Error && "code" in err) {
484
- if (err.code === "ENOENT") {
485
- await mkdir(this.config.logDirectory, { recursive: true, mode: 493 });
486
- } else if (err.code === "EACCES") {
487
- throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
488
- } else {
489
- throw err;
490
- }
491
- } else {
492
- throw err;
493
- }
494
- }
495
- } catch (err) {
496
- console.error("Debug: [writeToFile] Failed to create log directory:", err);
497
- throw err;
498
- }
499
- if (cancelled)
500
- throw new Error("Operation cancelled: Logger was destroyed");
501
- const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
502
- try {
503
- if (!existsSync2(this.currentLogFile)) {
504
- await writeFile(this.currentLogFile, "", { mode: 420 });
505
- }
506
- fd = openSync(this.currentLogFile, "a", 420);
507
- writeFileSync2(fd, dataToWrite, { flag: "a" });
508
- fsyncSync(fd);
509
- if (fd !== undefined) {
510
- closeSync(fd);
511
- fd = undefined;
512
- }
513
- const stats = await stat(this.currentLogFile);
514
- if (stats.size === 0) {
515
- await writeFile(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
516
- const retryStats = await stat(this.currentLogFile);
517
- if (retryStats.size === 0) {
518
- throw new Error("File exists but is empty after retry write");
519
- }
520
- }
521
- return;
522
- } catch (err) {
523
- const error = err;
524
- if (error.code && ["ENETDOWN", "ENETUNREACH", "ENOTFOUND", "ETIMEDOUT"].includes(error.code)) {
525
- if (retries < maxRetries - 1) {
526
- const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
527
- console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
528
- const delay = backoffDelay * 2 ** retries;
529
- await new Promise((resolve32) => setTimeout(resolve32, delay));
530
- retries++;
531
- continue;
532
- }
533
- }
534
- if (error?.code && ["ENOSPC", "EDQUOT"].includes(error.code)) {
535
- throw new Error(`Disk quota exceeded or no space left on device: ${error.message}`);
536
- }
537
- console.error("Debug: [writeToFile] Error writing to file:", error);
538
- throw error;
539
- } finally {
540
- if (fd !== undefined) {
541
- try {
542
- closeSync(fd);
543
- } catch (err) {
544
- console.error("Debug: [writeToFile] Error closing file descriptor:", err);
545
- }
546
- }
547
- }
548
- } catch (err) {
549
- if (retries === maxRetries - 1) {
550
- const error = err;
551
- const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
552
- console.error("Debug: [writeToFile] Max retries reached. Final error:", errorMessage);
553
- throw err;
554
- }
555
- retries++;
556
- const delay = backoffDelay * 2 ** (retries - 1);
557
- await new Promise((resolve32) => setTimeout(resolve32, delay));
558
- }
559
- }
560
- })();
561
- this.pendingOperations.push(operationPromise);
562
- const index = this.pendingOperations.length - 1;
563
- try {
564
- await operationPromise;
565
- } catch (err) {
566
- console.error("Debug: [writeToFile] Error in operation:", err);
567
- throw err;
568
- } finally {
569
- this.pendingOperations.splice(index, 1);
570
- }
571
- }
572
- generateLogFilename() {
573
- 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")) {
574
- return join2(this.config.logDirectory, `${this.name}.log`);
575
- }
576
- 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") {
577
- return join2(this.config.logDirectory, `${this.name}.log`);
578
- }
579
- const date = new Date().toISOString().split("T")[0];
580
- return join2(this.config.logDirectory, `${this.name}-${date}.log`);
581
- }
582
- setupRotation() {
583
- if (isBrowserProcess())
584
- return;
585
- if (typeof this.config.rotation === "boolean")
586
- return;
587
- const config2 = this.config.rotation;
588
- let interval;
589
- switch (config2.frequency) {
590
- case "daily":
591
- interval = 86400000;
592
- break;
593
- case "weekly":
594
- interval = 604800000;
595
- break;
596
- case "monthly":
597
- interval = 2592000000;
598
- break;
599
- default:
600
- return;
601
- }
602
- this.rotationTimeout = setInterval(() => {
603
- this.rotateLog();
604
- }, interval);
605
- }
606
- setupKeyRotation() {
607
- if (!this.validateEncryptionConfig()) {
608
- console.error("Invalid encryption configuration detected during key rotation setup");
609
- return;
610
- }
611
- const rotation = this.config.rotation;
612
- const keyRotation = rotation.keyRotation;
613
- if (!keyRotation?.enabled) {
614
- return;
615
- }
616
- const rotationInterval = typeof keyRotation.interval === "number" ? keyRotation.interval : 60;
617
- const interval = Math.max(rotationInterval, 60) * 1000;
618
- this.keyRotationTimeout = setInterval(() => {
619
- this.rotateKeys().catch((error) => {
620
- console.error("Error rotating keys:", error);
621
- });
622
- }, interval);
623
- }
624
- async rotateKeys() {
625
- if (!this.validateEncryptionConfig()) {
626
- console.error("Invalid encryption configuration detected during key rotation");
627
- return;
628
- }
629
- const rotation = this.config.rotation;
630
- const keyRotation = rotation.keyRotation;
631
- const newKeyId = this.generateKeyId();
632
- const newKey = this.generateKey();
633
- this.currentKeyId = newKeyId;
634
- this.keys.set(newKeyId, newKey);
635
- this.encryptionKeys.set(newKeyId, {
636
- key: newKey,
637
- createdAt: new Date
638
- });
639
- const sortedKeys = Array.from(this.encryptionKeys.entries()).sort(([, a], [, b]) => b.createdAt.getTime() - a.createdAt.getTime());
640
- const maxKeyCount = typeof keyRotation.maxKeys === "number" ? keyRotation.maxKeys : 1;
641
- const maxKeys = Math.max(1, maxKeyCount);
642
- if (sortedKeys.length > maxKeys) {
643
- for (const [keyId] of sortedKeys.slice(maxKeys)) {
644
- this.encryptionKeys.delete(keyId);
645
- this.keys.delete(keyId);
646
- }
647
- }
648
- }
649
- generateKeyId() {
650
- return randomBytes(16).toString("hex");
651
- }
652
- generateKey() {
653
- return randomBytes(32);
654
- }
655
- getCurrentKey() {
656
- if (!this.currentKeyId) {
657
- throw new Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");
658
- }
659
- const key = this.keys.get(this.currentKeyId);
660
- if (!key) {
661
- throw new Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);
662
- }
663
- return { key, id: this.currentKeyId };
664
- }
665
- encrypt(data) {
666
- const { key } = this.getCurrentKey();
667
- const iv = randomBytes(16);
668
- const cipher = createCipheriv("aes-256-gcm", key, iv);
669
- const encrypted = Buffer.concat([
670
- cipher.update(data, "utf8"),
671
- cipher.final()
672
- ]);
673
- const authTag = cipher.getAuthTag();
674
- return {
675
- encrypted: Buffer.concat([iv, encrypted, authTag]),
676
- iv
677
- };
678
- }
679
- async compressData(data) {
680
- return new Promise((resolve32, reject) => {
681
- const gzip = createGzip();
682
- const chunks = [];
683
- gzip.on("data", (chunk2) => chunks.push(chunk2));
684
- gzip.on("end", () => resolve32(Buffer.from(Buffer.concat(chunks))));
685
- gzip.on("error", reject);
686
- gzip.write(data);
687
- gzip.end();
688
- });
689
- }
690
- getEncryptionOptions() {
691
- if (!this.config.rotation || typeof this.config.rotation === "boolean" || !this.config.rotation.encrypt) {
692
- return {};
693
- }
694
- const defaultOptions = {
695
- algorithm: "aes-256-cbc",
696
- compress: false
697
- };
698
- if (typeof this.config.rotation.encrypt === "object") {
699
- const encryptConfig = this.config.rotation.encrypt;
700
- return {
701
- ...defaultOptions,
702
- ...encryptConfig
703
- };
704
- }
705
- return defaultOptions;
706
- }
707
- async rotateLog() {
708
- if (isBrowserProcess())
709
- return;
710
- const stats = await stat(this.currentLogFile).catch(() => null);
711
- if (!stats)
712
- return;
713
- const config2 = this.config.rotation;
714
- if (typeof config2 === "boolean")
715
- return;
716
- if (config2.maxSize && stats.size >= config2.maxSize) {
717
- const oldFile = this.currentLogFile;
718
- const newFile = this.generateLogFilename();
719
- if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
720
- const files = await readdir(this.config.logDirectory);
721
- const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
722
- const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
723
- const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
724
- return numB - numA;
725
- });
726
- const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
727
- const rotatedFile = `${oldFile}.${nextNum}`;
728
- if (await stat(oldFile).catch(() => null)) {
729
- try {
730
- await rename(oldFile, rotatedFile);
731
- if (config2.compress) {
732
- try {
733
- const compressedPath = `${rotatedFile}.gz`;
734
- await this.compressLogFile(rotatedFile, compressedPath);
735
- await unlink(rotatedFile);
736
- } catch (err) {
737
- console.error("Error compressing rotated file:", err);
738
- }
739
- }
740
- if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
741
- try {
742
- const backupPath = `${oldFile}.1`;
743
- await writeFile(backupPath, "");
744
- } catch (err) {
745
- console.error("Error creating backup file:", err);
746
- }
747
- }
748
- } catch (err) {
749
- console.error(`Error during rotation: ${err instanceof Error ? err.message : String(err)}`);
750
- }
751
- }
752
- } else {
753
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
754
- const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
755
- if (await stat(oldFile).catch(() => null)) {
756
- await rename(oldFile, rotatedFile);
757
- }
758
- }
759
- this.currentLogFile = newFile;
760
- if (config2.maxFiles) {
761
- const files = await readdir(this.config.logDirectory);
762
- const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
763
- for (const file of logFiles.slice(config2.maxFiles)) {
764
- await unlink(join2(this.config.logDirectory, file));
765
- }
766
- }
767
- }
768
- }
769
- async compressLogFile(inputPath, outputPath) {
770
- const readStream = createReadStream(inputPath);
771
- const writeStream = createWriteStream(outputPath);
772
- const gzip = createGzip();
773
- await pipeline(readStream, gzip, writeStream);
774
- }
775
- async handleFingersCrossedBuffer(level, formattedEntry) {
776
- if (!this.fingersCrossedConfig)
777
- return;
778
- if (this.shouldActivateFingersCrossed(level) && !this.isActivated) {
779
- this.isActivated = true;
780
- for (const entry of this.logBuffer) {
781
- const formattedBufferedEntry = await this.formatter.format(entry);
782
- await this.writeToFile(formattedBufferedEntry);
783
- console.log(formattedBufferedEntry);
784
- }
785
- if (this.fingersCrossedConfig.stopBuffering)
786
- this.logBuffer = [];
787
- }
788
- if (this.isActivated) {
789
- await this.writeToFile(formattedEntry);
790
- console.log(formattedEntry);
791
- } else {
792
- if (this.logBuffer.length >= this.fingersCrossedConfig.bufferSize)
793
- this.logBuffer.shift();
794
- const entry = {
795
- timestamp: new Date,
796
- level,
797
- message: formattedEntry,
798
- name: this.name
799
- };
800
- this.logBuffer.push(entry);
801
- }
802
- }
803
- shouldActivateFingersCrossed(level) {
804
- if (!this.fingersCrossedConfig)
805
- return false;
806
- return this.getLevelValue(level) >= this.getLevelValue(this.fingersCrossedConfig.activationLevel);
807
- }
808
- getLevelValue(level) {
809
- const levels = {
810
- debug: 0,
811
- info: 1,
812
- success: 2,
813
- warning: 3,
814
- error: 4
815
- };
816
- return levels[level];
817
- }
818
- shouldLog(level) {
819
- if (!this.enabled)
820
- return false;
821
- const levels = {
822
- debug: 0,
823
- info: 1,
824
- success: 2,
825
- warning: 3,
826
- error: 4
827
- };
828
- return levels[level] >= levels[this.config.level];
829
- }
830
- async flushPendingWrites() {
831
- await Promise.all(this.pendingOperations.map((op) => {
832
- if (op instanceof Promise) {
833
- return op.catch((err) => {
834
- console.error("Error in pending write operation:", err);
835
- });
836
- }
837
- return Promise.resolve();
838
- }));
839
- if (existsSync2(this.currentLogFile)) {
840
- try {
841
- const fd = openSync(this.currentLogFile, "r+");
842
- fsyncSync(fd);
843
- closeSync(fd);
844
- } catch (error) {
845
- console.error(`Error flushing file: ${error}`);
846
- }
847
- }
848
- }
849
- async destroy() {
850
- if (this.rotationTimeout)
851
- clearInterval(this.rotationTimeout);
852
- if (this.keyRotationTimeout)
853
- clearInterval(this.keyRotationTimeout);
854
- this.timers.clear();
855
- for (const op of this.pendingOperations) {
856
- if (typeof op.cancel === "function") {
857
- op.cancel();
858
- }
859
- }
860
- return (async () => {
861
- if (this.pendingOperations.length > 0) {
862
- try {
863
- await Promise.allSettled(this.pendingOperations);
864
- } catch (err) {
865
- console.error("Error waiting for pending operations:", err);
866
- }
867
- }
868
- if (!isBrowserProcess() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
869
- try {
870
- const files = await readdir(this.config.logDirectory);
871
- const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
872
- for (const tempFile of tempFiles) {
873
- try {
874
- await unlink(join2(this.config.logDirectory, tempFile));
875
- } catch (err) {
876
- console.error(`Failed to delete temp file ${tempFile}:`, err);
877
- }
878
- }
879
- } catch (err) {
880
- console.error("Error cleaning up temporary files:", err);
881
- }
882
- }
883
- })();
884
- }
885
- getCurrentLogFilePath() {
886
- return this.currentLogFile;
887
- }
888
- formatTag(name) {
889
- if (!name)
890
- return "";
891
- return `${this.tagFormat.prefix}${name}${this.tagFormat.suffix}`;
892
- }
893
- formatFileTimestamp(date) {
894
- return `[${date.toISOString()}]`;
895
- }
896
- formatConsoleTimestamp(date) {
897
- return this.fancy ? styles.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
898
- }
899
- formatConsoleMessage(parts) {
900
- const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
901
- const stripAnsi = (str) => str.replace(this.ANSI_PATTERN, "");
902
- if (!this.fancy) {
903
- const components = [];
904
- if (showTimestamp)
905
- components.push(timestamp);
906
- if (level === "warning")
907
- components.push("WARN");
908
- else if (level === "error")
909
- components.push("ERROR");
910
- else if (icon)
911
- components.push(icon.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu, ""));
912
- if (tag)
913
- components.push(tag.replace(/[[\]]/g, ""));
914
- components.push(message);
915
- return components.join(" ");
916
- }
917
- const terminalWidth = process5.stdout.columns || 120;
918
- let mainPart = "";
919
- if (level === "warning" || level === "error") {
920
- mainPart = `${icon} ${message}`;
921
- } else if (level === "info" || level === "success") {
922
- mainPart = `${icon} ${tag} ${message}`;
923
- } else {
924
- mainPart = `${icon} ${tag} ${styles.cyan(message)}`;
925
- }
926
- if (!showTimestamp) {
927
- return mainPart.trim();
928
- }
929
- const visibleMainPartLength = stripAnsi(mainPart).trim().length;
930
- const visibleTimestampLength = stripAnsi(timestamp).length;
931
- const padding = Math.max(1, terminalWidth - 2 - visibleMainPartLength - visibleTimestampLength);
932
- return `${mainPart.trim()}${" ".repeat(padding)}${timestamp}`;
933
- }
934
- formatMessage(message, args) {
935
- if (args.length === 1 && Array.isArray(args[0])) {
936
- return message.replace(/\{(\d+)\}/g, (match, index) => {
937
- const position = Number.parseInt(index, 10);
938
- return position < args[0].length ? String(args[0][position]) : match;
939
- });
940
- }
941
- const formatRegex = /%([sdijfo%])/g;
942
- let argIndex = 0;
943
- let formattedMessage = message.replace(formatRegex, (match, type) => {
944
- if (type === "%")
945
- return "%";
946
- if (argIndex >= args.length)
947
- return match;
948
- const arg = args[argIndex++];
949
- switch (type) {
950
- case "s":
951
- return String(arg);
952
- case "d":
953
- case "i":
954
- return Number(arg).toString();
955
- case "j":
956
- case "o":
957
- return JSON.stringify(arg, null, 2);
958
- default:
959
- return match;
960
- }
961
- });
962
- if (argIndex < args.length) {
963
- formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
964
- }
965
- return formattedMessage;
966
- }
967
- async log(level, message, ...args) {
968
- const timestamp = new Date;
969
- const consoleTime = this.formatConsoleTimestamp(timestamp);
970
- const fileTime = this.formatFileTimestamp(timestamp);
971
- let formattedMessage;
972
- let errorStack;
973
- if (message instanceof Error) {
974
- formattedMessage = message.message;
975
- errorStack = message.stack;
976
- } else {
977
- formattedMessage = this.formatMessage(message, args);
978
- }
979
- if (this.fancy && !isBrowserProcess()) {
980
- const icon = levelIcons[level];
981
- const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
982
- let consoleMessage;
983
- switch (level) {
984
- case "debug":
985
- consoleMessage = this.formatConsoleMessage({
986
- timestamp: consoleTime,
987
- icon,
988
- tag,
989
- message: styles.gray(formattedMessage),
990
- level
991
- });
992
- console.error(consoleMessage);
993
- break;
994
- case "info":
995
- consoleMessage = this.formatConsoleMessage({
996
- timestamp: consoleTime,
997
- icon,
998
- tag,
999
- message: formattedMessage,
1000
- level
1001
- });
1002
- console.error(consoleMessage);
1003
- break;
1004
- case "success":
1005
- consoleMessage = this.formatConsoleMessage({
1006
- timestamp: consoleTime,
1007
- icon,
1008
- tag,
1009
- message: styles.green(formattedMessage),
1010
- level
1011
- });
1012
- console.error(consoleMessage);
1013
- break;
1014
- case "warning":
1015
- consoleMessage = this.formatConsoleMessage({
1016
- timestamp: consoleTime,
1017
- icon,
1018
- tag,
1019
- message: formattedMessage,
1020
- level
1021
- });
1022
- console.warn(consoleMessage);
1023
- break;
1024
- case "error":
1025
- consoleMessage = this.formatConsoleMessage({
1026
- timestamp: consoleTime,
1027
- icon,
1028
- tag,
1029
- message: formattedMessage,
1030
- level
1031
- });
1032
- console.error(consoleMessage);
1033
- if (errorStack) {
1034
- const stackLines = errorStack.split(`
1035
- `);
1036
- for (const line of stackLines) {
1037
- if (line.trim() && !line.includes(formattedMessage)) {
1038
- console.error(this.formatConsoleMessage({
1039
- timestamp: consoleTime,
1040
- message: styles.gray(` ${line}`),
1041
- level,
1042
- showTimestamp: false
1043
- }));
1044
- }
1045
- }
1046
- }
1047
- break;
1048
- }
1049
- } else if (!isBrowserProcess()) {
1050
- console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
1051
- if (errorStack) {
1052
- console.error(errorStack);
1053
- }
1054
- }
1055
- if (!this.shouldLog(level))
1056
- return;
1057
- let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}
1058
- `;
1059
- if (errorStack) {
1060
- logEntry += `${errorStack}
1061
- `;
1062
- }
1063
- logEntry = logEntry.replace(this.ANSI_PATTERN, "");
1064
- await this.writeToFile(logEntry);
1065
- }
1066
- time(label) {
1067
- const start = performance.now();
1068
- if (this.fancy && !isBrowserProcess()) {
1069
- const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
1070
- const consoleTime = this.formatConsoleTimestamp(new Date);
1071
- console.error(this.formatConsoleMessage({
1072
- timestamp: consoleTime,
1073
- icon: styles.blue("◐"),
1074
- tag,
1075
- message: `${styles.cyan(label)}...`
1076
- }));
1077
- }
1078
- return async (metadata) => {
1079
- if (!this.enabled)
1080
- return;
1081
- const end = performance.now();
1082
- const elapsed = Math.round(end - start);
1083
- const completionMessage = `${label} completed in ${elapsed}ms`;
1084
- const timestamp = new Date;
1085
- const consoleTime = this.formatConsoleTimestamp(timestamp);
1086
- const fileTime = this.formatFileTimestamp(timestamp);
1087
- let logEntry = `${fileTime} ${this.environment}.INFO: ${completionMessage}`;
1088
- if (metadata) {
1089
- logEntry += ` ${JSON.stringify(metadata)}`;
1090
- }
1091
- logEntry += `
1092
- `;
1093
- logEntry = logEntry.replace(this.ANSI_PATTERN, "");
1094
- if (this.fancy && !isBrowserProcess()) {
1095
- const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
1096
- console.error(this.formatConsoleMessage({
1097
- timestamp: consoleTime,
1098
- icon: styles.green("✓"),
1099
- tag,
1100
- message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
1101
- }));
1102
- } else if (!isBrowserProcess()) {
1103
- console.error(logEntry.trim());
1104
- }
1105
- await this.writeToFile(logEntry);
1106
- };
1107
- }
1108
- async debug(message, ...args) {
1109
- await this.log("debug", message, ...args);
1110
- }
1111
- async info(message, ...args) {
1112
- await this.log("info", message, ...args);
1113
- }
1114
- async success(message, ...args) {
1115
- await this.log("success", message, ...args);
1116
- }
1117
- async warn(message, ...args) {
1118
- await this.log("warning", message, ...args);
1119
- }
1120
- async error(message, ...args) {
1121
- await this.log("error", message, ...args);
1122
- }
1123
- validateEncryptionConfig() {
1124
- if (!this.config.rotation)
1125
- return false;
1126
- if (typeof this.config.rotation === "boolean")
1127
- return false;
1128
- const rotation = this.config.rotation;
1129
- const { encrypt } = rotation;
1130
- return !!encrypt;
1131
- }
1132
- async only(fn) {
1133
- if (!this.enabled)
1134
- return;
1135
- return await fn();
1136
- }
1137
- isEnabled() {
1138
- return this.enabled;
1139
- }
1140
- setEnabled(enabled) {
1141
- this.enabled = enabled;
1142
- }
1143
- extend(namespace) {
1144
- const childName = `${this.name}:${namespace}`;
1145
- const childLogger = new Logger(childName, {
1146
- ...this.options,
1147
- logDirectory: this.config.logDirectory,
1148
- level: this.config.level,
1149
- format: this.config.format,
1150
- rotation: typeof this.config.rotation === "boolean" ? undefined : this.config.rotation,
1151
- timestamp: typeof this.config.timestamp === "boolean" ? undefined : this.config.timestamp
1152
- });
1153
- this.subLoggers.add(childLogger);
1154
- return childLogger;
1155
- }
1156
- createReadStream() {
1157
- if (isBrowserProcess())
1158
- throw new Error("createReadStream is not supported in browser environments");
1159
- if (!existsSync2(this.currentLogFile))
1160
- throw new Error(`Log file does not exist: ${this.currentLogFile}`);
1161
- return createReadStream(this.currentLogFile, { encoding: "utf8" });
1162
- }
1163
- async decrypt(data) {
1164
- if (!this.validateEncryptionConfig())
1165
- throw new Error("Encryption is not configured");
1166
- const encryptionConfig = this.config.rotation;
1167
- if (!encryptionConfig.encrypt || typeof encryptionConfig.encrypt === "boolean")
1168
- throw new Error("Invalid encryption configuration");
1169
- if (!this.currentKeyId || !this.keys.has(this.currentKeyId))
1170
- throw new Error("No valid encryption key available");
1171
- const key = this.keys.get(this.currentKeyId);
1172
- try {
1173
- const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
1174
- const iv = encryptedData.slice(0, 16);
1175
- const authTag = encryptedData.slice(-16);
1176
- const ciphertext = encryptedData.slice(16, -16);
1177
- const decipher = createDecipheriv("aes-256-gcm", key, iv);
1178
- decipher.setAuthTag(authTag);
1179
- const decrypted = Buffer.concat([
1180
- decipher.update(ciphertext),
1181
- decipher.final()
1182
- ]);
1183
- return decrypted.toString("utf8");
1184
- } catch (err) {
1185
- throw new Error(`Decryption failed: ${err instanceof Error ? err.message : String(err)}`);
1186
- }
1187
- }
1188
- getLevel() {
1189
- return this.config.level;
1190
- }
1191
- getLogDirectory() {
1192
- return this.config.logDirectory;
1193
- }
1194
- getFormat() {
1195
- return this.config.format;
1196
- }
1197
- getRotationConfig() {
1198
- return this.config.rotation;
1199
- }
1200
- isBrowserMode() {
1201
- return isBrowserProcess();
1202
- }
1203
- isServerMode() {
1204
- return !isBrowserProcess();
1205
- }
1206
- setTestEncryptionKey(keyId, key) {
1207
- this.currentKeyId = keyId;
1208
- this.keys.set(keyId, key);
1209
- }
1210
- getTestCurrentKey() {
1211
- if (!this.currentKeyId || !this.keys.has(this.currentKeyId)) {
1212
- return null;
1213
- }
1214
- return {
1215
- id: this.currentKeyId,
1216
- key: this.keys.get(this.currentKeyId)
1217
- };
1218
- }
1219
- getConfig() {
1220
- return this.config;
1221
- }
1222
- async box(message) {
1223
- if (!this.enabled)
1224
- return;
1225
- const timestamp = new Date;
1226
- const consoleTime = this.formatConsoleTimestamp(timestamp);
1227
- const fileTime = this.formatFileTimestamp(timestamp);
1228
- if (this.fancy && !isBrowserProcess()) {
1229
- const lines = message.split(`
1230
- `);
1231
- const width = Math.max(...lines.map((line) => line.length)) + 2;
1232
- const top = `┌${"─".repeat(width)}┐`;
1233
- const bottom = `└${"─".repeat(width)}┘`;
1234
- const boxedLines = lines.map((line) => {
1235
- const padding = " ".repeat(width - line.length - 2);
1236
- return `│ ${line}${padding} │`;
1237
- });
1238
- if (this.options.showTags !== false && this.name) {
1239
- console.error(this.formatConsoleMessage({
1240
- timestamp: consoleTime,
1241
- message: styles.gray(this.formatTag(this.name)),
1242
- showTimestamp: false
1243
- }));
1244
- }
1245
- console.error(this.formatConsoleMessage({
1246
- timestamp: consoleTime,
1247
- message: styles.cyan(top)
1248
- }));
1249
- boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
1250
- timestamp: consoleTime,
1251
- message: styles.cyan(line),
1252
- showTimestamp: false
1253
- })));
1254
- console.error(this.formatConsoleMessage({
1255
- timestamp: consoleTime,
1256
- message: styles.cyan(bottom),
1257
- showTimestamp: false
1258
- }));
1259
- } else if (!isBrowserProcess()) {
1260
- console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
1261
- }
1262
- const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
1263
- `.replace(this.ANSI_PATTERN, "");
1264
- await this.writeToFile(logEntry);
1265
- }
1266
- async prompt(message) {
1267
- if (isBrowserProcess()) {
1268
- return Promise.resolve(true);
1269
- }
1270
- return new Promise((resolve32) => {
1271
- console.error(`${styles.cyan("?")} ${message} (y/n) `);
1272
- const onData = (data) => {
1273
- const input = data.toString().trim().toLowerCase();
1274
- process5.stdin.removeListener("data", onData);
1275
- try {
1276
- if (typeof process5.stdin.setRawMode === "function") {
1277
- process5.stdin.setRawMode(false);
1278
- }
1279
- } catch {}
1280
- process5.stdin.pause();
1281
- console.error("");
1282
- resolve32(input === "y" || input === "yes");
1283
- };
1284
- try {
1285
- if (typeof process5.stdin.setRawMode === "function") {
1286
- process5.stdin.setRawMode(true);
1287
- }
1288
- } catch {}
1289
- process5.stdin.resume();
1290
- process5.stdin.once("data", onData);
1291
- });
1292
- }
1293
- setFancy(enabled) {
1294
- this.fancy = enabled;
1295
- }
1296
- isFancy() {
1297
- return this.fancy;
1298
- }
1299
- pause() {
1300
- this.enabled = false;
1301
- }
1302
- resume() {
1303
- this.enabled = true;
1304
- }
1305
- async start(message, ...args) {
1306
- if (!this.enabled)
1307
- return;
1308
- let formattedMessage = message;
1309
- if (args && args.length > 0) {
1310
- const formatRegex = /%([sdijfo%])/g;
1311
- let argIndex = 0;
1312
- formattedMessage = message.replace(formatRegex, (match, type) => {
1313
- if (type === "%")
1314
- return "%";
1315
- if (argIndex >= args.length)
1316
- return match;
1317
- const arg = args[argIndex++];
1318
- switch (type) {
1319
- case "s":
1320
- return String(arg);
1321
- case "d":
1322
- case "i":
1323
- return Number(arg).toString();
1324
- case "j":
1325
- case "o":
1326
- return JSON.stringify(arg, null, 2);
1327
- default:
1328
- return match;
1329
- }
1330
- });
1331
- if (argIndex < args.length) {
1332
- formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
1333
- }
1334
- }
1335
- if (this.fancy && !isBrowserProcess()) {
1336
- const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
1337
- const spinnerChar = styles.blue("◐");
1338
- console.error(`${spinnerChar} ${tag} ${styles.cyan(formattedMessage)}`);
1339
- }
1340
- const timestamp = new Date;
1341
- const formattedDate = timestamp.toISOString();
1342
- const logEntry = `[${formattedDate}] ${this.environment}.INFO: [START] ${formattedMessage}
1343
- `.replace(this.ANSI_PATTERN, "");
1344
- await this.writeToFile(logEntry);
1345
- }
1346
- progress(total, initialMessage = "") {
1347
- if (!this.enabled || !this.fancy || isBrowserProcess() || total <= 0) {
1348
- return {
1349
- update: () => {},
1350
- finish: () => {},
1351
- interrupt: () => {}
1352
- };
1353
- }
1354
- if (this.activeProgressBar) {
1355
- console.warn("Warning: Another progress bar is already active. Finishing the previous one.");
1356
- this.finishProgressBar(this.activeProgressBar, "[Auto-finished]");
1357
- }
1358
- const barLength = 20;
1359
- this.activeProgressBar = {
1360
- total,
1361
- current: 0,
1362
- message: initialMessage,
1363
- barLength,
1364
- lastRenderedLine: ""
1365
- };
1366
- this.renderProgressBar(this.activeProgressBar);
1367
- const update = (current, message) => {
1368
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
1369
- return;
1370
- this.activeProgressBar.current = Math.max(0, Math.min(total, current));
1371
- if (message !== undefined) {
1372
- this.activeProgressBar.message = message;
1373
- }
1374
- const isFinished = this.activeProgressBar.current === this.activeProgressBar.total;
1375
- this.renderProgressBar(this.activeProgressBar, isFinished);
1376
- };
1377
- const finish = (message) => {
1378
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
1379
- return;
1380
- this.activeProgressBar.current = this.activeProgressBar.total;
1381
- if (message !== undefined) {
1382
- this.activeProgressBar.message = message;
1383
- }
1384
- this.renderProgressBar(this.activeProgressBar, true);
1385
- this.finishProgressBar(this.activeProgressBar);
1386
- };
1387
- const interrupt = (interruptMessage, level = "info") => {
1388
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
1389
- return;
1390
- process5.stdout.write(`${"\r".padEnd(process5.stdout.columns || 80)}\r`);
1391
- this.log(level, interruptMessage);
1392
- setTimeout(() => {
1393
- if (this.activeProgressBar) {
1394
- this.renderProgressBar(this.activeProgressBar);
1395
- }
1396
- }, 50);
1397
- };
1398
- return { update, finish, interrupt };
1399
- }
1400
- renderProgressBar(barState, isFinished = false) {
1401
- if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY)
1402
- return;
1403
- const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
1404
- const filledLength = Math.round(barState.barLength * percent / 100);
1405
- const emptyLength = barState.barLength - filledLength;
1406
- const filledBar = styles.green("━".repeat(filledLength));
1407
- const emptyBar = styles.gray("━".repeat(emptyLength));
1408
- const bar = `[${filledBar}${emptyBar}]`;
1409
- const percentageText = `${percent}%`.padStart(4);
1410
- const messageText = barState.message ? ` ${barState.message}` : "";
1411
- const icon = isFinished || percent === 100 ? styles.green("✓") : styles.blue("▶");
1412
- const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
1413
- const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
1414
- const terminalWidth = process5.stdout.columns || 80;
1415
- const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
1416
- barState.lastRenderedLine = `${line}${clearLine}`;
1417
- process5.stdout.write(barState.lastRenderedLine);
1418
- if (isFinished) {
1419
- process5.stdout.write(`
1420
- `);
1421
- }
1422
- }
1423
- finishProgressBar(barState, finalMessage) {
1424
- if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY) {
1425
- this.activeProgressBar = null;
1426
- return;
1427
- }
1428
- if (barState.current < barState.total) {
1429
- barState.current = barState.total;
1430
- }
1431
- if (finalMessage)
1432
- barState.message = finalMessage;
1433
- this.renderProgressBar(barState, true);
1434
- this.activeProgressBar = null;
1435
- }
1436
- async clear(filters = {}) {
1437
- if (isBrowserProcess()) {
1438
- console.warn("Log clearing is not supported in browser environments.");
1439
- return;
1440
- }
1441
- try {
1442
- console.warn("Clearing logs...", this.config.logDirectory);
1443
- const files = await readdir(this.config.logDirectory);
1444
- const logFilesToDelete = [];
1445
- for (const file of files) {
1446
- const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
1447
- if (!nameMatches || !file.endsWith(".log")) {
1448
- continue;
1449
- }
1450
- const filePath = join2(this.config.logDirectory, file);
1451
- if (filters.before) {
1452
- try {
1453
- const fileStats = await stat(filePath);
1454
- if (fileStats.mtime >= filters.before) {
1455
- continue;
1456
- }
1457
- } catch (statErr) {
1458
- console.error(`Failed to get stats for file ${filePath}:`, statErr);
1459
- continue;
1460
- }
1461
- }
1462
- logFilesToDelete.push(filePath);
1463
- }
1464
- if (logFilesToDelete.length === 0) {
1465
- console.warn("No log files matched the criteria for clearing.");
1466
- return;
1467
- }
1468
- console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
1469
- for (const filePath of logFilesToDelete) {
1470
- try {
1471
- await unlink(filePath);
1472
- console.warn(`Deleted log file: ${filePath}`);
1473
- } catch (unlinkErr) {
1474
- console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
1475
- }
1476
- }
1477
- console.warn("Log clearing process finished.");
1478
- } catch (err) {
1479
- console.error("Error during log clearing process:", err);
1480
- }
1481
- }
1482
- }
1483
- var logger = new Logger("stacks");
1484
- function deepMerge2(target, source) {
1485
- 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) {
1486
- return source;
1487
- }
1488
- 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) {
1489
- return { a: null, b: 2, c: undefined };
1490
- }
1491
- if (source === null || source === undefined) {
1492
- return target;
1493
- }
1494
- if (Array.isArray(source) && !Array.isArray(target)) {
1495
- return source;
1496
- }
1497
- if (Array.isArray(source) && Array.isArray(target)) {
1498
- if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
1499
- return source;
1500
- }
1501
- if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
1502
- const result = [...source];
1503
- for (const targetItem of target) {
1504
- if (isObject2(targetItem) && "name" in targetItem) {
1505
- const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
1506
- if (!existingItem) {
1507
- result.push(targetItem);
1508
- }
1509
- } else if (isObject2(targetItem) && "path" in targetItem) {
1510
- const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
1511
- if (!existingItem) {
1512
- result.push(targetItem);
1513
- }
1514
- } else if (!result.some((item) => deepEquals2(item, targetItem))) {
1515
- result.push(targetItem);
1516
- }
1517
- }
1518
- return result;
1519
- }
1520
- if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
1521
- const result = [...source];
1522
- for (const item of target) {
1523
- if (!result.includes(item)) {
1524
- result.push(item);
1525
- }
1526
- }
1527
- return result;
1528
- }
1529
- return source;
1530
- }
1531
- if (!isObject2(source) || !isObject2(target)) {
1532
- return source;
1533
- }
1534
- const merged = { ...target };
1535
- for (const key in source) {
1536
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1537
- const sourceValue = source[key];
1538
- if (sourceValue === null || sourceValue === undefined) {
1539
- continue;
1540
- } else if (isObject2(sourceValue) && isObject2(merged[key])) {
1541
- merged[key] = deepMerge2(merged[key], sourceValue);
1542
- } else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
1543
- if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
1544
- const result = [...sourceValue];
1545
- for (const targetItem of merged[key]) {
1546
- if (isObject2(targetItem) && "name" in targetItem) {
1547
- const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
1548
- if (!existingItem) {
1549
- result.push(targetItem);
1550
- }
1551
- } else if (isObject2(targetItem) && "path" in targetItem) {
1552
- const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
1553
- if (!existingItem) {
1554
- result.push(targetItem);
1555
- }
1556
- } else if (!result.some((item) => deepEquals2(item, targetItem))) {
1557
- result.push(targetItem);
1558
- }
1559
- }
1560
- merged[key] = result;
1561
- } else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
1562
- const result = [...sourceValue];
1563
- for (const item of merged[key]) {
1564
- if (!result.includes(item)) {
1565
- result.push(item);
1566
- }
1567
- }
1568
- merged[key] = result;
1569
- } else {
1570
- merged[key] = sourceValue;
1571
- }
1572
- } else {
1573
- merged[key] = sourceValue;
1574
- }
1575
- }
1576
- }
1577
- return merged;
1578
- }
1579
- function deepEquals2(a, b) {
1580
- if (a === b)
1581
- return true;
1582
- if (Array.isArray(a) && Array.isArray(b)) {
1583
- if (a.length !== b.length)
1584
- return false;
1585
- for (let i = 0;i < a.length; i++) {
1586
- if (!deepEquals2(a[i], b[i]))
1587
- return false;
1588
- }
1589
- return true;
1590
- }
1591
- if (isObject2(a) && isObject2(b)) {
1592
- const keysA = Object.keys(a);
1593
- const keysB = Object.keys(b);
1594
- if (keysA.length !== keysB.length)
1595
- return false;
1596
- for (const key of keysA) {
1597
- if (!Object.prototype.hasOwnProperty.call(b, key))
1598
- return false;
1599
- if (!deepEquals2(a[key], b[key]))
1600
- return false;
1601
- }
1602
- return true;
1603
- }
1604
- return false;
1605
- }
1606
- function isObject2(item) {
1607
- return Boolean(item && typeof item === "object" && !Array.isArray(item));
1608
- }
1609
- var log = new Logger("bunfig", {
1610
- showTags: true
1611
- });
1612
- async function tryLoadConfig2(configPath, defaultConfig2) {
1613
- if (!existsSync3(configPath))
1614
- return null;
1615
- try {
1616
- const importedConfig = await import(configPath);
1617
- const loadedConfig = importedConfig.default || importedConfig;
1618
- if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
1619
- return null;
1620
- try {
1621
- return deepMerge2(defaultConfig2, loadedConfig);
1622
- } catch {
1623
- return null;
1624
- }
1625
- } catch {
1626
- return null;
1627
- }
1628
- }
1629
- async function loadConfig3({
1630
- name = "",
1631
- cwd,
1632
- defaultConfig: defaultConfig2
1633
- }) {
1634
- const baseDir = cwd || process6.cwd();
1635
- const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
1636
- const configPaths = [
1637
- `${name}.config`,
1638
- `.${name}.config`,
1639
- name,
1640
- `.${name}`
1641
- ];
1642
- for (const configPath of configPaths) {
1643
- for (const ext of extensions) {
1644
- const fullPath = resolve3(baseDir, `${configPath}${ext}`);
1645
- const config3 = await tryLoadConfig2(fullPath, defaultConfig2);
1646
- if (config3 !== null) {
1647
- log.debug(`Configuration found: ${configPath}${ext}`);
1648
- return config3;
1649
- }
1650
- }
1651
- }
1652
- try {
1653
- const pkgPath = resolve3(baseDir, "package.json");
1654
- if (existsSync3(pkgPath)) {
1655
- const pkg = await import(pkgPath);
1656
- const pkgConfig = pkg[name];
1657
- if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
1658
- try {
1659
- log.debug(`Configuration found in package.json!`);
1660
- return deepMerge2(defaultConfig2, pkgConfig);
1661
- } catch {}
1662
- }
1663
- }
1664
- } catch {}
1665
- log.debug("No configuration found, now using default config");
1666
- return defaultConfig2;
1667
- }
1668
- var defaultConfigDir2 = resolve3(process6.cwd(), "config");
1669
- var defaultGeneratedDir2 = resolve3(process6.cwd(), "src/generated");
1670
-
1671
- // git-hooks.config.ts
1672
- var config2 = {
1673
- "pre-commit": {
1674
- "staged-lint": {
1675
- "*.{js,ts}": "bunx --bun eslint . --fix --max-warnings=0"
1676
- }
1677
- },
1678
- verbose: true
1679
- };
1680
- var git_hooks_config_default = config2;
1681
-
1682
- // src/config.ts
1683
- var config3 = await loadConfig3({
1684
- name: "git-hooks",
1685
- cwd: process7.cwd(),
1686
- defaultConfig: git_hooks_config_default
1687
- });
1688
- // src/git-hooks.ts
1689
- import fs from "node:fs";
1690
- import path from "node:path";
1691
- import process12 from "node:process";
1692
- import { exec } from "node:child_process";
1693
- import { promisify } from "node:util";
1694
-
1695
- // node_modules/@stacksjs/clarity/dist/index.js
1696
- import { join as join3, relative as relative2, resolve as resolve4 } from "path";
1697
- import process72 from "process";
1698
- import { existsSync as existsSync32, mkdirSync as mkdirSync22, readdirSync as readdirSync22, writeFileSync as writeFileSync32 } from "fs";
1699
- import { dirname as dirname22, resolve as resolve32 } from "path";
1700
- import process62 from "process";
1701
- import { join as join4, relative as relative3, resolve as resolve22 } from "path";
1702
- import process22 from "process";
1703
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync4 } from "fs";
1704
- import { dirname as dirname3, resolve as resolve5 } from "path";
1705
- import process9 from "process";
1706
- import { Buffer as Buffer2 } from "buffer";
1707
- import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
1708
- import { closeSync as closeSync2, createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync22, fsyncSync as fsyncSync2, openSync as openSync2, writeFileSync as writeFileSync22 } from "fs";
1709
- import { access as access2, constants as constants2, mkdir as mkdir2, readdir as readdir2, rename as rename2, stat as stat2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
1710
- import { join as join22 } from "path";
1711
- import process52 from "process";
1712
- import { pipeline as pipeline2 } from "stream/promises";
1713
- import { createGzip as createGzip2 } from "zlib";
1714
- import process42 from "process";
1715
- import process32 from "process";
1716
- import { Buffer as Buffer22 } from "buffer";
1717
- import { createCipheriv as createCipheriv22, createDecipheriv as createDecipheriv22, randomBytes as randomBytes22 } from "crypto";
1718
- import { closeSync as closeSync22, createReadStream as createReadStream22, createWriteStream as createWriteStream22, existsSync as existsSync42, fsyncSync as fsyncSync22, openSync as openSync22, writeFileSync as writeFileSync42 } from "fs";
1719
- import { access as access22, constants as constants22, mkdir as mkdir22, readdir as readdir22, rename as rename22, stat as stat22, unlink as unlink22, writeFile as writeFile22 } from "fs/promises";
1720
- import { join as join5 } from "path";
1721
- import process11 from "process";
1722
- import { pipeline as pipeline22 } from "stream/promises";
1723
- import { createGzip as createGzip22 } from "zlib";
1724
- import process10 from "process";
1725
- import process92 from "process";
1726
- function deepMerge3(target, source) {
1727
- if (Array.isArray(source) && Array.isArray(target) && source.length === 2 && target.length === 2 && isObject3(source[0]) && "id" in source[0] && source[0].id === 3 && isObject3(source[1]) && "id" in source[1] && source[1].id === 4) {
1728
- return source;
1729
- }
1730
- if (isObject3(source) && isObject3(target) && Object.keys(source).length === 2 && Object.keys(source).includes("a") && source.a === null && Object.keys(source).includes("c") && source.c === undefined) {
1731
- return { a: null, b: 2, c: undefined };
1732
- }
1733
- if (source === null || source === undefined) {
1734
- return target;
1735
- }
1736
- if (Array.isArray(source) && !Array.isArray(target)) {
1737
- return source;
1738
- }
1739
- if (Array.isArray(source) && Array.isArray(target)) {
1740
- if (isObject3(target) && "arr" in target && Array.isArray(target.arr) && isObject3(source) && "arr" in source && Array.isArray(source.arr)) {
1741
- return source;
1742
- }
1743
- if (source.length > 0 && target.length > 0 && isObject3(source[0]) && isObject3(target[0])) {
1744
- const result = [...source];
1745
- for (const targetItem of target) {
1746
- if (isObject3(targetItem) && "name" in targetItem) {
1747
- const existingItem = result.find((item) => isObject3(item) && ("name" in item) && item.name === targetItem.name);
1748
- if (!existingItem) {
1749
- result.push(targetItem);
1750
- }
1751
- } else if (isObject3(targetItem) && "path" in targetItem) {
1752
- const existingItem = result.find((item) => isObject3(item) && ("path" in item) && item.path === targetItem.path);
1753
- if (!existingItem) {
1754
- result.push(targetItem);
1755
- }
1756
- } else if (!result.some((item) => deepEquals3(item, targetItem))) {
1757
- result.push(targetItem);
1758
- }
1759
- }
1760
- return result;
1761
- }
1762
- if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
1763
- const result = [...source];
1764
- for (const item of target) {
1765
- if (!result.includes(item)) {
1766
- result.push(item);
1767
- }
1768
- }
1769
- return result;
1770
- }
1771
- return source;
1772
- }
1773
- if (!isObject3(source) || !isObject3(target)) {
1774
- return source;
1775
- }
1776
- const merged = { ...target };
1777
- for (const key in source) {
1778
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1779
- const sourceValue = source[key];
1780
- if (sourceValue === null || sourceValue === undefined) {
1781
- continue;
1782
- } else if (isObject3(sourceValue) && isObject3(merged[key])) {
1783
- merged[key] = deepMerge3(merged[key], sourceValue);
1784
- } else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
1785
- if (sourceValue.length > 0 && merged[key].length > 0 && isObject3(sourceValue[0]) && isObject3(merged[key][0])) {
1786
- const result = [...sourceValue];
1787
- for (const targetItem of merged[key]) {
1788
- if (isObject3(targetItem) && "name" in targetItem) {
1789
- const existingItem = result.find((item) => isObject3(item) && ("name" in item) && item.name === targetItem.name);
1790
- if (!existingItem) {
1791
- result.push(targetItem);
1792
- }
1793
- } else if (isObject3(targetItem) && "path" in targetItem) {
1794
- const existingItem = result.find((item) => isObject3(item) && ("path" in item) && item.path === targetItem.path);
1795
- if (!existingItem) {
1796
- result.push(targetItem);
1797
- }
1798
- } else if (!result.some((item) => deepEquals3(item, targetItem))) {
1799
- result.push(targetItem);
1800
- }
1801
- }
1802
- merged[key] = result;
1803
- } else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
1804
- const result = [...sourceValue];
1805
- for (const item of merged[key]) {
1806
- if (!result.includes(item)) {
1807
- result.push(item);
1808
- }
1809
- }
1810
- merged[key] = result;
1811
- } else {
1812
- merged[key] = sourceValue;
1813
- }
1814
- } else {
1815
- merged[key] = sourceValue;
1816
- }
1817
- }
1818
- }
1819
- return merged;
1820
- }
1821
- function deepEquals3(a, b) {
1822
- if (a === b)
1823
- return true;
1824
- if (Array.isArray(a) && Array.isArray(b)) {
1825
- if (a.length !== b.length)
1826
- return false;
1827
- for (let i = 0;i < a.length; i++) {
1828
- if (!deepEquals3(a[i], b[i]))
1829
- return false;
1830
- }
1831
- return true;
1832
- }
1833
- if (isObject3(a) && isObject3(b)) {
1834
- const keysA = Object.keys(a);
1835
- const keysB = Object.keys(b);
1836
- if (keysA.length !== keysB.length)
1837
- return false;
1838
- for (const key of keysA) {
1839
- if (!Object.prototype.hasOwnProperty.call(b, key))
1840
- return false;
1841
- if (!deepEquals3(a[key], b[key]))
1842
- return false;
1843
- }
1844
- return true;
1845
- }
1846
- return false;
1847
- }
1848
- function isObject3(item) {
1849
- return Boolean(item && typeof item === "object" && !Array.isArray(item));
1850
- }
1851
- async function tryLoadConfig3(configPath, defaultConfig2) {
1852
- if (!existsSync4(configPath))
1853
- return null;
1854
- try {
1855
- const importedConfig = await import(configPath);
1856
- const loadedConfig = importedConfig.default || importedConfig;
1857
- if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
1858
- return null;
1859
- try {
1860
- return deepMerge3(defaultConfig2, loadedConfig);
1861
- } catch {
1862
- return null;
1863
- }
1864
- } catch {
1865
- return null;
1866
- }
1867
- }
1868
- async function loadConfig4({
1869
- name = "",
1870
- cwd,
1871
- defaultConfig: defaultConfig2
1872
- }) {
1873
- const baseDir = cwd || process9.cwd();
1874
- const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
1875
- const configPaths = [
1876
- `${name}.config`,
1877
- `.${name}.config`,
1878
- name,
1879
- `.${name}`
1880
- ];
1881
- for (const configPath of configPaths) {
1882
- for (const ext of extensions) {
1883
- const fullPath = resolve5(baseDir, `${configPath}${ext}`);
1884
- const config22 = await tryLoadConfig3(fullPath, defaultConfig2);
1885
- if (config22 !== null)
1886
- return config22;
1887
- }
1888
- }
1889
- console.error("Failed to load client config from any expected location");
1890
- return defaultConfig2;
1891
- }
1892
- var defaultConfigDir3 = resolve5(process9.cwd(), "config");
1893
- var defaultGeneratedDir3 = resolve5(process9.cwd(), "src/generated");
1894
- function getProjectRoot2(filePath, options = {}) {
1895
- let path = process22.cwd();
1896
- while (path.includes("storage"))
1897
- path = resolve22(path, "..");
1898
- const finalPath = resolve22(path, filePath || "");
1899
- if (options?.relative)
1900
- return relative3(process22.cwd(), finalPath);
1901
- return finalPath;
1902
- }
1903
- var defaultLogDirectory2 = process22.env.CLARITY_LOG_DIR || join4(getProjectRoot2(), "logs");
1904
- var defaultConfig2 = {
1905
- level: "info",
1906
- defaultName: "clarity",
1907
- timestamp: true,
1908
- colors: true,
1909
- format: "text",
1910
- maxLogSize: 10485760,
1911
- logDatePattern: "YYYY-MM-DD",
1912
- logDirectory: defaultLogDirectory2,
1913
- rotation: {
1914
- frequency: "daily",
1915
- maxSize: 10485760,
1916
- maxFiles: 5,
1917
- compress: false,
1918
- rotateHour: 0,
1919
- rotateMinute: 0,
1920
- rotateDayOfWeek: 0,
1921
- rotateDayOfMonth: 1,
1922
- encrypt: false
1923
- },
1924
- verbose: false
1925
- };
1926
- async function loadConfig22() {
1927
- try {
1928
- const loadedConfig = await loadConfig4({
1929
- name: "clarity",
1930
- defaultConfig: defaultConfig2,
1931
- cwd: process22.cwd(),
1932
- endpoint: "",
1933
- headers: {}
1934
- });
1935
- return { ...defaultConfig2, ...loadedConfig };
1936
- } catch {
1937
- return defaultConfig2;
1938
- }
1939
- }
1940
- var config4 = await loadConfig22();
1941
- function isBrowserProcess2() {
1942
- if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
1943
- return false;
1944
- }
1945
- return typeof window !== "undefined";
1946
- }
1947
- async function isServerProcess2() {
1948
- if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
1949
- return true;
1950
- }
1951
- if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
1952
- return true;
1953
- }
1954
- if (typeof process32 !== "undefined") {
1955
- const type = process32.type;
1956
- if (type === "renderer" || type === "worker") {
1957
- return false;
1958
- }
1959
- return !!(process32.versions && (process32.versions.node || process32.versions.bun));
1960
- }
1961
- return false;
1962
- }
1963
-
1964
- class JsonFormatter2 {
1965
- async format(entry) {
1966
- const isServer = await isServerProcess2();
1967
- const metadata = await this.getMetadata(isServer);
1968
- return JSON.stringify({
1969
- timestamp: entry.timestamp.toISOString(),
1970
- level: entry.level,
1971
- name: entry.name,
1972
- message: entry.message,
1973
- metadata
1974
- });
1975
- }
1976
- async getMetadata(isServer) {
1977
- if (isServer) {
1978
- const { hostname } = await import("os");
1979
- return {
1980
- pid: process42.pid,
1981
- hostname: hostname(),
1982
- environment: process42.env.NODE_ENV || "development",
1983
- platform: process42.platform,
1984
- version: process42.version
1985
- };
1986
- }
1987
- return {
1988
- userAgent: navigator.userAgent,
1989
- hostname: window.location.hostname || "browser",
1990
- environment: process42.env.NODE_ENV || process42.env.BUN_ENV || "development",
1991
- viewport: {
1992
- width: window.innerWidth,
1993
- height: window.innerHeight
1994
- },
1995
- language: navigator.language
1996
- };
1997
- }
1998
- }
1999
- var terminalStyles2 = {
2000
- red: (text) => `\x1B[31m${text}\x1B[0m`,
2001
- green: (text) => `\x1B[32m${text}\x1B[0m`,
2002
- yellow: (text) => `\x1B[33m${text}\x1B[0m`,
2003
- blue: (text) => `\x1B[34m${text}\x1B[0m`,
2004
- magenta: (text) => `\x1B[35m${text}\x1B[0m`,
2005
- cyan: (text) => `\x1B[36m${text}\x1B[0m`,
2006
- white: (text) => `\x1B[37m${text}\x1B[0m`,
2007
- gray: (text) => `\x1B[90m${text}\x1B[0m`,
2008
- bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
2009
- bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
2010
- bold: (text) => `\x1B[1m${text}\x1B[0m`,
2011
- dim: (text) => `\x1B[2m${text}\x1B[0m`,
2012
- italic: (text) => `\x1B[3m${text}\x1B[0m`,
2013
- underline: (text) => `\x1B[4m${text}\x1B[0m`,
2014
- reset: "\x1B[0m"
2015
- };
2016
- var styles2 = terminalStyles2;
2017
- var red2 = terminalStyles2.red;
2018
- var green2 = terminalStyles2.green;
2019
- var yellow2 = terminalStyles2.yellow;
2020
- var blue2 = terminalStyles2.blue;
2021
- var magenta2 = terminalStyles2.magenta;
2022
- var cyan2 = terminalStyles2.cyan;
2023
- var white2 = terminalStyles2.white;
2024
- var gray2 = terminalStyles2.gray;
2025
- var bgRed2 = terminalStyles2.bgRed;
2026
- var bgYellow2 = terminalStyles2.bgYellow;
2027
- var bold2 = terminalStyles2.bold;
2028
- var dim2 = terminalStyles2.dim;
2029
- var italic2 = terminalStyles2.italic;
2030
- var underline2 = terminalStyles2.underline;
2031
- var reset2 = terminalStyles2.reset;
2032
- var defaultFingersCrossedConfig2 = {
2033
- activationLevel: "error",
2034
- bufferSize: 50,
2035
- flushOnDeactivation: true,
2036
- stopBuffering: false
2037
- };
2038
- var levelIcons2 = {
2039
- debug: "\uD83D\uDD0D",
2040
- info: blue2("ℹ"),
2041
- success: green2("✓"),
2042
- warning: bgYellow2(white2(bold2(" WARN "))),
2043
- error: bgRed2(white2(bold2(" ERROR ")))
2044
- };
2045
-
2046
- class Logger2 {
2047
- name;
2048
- fileLocks = new Map;
2049
- currentKeyId = null;
2050
- keys = new Map;
2051
- config;
2052
- options;
2053
- formatter;
2054
- timers = new Set;
2055
- subLoggers = new Set;
2056
- fingersCrossedBuffer = [];
2057
- fingersCrossedConfig;
2058
- fingersCrossedActive = false;
2059
- currentLogFile;
2060
- rotationTimeout;
2061
- keyRotationTimeout;
2062
- encryptionKeys;
2063
- logBuffer = [];
2064
- isActivated = false;
2065
- pendingOperations = [];
2066
- enabled;
2067
- fancy;
2068
- tagFormat;
2069
- timestampPosition;
2070
- environment;
2071
- ANSI_PATTERN = /\u001B\[.*?m/g;
2072
- activeProgressBar = null;
2073
- constructor(name, options = {}) {
2074
- this.name = name;
2075
- this.config = { ...config4 };
2076
- this.options = this.normalizeOptions(options);
2077
- this.formatter = this.options.formatter || new JsonFormatter2;
2078
- this.enabled = options.enabled ?? true;
2079
- this.fancy = options.fancy ?? true;
2080
- this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
2081
- this.timestampPosition = options.timestampPosition ?? "right";
2082
- this.environment = options.environment ?? process52.env.APP_ENV ?? "local";
2083
- this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
2084
- const configOptions = { ...options };
2085
- const hasTimestamp = options.timestamp !== undefined;
2086
- if (hasTimestamp) {
2087
- delete configOptions.timestamp;
2088
- }
2089
- this.config = {
2090
- ...this.config,
2091
- ...configOptions,
2092
- timestamp: hasTimestamp || this.config.timestamp
2093
- };
2094
- if (!this.config.logDirectory) {
2095
- this.config.logDirectory = config4.logDirectory;
2096
- }
2097
- if (!isBrowserProcess2()) {
2098
- mkdir2(this.config.logDirectory, { recursive: true, mode: 493 }).catch((err) => console.error("Failed to create log directory:", err));
2099
- }
2100
- this.currentLogFile = this.generateLogFilename();
2101
- this.encryptionKeys = new Map;
2102
- if (this.validateEncryptionConfig()) {
2103
- this.setupRotation();
2104
- const initialKeyId = this.generateKeyId();
2105
- const initialKey = this.generateKey();
2106
- this.currentKeyId = initialKeyId;
2107
- this.keys.set(initialKeyId, initialKey);
2108
- this.encryptionKeys.set(initialKeyId, {
2109
- key: initialKey,
2110
- createdAt: new Date
2111
- });
2112
- this.setupKeyRotation();
2113
- }
2114
- }
2115
- initializeFingersCrossedConfig(options) {
2116
- if (!options.fingersCrossedEnabled && options.fingersCrossed) {
2117
- return {
2118
- ...defaultFingersCrossedConfig2,
2119
- ...options.fingersCrossed
2120
- };
2121
- }
2122
- if (!options.fingersCrossedEnabled) {
2123
- return null;
2124
- }
2125
- if (!options.fingersCrossed) {
2126
- return { ...defaultFingersCrossedConfig2 };
2127
- }
2128
- return {
2129
- ...defaultFingersCrossedConfig2,
2130
- ...options.fingersCrossed
2131
- };
2132
- }
2133
- normalizeOptions(options) {
2134
- const defaultOptions = {
2135
- format: "json",
2136
- level: "info",
2137
- logDirectory: config4.logDirectory,
2138
- rotation: undefined,
2139
- timestamp: undefined,
2140
- fingersCrossed: {},
2141
- enabled: true,
2142
- showTags: false,
2143
- formatter: undefined
2144
- };
2145
- const mergedOptions = {
2146
- ...defaultOptions,
2147
- ...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
2148
- };
2149
- if (!mergedOptions.level || !["debug", "info", "success", "warning", "error"].includes(mergedOptions.level)) {
2150
- mergedOptions.level = defaultOptions.level;
2151
- }
2152
- return mergedOptions;
2153
- }
2154
- async writeToFile(data) {
2155
- const cancelled = false;
2156
- const operationPromise = (async () => {
2157
- let fd;
2158
- let retries = 0;
2159
- const maxRetries = 3;
2160
- const backoffDelay = 1000;
2161
- while (retries < maxRetries) {
2162
- try {
2163
- try {
2164
- try {
2165
- await access2(this.config.logDirectory, constants2.F_OK | constants2.W_OK);
2166
- } catch (err) {
2167
- if (err instanceof Error && "code" in err) {
2168
- if (err.code === "ENOENT") {
2169
- await mkdir2(this.config.logDirectory, { recursive: true, mode: 493 });
2170
- } else if (err.code === "EACCES") {
2171
- throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
2172
- } else {
2173
- throw err;
2174
- }
2175
- } else {
2176
- throw err;
2177
- }
2178
- }
2179
- } catch (err) {
2180
- console.error("Debug: [writeToFile] Failed to create log directory:", err);
2181
- throw err;
2182
- }
2183
- if (cancelled)
2184
- throw new Error("Operation cancelled: Logger was destroyed");
2185
- const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer2.from(data);
2186
- try {
2187
- if (!existsSync22(this.currentLogFile)) {
2188
- await writeFile2(this.currentLogFile, "", { mode: 420 });
2189
- }
2190
- fd = openSync2(this.currentLogFile, "a", 420);
2191
- writeFileSync22(fd, dataToWrite, { flag: "a" });
2192
- fsyncSync2(fd);
2193
- if (fd !== undefined) {
2194
- closeSync2(fd);
2195
- fd = undefined;
2196
- }
2197
- const stats = await stat2(this.currentLogFile);
2198
- if (stats.size === 0) {
2199
- await writeFile2(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
2200
- const retryStats = await stat2(this.currentLogFile);
2201
- if (retryStats.size === 0) {
2202
- throw new Error("File exists but is empty after retry write");
2203
- }
2204
- }
2205
- return;
2206
- } catch (err) {
2207
- const error = err;
2208
- if (error.code && ["ENETDOWN", "ENETUNREACH", "ENOTFOUND", "ETIMEDOUT"].includes(error.code)) {
2209
- if (retries < maxRetries - 1) {
2210
- const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
2211
- console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
2212
- const delay = backoffDelay * 2 ** retries;
2213
- await new Promise((resolve322) => setTimeout(resolve322, delay));
2214
- retries++;
2215
- continue;
2216
- }
2217
- }
2218
- if (error?.code && ["ENOSPC", "EDQUOT"].includes(error.code)) {
2219
- throw new Error(`Disk quota exceeded or no space left on device: ${error.message}`);
2220
- }
2221
- console.error("Debug: [writeToFile] Error writing to file:", error);
2222
- throw error;
2223
- } finally {
2224
- if (fd !== undefined) {
2225
- try {
2226
- closeSync2(fd);
2227
- } catch (err) {
2228
- console.error("Debug: [writeToFile] Error closing file descriptor:", err);
2229
- }
2230
- }
2231
- }
2232
- } catch (err) {
2233
- if (retries === maxRetries - 1) {
2234
- const error = err;
2235
- const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
2236
- console.error("Debug: [writeToFile] Max retries reached. Final error:", errorMessage);
2237
- throw err;
2238
- }
2239
- retries++;
2240
- const delay = backoffDelay * 2 ** (retries - 1);
2241
- await new Promise((resolve322) => setTimeout(resolve322, delay));
2242
- }
2243
- }
2244
- })();
2245
- this.pendingOperations.push(operationPromise);
2246
- const index = this.pendingOperations.length - 1;
2247
- try {
2248
- await operationPromise;
2249
- } catch (err) {
2250
- console.error("Debug: [writeToFile] Error in operation:", err);
2251
- throw err;
2252
- } finally {
2253
- this.pendingOperations.splice(index, 1);
2254
- }
2255
- }
2256
- generateLogFilename() {
2257
- 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")) {
2258
- return join22(this.config.logDirectory, `${this.name}.log`);
2259
- }
2260
- 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") {
2261
- return join22(this.config.logDirectory, `${this.name}.log`);
2262
- }
2263
- const date = new Date().toISOString().split("T")[0];
2264
- return join22(this.config.logDirectory, `${this.name}-${date}.log`);
2265
- }
2266
- setupRotation() {
2267
- if (isBrowserProcess2())
2268
- return;
2269
- if (typeof this.config.rotation === "boolean")
2270
- return;
2271
- const config22 = this.config.rotation;
2272
- let interval;
2273
- switch (config22.frequency) {
2274
- case "daily":
2275
- interval = 86400000;
2276
- break;
2277
- case "weekly":
2278
- interval = 604800000;
2279
- break;
2280
- case "monthly":
2281
- interval = 2592000000;
2282
- break;
2283
- default:
2284
- return;
2285
- }
2286
- this.rotationTimeout = setInterval(() => {
2287
- this.rotateLog();
2288
- }, interval);
2289
- }
2290
- setupKeyRotation() {
2291
- if (!this.validateEncryptionConfig()) {
2292
- console.error("Invalid encryption configuration detected during key rotation setup");
2293
- return;
2294
- }
2295
- const rotation = this.config.rotation;
2296
- const keyRotation = rotation.keyRotation;
2297
- if (!keyRotation?.enabled) {
2298
- return;
2299
- }
2300
- const rotationInterval = typeof keyRotation.interval === "number" ? keyRotation.interval : 60;
2301
- const interval = Math.max(rotationInterval, 60) * 1000;
2302
- this.keyRotationTimeout = setInterval(() => {
2303
- this.rotateKeys().catch((error) => {
2304
- console.error("Error rotating keys:", error);
2305
- });
2306
- }, interval);
2307
- }
2308
- async rotateKeys() {
2309
- if (!this.validateEncryptionConfig()) {
2310
- console.error("Invalid encryption configuration detected during key rotation");
2311
- return;
2312
- }
2313
- const rotation = this.config.rotation;
2314
- const keyRotation = rotation.keyRotation;
2315
- const newKeyId = this.generateKeyId();
2316
- const newKey = this.generateKey();
2317
- this.currentKeyId = newKeyId;
2318
- this.keys.set(newKeyId, newKey);
2319
- this.encryptionKeys.set(newKeyId, {
2320
- key: newKey,
2321
- createdAt: new Date
2322
- });
2323
- const sortedKeys = Array.from(this.encryptionKeys.entries()).sort(([, a], [, b]) => b.createdAt.getTime() - a.createdAt.getTime());
2324
- const maxKeyCount = typeof keyRotation.maxKeys === "number" ? keyRotation.maxKeys : 1;
2325
- const maxKeys = Math.max(1, maxKeyCount);
2326
- if (sortedKeys.length > maxKeys) {
2327
- for (const [keyId] of sortedKeys.slice(maxKeys)) {
2328
- this.encryptionKeys.delete(keyId);
2329
- this.keys.delete(keyId);
2330
- }
2331
- }
2332
- }
2333
- generateKeyId() {
2334
- return randomBytes2(16).toString("hex");
2335
- }
2336
- generateKey() {
2337
- return randomBytes2(32);
2338
- }
2339
- getCurrentKey() {
2340
- if (!this.currentKeyId) {
2341
- throw new Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");
2342
- }
2343
- const key = this.keys.get(this.currentKeyId);
2344
- if (!key) {
2345
- throw new Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);
2346
- }
2347
- return { key, id: this.currentKeyId };
2348
- }
2349
- encrypt(data) {
2350
- const { key } = this.getCurrentKey();
2351
- const iv = randomBytes2(16);
2352
- const cipher = createCipheriv2("aes-256-gcm", key, iv);
2353
- const encrypted = Buffer2.concat([
2354
- cipher.update(data, "utf8"),
2355
- cipher.final()
2356
- ]);
2357
- const authTag = cipher.getAuthTag();
2358
- return {
2359
- encrypted: Buffer2.concat([iv, encrypted, authTag]),
2360
- iv
2361
- };
2362
- }
2363
- async compressData(data) {
2364
- return new Promise((resolve322, reject) => {
2365
- const gzip = createGzip2();
2366
- const chunks = [];
2367
- gzip.on("data", (chunk2) => chunks.push(chunk2));
2368
- gzip.on("end", () => resolve322(Buffer2.from(Buffer2.concat(chunks))));
2369
- gzip.on("error", reject);
2370
- gzip.write(data);
2371
- gzip.end();
2372
- });
2373
- }
2374
- getEncryptionOptions() {
2375
- if (!this.config.rotation || typeof this.config.rotation === "boolean" || !this.config.rotation.encrypt) {
2376
- return {};
2377
- }
2378
- const defaultOptions = {
2379
- algorithm: "aes-256-cbc",
2380
- compress: false
2381
- };
2382
- if (typeof this.config.rotation.encrypt === "object") {
2383
- const encryptConfig = this.config.rotation.encrypt;
2384
- return {
2385
- ...defaultOptions,
2386
- ...encryptConfig
2387
- };
2388
- }
2389
- return defaultOptions;
2390
- }
2391
- async rotateLog() {
2392
- if (isBrowserProcess2())
2393
- return;
2394
- const stats = await stat2(this.currentLogFile).catch(() => null);
2395
- if (!stats)
2396
- return;
2397
- const config22 = this.config.rotation;
2398
- if (typeof config22 === "boolean")
2399
- return;
2400
- if (config22.maxSize && stats.size >= config22.maxSize) {
2401
- const oldFile = this.currentLogFile;
2402
- const newFile = this.generateLogFilename();
2403
- if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
2404
- const files = await readdir2(this.config.logDirectory);
2405
- const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
2406
- const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
2407
- const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
2408
- return numB - numA;
2409
- });
2410
- const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
2411
- const rotatedFile = `${oldFile}.${nextNum}`;
2412
- if (await stat2(oldFile).catch(() => null)) {
2413
- try {
2414
- await rename2(oldFile, rotatedFile);
2415
- if (config22.compress) {
2416
- try {
2417
- const compressedPath = `${rotatedFile}.gz`;
2418
- await this.compressLogFile(rotatedFile, compressedPath);
2419
- await unlink2(rotatedFile);
2420
- } catch (err) {
2421
- console.error("Error compressing rotated file:", err);
2422
- }
2423
- }
2424
- if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
2425
- try {
2426
- const backupPath = `${oldFile}.1`;
2427
- await writeFile2(backupPath, "");
2428
- } catch (err) {
2429
- console.error("Error creating backup file:", err);
2430
- }
2431
- }
2432
- } catch (err) {
2433
- console.error(`Error during rotation: ${err instanceof Error ? err.message : String(err)}`);
2434
- }
2435
- }
2436
- } else {
2437
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
2438
- const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
2439
- if (await stat2(oldFile).catch(() => null)) {
2440
- await rename2(oldFile, rotatedFile);
2441
- }
2442
- }
2443
- this.currentLogFile = newFile;
2444
- if (config22.maxFiles) {
2445
- const files = await readdir2(this.config.logDirectory);
2446
- const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
2447
- for (const file of logFiles.slice(config22.maxFiles)) {
2448
- await unlink2(join22(this.config.logDirectory, file));
2449
- }
2450
- }
2451
- }
2452
- }
2453
- async compressLogFile(inputPath, outputPath) {
2454
- const readStream = createReadStream2(inputPath);
2455
- const writeStream = createWriteStream2(outputPath);
2456
- const gzip = createGzip2();
2457
- await pipeline2(readStream, gzip, writeStream);
2458
- }
2459
- async handleFingersCrossedBuffer(level, formattedEntry) {
2460
- if (!this.fingersCrossedConfig)
2461
- return;
2462
- if (this.shouldActivateFingersCrossed(level) && !this.isActivated) {
2463
- this.isActivated = true;
2464
- for (const entry of this.logBuffer) {
2465
- const formattedBufferedEntry = await this.formatter.format(entry);
2466
- await this.writeToFile(formattedBufferedEntry);
2467
- console.log(formattedBufferedEntry);
2468
- }
2469
- if (this.fingersCrossedConfig.stopBuffering)
2470
- this.logBuffer = [];
2471
- }
2472
- if (this.isActivated) {
2473
- await this.writeToFile(formattedEntry);
2474
- console.log(formattedEntry);
2475
- } else {
2476
- if (this.logBuffer.length >= this.fingersCrossedConfig.bufferSize)
2477
- this.logBuffer.shift();
2478
- const entry = {
2479
- timestamp: new Date,
2480
- level,
2481
- message: formattedEntry,
2482
- name: this.name
2483
- };
2484
- this.logBuffer.push(entry);
2485
- }
2486
- }
2487
- shouldActivateFingersCrossed(level) {
2488
- if (!this.fingersCrossedConfig)
2489
- return false;
2490
- return this.getLevelValue(level) >= this.getLevelValue(this.fingersCrossedConfig.activationLevel);
2491
- }
2492
- getLevelValue(level) {
2493
- const levels = {
2494
- debug: 0,
2495
- info: 1,
2496
- success: 2,
2497
- warning: 3,
2498
- error: 4
2499
- };
2500
- return levels[level];
2501
- }
2502
- shouldLog(level) {
2503
- if (!this.enabled)
2504
- return false;
2505
- const levels = {
2506
- debug: 0,
2507
- info: 1,
2508
- success: 2,
2509
- warning: 3,
2510
- error: 4
2511
- };
2512
- return levels[level] >= levels[this.config.level];
2513
- }
2514
- async flushPendingWrites() {
2515
- await Promise.all(this.pendingOperations.map((op) => {
2516
- if (op instanceof Promise) {
2517
- return op.catch((err) => {
2518
- console.error("Error in pending write operation:", err);
2519
- });
2520
- }
2521
- return Promise.resolve();
2522
- }));
2523
- if (existsSync22(this.currentLogFile)) {
2524
- try {
2525
- const fd = openSync2(this.currentLogFile, "r+");
2526
- fsyncSync2(fd);
2527
- closeSync2(fd);
2528
- } catch (error) {
2529
- console.error(`Error flushing file: ${error}`);
2530
- }
2531
- }
2532
- }
2533
- async destroy() {
2534
- if (this.rotationTimeout)
2535
- clearInterval(this.rotationTimeout);
2536
- if (this.keyRotationTimeout)
2537
- clearInterval(this.keyRotationTimeout);
2538
- this.timers.clear();
2539
- for (const op of this.pendingOperations) {
2540
- if (typeof op.cancel === "function") {
2541
- op.cancel();
2542
- }
2543
- }
2544
- return (async () => {
2545
- if (this.pendingOperations.length > 0) {
2546
- try {
2547
- await Promise.allSettled(this.pendingOperations);
2548
- } catch (err) {
2549
- console.error("Error waiting for pending operations:", err);
2550
- }
2551
- }
2552
- if (!isBrowserProcess2() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
2553
- try {
2554
- const files = await readdir2(this.config.logDirectory);
2555
- const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
2556
- for (const tempFile of tempFiles) {
2557
- try {
2558
- await unlink2(join22(this.config.logDirectory, tempFile));
2559
- } catch (err) {
2560
- console.error(`Failed to delete temp file ${tempFile}:`, err);
2561
- }
2562
- }
2563
- } catch (err) {
2564
- console.error("Error cleaning up temporary files:", err);
2565
- }
2566
- }
2567
- })();
2568
- }
2569
- getCurrentLogFilePath() {
2570
- return this.currentLogFile;
2571
- }
2572
- formatTag(name) {
2573
- if (!name)
2574
- return "";
2575
- return `${this.tagFormat.prefix}${name}${this.tagFormat.suffix}`;
2576
- }
2577
- formatFileTimestamp(date) {
2578
- return `[${date.toISOString()}]`;
2579
- }
2580
- formatConsoleTimestamp(date) {
2581
- return this.fancy ? styles2.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
2582
- }
2583
- formatConsoleMessage(parts) {
2584
- const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
2585
- const stripAnsi = (str) => str.replace(this.ANSI_PATTERN, "");
2586
- if (!this.fancy) {
2587
- const components = [];
2588
- if (showTimestamp)
2589
- components.push(timestamp);
2590
- if (level === "warning")
2591
- components.push("WARN");
2592
- else if (level === "error")
2593
- components.push("ERROR");
2594
- else if (icon)
2595
- components.push(icon.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu, ""));
2596
- if (tag)
2597
- components.push(tag.replace(/[[\]]/g, ""));
2598
- components.push(message);
2599
- return components.join(" ");
2600
- }
2601
- const terminalWidth = process52.stdout.columns || 120;
2602
- let mainPart = "";
2603
- if (level === "warning" || level === "error") {
2604
- mainPart = `${icon} ${message}`;
2605
- } else if (level === "info" || level === "success") {
2606
- mainPart = `${icon} ${tag} ${message}`;
2607
- } else {
2608
- mainPart = `${icon} ${tag} ${styles2.cyan(message)}`;
2609
- }
2610
- if (!showTimestamp) {
2611
- return mainPart.trim();
2612
- }
2613
- const visibleMainPartLength = stripAnsi(mainPart).trim().length;
2614
- const visibleTimestampLength = stripAnsi(timestamp).length;
2615
- const padding = Math.max(1, terminalWidth - 2 - visibleMainPartLength - visibleTimestampLength);
2616
- return `${mainPart.trim()}${" ".repeat(padding)}${timestamp}`;
2617
- }
2618
- formatMessage(message, args) {
2619
- if (args.length === 1 && Array.isArray(args[0])) {
2620
- return message.replace(/\{(\d+)\}/g, (match, index) => {
2621
- const position = Number.parseInt(index, 10);
2622
- return position < args[0].length ? String(args[0][position]) : match;
2623
- });
2624
- }
2625
- const formatRegex = /%([sdijfo%])/g;
2626
- let argIndex = 0;
2627
- let formattedMessage = message.replace(formatRegex, (match, type) => {
2628
- if (type === "%")
2629
- return "%";
2630
- if (argIndex >= args.length)
2631
- return match;
2632
- const arg = args[argIndex++];
2633
- switch (type) {
2634
- case "s":
2635
- return String(arg);
2636
- case "d":
2637
- case "i":
2638
- return Number(arg).toString();
2639
- case "j":
2640
- case "o":
2641
- return JSON.stringify(arg, null, 2);
2642
- default:
2643
- return match;
2644
- }
2645
- });
2646
- if (argIndex < args.length) {
2647
- formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
2648
- }
2649
- return formattedMessage;
2650
- }
2651
- async log(level, message, ...args) {
2652
- const timestamp = new Date;
2653
- const consoleTime = this.formatConsoleTimestamp(timestamp);
2654
- const fileTime = this.formatFileTimestamp(timestamp);
2655
- let formattedMessage;
2656
- let errorStack;
2657
- if (message instanceof Error) {
2658
- formattedMessage = message.message;
2659
- errorStack = message.stack;
2660
- } else {
2661
- formattedMessage = this.formatMessage(message, args);
2662
- }
2663
- if (this.fancy && !isBrowserProcess2()) {
2664
- const icon = levelIcons2[level];
2665
- const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
2666
- let consoleMessage;
2667
- switch (level) {
2668
- case "debug":
2669
- consoleMessage = this.formatConsoleMessage({
2670
- timestamp: consoleTime,
2671
- icon,
2672
- tag,
2673
- message: styles2.gray(formattedMessage),
2674
- level
2675
- });
2676
- console.error(consoleMessage);
2677
- break;
2678
- case "info":
2679
- consoleMessage = this.formatConsoleMessage({
2680
- timestamp: consoleTime,
2681
- icon,
2682
- tag,
2683
- message: formattedMessage,
2684
- level
2685
- });
2686
- console.error(consoleMessage);
2687
- break;
2688
- case "success":
2689
- consoleMessage = this.formatConsoleMessage({
2690
- timestamp: consoleTime,
2691
- icon,
2692
- tag,
2693
- message: styles2.green(formattedMessage),
2694
- level
2695
- });
2696
- console.error(consoleMessage);
2697
- break;
2698
- case "warning":
2699
- consoleMessage = this.formatConsoleMessage({
2700
- timestamp: consoleTime,
2701
- icon,
2702
- tag,
2703
- message: formattedMessage,
2704
- level
2705
- });
2706
- console.warn(consoleMessage);
2707
- break;
2708
- case "error":
2709
- consoleMessage = this.formatConsoleMessage({
2710
- timestamp: consoleTime,
2711
- icon,
2712
- tag,
2713
- message: formattedMessage,
2714
- level
2715
- });
2716
- console.error(consoleMessage);
2717
- if (errorStack) {
2718
- const stackLines = errorStack.split(`
2719
- `);
2720
- for (const line of stackLines) {
2721
- if (line.trim() && !line.includes(formattedMessage)) {
2722
- console.error(this.formatConsoleMessage({
2723
- timestamp: consoleTime,
2724
- message: styles2.gray(` ${line}`),
2725
- level,
2726
- showTimestamp: false
2727
- }));
2728
- }
2729
- }
2730
- }
2731
- break;
2732
- }
2733
- } else if (!isBrowserProcess2()) {
2734
- console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
2735
- if (errorStack) {
2736
- console.error(errorStack);
2737
- }
2738
- }
2739
- if (!this.shouldLog(level))
2740
- return;
2741
- let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}
2742
- `;
2743
- if (errorStack) {
2744
- logEntry += `${errorStack}
2745
- `;
2746
- }
2747
- logEntry = logEntry.replace(this.ANSI_PATTERN, "");
2748
- await this.writeToFile(logEntry);
2749
- }
2750
- time(label) {
2751
- const start = performance.now();
2752
- if (this.fancy && !isBrowserProcess2()) {
2753
- const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
2754
- const consoleTime = this.formatConsoleTimestamp(new Date);
2755
- console.error(this.formatConsoleMessage({
2756
- timestamp: consoleTime,
2757
- icon: styles2.blue("◐"),
2758
- tag,
2759
- message: `${styles2.cyan(label)}...`
2760
- }));
2761
- }
2762
- return async (metadata) => {
2763
- if (!this.enabled)
2764
- return;
2765
- const end = performance.now();
2766
- const elapsed = Math.round(end - start);
2767
- const completionMessage = `${label} completed in ${elapsed}ms`;
2768
- const timestamp = new Date;
2769
- const consoleTime = this.formatConsoleTimestamp(timestamp);
2770
- const fileTime = this.formatFileTimestamp(timestamp);
2771
- let logEntry = `${fileTime} ${this.environment}.INFO: ${completionMessage}`;
2772
- if (metadata) {
2773
- logEntry += ` ${JSON.stringify(metadata)}`;
2774
- }
2775
- logEntry += `
2776
- `;
2777
- logEntry = logEntry.replace(this.ANSI_PATTERN, "");
2778
- if (this.fancy && !isBrowserProcess2()) {
2779
- const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
2780
- console.error(this.formatConsoleMessage({
2781
- timestamp: consoleTime,
2782
- icon: styles2.green("✓"),
2783
- tag,
2784
- message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
2785
- }));
2786
- } else if (!isBrowserProcess2()) {
2787
- console.error(logEntry.trim());
2788
- }
2789
- await this.writeToFile(logEntry);
2790
- };
2791
- }
2792
- async debug(message, ...args) {
2793
- await this.log("debug", message, ...args);
2794
- }
2795
- async info(message, ...args) {
2796
- await this.log("info", message, ...args);
2797
- }
2798
- async success(message, ...args) {
2799
- await this.log("success", message, ...args);
2800
- }
2801
- async warn(message, ...args) {
2802
- await this.log("warning", message, ...args);
2803
- }
2804
- async error(message, ...args) {
2805
- await this.log("error", message, ...args);
2806
- }
2807
- validateEncryptionConfig() {
2808
- if (!this.config.rotation)
2809
- return false;
2810
- if (typeof this.config.rotation === "boolean")
2811
- return false;
2812
- const rotation = this.config.rotation;
2813
- const { encrypt } = rotation;
2814
- return !!encrypt;
2815
- }
2816
- async only(fn) {
2817
- if (!this.enabled)
2818
- return;
2819
- return await fn();
2820
- }
2821
- isEnabled() {
2822
- return this.enabled;
2823
- }
2824
- setEnabled(enabled) {
2825
- this.enabled = enabled;
2826
- }
2827
- extend(namespace) {
2828
- const childName = `${this.name}:${namespace}`;
2829
- const childLogger = new Logger2(childName, {
2830
- ...this.options,
2831
- logDirectory: this.config.logDirectory,
2832
- level: this.config.level,
2833
- format: this.config.format,
2834
- rotation: typeof this.config.rotation === "boolean" ? undefined : this.config.rotation,
2835
- timestamp: typeof this.config.timestamp === "boolean" ? undefined : this.config.timestamp
2836
- });
2837
- this.subLoggers.add(childLogger);
2838
- return childLogger;
2839
- }
2840
- createReadStream() {
2841
- if (isBrowserProcess2())
2842
- throw new Error("createReadStream is not supported in browser environments");
2843
- if (!existsSync22(this.currentLogFile))
2844
- throw new Error(`Log file does not exist: ${this.currentLogFile}`);
2845
- return createReadStream2(this.currentLogFile, { encoding: "utf8" });
2846
- }
2847
- async decrypt(data) {
2848
- if (!this.validateEncryptionConfig())
2849
- throw new Error("Encryption is not configured");
2850
- const encryptionConfig = this.config.rotation;
2851
- if (!encryptionConfig.encrypt || typeof encryptionConfig.encrypt === "boolean")
2852
- throw new Error("Invalid encryption configuration");
2853
- if (!this.currentKeyId || !this.keys.has(this.currentKeyId))
2854
- throw new Error("No valid encryption key available");
2855
- const key = this.keys.get(this.currentKeyId);
2856
- try {
2857
- const encryptedData = Buffer2.isBuffer(data) ? data : Buffer2.from(data, "base64");
2858
- const iv = encryptedData.slice(0, 16);
2859
- const authTag = encryptedData.slice(-16);
2860
- const ciphertext = encryptedData.slice(16, -16);
2861
- const decipher = createDecipheriv2("aes-256-gcm", key, iv);
2862
- decipher.setAuthTag(authTag);
2863
- const decrypted = Buffer2.concat([
2864
- decipher.update(ciphertext),
2865
- decipher.final()
2866
- ]);
2867
- return decrypted.toString("utf8");
2868
- } catch (err) {
2869
- throw new Error(`Decryption failed: ${err instanceof Error ? err.message : String(err)}`);
2870
- }
2871
- }
2872
- getLevel() {
2873
- return this.config.level;
2874
- }
2875
- getLogDirectory() {
2876
- return this.config.logDirectory;
2877
- }
2878
- getFormat() {
2879
- return this.config.format;
2880
- }
2881
- getRotationConfig() {
2882
- return this.config.rotation;
2883
- }
2884
- isBrowserMode() {
2885
- return isBrowserProcess2();
2886
- }
2887
- isServerMode() {
2888
- return !isBrowserProcess2();
2889
- }
2890
- setTestEncryptionKey(keyId, key) {
2891
- this.currentKeyId = keyId;
2892
- this.keys.set(keyId, key);
2893
- }
2894
- getTestCurrentKey() {
2895
- if (!this.currentKeyId || !this.keys.has(this.currentKeyId)) {
2896
- return null;
2897
- }
2898
- return {
2899
- id: this.currentKeyId,
2900
- key: this.keys.get(this.currentKeyId)
2901
- };
2902
- }
2903
- getConfig() {
2904
- return this.config;
2905
- }
2906
- async box(message) {
2907
- if (!this.enabled)
2908
- return;
2909
- const timestamp = new Date;
2910
- const consoleTime = this.formatConsoleTimestamp(timestamp);
2911
- const fileTime = this.formatFileTimestamp(timestamp);
2912
- if (this.fancy && !isBrowserProcess2()) {
2913
- const lines = message.split(`
2914
- `);
2915
- const width = Math.max(...lines.map((line) => line.length)) + 2;
2916
- const top = `┌${"─".repeat(width)}┐`;
2917
- const bottom = `└${"─".repeat(width)}┘`;
2918
- const boxedLines = lines.map((line) => {
2919
- const padding = " ".repeat(width - line.length - 2);
2920
- return `│ ${line}${padding} │`;
2921
- });
2922
- if (this.options.showTags !== false && this.name) {
2923
- console.error(this.formatConsoleMessage({
2924
- timestamp: consoleTime,
2925
- message: styles2.gray(this.formatTag(this.name)),
2926
- showTimestamp: false
2927
- }));
2928
- }
2929
- console.error(this.formatConsoleMessage({
2930
- timestamp: consoleTime,
2931
- message: styles2.cyan(top)
2932
- }));
2933
- boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
2934
- timestamp: consoleTime,
2935
- message: styles2.cyan(line),
2936
- showTimestamp: false
2937
- })));
2938
- console.error(this.formatConsoleMessage({
2939
- timestamp: consoleTime,
2940
- message: styles2.cyan(bottom),
2941
- showTimestamp: false
2942
- }));
2943
- } else if (!isBrowserProcess2()) {
2944
- console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
2945
- }
2946
- const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
2947
- `.replace(this.ANSI_PATTERN, "");
2948
- await this.writeToFile(logEntry);
2949
- }
2950
- async prompt(message) {
2951
- if (isBrowserProcess2()) {
2952
- return Promise.resolve(true);
2953
- }
2954
- return new Promise((resolve322) => {
2955
- console.error(`${styles2.cyan("?")} ${message} (y/n) `);
2956
- const onData = (data) => {
2957
- const input = data.toString().trim().toLowerCase();
2958
- process52.stdin.removeListener("data", onData);
2959
- try {
2960
- if (typeof process52.stdin.setRawMode === "function") {
2961
- process52.stdin.setRawMode(false);
2962
- }
2963
- } catch {}
2964
- process52.stdin.pause();
2965
- console.error("");
2966
- resolve322(input === "y" || input === "yes");
2967
- };
2968
- try {
2969
- if (typeof process52.stdin.setRawMode === "function") {
2970
- process52.stdin.setRawMode(true);
2971
- }
2972
- } catch {}
2973
- process52.stdin.resume();
2974
- process52.stdin.once("data", onData);
2975
- });
2976
- }
2977
- setFancy(enabled) {
2978
- this.fancy = enabled;
2979
- }
2980
- isFancy() {
2981
- return this.fancy;
2982
- }
2983
- pause() {
2984
- this.enabled = false;
2985
- }
2986
- resume() {
2987
- this.enabled = true;
2988
- }
2989
- async start(message, ...args) {
2990
- if (!this.enabled)
2991
- return;
2992
- let formattedMessage = message;
2993
- if (args && args.length > 0) {
2994
- const formatRegex = /%([sdijfo%])/g;
2995
- let argIndex = 0;
2996
- formattedMessage = message.replace(formatRegex, (match, type) => {
2997
- if (type === "%")
2998
- return "%";
2999
- if (argIndex >= args.length)
3000
- return match;
3001
- const arg = args[argIndex++];
3002
- switch (type) {
3003
- case "s":
3004
- return String(arg);
3005
- case "d":
3006
- case "i":
3007
- return Number(arg).toString();
3008
- case "j":
3009
- case "o":
3010
- return JSON.stringify(arg, null, 2);
3011
- default:
3012
- return match;
3013
- }
3014
- });
3015
- if (argIndex < args.length) {
3016
- formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
3017
- }
3018
- }
3019
- if (this.fancy && !isBrowserProcess2()) {
3020
- const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
3021
- const spinnerChar = styles2.blue("◐");
3022
- console.error(`${spinnerChar} ${tag} ${styles2.cyan(formattedMessage)}`);
3023
- }
3024
- const timestamp = new Date;
3025
- const formattedDate = timestamp.toISOString();
3026
- const logEntry = `[${formattedDate}] ${this.environment}.INFO: [START] ${formattedMessage}
3027
- `.replace(this.ANSI_PATTERN, "");
3028
- await this.writeToFile(logEntry);
3029
- }
3030
- progress(total, initialMessage = "") {
3031
- if (!this.enabled || !this.fancy || isBrowserProcess2() || total <= 0) {
3032
- return {
3033
- update: () => {},
3034
- finish: () => {},
3035
- interrupt: () => {}
3036
- };
3037
- }
3038
- if (this.activeProgressBar) {
3039
- console.warn("Warning: Another progress bar is already active. Finishing the previous one.");
3040
- this.finishProgressBar(this.activeProgressBar, "[Auto-finished]");
3041
- }
3042
- const barLength = 20;
3043
- this.activeProgressBar = {
3044
- total,
3045
- current: 0,
3046
- message: initialMessage,
3047
- barLength,
3048
- lastRenderedLine: ""
3049
- };
3050
- this.renderProgressBar(this.activeProgressBar);
3051
- const update = (current, message) => {
3052
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
3053
- return;
3054
- this.activeProgressBar.current = Math.max(0, Math.min(total, current));
3055
- if (message !== undefined) {
3056
- this.activeProgressBar.message = message;
3057
- }
3058
- const isFinished = this.activeProgressBar.current === this.activeProgressBar.total;
3059
- this.renderProgressBar(this.activeProgressBar, isFinished);
3060
- };
3061
- const finish = (message) => {
3062
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
3063
- return;
3064
- this.activeProgressBar.current = this.activeProgressBar.total;
3065
- if (message !== undefined) {
3066
- this.activeProgressBar.message = message;
3067
- }
3068
- this.renderProgressBar(this.activeProgressBar, true);
3069
- this.finishProgressBar(this.activeProgressBar);
3070
- };
3071
- const interrupt = (interruptMessage, level = "info") => {
3072
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
3073
- return;
3074
- process52.stdout.write(`${"\r".padEnd(process52.stdout.columns || 80)}\r`);
3075
- this.log(level, interruptMessage);
3076
- setTimeout(() => {
3077
- if (this.activeProgressBar) {
3078
- this.renderProgressBar(this.activeProgressBar);
3079
- }
3080
- }, 50);
3081
- };
3082
- return { update, finish, interrupt };
3083
- }
3084
- renderProgressBar(barState, isFinished = false) {
3085
- if (!this.enabled || !this.fancy || isBrowserProcess2() || !process52.stdout.isTTY)
3086
- return;
3087
- const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
3088
- const filledLength = Math.round(barState.barLength * percent / 100);
3089
- const emptyLength = barState.barLength - filledLength;
3090
- const filledBar = styles2.green("━".repeat(filledLength));
3091
- const emptyBar = styles2.gray("━".repeat(emptyLength));
3092
- const bar = `[${filledBar}${emptyBar}]`;
3093
- const percentageText = `${percent}%`.padStart(4);
3094
- const messageText = barState.message ? ` ${barState.message}` : "";
3095
- const icon = isFinished || percent === 100 ? styles2.green("✓") : styles2.blue("▶");
3096
- const tag = this.options.showTags !== false && this.name ? ` ${styles2.gray(this.formatTag(this.name))}` : "";
3097
- const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
3098
- const terminalWidth = process52.stdout.columns || 80;
3099
- const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
3100
- barState.lastRenderedLine = `${line}${clearLine}`;
3101
- process52.stdout.write(barState.lastRenderedLine);
3102
- if (isFinished) {
3103
- process52.stdout.write(`
3104
- `);
3105
- }
3106
- }
3107
- finishProgressBar(barState, finalMessage) {
3108
- if (!this.enabled || !this.fancy || isBrowserProcess2() || !process52.stdout.isTTY) {
3109
- this.activeProgressBar = null;
3110
- return;
3111
- }
3112
- if (barState.current < barState.total) {
3113
- barState.current = barState.total;
3114
- }
3115
- if (finalMessage)
3116
- barState.message = finalMessage;
3117
- this.renderProgressBar(barState, true);
3118
- this.activeProgressBar = null;
3119
- }
3120
- async clear(filters = {}) {
3121
- if (isBrowserProcess2()) {
3122
- console.warn("Log clearing is not supported in browser environments.");
3123
- return;
3124
- }
3125
- try {
3126
- console.warn("Clearing logs...", this.config.logDirectory);
3127
- const files = await readdir2(this.config.logDirectory);
3128
- const logFilesToDelete = [];
3129
- for (const file of files) {
3130
- const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
3131
- if (!nameMatches || !file.endsWith(".log")) {
3132
- continue;
3133
- }
3134
- const filePath = join22(this.config.logDirectory, file);
3135
- if (filters.before) {
3136
- try {
3137
- const fileStats = await stat2(filePath);
3138
- if (fileStats.mtime >= filters.before) {
3139
- continue;
3140
- }
3141
- } catch (statErr) {
3142
- console.error(`Failed to get stats for file ${filePath}:`, statErr);
3143
- continue;
3144
- }
3145
- }
3146
- logFilesToDelete.push(filePath);
3147
- }
3148
- if (logFilesToDelete.length === 0) {
3149
- console.warn("No log files matched the criteria for clearing.");
3150
- return;
3151
- }
3152
- console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
3153
- for (const filePath of logFilesToDelete) {
3154
- try {
3155
- await unlink2(filePath);
3156
- console.warn(`Deleted log file: ${filePath}`);
3157
- } catch (unlinkErr) {
3158
- console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
3159
- }
3160
- }
3161
- console.warn("Log clearing process finished.");
3162
- } catch (err) {
3163
- console.error("Error during log clearing process:", err);
3164
- }
3165
- }
3166
- }
3167
- var logger2 = new Logger2("stacks");
3168
- function deepMerge22(target, source) {
3169
- if (Array.isArray(source) && Array.isArray(target) && source.length === 2 && target.length === 2 && isObject22(source[0]) && "id" in source[0] && source[0].id === 3 && isObject22(source[1]) && "id" in source[1] && source[1].id === 4) {
217
+ },
218
+ "commit-msg": "bunx gitlint .git/COMMIT_EDITMSG",
219
+ verbose: true
220
+ };
221
+ var git_hooks_config_default = config;
222
+
223
+ // src/config.ts
224
+ var config2 = await loadConfig({
225
+ name: "git-hooks",
226
+ cwd: process2.cwd(),
227
+ defaultConfig: git_hooks_config_default
228
+ });
229
+ // src/git-hooks.ts
230
+ import fs from "node:fs";
231
+ import path from "node:path";
232
+ import process6 from "node:process";
233
+ import { exec } from "node:child_process";
234
+ import { promisify } from "node:util";
235
+
236
+ // node_modules/@stacksjs/clarity/dist/index.js
237
+ import { join, relative, resolve as resolve2 } from "path";
238
+ import process22 from "process";
239
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
240
+ import { dirname as dirname2, resolve as resolve3 } from "path";
241
+ import process3 from "process";
242
+ import { Buffer } from "buffer";
243
+ import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
244
+ import { closeSync, createReadStream, createWriteStream, existsSync as existsSync22, fsyncSync, openSync, writeFileSync as writeFileSync22 } from "fs";
245
+ import { access, constants, mkdir, readdir, rename, stat, unlink, writeFile } from "fs/promises";
246
+ import { join as join2 } from "path";
247
+ import process5 from "process";
248
+ import { pipeline } from "stream/promises";
249
+ import { createGzip } from "zlib";
250
+ import process4 from "process";
251
+ import process32 from "process";
252
+ function deepMerge2(target, source) {
253
+ 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) {
3170
254
  return source;
3171
255
  }
3172
- if (isObject22(source) && isObject22(target) && Object.keys(source).length === 2 && Object.keys(source).includes("a") && source.a === null && Object.keys(source).includes("c") && source.c === undefined) {
256
+ 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) {
3173
257
  return { a: null, b: 2, c: undefined };
3174
258
  }
3175
259
  if (source === null || source === undefined) {
@@ -3179,23 +263,23 @@ function deepMerge22(target, source) {
3179
263
  return source;
3180
264
  }
3181
265
  if (Array.isArray(source) && Array.isArray(target)) {
3182
- if (isObject22(target) && "arr" in target && Array.isArray(target.arr) && isObject22(source) && "arr" in source && Array.isArray(source.arr)) {
266
+ if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
3183
267
  return source;
3184
268
  }
3185
- if (source.length > 0 && target.length > 0 && isObject22(source[0]) && isObject22(target[0])) {
269
+ if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
3186
270
  const result = [...source];
3187
271
  for (const targetItem of target) {
3188
- if (isObject22(targetItem) && "name" in targetItem) {
3189
- const existingItem = result.find((item) => isObject22(item) && ("name" in item) && item.name === targetItem.name);
272
+ if (isObject2(targetItem) && "name" in targetItem) {
273
+ const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
3190
274
  if (!existingItem) {
3191
275
  result.push(targetItem);
3192
276
  }
3193
- } else if (isObject22(targetItem) && "path" in targetItem) {
3194
- const existingItem = result.find((item) => isObject22(item) && ("path" in item) && item.path === targetItem.path);
277
+ } else if (isObject2(targetItem) && "path" in targetItem) {
278
+ const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
3195
279
  if (!existingItem) {
3196
280
  result.push(targetItem);
3197
281
  }
3198
- } else if (!result.some((item) => deepEquals22(item, targetItem))) {
282
+ } else if (!result.some((item) => deepEquals2(item, targetItem))) {
3199
283
  result.push(targetItem);
3200
284
  }
3201
285
  }
@@ -3212,7 +296,7 @@ function deepMerge22(target, source) {
3212
296
  }
3213
297
  return source;
3214
298
  }
3215
- if (!isObject22(source) || !isObject22(target)) {
299
+ if (!isObject2(source) || !isObject2(target)) {
3216
300
  return source;
3217
301
  }
3218
302
  const merged = { ...target };
@@ -3221,23 +305,23 @@ function deepMerge22(target, source) {
3221
305
  const sourceValue = source[key];
3222
306
  if (sourceValue === null || sourceValue === undefined) {
3223
307
  continue;
3224
- } else if (isObject22(sourceValue) && isObject22(merged[key])) {
3225
- merged[key] = deepMerge22(merged[key], sourceValue);
308
+ } else if (isObject2(sourceValue) && isObject2(merged[key])) {
309
+ merged[key] = deepMerge2(merged[key], sourceValue);
3226
310
  } else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
3227
- if (sourceValue.length > 0 && merged[key].length > 0 && isObject22(sourceValue[0]) && isObject22(merged[key][0])) {
311
+ if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
3228
312
  const result = [...sourceValue];
3229
313
  for (const targetItem of merged[key]) {
3230
- if (isObject22(targetItem) && "name" in targetItem) {
3231
- const existingItem = result.find((item) => isObject22(item) && ("name" in item) && item.name === targetItem.name);
314
+ if (isObject2(targetItem) && "name" in targetItem) {
315
+ const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
3232
316
  if (!existingItem) {
3233
317
  result.push(targetItem);
3234
318
  }
3235
- } else if (isObject22(targetItem) && "path" in targetItem) {
3236
- const existingItem = result.find((item) => isObject22(item) && ("path" in item) && item.path === targetItem.path);
319
+ } else if (isObject2(targetItem) && "path" in targetItem) {
320
+ const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
3237
321
  if (!existingItem) {
3238
322
  result.push(targetItem);
3239
323
  }
3240
- } else if (!result.some((item) => deepEquals22(item, targetItem))) {
324
+ } else if (!result.some((item) => deepEquals2(item, targetItem))) {
3241
325
  result.push(targetItem);
3242
326
  }
3243
327
  }
@@ -3260,19 +344,19 @@ function deepMerge22(target, source) {
3260
344
  }
3261
345
  return merged;
3262
346
  }
3263
- function deepEquals22(a, b) {
347
+ function deepEquals2(a, b) {
3264
348
  if (a === b)
3265
349
  return true;
3266
350
  if (Array.isArray(a) && Array.isArray(b)) {
3267
351
  if (a.length !== b.length)
3268
352
  return false;
3269
353
  for (let i = 0;i < a.length; i++) {
3270
- if (!deepEquals22(a[i], b[i]))
354
+ if (!deepEquals2(a[i], b[i]))
3271
355
  return false;
3272
356
  }
3273
357
  return true;
3274
358
  }
3275
- if (isObject22(a) && isObject22(b)) {
359
+ if (isObject2(a) && isObject2(b)) {
3276
360
  const keysA = Object.keys(a);
3277
361
  const keysB = Object.keys(b);
3278
362
  if (keysA.length !== keysB.length)
@@ -3280,21 +364,18 @@ function deepEquals22(a, b) {
3280
364
  for (const key of keysA) {
3281
365
  if (!Object.prototype.hasOwnProperty.call(b, key))
3282
366
  return false;
3283
- if (!deepEquals22(a[key], b[key]))
367
+ if (!deepEquals2(a[key], b[key]))
3284
368
  return false;
3285
369
  }
3286
370
  return true;
3287
371
  }
3288
372
  return false;
3289
373
  }
3290
- function isObject22(item) {
374
+ function isObject2(item) {
3291
375
  return Boolean(item && typeof item === "object" && !Array.isArray(item));
3292
376
  }
3293
- var log2 = new Logger2("bunfig", {
3294
- showTags: true
3295
- });
3296
- async function tryLoadConfig22(configPath, defaultConfig22) {
3297
- if (!existsSync32(configPath))
377
+ async function tryLoadConfig2(configPath, defaultConfig) {
378
+ if (!existsSync2(configPath))
3298
379
  return null;
3299
380
  try {
3300
381
  const importedConfig = await import(configPath);
@@ -3302,7 +383,7 @@ async function tryLoadConfig22(configPath, defaultConfig22) {
3302
383
  if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
3303
384
  return null;
3304
385
  try {
3305
- return deepMerge22(defaultConfig22, loadedConfig);
386
+ return deepMerge2(defaultConfig, loadedConfig);
3306
387
  } catch {
3307
388
  return null;
3308
389
  }
@@ -3310,12 +391,12 @@ async function tryLoadConfig22(configPath, defaultConfig22) {
3310
391
  return null;
3311
392
  }
3312
393
  }
3313
- async function loadConfig32({
394
+ async function loadConfig2({
3314
395
  name = "",
3315
396
  cwd,
3316
- defaultConfig: defaultConfig22
397
+ defaultConfig
3317
398
  }) {
3318
- const baseDir = cwd || process62.cwd();
399
+ const baseDir = cwd || process3.cwd();
3319
400
  const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
3320
401
  const configPaths = [
3321
402
  `${name}.config`,
@@ -3325,43 +406,40 @@ async function loadConfig32({
3325
406
  ];
3326
407
  for (const configPath of configPaths) {
3327
408
  for (const ext of extensions) {
3328
- const fullPath = resolve32(baseDir, `${configPath}${ext}`);
3329
- const config32 = await tryLoadConfig22(fullPath, defaultConfig22);
3330
- if (config32 !== null) {
3331
- log2.debug(`Configuration found: ${configPath}${ext}`);
3332
- return config32;
409
+ const fullPath = resolve3(baseDir, `${configPath}${ext}`);
410
+ const config22 = await tryLoadConfig2(fullPath, defaultConfig);
411
+ if (config22 !== null) {
412
+ return config22;
3333
413
  }
3334
414
  }
3335
415
  }
3336
416
  try {
3337
- const pkgPath = resolve32(baseDir, "package.json");
3338
- if (existsSync32(pkgPath)) {
417
+ const pkgPath = resolve3(baseDir, "package.json");
418
+ if (existsSync2(pkgPath)) {
3339
419
  const pkg = await import(pkgPath);
3340
420
  const pkgConfig = pkg[name];
3341
421
  if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
3342
422
  try {
3343
- log2.debug(`Configuration found in package.json!`);
3344
- return deepMerge22(defaultConfig22, pkgConfig);
423
+ return deepMerge2(defaultConfig, pkgConfig);
3345
424
  } catch {}
3346
425
  }
3347
426
  }
3348
427
  } catch {}
3349
- log2.debug("No configuration found, now using default config");
3350
- return defaultConfig22;
428
+ return defaultConfig;
3351
429
  }
3352
- var defaultConfigDir22 = resolve32(process62.cwd(), "config");
3353
- var defaultGeneratedDir22 = resolve32(process62.cwd(), "src/generated");
3354
- function getProjectRoot22(filePath, options = {}) {
3355
- let path = process72.cwd();
430
+ var defaultConfigDir2 = resolve3(process3.cwd(), "config");
431
+ var defaultGeneratedDir2 = resolve3(process3.cwd(), "src/generated");
432
+ function getProjectRoot(filePath, options = {}) {
433
+ let path = process22.cwd();
3356
434
  while (path.includes("storage"))
3357
- path = resolve4(path, "..");
3358
- const finalPath = resolve4(path, filePath || "");
435
+ path = resolve2(path, "..");
436
+ const finalPath = resolve2(path, filePath || "");
3359
437
  if (options?.relative)
3360
- return relative2(process72.cwd(), finalPath);
438
+ return relative(process22.cwd(), finalPath);
3361
439
  return finalPath;
3362
440
  }
3363
- var defaultLogDirectory22 = process72.env.CLARITY_LOG_DIR || join3(getProjectRoot22(), "logs");
3364
- var defaultConfig22 = {
441
+ var defaultLogDirectory = process22.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
442
+ var defaultConfig = {
3365
443
  level: "info",
3366
444
  defaultName: "clarity",
3367
445
  timestamp: true,
@@ -3369,7 +447,7 @@ var defaultConfig22 = {
3369
447
  format: "text",
3370
448
  maxLogSize: 10485760,
3371
449
  logDatePattern: "YYYY-MM-DD",
3372
- logDirectory: defaultLogDirectory22,
450
+ logDirectory: defaultLogDirectory,
3373
451
  rotation: {
3374
452
  frequency: "daily",
3375
453
  maxSize: 10485760,
@@ -3383,46 +461,46 @@ var defaultConfig22 = {
3383
461
  },
3384
462
  verbose: false
3385
463
  };
3386
- async function loadConfig42() {
464
+ async function loadConfig22() {
3387
465
  try {
3388
- const loadedConfig = await loadConfig32({
466
+ const loadedConfig = await loadConfig2({
3389
467
  name: "clarity",
3390
- defaultConfig: defaultConfig22,
3391
- cwd: process72.cwd(),
468
+ defaultConfig,
469
+ cwd: process22.cwd(),
3392
470
  endpoint: "",
3393
471
  headers: {}
3394
472
  });
3395
- return { ...defaultConfig22, ...loadedConfig };
473
+ return { ...defaultConfig, ...loadedConfig };
3396
474
  } catch {
3397
- return defaultConfig22;
475
+ return defaultConfig;
3398
476
  }
3399
477
  }
3400
- var config22 = await loadConfig42();
3401
- function isBrowserProcess22() {
3402
- if (process92.env.NODE_ENV === "test" || process92.env.BUN_ENV === "test") {
478
+ var config3 = await loadConfig22();
479
+ function isBrowserProcess() {
480
+ if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
3403
481
  return false;
3404
482
  }
3405
483
  return typeof window !== "undefined";
3406
484
  }
3407
- async function isServerProcess22() {
3408
- if (process92.env.NODE_ENV === "test" || process92.env.BUN_ENV === "test") {
485
+ async function isServerProcess() {
486
+ if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
3409
487
  return true;
3410
488
  }
3411
489
  if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
3412
490
  return true;
3413
491
  }
3414
- if (typeof process92 !== "undefined") {
3415
- const type = process92.type;
492
+ if (typeof process32 !== "undefined") {
493
+ const type = process32.type;
3416
494
  if (type === "renderer" || type === "worker") {
3417
495
  return false;
3418
496
  }
3419
- return !!(process92.versions && (process92.versions.node || process92.versions.bun));
497
+ return !!(process32.versions && (process32.versions.node || process32.versions.bun));
3420
498
  }
3421
499
  return false;
3422
500
  }
3423
- class JsonFormatter22 {
501
+ class JsonFormatter {
3424
502
  async format(entry) {
3425
- const isServer = await isServerProcess22();
503
+ const isServer = await isServerProcess();
3426
504
  const metadata = await this.getMetadata(isServer);
3427
505
  return JSON.stringify({
3428
506
  timestamp: entry.timestamp.toISOString(),
@@ -3436,17 +514,17 @@ class JsonFormatter22 {
3436
514
  if (isServer) {
3437
515
  const { hostname } = await import("os");
3438
516
  return {
3439
- pid: process10.pid,
517
+ pid: process4.pid,
3440
518
  hostname: hostname(),
3441
- environment: process10.env.NODE_ENV || "development",
3442
- platform: process10.platform,
3443
- version: process10.version
519
+ environment: process4.env.NODE_ENV || "development",
520
+ platform: process4.platform,
521
+ version: process4.version
3444
522
  };
3445
523
  }
3446
524
  return {
3447
525
  userAgent: navigator.userAgent,
3448
526
  hostname: window.location.hostname || "browser",
3449
- environment: process10.env.NODE_ENV || process10.env.BUN_ENV || "development",
527
+ environment: process4.env.NODE_ENV || process4.env.BUN_ENV || "development",
3450
528
  viewport: {
3451
529
  width: window.innerWidth,
3452
530
  height: window.innerHeight
@@ -3455,7 +533,7 @@ class JsonFormatter22 {
3455
533
  };
3456
534
  }
3457
535
  }
3458
- var terminalStyles22 = {
536
+ var terminalStyles = {
3459
537
  red: (text) => `\x1B[31m${text}\x1B[0m`,
3460
538
  green: (text) => `\x1B[32m${text}\x1B[0m`,
3461
539
  yellow: (text) => `\x1B[33m${text}\x1B[0m`,
@@ -3472,37 +550,37 @@ var terminalStyles22 = {
3472
550
  underline: (text) => `\x1B[4m${text}\x1B[0m`,
3473
551
  reset: "\x1B[0m"
3474
552
  };
3475
- var styles22 = terminalStyles22;
3476
- var red22 = terminalStyles22.red;
3477
- var green22 = terminalStyles22.green;
3478
- var yellow22 = terminalStyles22.yellow;
3479
- var blue22 = terminalStyles22.blue;
3480
- var magenta22 = terminalStyles22.magenta;
3481
- var cyan22 = terminalStyles22.cyan;
3482
- var white22 = terminalStyles22.white;
3483
- var gray22 = terminalStyles22.gray;
3484
- var bgRed22 = terminalStyles22.bgRed;
3485
- var bgYellow22 = terminalStyles22.bgYellow;
3486
- var bold22 = terminalStyles22.bold;
3487
- var dim22 = terminalStyles22.dim;
3488
- var italic22 = terminalStyles22.italic;
3489
- var underline22 = terminalStyles22.underline;
3490
- var reset22 = terminalStyles22.reset;
3491
- var defaultFingersCrossedConfig22 = {
553
+ var styles = terminalStyles;
554
+ var red = terminalStyles.red;
555
+ var green = terminalStyles.green;
556
+ var yellow = terminalStyles.yellow;
557
+ var blue = terminalStyles.blue;
558
+ var magenta = terminalStyles.magenta;
559
+ var cyan = terminalStyles.cyan;
560
+ var white = terminalStyles.white;
561
+ var gray = terminalStyles.gray;
562
+ var bgRed = terminalStyles.bgRed;
563
+ var bgYellow = terminalStyles.bgYellow;
564
+ var bold = terminalStyles.bold;
565
+ var dim = terminalStyles.dim;
566
+ var italic = terminalStyles.italic;
567
+ var underline = terminalStyles.underline;
568
+ var reset = terminalStyles.reset;
569
+ var defaultFingersCrossedConfig = {
3492
570
  activationLevel: "error",
3493
571
  bufferSize: 50,
3494
572
  flushOnDeactivation: true,
3495
573
  stopBuffering: false
3496
574
  };
3497
- var levelIcons22 = {
575
+ var levelIcons = {
3498
576
  debug: "\uD83D\uDD0D",
3499
- info: blue22("ℹ"),
3500
- success: green22("✓"),
3501
- warning: bgYellow22(white22(bold22(" WARN "))),
3502
- error: bgRed22(white22(bold22(" ERROR ")))
577
+ info: blue("ℹ"),
578
+ success: green("✓"),
579
+ warning: bgYellow(white(bold(" WARN "))),
580
+ error: bgRed(white(bold(" ERROR ")))
3503
581
  };
3504
582
 
3505
- class Logger22 {
583
+ class Logger {
3506
584
  name;
3507
585
  fileLocks = new Map;
3508
586
  currentKeyId = null;
@@ -3531,14 +609,14 @@ class Logger22 {
3531
609
  activeProgressBar = null;
3532
610
  constructor(name, options = {}) {
3533
611
  this.name = name;
3534
- this.config = { ...config22 };
612
+ this.config = { ...config3 };
3535
613
  this.options = this.normalizeOptions(options);
3536
- this.formatter = this.options.formatter || new JsonFormatter22;
614
+ this.formatter = this.options.formatter || new JsonFormatter;
3537
615
  this.enabled = options.enabled ?? true;
3538
616
  this.fancy = options.fancy ?? true;
3539
617
  this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
3540
618
  this.timestampPosition = options.timestampPosition ?? "right";
3541
- this.environment = options.environment ?? process11.env.APP_ENV ?? "local";
619
+ this.environment = options.environment ?? process5.env.APP_ENV ?? "local";
3542
620
  this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
3543
621
  const configOptions = { ...options };
3544
622
  const hasTimestamp = options.timestamp !== undefined;
@@ -3550,12 +628,6 @@ class Logger22 {
3550
628
  ...configOptions,
3551
629
  timestamp: hasTimestamp || this.config.timestamp
3552
630
  };
3553
- if (!this.config.logDirectory) {
3554
- this.config.logDirectory = config22.logDirectory;
3555
- }
3556
- if (!isBrowserProcess22()) {
3557
- mkdir22(this.config.logDirectory, { recursive: true, mode: 493 }).catch((err) => console.error("Failed to create log directory:", err));
3558
- }
3559
631
  this.currentLogFile = this.generateLogFilename();
3560
632
  this.encryptionKeys = new Map;
3561
633
  if (this.validateEncryptionConfig()) {
@@ -3574,7 +646,7 @@ class Logger22 {
3574
646
  initializeFingersCrossedConfig(options) {
3575
647
  if (!options.fingersCrossedEnabled && options.fingersCrossed) {
3576
648
  return {
3577
- ...defaultFingersCrossedConfig22,
649
+ ...defaultFingersCrossedConfig,
3578
650
  ...options.fingersCrossed
3579
651
  };
3580
652
  }
@@ -3582,10 +654,10 @@ class Logger22 {
3582
654
  return null;
3583
655
  }
3584
656
  if (!options.fingersCrossed) {
3585
- return { ...defaultFingersCrossedConfig22 };
657
+ return { ...defaultFingersCrossedConfig };
3586
658
  }
3587
659
  return {
3588
- ...defaultFingersCrossedConfig22,
660
+ ...defaultFingersCrossedConfig,
3589
661
  ...options.fingersCrossed
3590
662
  };
3591
663
  }
@@ -3593,7 +665,7 @@ class Logger22 {
3593
665
  const defaultOptions = {
3594
666
  format: "json",
3595
667
  level: "info",
3596
- logDirectory: config22.logDirectory,
668
+ logDirectory: config3.logDirectory,
3597
669
  rotation: undefined,
3598
670
  timestamp: undefined,
3599
671
  fingersCrossed: {},
@@ -3621,11 +693,11 @@ class Logger22 {
3621
693
  try {
3622
694
  try {
3623
695
  try {
3624
- await access22(this.config.logDirectory, constants22.F_OK | constants22.W_OK);
696
+ await access(this.config.logDirectory, constants.F_OK | constants.W_OK);
3625
697
  } catch (err) {
3626
698
  if (err instanceof Error && "code" in err) {
3627
699
  if (err.code === "ENOENT") {
3628
- await mkdir22(this.config.logDirectory, { recursive: true, mode: 493 });
700
+ await mkdir(this.config.logDirectory, { recursive: true, mode: 493 });
3629
701
  } else if (err.code === "EACCES") {
3630
702
  throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
3631
703
  } else {
@@ -3641,22 +713,22 @@ class Logger22 {
3641
713
  }
3642
714
  if (cancelled)
3643
715
  throw new Error("Operation cancelled: Logger was destroyed");
3644
- const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer22.from(data);
716
+ const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
3645
717
  try {
3646
- if (!existsSync42(this.currentLogFile)) {
3647
- await writeFile22(this.currentLogFile, "", { mode: 420 });
718
+ if (!existsSync22(this.currentLogFile)) {
719
+ await writeFile(this.currentLogFile, "", { mode: 420 });
3648
720
  }
3649
- fd = openSync22(this.currentLogFile, "a", 420);
3650
- writeFileSync42(fd, dataToWrite, { flag: "a" });
3651
- fsyncSync22(fd);
721
+ fd = openSync(this.currentLogFile, "a", 420);
722
+ writeFileSync22(fd, dataToWrite, { flag: "a" });
723
+ fsyncSync(fd);
3652
724
  if (fd !== undefined) {
3653
- closeSync22(fd);
725
+ closeSync(fd);
3654
726
  fd = undefined;
3655
727
  }
3656
- const stats = await stat22(this.currentLogFile);
728
+ const stats = await stat(this.currentLogFile);
3657
729
  if (stats.size === 0) {
3658
- await writeFile22(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
3659
- const retryStats = await stat22(this.currentLogFile);
730
+ await writeFile(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
731
+ const retryStats = await stat(this.currentLogFile);
3660
732
  if (retryStats.size === 0) {
3661
733
  throw new Error("File exists but is empty after retry write");
3662
734
  }
@@ -3669,7 +741,7 @@ class Logger22 {
3669
741
  const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
3670
742
  console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
3671
743
  const delay = backoffDelay * 2 ** retries;
3672
- await new Promise((resolve52) => setTimeout(resolve52, delay));
744
+ await new Promise((resolve32) => setTimeout(resolve32, delay));
3673
745
  retries++;
3674
746
  continue;
3675
747
  }
@@ -3682,7 +754,7 @@ class Logger22 {
3682
754
  } finally {
3683
755
  if (fd !== undefined) {
3684
756
  try {
3685
- closeSync22(fd);
757
+ closeSync(fd);
3686
758
  } catch (err) {
3687
759
  console.error("Debug: [writeToFile] Error closing file descriptor:", err);
3688
760
  }
@@ -3697,7 +769,7 @@ class Logger22 {
3697
769
  }
3698
770
  retries++;
3699
771
  const delay = backoffDelay * 2 ** (retries - 1);
3700
- await new Promise((resolve52) => setTimeout(resolve52, delay));
772
+ await new Promise((resolve32) => setTimeout(resolve32, delay));
3701
773
  }
3702
774
  }
3703
775
  })();
@@ -3714,22 +786,22 @@ class Logger22 {
3714
786
  }
3715
787
  generateLogFilename() {
3716
788
  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")) {
3717
- return join5(this.config.logDirectory, `${this.name}.log`);
789
+ return join2(this.config.logDirectory, `${this.name}.log`);
3718
790
  }
3719
791
  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") {
3720
- return join5(this.config.logDirectory, `${this.name}.log`);
792
+ return join2(this.config.logDirectory, `${this.name}.log`);
3721
793
  }
3722
794
  const date = new Date().toISOString().split("T")[0];
3723
- return join5(this.config.logDirectory, `${this.name}-${date}.log`);
795
+ return join2(this.config.logDirectory, `${this.name}-${date}.log`);
3724
796
  }
3725
797
  setupRotation() {
3726
- if (isBrowserProcess22())
798
+ if (isBrowserProcess())
3727
799
  return;
3728
800
  if (typeof this.config.rotation === "boolean")
3729
801
  return;
3730
- const config32 = this.config.rotation;
802
+ const config22 = this.config.rotation;
3731
803
  let interval;
3732
- switch (config32.frequency) {
804
+ switch (config22.frequency) {
3733
805
  case "daily":
3734
806
  interval = 86400000;
3735
807
  break;
@@ -3790,10 +862,10 @@ class Logger22 {
3790
862
  }
3791
863
  }
3792
864
  generateKeyId() {
3793
- return randomBytes22(16).toString("hex");
865
+ return randomBytes(16).toString("hex");
3794
866
  }
3795
867
  generateKey() {
3796
- return randomBytes22(32);
868
+ return randomBytes(32);
3797
869
  }
3798
870
  getCurrentKey() {
3799
871
  if (!this.currentKeyId) {
@@ -3807,24 +879,24 @@ class Logger22 {
3807
879
  }
3808
880
  encrypt(data) {
3809
881
  const { key } = this.getCurrentKey();
3810
- const iv = randomBytes22(16);
3811
- const cipher = createCipheriv22("aes-256-gcm", key, iv);
3812
- const encrypted = Buffer22.concat([
882
+ const iv = randomBytes(16);
883
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
884
+ const encrypted = Buffer.concat([
3813
885
  cipher.update(data, "utf8"),
3814
886
  cipher.final()
3815
887
  ]);
3816
888
  const authTag = cipher.getAuthTag();
3817
889
  return {
3818
- encrypted: Buffer22.concat([iv, encrypted, authTag]),
890
+ encrypted: Buffer.concat([iv, encrypted, authTag]),
3819
891
  iv
3820
892
  };
3821
893
  }
3822
894
  async compressData(data) {
3823
- return new Promise((resolve52, reject) => {
3824
- const gzip = createGzip22();
895
+ return new Promise((resolve32, reject) => {
896
+ const gzip = createGzip();
3825
897
  const chunks = [];
3826
898
  gzip.on("data", (chunk2) => chunks.push(chunk2));
3827
- gzip.on("end", () => resolve52(Buffer22.from(Buffer22.concat(chunks))));
899
+ gzip.on("end", () => resolve32(Buffer.from(Buffer.concat(chunks))));
3828
900
  gzip.on("error", reject);
3829
901
  gzip.write(data);
3830
902
  gzip.end();
@@ -3848,19 +920,19 @@ class Logger22 {
3848
920
  return defaultOptions;
3849
921
  }
3850
922
  async rotateLog() {
3851
- if (isBrowserProcess22())
923
+ if (isBrowserProcess())
3852
924
  return;
3853
- const stats = await stat22(this.currentLogFile).catch(() => null);
925
+ const stats = await stat(this.currentLogFile).catch(() => null);
3854
926
  if (!stats)
3855
927
  return;
3856
- const config32 = this.config.rotation;
3857
- if (typeof config32 === "boolean")
928
+ const config22 = this.config.rotation;
929
+ if (typeof config22 === "boolean")
3858
930
  return;
3859
- if (config32.maxSize && stats.size >= config32.maxSize) {
931
+ if (config22.maxSize && stats.size >= config22.maxSize) {
3860
932
  const oldFile = this.currentLogFile;
3861
933
  const newFile = this.generateLogFilename();
3862
934
  if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
3863
- const files = await readdir22(this.config.logDirectory);
935
+ const files = await readdir(this.config.logDirectory);
3864
936
  const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
3865
937
  const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
3866
938
  const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
@@ -3868,14 +940,14 @@ class Logger22 {
3868
940
  });
3869
941
  const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
3870
942
  const rotatedFile = `${oldFile}.${nextNum}`;
3871
- if (await stat22(oldFile).catch(() => null)) {
943
+ if (await stat(oldFile).catch(() => null)) {
3872
944
  try {
3873
- await rename22(oldFile, rotatedFile);
3874
- if (config32.compress) {
945
+ await rename(oldFile, rotatedFile);
946
+ if (config22.compress) {
3875
947
  try {
3876
948
  const compressedPath = `${rotatedFile}.gz`;
3877
949
  await this.compressLogFile(rotatedFile, compressedPath);
3878
- await unlink22(rotatedFile);
950
+ await unlink(rotatedFile);
3879
951
  } catch (err) {
3880
952
  console.error("Error compressing rotated file:", err);
3881
953
  }
@@ -3883,7 +955,7 @@ class Logger22 {
3883
955
  if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
3884
956
  try {
3885
957
  const backupPath = `${oldFile}.1`;
3886
- await writeFile22(backupPath, "");
958
+ await writeFile(backupPath, "");
3887
959
  } catch (err) {
3888
960
  console.error("Error creating backup file:", err);
3889
961
  }
@@ -3895,25 +967,25 @@ class Logger22 {
3895
967
  } else {
3896
968
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
3897
969
  const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
3898
- if (await stat22(oldFile).catch(() => null)) {
3899
- await rename22(oldFile, rotatedFile);
970
+ if (await stat(oldFile).catch(() => null)) {
971
+ await rename(oldFile, rotatedFile);
3900
972
  }
3901
973
  }
3902
974
  this.currentLogFile = newFile;
3903
- if (config32.maxFiles) {
3904
- const files = await readdir22(this.config.logDirectory);
975
+ if (config22.maxFiles) {
976
+ const files = await readdir(this.config.logDirectory);
3905
977
  const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
3906
- for (const file of logFiles.slice(config32.maxFiles)) {
3907
- await unlink22(join5(this.config.logDirectory, file));
978
+ for (const file of logFiles.slice(config22.maxFiles)) {
979
+ await unlink(join2(this.config.logDirectory, file));
3908
980
  }
3909
981
  }
3910
982
  }
3911
983
  }
3912
984
  async compressLogFile(inputPath, outputPath) {
3913
- const readStream = createReadStream22(inputPath);
3914
- const writeStream = createWriteStream22(outputPath);
3915
- const gzip = createGzip22();
3916
- await pipeline22(readStream, gzip, writeStream);
985
+ const readStream = createReadStream(inputPath);
986
+ const writeStream = createWriteStream(outputPath);
987
+ const gzip = createGzip();
988
+ await pipeline(readStream, gzip, writeStream);
3917
989
  }
3918
990
  async handleFingersCrossedBuffer(level, formattedEntry) {
3919
991
  if (!this.fingersCrossedConfig)
@@ -3979,11 +1051,11 @@ class Logger22 {
3979
1051
  }
3980
1052
  return Promise.resolve();
3981
1053
  }));
3982
- if (existsSync42(this.currentLogFile)) {
1054
+ if (existsSync22(this.currentLogFile)) {
3983
1055
  try {
3984
- const fd = openSync22(this.currentLogFile, "r+");
3985
- fsyncSync22(fd);
3986
- closeSync22(fd);
1056
+ const fd = openSync(this.currentLogFile, "r+");
1057
+ fsyncSync(fd);
1058
+ closeSync(fd);
3987
1059
  } catch (error) {
3988
1060
  console.error(`Error flushing file: ${error}`);
3989
1061
  }
@@ -4008,13 +1080,13 @@ class Logger22 {
4008
1080
  console.error("Error waiting for pending operations:", err);
4009
1081
  }
4010
1082
  }
4011
- if (!isBrowserProcess22() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
1083
+ if (!isBrowserProcess() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
4012
1084
  try {
4013
- const files = await readdir22(this.config.logDirectory);
1085
+ const files = await readdir(this.config.logDirectory);
4014
1086
  const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
4015
1087
  for (const tempFile of tempFiles) {
4016
1088
  try {
4017
- await unlink22(join5(this.config.logDirectory, tempFile));
1089
+ await unlink(join2(this.config.logDirectory, tempFile));
4018
1090
  } catch (err) {
4019
1091
  console.error(`Failed to delete temp file ${tempFile}:`, err);
4020
1092
  }
@@ -4037,7 +1109,7 @@ class Logger22 {
4037
1109
  return `[${date.toISOString()}]`;
4038
1110
  }
4039
1111
  formatConsoleTimestamp(date) {
4040
- return this.fancy ? styles22.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
1112
+ return this.fancy ? styles.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
4041
1113
  }
4042
1114
  formatConsoleMessage(parts) {
4043
1115
  const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
@@ -4057,14 +1129,14 @@ class Logger22 {
4057
1129
  components.push(message);
4058
1130
  return components.join(" ");
4059
1131
  }
4060
- const terminalWidth = process11.stdout.columns || 120;
1132
+ const terminalWidth = process5.stdout.columns || 120;
4061
1133
  let mainPart = "";
4062
1134
  if (level === "warning" || level === "error") {
4063
1135
  mainPart = `${icon} ${message}`;
4064
1136
  } else if (level === "info" || level === "success") {
4065
1137
  mainPart = `${icon} ${tag} ${message}`;
4066
1138
  } else {
4067
- mainPart = `${icon} ${tag} ${styles22.cyan(message)}`;
1139
+ mainPart = `${icon} ${tag} ${styles.cyan(message)}`;
4068
1140
  }
4069
1141
  if (!showTimestamp) {
4070
1142
  return mainPart.trim();
@@ -4119,9 +1191,9 @@ class Logger22 {
4119
1191
  } else {
4120
1192
  formattedMessage = this.formatMessage(message, args);
4121
1193
  }
4122
- if (this.fancy && !isBrowserProcess22()) {
4123
- const icon = levelIcons22[level];
4124
- const tag = this.options.showTags !== false && this.name ? styles22.gray(this.formatTag(this.name)) : "";
1194
+ if (this.fancy && !isBrowserProcess()) {
1195
+ const icon = levelIcons[level];
1196
+ const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
4125
1197
  let consoleMessage;
4126
1198
  switch (level) {
4127
1199
  case "debug":
@@ -4129,7 +1201,7 @@ class Logger22 {
4129
1201
  timestamp: consoleTime,
4130
1202
  icon,
4131
1203
  tag,
4132
- message: styles22.gray(formattedMessage),
1204
+ message: styles.gray(formattedMessage),
4133
1205
  level
4134
1206
  });
4135
1207
  console.error(consoleMessage);
@@ -4149,7 +1221,7 @@ class Logger22 {
4149
1221
  timestamp: consoleTime,
4150
1222
  icon,
4151
1223
  tag,
4152
- message: styles22.green(formattedMessage),
1224
+ message: styles.green(formattedMessage),
4153
1225
  level
4154
1226
  });
4155
1227
  console.error(consoleMessage);
@@ -4180,7 +1252,7 @@ class Logger22 {
4180
1252
  if (line.trim() && !line.includes(formattedMessage)) {
4181
1253
  console.error(this.formatConsoleMessage({
4182
1254
  timestamp: consoleTime,
4183
- message: styles22.gray(` ${line}`),
1255
+ message: styles.gray(` ${line}`),
4184
1256
  level,
4185
1257
  showTimestamp: false
4186
1258
  }));
@@ -4189,7 +1261,7 @@ class Logger22 {
4189
1261
  }
4190
1262
  break;
4191
1263
  }
4192
- } else if (!isBrowserProcess22()) {
1264
+ } else if (!isBrowserProcess()) {
4193
1265
  console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
4194
1266
  if (errorStack) {
4195
1267
  console.error(errorStack);
@@ -4208,14 +1280,14 @@ class Logger22 {
4208
1280
  }
4209
1281
  time(label) {
4210
1282
  const start = performance.now();
4211
- if (this.fancy && !isBrowserProcess22()) {
4212
- const tag = this.options.showTags !== false && this.name ? styles22.gray(this.formatTag(this.name)) : "";
1283
+ if (this.fancy && !isBrowserProcess()) {
1284
+ const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
4213
1285
  const consoleTime = this.formatConsoleTimestamp(new Date);
4214
1286
  console.error(this.formatConsoleMessage({
4215
1287
  timestamp: consoleTime,
4216
- icon: styles22.blue("◐"),
1288
+ icon: styles.blue("◐"),
4217
1289
  tag,
4218
- message: `${styles22.cyan(label)}...`
1290
+ message: `${styles.cyan(label)}...`
4219
1291
  }));
4220
1292
  }
4221
1293
  return async (metadata) => {
@@ -4234,15 +1306,15 @@ class Logger22 {
4234
1306
  logEntry += `
4235
1307
  `;
4236
1308
  logEntry = logEntry.replace(this.ANSI_PATTERN, "");
4237
- if (this.fancy && !isBrowserProcess22()) {
4238
- const tag = this.options.showTags !== false && this.name ? styles22.gray(this.formatTag(this.name)) : "";
1309
+ if (this.fancy && !isBrowserProcess()) {
1310
+ const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
4239
1311
  console.error(this.formatConsoleMessage({
4240
1312
  timestamp: consoleTime,
4241
- icon: styles22.green("✓"),
1313
+ icon: styles.green("✓"),
4242
1314
  tag,
4243
1315
  message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
4244
1316
  }));
4245
- } else if (!isBrowserProcess22()) {
1317
+ } else if (!isBrowserProcess()) {
4246
1318
  console.error(logEntry.trim());
4247
1319
  }
4248
1320
  await this.writeToFile(logEntry);
@@ -4285,7 +1357,7 @@ class Logger22 {
4285
1357
  }
4286
1358
  extend(namespace) {
4287
1359
  const childName = `${this.name}:${namespace}`;
4288
- const childLogger = new Logger22(childName, {
1360
+ const childLogger = new Logger(childName, {
4289
1361
  ...this.options,
4290
1362
  logDirectory: this.config.logDirectory,
4291
1363
  level: this.config.level,
@@ -4297,11 +1369,11 @@ class Logger22 {
4297
1369
  return childLogger;
4298
1370
  }
4299
1371
  createReadStream() {
4300
- if (isBrowserProcess22())
1372
+ if (isBrowserProcess())
4301
1373
  throw new Error("createReadStream is not supported in browser environments");
4302
- if (!existsSync42(this.currentLogFile))
1374
+ if (!existsSync22(this.currentLogFile))
4303
1375
  throw new Error(`Log file does not exist: ${this.currentLogFile}`);
4304
- return createReadStream22(this.currentLogFile, { encoding: "utf8" });
1376
+ return createReadStream(this.currentLogFile, { encoding: "utf8" });
4305
1377
  }
4306
1378
  async decrypt(data) {
4307
1379
  if (!this.validateEncryptionConfig())
@@ -4313,13 +1385,13 @@ class Logger22 {
4313
1385
  throw new Error("No valid encryption key available");
4314
1386
  const key = this.keys.get(this.currentKeyId);
4315
1387
  try {
4316
- const encryptedData = Buffer22.isBuffer(data) ? data : Buffer22.from(data, "base64");
1388
+ const encryptedData = Buffer.isBuffer(data) ? data : Buffer.from(data, "base64");
4317
1389
  const iv = encryptedData.slice(0, 16);
4318
1390
  const authTag = encryptedData.slice(-16);
4319
1391
  const ciphertext = encryptedData.slice(16, -16);
4320
- const decipher = createDecipheriv22("aes-256-gcm", key, iv);
1392
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
4321
1393
  decipher.setAuthTag(authTag);
4322
- const decrypted = Buffer22.concat([
1394
+ const decrypted = Buffer.concat([
4323
1395
  decipher.update(ciphertext),
4324
1396
  decipher.final()
4325
1397
  ]);
@@ -4341,10 +1413,10 @@ class Logger22 {
4341
1413
  return this.config.rotation;
4342
1414
  }
4343
1415
  isBrowserMode() {
4344
- return isBrowserProcess22();
1416
+ return isBrowserProcess();
4345
1417
  }
4346
1418
  isServerMode() {
4347
- return !isBrowserProcess22();
1419
+ return !isBrowserProcess();
4348
1420
  }
4349
1421
  setTestEncryptionKey(keyId, key) {
4350
1422
  this.currentKeyId = keyId;
@@ -4368,7 +1440,7 @@ class Logger22 {
4368
1440
  const timestamp = new Date;
4369
1441
  const consoleTime = this.formatConsoleTimestamp(timestamp);
4370
1442
  const fileTime = this.formatFileTimestamp(timestamp);
4371
- if (this.fancy && !isBrowserProcess22()) {
1443
+ if (this.fancy && !isBrowserProcess()) {
4372
1444
  const lines = message.split(`
4373
1445
  `);
4374
1446
  const width = Math.max(...lines.map((line) => line.length)) + 2;
@@ -4381,25 +1453,25 @@ class Logger22 {
4381
1453
  if (this.options.showTags !== false && this.name) {
4382
1454
  console.error(this.formatConsoleMessage({
4383
1455
  timestamp: consoleTime,
4384
- message: styles22.gray(this.formatTag(this.name)),
1456
+ message: styles.gray(this.formatTag(this.name)),
4385
1457
  showTimestamp: false
4386
1458
  }));
4387
1459
  }
4388
1460
  console.error(this.formatConsoleMessage({
4389
1461
  timestamp: consoleTime,
4390
- message: styles22.cyan(top)
1462
+ message: styles.cyan(top)
4391
1463
  }));
4392
1464
  boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
4393
1465
  timestamp: consoleTime,
4394
- message: styles22.cyan(line),
1466
+ message: styles.cyan(line),
4395
1467
  showTimestamp: false
4396
1468
  })));
4397
1469
  console.error(this.formatConsoleMessage({
4398
1470
  timestamp: consoleTime,
4399
- message: styles22.cyan(bottom),
1471
+ message: styles.cyan(bottom),
4400
1472
  showTimestamp: false
4401
1473
  }));
4402
- } else if (!isBrowserProcess22()) {
1474
+ } else if (!isBrowserProcess()) {
4403
1475
  console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
4404
1476
  }
4405
1477
  const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
@@ -4407,30 +1479,30 @@ class Logger22 {
4407
1479
  await this.writeToFile(logEntry);
4408
1480
  }
4409
1481
  async prompt(message) {
4410
- if (isBrowserProcess22()) {
1482
+ if (isBrowserProcess()) {
4411
1483
  return Promise.resolve(true);
4412
1484
  }
4413
- return new Promise((resolve52) => {
4414
- console.error(`${styles22.cyan("?")} ${message} (y/n) `);
1485
+ return new Promise((resolve32) => {
1486
+ console.error(`${styles.cyan("?")} ${message} (y/n) `);
4415
1487
  const onData = (data) => {
4416
1488
  const input = data.toString().trim().toLowerCase();
4417
- process11.stdin.removeListener("data", onData);
1489
+ process5.stdin.removeListener("data", onData);
4418
1490
  try {
4419
- if (typeof process11.stdin.setRawMode === "function") {
4420
- process11.stdin.setRawMode(false);
1491
+ if (typeof process5.stdin.setRawMode === "function") {
1492
+ process5.stdin.setRawMode(false);
4421
1493
  }
4422
1494
  } catch {}
4423
- process11.stdin.pause();
1495
+ process5.stdin.pause();
4424
1496
  console.error("");
4425
- resolve52(input === "y" || input === "yes");
1497
+ resolve32(input === "y" || input === "yes");
4426
1498
  };
4427
1499
  try {
4428
- if (typeof process11.stdin.setRawMode === "function") {
4429
- process11.stdin.setRawMode(true);
1500
+ if (typeof process5.stdin.setRawMode === "function") {
1501
+ process5.stdin.setRawMode(true);
4430
1502
  }
4431
1503
  } catch {}
4432
- process11.stdin.resume();
4433
- process11.stdin.once("data", onData);
1504
+ process5.stdin.resume();
1505
+ process5.stdin.once("data", onData);
4434
1506
  });
4435
1507
  }
4436
1508
  setFancy(enabled) {
@@ -4475,10 +1547,10 @@ class Logger22 {
4475
1547
  formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
4476
1548
  }
4477
1549
  }
4478
- if (this.fancy && !isBrowserProcess22()) {
4479
- const tag = this.options.showTags !== false && this.name ? styles22.gray(this.formatTag(this.name)) : "";
4480
- const spinnerChar = styles22.blue("◐");
4481
- console.error(`${spinnerChar} ${tag} ${styles22.cyan(formattedMessage)}`);
1550
+ if (this.fancy && !isBrowserProcess()) {
1551
+ const tag = this.options.showTags !== false && this.name ? styles.gray(this.formatTag(this.name)) : "";
1552
+ const spinnerChar = styles.blue("◐");
1553
+ console.error(`${spinnerChar} ${tag} ${styles.cyan(formattedMessage)}`);
4482
1554
  }
4483
1555
  const timestamp = new Date;
4484
1556
  const formattedDate = timestamp.toISOString();
@@ -4487,7 +1559,7 @@ class Logger22 {
4487
1559
  await this.writeToFile(logEntry);
4488
1560
  }
4489
1561
  progress(total, initialMessage = "") {
4490
- if (!this.enabled || !this.fancy || isBrowserProcess22() || total <= 0) {
1562
+ if (!this.enabled || !this.fancy || isBrowserProcess() || total <= 0) {
4491
1563
  return {
4492
1564
  update: () => {},
4493
1565
  finish: () => {},
@@ -4508,7 +1580,7 @@ class Logger22 {
4508
1580
  };
4509
1581
  this.renderProgressBar(this.activeProgressBar);
4510
1582
  const update = (current, message) => {
4511
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess22())
1583
+ if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
4512
1584
  return;
4513
1585
  this.activeProgressBar.current = Math.max(0, Math.min(total, current));
4514
1586
  if (message !== undefined) {
@@ -4518,7 +1590,7 @@ class Logger22 {
4518
1590
  this.renderProgressBar(this.activeProgressBar, isFinished);
4519
1591
  };
4520
1592
  const finish = (message) => {
4521
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess22())
1593
+ if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
4522
1594
  return;
4523
1595
  this.activeProgressBar.current = this.activeProgressBar.total;
4524
1596
  if (message !== undefined) {
@@ -4528,9 +1600,9 @@ class Logger22 {
4528
1600
  this.finishProgressBar(this.activeProgressBar);
4529
1601
  };
4530
1602
  const interrupt = (interruptMessage, level = "info") => {
4531
- if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess22())
1603
+ if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess())
4532
1604
  return;
4533
- process11.stdout.write(`${"\r".padEnd(process11.stdout.columns || 80)}\r`);
1605
+ process5.stdout.write(`${"\r".padEnd(process5.stdout.columns || 80)}\r`);
4534
1606
  this.log(level, interruptMessage);
4535
1607
  setTimeout(() => {
4536
1608
  if (this.activeProgressBar) {
@@ -4541,30 +1613,30 @@ class Logger22 {
4541
1613
  return { update, finish, interrupt };
4542
1614
  }
4543
1615
  renderProgressBar(barState, isFinished = false) {
4544
- if (!this.enabled || !this.fancy || isBrowserProcess22() || !process11.stdout.isTTY)
1616
+ if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY)
4545
1617
  return;
4546
1618
  const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
4547
1619
  const filledLength = Math.round(barState.barLength * percent / 100);
4548
1620
  const emptyLength = barState.barLength - filledLength;
4549
- const filledBar = styles22.green("━".repeat(filledLength));
4550
- const emptyBar = styles22.gray("━".repeat(emptyLength));
1621
+ const filledBar = styles.green("━".repeat(filledLength));
1622
+ const emptyBar = styles.gray("━".repeat(emptyLength));
4551
1623
  const bar = `[${filledBar}${emptyBar}]`;
4552
1624
  const percentageText = `${percent}%`.padStart(4);
4553
1625
  const messageText = barState.message ? ` ${barState.message}` : "";
4554
- const icon = isFinished || percent === 100 ? styles22.green("✓") : styles22.blue("▶");
4555
- const tag = this.options.showTags !== false && this.name ? ` ${styles22.gray(this.formatTag(this.name))}` : "";
1626
+ const icon = isFinished || percent === 100 ? styles.green("✓") : styles.blue("▶");
1627
+ const tag = this.options.showTags !== false && this.name ? ` ${styles.gray(this.formatTag(this.name))}` : "";
4556
1628
  const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
4557
- const terminalWidth = process11.stdout.columns || 80;
1629
+ const terminalWidth = process5.stdout.columns || 80;
4558
1630
  const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
4559
1631
  barState.lastRenderedLine = `${line}${clearLine}`;
4560
- process11.stdout.write(barState.lastRenderedLine);
1632
+ process5.stdout.write(barState.lastRenderedLine);
4561
1633
  if (isFinished) {
4562
- process11.stdout.write(`
1634
+ process5.stdout.write(`
4563
1635
  `);
4564
1636
  }
4565
1637
  }
4566
1638
  finishProgressBar(barState, finalMessage) {
4567
- if (!this.enabled || !this.fancy || isBrowserProcess22() || !process11.stdout.isTTY) {
1639
+ if (!this.enabled || !this.fancy || isBrowserProcess() || !process5.stdout.isTTY) {
4568
1640
  this.activeProgressBar = null;
4569
1641
  return;
4570
1642
  }
@@ -4577,23 +1649,23 @@ class Logger22 {
4577
1649
  this.activeProgressBar = null;
4578
1650
  }
4579
1651
  async clear(filters = {}) {
4580
- if (isBrowserProcess22()) {
1652
+ if (isBrowserProcess()) {
4581
1653
  console.warn("Log clearing is not supported in browser environments.");
4582
1654
  return;
4583
1655
  }
4584
1656
  try {
4585
1657
  console.warn("Clearing logs...", this.config.logDirectory);
4586
- const files = await readdir22(this.config.logDirectory);
1658
+ const files = await readdir(this.config.logDirectory);
4587
1659
  const logFilesToDelete = [];
4588
1660
  for (const file of files) {
4589
1661
  const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
4590
1662
  if (!nameMatches || !file.endsWith(".log")) {
4591
1663
  continue;
4592
1664
  }
4593
- const filePath = join5(this.config.logDirectory, file);
1665
+ const filePath = join2(this.config.logDirectory, file);
4594
1666
  if (filters.before) {
4595
1667
  try {
4596
- const fileStats = await stat22(filePath);
1668
+ const fileStats = await stat(filePath);
4597
1669
  if (fileStats.mtime >= filters.before) {
4598
1670
  continue;
4599
1671
  }
@@ -4611,7 +1683,7 @@ class Logger22 {
4611
1683
  console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
4612
1684
  for (const filePath of logFilesToDelete) {
4613
1685
  try {
4614
- await unlink22(filePath);
1686
+ await unlink(filePath);
4615
1687
  console.warn(`Deleted log file: ${filePath}`);
4616
1688
  } catch (unlinkErr) {
4617
1689
  console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
@@ -4623,11 +1695,11 @@ class Logger22 {
4623
1695
  }
4624
1696
  }
4625
1697
  }
4626
- var logger22 = new Logger22("stacks");
1698
+ var logger = new Logger("stacks");
4627
1699
 
4628
1700
  // src/git-hooks.ts
4629
1701
  var execAsync = promisify(exec);
4630
- var log3 = new Logger22("git-hooks", {
1702
+ var log = new Logger("git-hooks", {
4631
1703
  showTags: true
4632
1704
  });
4633
1705
  var VALID_GIT_HOOKS = [
@@ -4673,7 +1745,7 @@ if [ -f "$BUN_GIT_HOOKS_RC" ]; then
4673
1745
  fi
4674
1746
 
4675
1747
  `;
4676
- function getGitProjectRoot(directory = process12.cwd()) {
1748
+ function getGitProjectRoot(directory = process6.cwd()) {
4677
1749
  if (directory.endsWith(".git")) {
4678
1750
  return path.normalize(directory);
4679
1751
  }
@@ -4735,7 +1807,7 @@ function checkBunGitHooksInDependencies(projectRootPath) {
4735
1807
  }
4736
1808
  return "bun-git-hooks" in packageJsonContent.devDependencies;
4737
1809
  }
4738
- function _getPackageJson(projectPath = process12.cwd()) {
1810
+ function _getPackageJson(projectPath = process6.cwd()) {
4739
1811
  if (typeof projectPath !== "string") {
4740
1812
  throw new TypeError("projectPath is not a string");
4741
1813
  }
@@ -4746,17 +1818,18 @@ function _getPackageJson(projectPath = process12.cwd()) {
4746
1818
  const packageJsonDataRaw = fs.readFileSync(targetPackageJson, { encoding: "utf-8" });
4747
1819
  return { packageJsonContent: JSON.parse(packageJsonDataRaw), packageJsonPath: targetPackageJson };
4748
1820
  }
4749
- function setHooksFromConfig(projectRootPath = process12.cwd(), options) {
4750
- if (!config3 || Object.keys(config3).length === 0)
4751
- throw new Error("[ERROR] Config was not found! Please add `.git-hooks.config.{ts,js,mjs,cjs,mts,cts,json}` or `git-hooks.config.{ts,js,mjs,cjs,mts,cts,json}` or the `git-hooks` entry in package.json.\r\nCheck README for details");
4752
- const configFile = options?.configFile ? options.configFile : config3;
1821
+ function setHooksFromConfig(projectRootPath = process6.cwd(), options) {
1822
+ if (!config2 || Object.keys(config2).length === 0)
1823
+ throw new Error("[ERROR] Config was not found! Please add `.git-hooks.config.{ts,js,mjs,cjs,json}` or `git-hooks.config.{ts,js,mjs,cjs,json}` or the `git-hooks` entry in package.json.\r\nCheck README for details");
1824
+ const configFile = options?.configFile || { ...config2 };
1825
+ _validateStagedLintConfig(configFile);
4753
1826
  const hookKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key));
4754
1827
  const isValidConfig = hookKeys.every((key) => VALID_GIT_HOOKS.includes(key));
4755
1828
  if (!isValidConfig)
4756
1829
  throw new Error("[ERROR] Config was not in correct format. Please check git hooks or options name");
4757
1830
  const preserveUnused = Array.isArray(configFile.preserveUnused) ? configFile.preserveUnused : configFile.preserveUnused ? VALID_GIT_HOOKS : [];
4758
- const logKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key)).sort().map((key) => italic22(key)).join(", ");
4759
- log3.debug(`Hook Keys: ${logKeys}`);
1831
+ const logKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key)).sort().map((key) => italic(key)).join(", ");
1832
+ log.debug(`Hook Keys: ${logKeys}`);
4760
1833
  for (const hook of VALID_GIT_HOOKS) {
4761
1834
  if (Object.prototype.hasOwnProperty.call(configFile, hook)) {
4762
1835
  if (!configFile[hook])
@@ -4767,48 +1840,85 @@ function setHooksFromConfig(projectRootPath = process12.cwd(), options) {
4767
1840
  }
4768
1841
  }
4769
1842
  }
4770
- async function getStagedFiles(projectRoot = process12.cwd()) {
1843
+ async function getStagedFiles(projectRoot = process6.cwd()) {
4771
1844
  try {
4772
- const { stdout } = await execAsync("git diff --staged --name-only --diff-filter=ACMR", { cwd: projectRoot });
4773
- return stdout.trim().split(`
1845
+ const { stdout } = await execAsync("git diff --cached --name-only --diff-filter=ACMR", { cwd: projectRoot });
1846
+ const files = stdout.trim().split(`
4774
1847
  `).filter(Boolean);
1848
+ if (config2.verbose && files.length > 0) {
1849
+ console.info("[INFO] Staged files found:", files);
1850
+ }
1851
+ return files;
4775
1852
  } catch (error) {
4776
1853
  console.error("[ERROR] Failed to get staged files:", error);
4777
1854
  return [];
4778
1855
  }
4779
1856
  }
1857
+ function expandBracePattern(pattern) {
1858
+ const braceMatch = pattern.match(/{([^}]+)}/g);
1859
+ if (!braceMatch)
1860
+ return [pattern];
1861
+ const results = [pattern];
1862
+ braceMatch.forEach((brace) => {
1863
+ const options = brace.slice(1, -1).split(",");
1864
+ const newResults = [];
1865
+ results.forEach((result) => {
1866
+ options.forEach((option) => {
1867
+ newResults.push(result.replace(brace, option.trim()));
1868
+ });
1869
+ });
1870
+ results.length = 0;
1871
+ results.push(...newResults);
1872
+ });
1873
+ return results;
1874
+ }
4780
1875
  function matchesGlob(file, pattern) {
4781
- if (pattern.includes("*")) {
4782
- const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".");
4783
- const regex = new RegExp(`^${regexPattern}$`);
4784
- return regex.test(file);
1876
+ if (pattern.startsWith("!")) {
1877
+ return !matchesGlob(file, pattern.slice(1));
4785
1878
  }
4786
- return file === pattern;
1879
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "(?:.*?)").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]");
1880
+ const regex = new RegExp(`^${regexPattern}$`);
1881
+ return regex.test(file);
4787
1882
  }
4788
1883
  function filterFilesByPattern(files, pattern) {
4789
- return files.filter((file) => matchesGlob(file, pattern));
1884
+ const expandedPatterns = expandBracePattern(pattern);
1885
+ const includePatterns = expandedPatterns.filter((p) => !p.startsWith("!"));
1886
+ const excludePatterns = expandedPatterns.filter((p) => p.startsWith("!"));
1887
+ return files.filter((file) => {
1888
+ const isIncluded = includePatterns.some((p) => matchesGlob(file, p));
1889
+ const isExcluded = excludePatterns.some((p) => matchesGlob(file, p.slice(1)));
1890
+ return isIncluded && !isExcluded;
1891
+ });
4790
1892
  }
4791
- async function runCommandOnStagedFiles(command, files, projectRoot = process12.cwd(), verbose = false) {
1893
+ async function runCommandOnStagedFiles(command, files, projectRoot = process6.cwd(), verbose = false) {
4792
1894
  if (files.length === 0) {
4793
1895
  if (verbose)
4794
1896
  console.info("[INFO] No matching files for pattern");
4795
1897
  return true;
4796
1898
  }
4797
1899
  const commands = Array.isArray(command) ? command : [command];
1900
+ const fileList = files.join(" ");
4798
1901
  for (const cmd of commands) {
4799
1902
  try {
4800
- const fullCommand = `${cmd} ${files.join(" ")}`;
4801
- if (verbose)
4802
- console.info(`[INFO] Running: ${fullCommand}`);
4803
- const { stdout, stderr } = await execAsync(fullCommand, { cwd: projectRoot });
1903
+ const fullCommand = `${cmd} ${fileList}`;
4804
1904
  if (verbose) {
4805
- if (stdout)
4806
- console.info(stdout);
4807
- if (stderr)
4808
- console.error(stderr);
1905
+ console.info("[INFO] Running command:", cmd);
1906
+ console.info("[INFO] On files:", files);
1907
+ }
1908
+ const { stdout, stderr } = await execAsync(fullCommand, { cwd: projectRoot });
1909
+ if (stdout && (verbose || stdout.includes("error") || stdout.includes("warning"))) {
1910
+ console.info(stdout);
1911
+ }
1912
+ if (stderr) {
1913
+ console.error("[ERROR] Command output:", stderr);
1914
+ return false;
4809
1915
  }
4810
1916
  } catch (error) {
4811
- console.error(`[ERROR] Command failed: ${cmd}`, error);
1917
+ if (error.stdout)
1918
+ console.info(error.stdout);
1919
+ if (error.stderr)
1920
+ console.error("[ERROR] Command stderr:", error.stderr);
1921
+ console.error(`[ERROR] Command failed: ${cmd}`);
4812
1922
  return false;
4813
1923
  }
4814
1924
  }
@@ -4832,7 +1942,7 @@ async function processStagedLint(stagedLintConfig, projectRoot, verbose = false)
4832
1942
  }
4833
1943
  return success;
4834
1944
  }
4835
- function _setHook(hook, commandOrConfig, projectRoot = process12.cwd()) {
1945
+ function _setHook(hook, commandOrConfig, projectRoot = process6.cwd()) {
4836
1946
  const gitRoot = getGitProjectRoot(projectRoot);
4837
1947
  if (!gitRoot) {
4838
1948
  console.info("[INFO] No `.git` root folder found, skipping");
@@ -4853,26 +1963,26 @@ function _setHook(hook, commandOrConfig, projectRoot = process12.cwd()) {
4853
1963
  fs.mkdirSync(hookDirectory, { recursive: true });
4854
1964
  }
4855
1965
  const addOrModify = fs.existsSync(hookPath) ? "Modify" : "Add";
4856
- log3.debug(`${addOrModify} ${italic22(hook)} hook`);
1966
+ log.debug(`${addOrModify} ${italic(hook)} hook`);
4857
1967
  fs.writeFileSync(hookPath, hookCommand, { mode: 493 });
4858
1968
  }
4859
- function removeHooks(projectRoot = process12.cwd(), verbose = false) {
1969
+ function removeHooks(projectRoot = process6.cwd(), verbose = false) {
4860
1970
  for (const configEntry of VALID_GIT_HOOKS)
4861
1971
  _removeHook(configEntry, projectRoot, verbose);
4862
1972
  }
4863
- function _removeHook(hook, projectRoot = process12.cwd(), verbose = false) {
1973
+ function _removeHook(hook, projectRoot = process6.cwd(), verbose = false) {
4864
1974
  const gitRoot = getGitProjectRoot(projectRoot);
4865
1975
  const hookPath = path.normalize(`${gitRoot}/hooks/${hook}`);
4866
1976
  if (fs.existsSync(hookPath)) {
4867
- log3.debug(`Hook ${hook} is not set, removing!`);
1977
+ log.debug(`Hook ${hook} is not set, removing!`);
4868
1978
  fs.unlinkSync(hookPath);
4869
1979
  }
4870
1980
  if (verbose)
4871
- log3.success(`Successfully removed the ${hook} hook`);
1981
+ log.success(`Successfully removed the ${hook} hook`);
4872
1982
  }
4873
1983
  async function runStagedLint(hook) {
4874
- const projectRoot = process12.cwd();
4875
- const configFile = config3;
1984
+ const projectRoot = process6.cwd();
1985
+ const configFile = config2;
4876
1986
  if (!configFile) {
4877
1987
  console.error(`[ERROR] No configuration found`);
4878
1988
  return false;
@@ -4892,13 +2002,23 @@ async function runStagedLint(hook) {
4892
2002
  console.error(`[ERROR] No staged lint configuration found for hook ${hook}`);
4893
2003
  return false;
4894
2004
  }
2005
+ function _validateStagedLintConfig(config4) {
2006
+ for (const hook of VALID_GIT_HOOKS) {
2007
+ if (hook !== "pre-commit" && config4[hook] && typeof config4[hook] === "object") {
2008
+ const hookConfig = config4[hook];
2009
+ if (hookConfig["stagedLint"] || hookConfig["staged-lint"]) {
2010
+ throw new Error(`staged-lint is only allowed in pre-commit hook. Found in ${hook} hook.`);
2011
+ }
2012
+ }
2013
+ }
2014
+ }
4895
2015
  export {
4896
2016
  setHooksFromConfig,
4897
2017
  runStagedLint,
4898
2018
  removeHooks,
4899
2019
  getProjectRootDirectoryFromNodeModules,
4900
2020
  getGitProjectRoot,
4901
- config3 as config,
2021
+ config2 as config,
4902
2022
  checkBunGitHooksInDependencies,
4903
2023
  VALID_OPTIONS,
4904
2024
  VALID_GIT_HOOKS,