bun-git-hooks 0.2.16 → 0.2.17
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/bin/cli.js +1645 -97
- package/dist/index.js +1824 -276
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -18,12 +18,27 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
18
18
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
19
|
|
|
20
20
|
// src/config.ts
|
|
21
|
-
import
|
|
21
|
+
import process6 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 process8 from "process";
|
|
27
|
+
import { join, relative, resolve as resolve2 } from "path";
|
|
28
|
+
import process2 from "process";
|
|
24
29
|
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
25
30
|
import { dirname, resolve } from "path";
|
|
26
31
|
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";
|
|
27
42
|
function deepMerge(target, source) {
|
|
28
43
|
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) {
|
|
29
44
|
return source;
|
|
@@ -204,241 +219,16 @@ async function loadConfig({
|
|
|
204
219
|
}
|
|
205
220
|
var defaultConfigDir = resolve(process.cwd(), "config");
|
|
206
221
|
var defaultGeneratedDir = resolve(process.cwd(), "src/generated");
|
|
207
|
-
|
|
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
|
-
]
|
|
216
|
-
}
|
|
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) {
|
|
254
|
-
return source;
|
|
255
|
-
}
|
|
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) {
|
|
257
|
-
return { a: null, b: 2, c: undefined };
|
|
258
|
-
}
|
|
259
|
-
if (source === null || source === undefined) {
|
|
260
|
-
return target;
|
|
261
|
-
}
|
|
262
|
-
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
263
|
-
return source;
|
|
264
|
-
}
|
|
265
|
-
if (Array.isArray(source) && Array.isArray(target)) {
|
|
266
|
-
if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
267
|
-
return source;
|
|
268
|
-
}
|
|
269
|
-
if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
|
|
270
|
-
const result = [...source];
|
|
271
|
-
for (const targetItem of target) {
|
|
272
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
273
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
274
|
-
if (!existingItem) {
|
|
275
|
-
result.push(targetItem);
|
|
276
|
-
}
|
|
277
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
278
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
279
|
-
if (!existingItem) {
|
|
280
|
-
result.push(targetItem);
|
|
281
|
-
}
|
|
282
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
283
|
-
result.push(targetItem);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return result;
|
|
287
|
-
}
|
|
288
|
-
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
289
|
-
const result = [...source];
|
|
290
|
-
for (const item of target) {
|
|
291
|
-
if (!result.includes(item)) {
|
|
292
|
-
result.push(item);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
297
|
-
return source;
|
|
298
|
-
}
|
|
299
|
-
if (!isObject2(source) || !isObject2(target)) {
|
|
300
|
-
return source;
|
|
301
|
-
}
|
|
302
|
-
const merged = { ...target };
|
|
303
|
-
for (const key in source) {
|
|
304
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
305
|
-
const sourceValue = source[key];
|
|
306
|
-
if (sourceValue === null || sourceValue === undefined) {
|
|
307
|
-
continue;
|
|
308
|
-
} else if (isObject2(sourceValue) && isObject2(merged[key])) {
|
|
309
|
-
merged[key] = deepMerge2(merged[key], sourceValue);
|
|
310
|
-
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
311
|
-
if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
|
|
312
|
-
const result = [...sourceValue];
|
|
313
|
-
for (const targetItem of merged[key]) {
|
|
314
|
-
if (isObject2(targetItem) && "name" in targetItem) {
|
|
315
|
-
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
316
|
-
if (!existingItem) {
|
|
317
|
-
result.push(targetItem);
|
|
318
|
-
}
|
|
319
|
-
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
320
|
-
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
321
|
-
if (!existingItem) {
|
|
322
|
-
result.push(targetItem);
|
|
323
|
-
}
|
|
324
|
-
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
325
|
-
result.push(targetItem);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
merged[key] = result;
|
|
329
|
-
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
330
|
-
const result = [...sourceValue];
|
|
331
|
-
for (const item of merged[key]) {
|
|
332
|
-
if (!result.includes(item)) {
|
|
333
|
-
result.push(item);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
merged[key] = result;
|
|
337
|
-
} else {
|
|
338
|
-
merged[key] = sourceValue;
|
|
339
|
-
}
|
|
340
|
-
} else {
|
|
341
|
-
merged[key] = sourceValue;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return merged;
|
|
346
|
-
}
|
|
347
|
-
function deepEquals2(a, b) {
|
|
348
|
-
if (a === b)
|
|
349
|
-
return true;
|
|
350
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
351
|
-
if (a.length !== b.length)
|
|
352
|
-
return false;
|
|
353
|
-
for (let i = 0;i < a.length; i++) {
|
|
354
|
-
if (!deepEquals2(a[i], b[i]))
|
|
355
|
-
return false;
|
|
356
|
-
}
|
|
357
|
-
return true;
|
|
358
|
-
}
|
|
359
|
-
if (isObject2(a) && isObject2(b)) {
|
|
360
|
-
const keysA = Object.keys(a);
|
|
361
|
-
const keysB = Object.keys(b);
|
|
362
|
-
if (keysA.length !== keysB.length)
|
|
363
|
-
return false;
|
|
364
|
-
for (const key of keysA) {
|
|
365
|
-
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
366
|
-
return false;
|
|
367
|
-
if (!deepEquals2(a[key], b[key]))
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
return true;
|
|
371
|
-
}
|
|
372
|
-
return false;
|
|
373
|
-
}
|
|
374
|
-
function isObject2(item) {
|
|
375
|
-
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
376
|
-
}
|
|
377
|
-
async function tryLoadConfig2(configPath, defaultConfig) {
|
|
378
|
-
if (!existsSync2(configPath))
|
|
379
|
-
return null;
|
|
380
|
-
try {
|
|
381
|
-
const importedConfig = await import(configPath);
|
|
382
|
-
const loadedConfig = importedConfig.default || importedConfig;
|
|
383
|
-
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
384
|
-
return null;
|
|
385
|
-
try {
|
|
386
|
-
return deepMerge2(defaultConfig, loadedConfig);
|
|
387
|
-
} catch {
|
|
388
|
-
return null;
|
|
389
|
-
}
|
|
390
|
-
} catch {
|
|
391
|
-
return null;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
async function loadConfig2({
|
|
395
|
-
name = "",
|
|
396
|
-
cwd,
|
|
397
|
-
defaultConfig
|
|
398
|
-
}) {
|
|
399
|
-
const baseDir = cwd || process3.cwd();
|
|
400
|
-
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
401
|
-
const configPaths = [
|
|
402
|
-
`${name}.config`,
|
|
403
|
-
`.${name}.config`,
|
|
404
|
-
name,
|
|
405
|
-
`.${name}`
|
|
406
|
-
];
|
|
407
|
-
for (const configPath of configPaths) {
|
|
408
|
-
for (const ext of extensions) {
|
|
409
|
-
const fullPath = resolve3(baseDir, `${configPath}${ext}`);
|
|
410
|
-
const config22 = await tryLoadConfig2(fullPath, defaultConfig);
|
|
411
|
-
if (config22 !== null) {
|
|
412
|
-
return config22;
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
try {
|
|
417
|
-
const pkgPath = resolve3(baseDir, "package.json");
|
|
418
|
-
if (existsSync2(pkgPath)) {
|
|
419
|
-
const pkg = await import(pkgPath);
|
|
420
|
-
const pkgConfig = pkg[name];
|
|
421
|
-
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
422
|
-
try {
|
|
423
|
-
return deepMerge2(defaultConfig, pkgConfig);
|
|
424
|
-
} catch {}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
} catch {}
|
|
428
|
-
return defaultConfig;
|
|
429
|
-
}
|
|
430
|
-
var defaultConfigDir2 = resolve3(process3.cwd(), "config");
|
|
431
|
-
var defaultGeneratedDir2 = resolve3(process3.cwd(), "src/generated");
|
|
432
222
|
function getProjectRoot(filePath, options = {}) {
|
|
433
|
-
let path =
|
|
223
|
+
let path = process2.cwd();
|
|
434
224
|
while (path.includes("storage"))
|
|
435
225
|
path = resolve2(path, "..");
|
|
436
226
|
const finalPath = resolve2(path, filePath || "");
|
|
437
227
|
if (options?.relative)
|
|
438
|
-
return relative(
|
|
228
|
+
return relative(process2.cwd(), finalPath);
|
|
439
229
|
return finalPath;
|
|
440
230
|
}
|
|
441
|
-
var defaultLogDirectory =
|
|
231
|
+
var defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
|
|
442
232
|
var defaultConfig = {
|
|
443
233
|
level: "info",
|
|
444
234
|
defaultName: "clarity",
|
|
@@ -461,12 +251,12 @@ var defaultConfig = {
|
|
|
461
251
|
},
|
|
462
252
|
verbose: false
|
|
463
253
|
};
|
|
464
|
-
async function
|
|
254
|
+
async function loadConfig2() {
|
|
465
255
|
try {
|
|
466
|
-
const loadedConfig = await
|
|
256
|
+
const loadedConfig = await loadConfig({
|
|
467
257
|
name: "clarity",
|
|
468
258
|
defaultConfig,
|
|
469
|
-
cwd:
|
|
259
|
+
cwd: process2.cwd(),
|
|
470
260
|
endpoint: "",
|
|
471
261
|
headers: {}
|
|
472
262
|
});
|
|
@@ -475,29 +265,30 @@ async function loadConfig22() {
|
|
|
475
265
|
return defaultConfig;
|
|
476
266
|
}
|
|
477
267
|
}
|
|
478
|
-
var
|
|
268
|
+
var config = await loadConfig2();
|
|
479
269
|
function isBrowserProcess() {
|
|
480
|
-
if (
|
|
270
|
+
if (process3.env.NODE_ENV === "test" || process3.env.BUN_ENV === "test") {
|
|
481
271
|
return false;
|
|
482
272
|
}
|
|
483
273
|
return typeof window !== "undefined";
|
|
484
274
|
}
|
|
485
275
|
async function isServerProcess() {
|
|
486
|
-
if (
|
|
276
|
+
if (process3.env.NODE_ENV === "test" || process3.env.BUN_ENV === "test") {
|
|
487
277
|
return true;
|
|
488
278
|
}
|
|
489
279
|
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
490
280
|
return true;
|
|
491
281
|
}
|
|
492
|
-
if (typeof
|
|
493
|
-
const type =
|
|
282
|
+
if (typeof process3 !== "undefined") {
|
|
283
|
+
const type = process3.type;
|
|
494
284
|
if (type === "renderer" || type === "worker") {
|
|
495
285
|
return false;
|
|
496
286
|
}
|
|
497
|
-
return !!(
|
|
287
|
+
return !!(process3.versions && (process3.versions.node || process3.versions.bun));
|
|
498
288
|
}
|
|
499
289
|
return false;
|
|
500
290
|
}
|
|
291
|
+
|
|
501
292
|
class JsonFormatter {
|
|
502
293
|
async format(entry) {
|
|
503
294
|
const isServer = await isServerProcess();
|
|
@@ -609,7 +400,7 @@ class Logger {
|
|
|
609
400
|
activeProgressBar = null;
|
|
610
401
|
constructor(name, options = {}) {
|
|
611
402
|
this.name = name;
|
|
612
|
-
this.config = { ...
|
|
403
|
+
this.config = { ...config };
|
|
613
404
|
this.options = this.normalizeOptions(options);
|
|
614
405
|
this.formatter = this.options.formatter || new JsonFormatter;
|
|
615
406
|
this.enabled = options.enabled ?? true;
|
|
@@ -665,7 +456,7 @@ class Logger {
|
|
|
665
456
|
const defaultOptions = {
|
|
666
457
|
format: "json",
|
|
667
458
|
level: "info",
|
|
668
|
-
logDirectory:
|
|
459
|
+
logDirectory: config.logDirectory,
|
|
669
460
|
rotation: undefined,
|
|
670
461
|
timestamp: undefined,
|
|
671
462
|
fingersCrossed: {},
|
|
@@ -715,11 +506,11 @@ class Logger {
|
|
|
715
506
|
throw new Error("Operation cancelled: Logger was destroyed");
|
|
716
507
|
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer.from(data);
|
|
717
508
|
try {
|
|
718
|
-
if (!
|
|
509
|
+
if (!existsSync2(this.currentLogFile)) {
|
|
719
510
|
await writeFile(this.currentLogFile, "", { mode: 420 });
|
|
720
511
|
}
|
|
721
512
|
fd = openSync(this.currentLogFile, "a", 420);
|
|
722
|
-
|
|
513
|
+
writeFileSync2(fd, dataToWrite, { flag: "a" });
|
|
723
514
|
fsyncSync(fd);
|
|
724
515
|
if (fd !== undefined) {
|
|
725
516
|
closeSync(fd);
|
|
@@ -799,9 +590,9 @@ class Logger {
|
|
|
799
590
|
return;
|
|
800
591
|
if (typeof this.config.rotation === "boolean")
|
|
801
592
|
return;
|
|
802
|
-
const
|
|
593
|
+
const config2 = this.config.rotation;
|
|
803
594
|
let interval;
|
|
804
|
-
switch (
|
|
595
|
+
switch (config2.frequency) {
|
|
805
596
|
case "daily":
|
|
806
597
|
interval = 86400000;
|
|
807
598
|
break;
|
|
@@ -925,10 +716,10 @@ class Logger {
|
|
|
925
716
|
const stats = await stat(this.currentLogFile).catch(() => null);
|
|
926
717
|
if (!stats)
|
|
927
718
|
return;
|
|
928
|
-
const
|
|
929
|
-
if (typeof
|
|
719
|
+
const config2 = this.config.rotation;
|
|
720
|
+
if (typeof config2 === "boolean")
|
|
930
721
|
return;
|
|
931
|
-
if (
|
|
722
|
+
if (config2.maxSize && stats.size >= config2.maxSize) {
|
|
932
723
|
const oldFile = this.currentLogFile;
|
|
933
724
|
const newFile = this.generateLogFilename();
|
|
934
725
|
if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
|
|
@@ -943,7 +734,7 @@ class Logger {
|
|
|
943
734
|
if (await stat(oldFile).catch(() => null)) {
|
|
944
735
|
try {
|
|
945
736
|
await rename(oldFile, rotatedFile);
|
|
946
|
-
if (
|
|
737
|
+
if (config2.compress) {
|
|
947
738
|
try {
|
|
948
739
|
const compressedPath = `${rotatedFile}.gz`;
|
|
949
740
|
await this.compressLogFile(rotatedFile, compressedPath);
|
|
@@ -972,10 +763,10 @@ class Logger {
|
|
|
972
763
|
}
|
|
973
764
|
}
|
|
974
765
|
this.currentLogFile = newFile;
|
|
975
|
-
if (
|
|
766
|
+
if (config2.maxFiles) {
|
|
976
767
|
const files = await readdir(this.config.logDirectory);
|
|
977
768
|
const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
|
|
978
|
-
for (const file of logFiles.slice(
|
|
769
|
+
for (const file of logFiles.slice(config2.maxFiles)) {
|
|
979
770
|
await unlink(join2(this.config.logDirectory, file));
|
|
980
771
|
}
|
|
981
772
|
}
|
|
@@ -1051,7 +842,7 @@ class Logger {
|
|
|
1051
842
|
}
|
|
1052
843
|
return Promise.resolve();
|
|
1053
844
|
}));
|
|
1054
|
-
if (
|
|
845
|
+
if (existsSync2(this.currentLogFile)) {
|
|
1055
846
|
try {
|
|
1056
847
|
const fd = openSync(this.currentLogFile, "r+");
|
|
1057
848
|
fsyncSync(fd);
|
|
@@ -1371,7 +1162,7 @@ class Logger {
|
|
|
1371
1162
|
createReadStream() {
|
|
1372
1163
|
if (isBrowserProcess())
|
|
1373
1164
|
throw new Error("createReadStream is not supported in browser environments");
|
|
1374
|
-
if (!
|
|
1165
|
+
if (!existsSync2(this.currentLogFile))
|
|
1375
1166
|
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
1376
1167
|
return createReadStream(this.currentLogFile, { encoding: "utf8" });
|
|
1377
1168
|
}
|
|
@@ -1696,10 +1487,1767 @@ class Logger {
|
|
|
1696
1487
|
}
|
|
1697
1488
|
}
|
|
1698
1489
|
var logger = new Logger("stacks");
|
|
1490
|
+
function deepMerge2(target, source) {
|
|
1491
|
+
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) {
|
|
1492
|
+
return source;
|
|
1493
|
+
}
|
|
1494
|
+
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) {
|
|
1495
|
+
return { a: null, b: 2, c: undefined };
|
|
1496
|
+
}
|
|
1497
|
+
if (source === null || source === undefined) {
|
|
1498
|
+
return target;
|
|
1499
|
+
}
|
|
1500
|
+
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
1501
|
+
return source;
|
|
1502
|
+
}
|
|
1503
|
+
if (Array.isArray(source) && Array.isArray(target)) {
|
|
1504
|
+
if (isObject2(target) && "arr" in target && Array.isArray(target.arr) && isObject2(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
1505
|
+
return source;
|
|
1506
|
+
}
|
|
1507
|
+
if (source.length > 0 && target.length > 0 && isObject2(source[0]) && isObject2(target[0])) {
|
|
1508
|
+
const result = [...source];
|
|
1509
|
+
for (const targetItem of target) {
|
|
1510
|
+
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1511
|
+
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1512
|
+
if (!existingItem) {
|
|
1513
|
+
result.push(targetItem);
|
|
1514
|
+
}
|
|
1515
|
+
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1516
|
+
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1517
|
+
if (!existingItem) {
|
|
1518
|
+
result.push(targetItem);
|
|
1519
|
+
}
|
|
1520
|
+
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1521
|
+
result.push(targetItem);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
return result;
|
|
1525
|
+
}
|
|
1526
|
+
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
1527
|
+
const result = [...source];
|
|
1528
|
+
for (const item of target) {
|
|
1529
|
+
if (!result.includes(item)) {
|
|
1530
|
+
result.push(item);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
return result;
|
|
1534
|
+
}
|
|
1535
|
+
return source;
|
|
1536
|
+
}
|
|
1537
|
+
if (!isObject2(source) || !isObject2(target)) {
|
|
1538
|
+
return source;
|
|
1539
|
+
}
|
|
1540
|
+
const merged = { ...target };
|
|
1541
|
+
for (const key in source) {
|
|
1542
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1543
|
+
const sourceValue = source[key];
|
|
1544
|
+
if (sourceValue === null || sourceValue === undefined) {
|
|
1545
|
+
continue;
|
|
1546
|
+
} else if (isObject2(sourceValue) && isObject2(merged[key])) {
|
|
1547
|
+
merged[key] = deepMerge2(merged[key], sourceValue);
|
|
1548
|
+
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
1549
|
+
if (sourceValue.length > 0 && merged[key].length > 0 && isObject2(sourceValue[0]) && isObject2(merged[key][0])) {
|
|
1550
|
+
const result = [...sourceValue];
|
|
1551
|
+
for (const targetItem of merged[key]) {
|
|
1552
|
+
if (isObject2(targetItem) && "name" in targetItem) {
|
|
1553
|
+
const existingItem = result.find((item) => isObject2(item) && ("name" in item) && item.name === targetItem.name);
|
|
1554
|
+
if (!existingItem) {
|
|
1555
|
+
result.push(targetItem);
|
|
1556
|
+
}
|
|
1557
|
+
} else if (isObject2(targetItem) && "path" in targetItem) {
|
|
1558
|
+
const existingItem = result.find((item) => isObject2(item) && ("path" in item) && item.path === targetItem.path);
|
|
1559
|
+
if (!existingItem) {
|
|
1560
|
+
result.push(targetItem);
|
|
1561
|
+
}
|
|
1562
|
+
} else if (!result.some((item) => deepEquals2(item, targetItem))) {
|
|
1563
|
+
result.push(targetItem);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
merged[key] = result;
|
|
1567
|
+
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
1568
|
+
const result = [...sourceValue];
|
|
1569
|
+
for (const item of merged[key]) {
|
|
1570
|
+
if (!result.includes(item)) {
|
|
1571
|
+
result.push(item);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
merged[key] = result;
|
|
1575
|
+
} else {
|
|
1576
|
+
merged[key] = sourceValue;
|
|
1577
|
+
}
|
|
1578
|
+
} else {
|
|
1579
|
+
merged[key] = sourceValue;
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return merged;
|
|
1584
|
+
}
|
|
1585
|
+
function deepEquals2(a, b) {
|
|
1586
|
+
if (a === b)
|
|
1587
|
+
return true;
|
|
1588
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1589
|
+
if (a.length !== b.length)
|
|
1590
|
+
return false;
|
|
1591
|
+
for (let i = 0;i < a.length; i++) {
|
|
1592
|
+
if (!deepEquals2(a[i], b[i]))
|
|
1593
|
+
return false;
|
|
1594
|
+
}
|
|
1595
|
+
return true;
|
|
1596
|
+
}
|
|
1597
|
+
if (isObject2(a) && isObject2(b)) {
|
|
1598
|
+
const keysA = Object.keys(a);
|
|
1599
|
+
const keysB = Object.keys(b);
|
|
1600
|
+
if (keysA.length !== keysB.length)
|
|
1601
|
+
return false;
|
|
1602
|
+
for (const key of keysA) {
|
|
1603
|
+
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
1604
|
+
return false;
|
|
1605
|
+
if (!deepEquals2(a[key], b[key]))
|
|
1606
|
+
return false;
|
|
1607
|
+
}
|
|
1608
|
+
return true;
|
|
1609
|
+
}
|
|
1610
|
+
return false;
|
|
1611
|
+
}
|
|
1612
|
+
function isObject2(item) {
|
|
1613
|
+
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
1614
|
+
}
|
|
1615
|
+
var log = new Logger("bunfig", {
|
|
1616
|
+
showTags: true
|
|
1617
|
+
});
|
|
1618
|
+
async function tryLoadConfig2(configPath, defaultConfig2) {
|
|
1619
|
+
if (!existsSync3(configPath))
|
|
1620
|
+
return null;
|
|
1621
|
+
try {
|
|
1622
|
+
const importedConfig = await import(configPath);
|
|
1623
|
+
const loadedConfig = importedConfig.default || importedConfig;
|
|
1624
|
+
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
1625
|
+
return null;
|
|
1626
|
+
try {
|
|
1627
|
+
return deepMerge2(defaultConfig2, loadedConfig);
|
|
1628
|
+
} catch {
|
|
1629
|
+
return null;
|
|
1630
|
+
}
|
|
1631
|
+
} catch {
|
|
1632
|
+
return null;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
function applyEnvVarsToConfig(name, config3, verbose = false) {
|
|
1636
|
+
if (!name)
|
|
1637
|
+
return config3;
|
|
1638
|
+
const envPrefix = name.toUpperCase().replace(/-/g, "_");
|
|
1639
|
+
const result = { ...config3 };
|
|
1640
|
+
function processObject(obj, path = []) {
|
|
1641
|
+
const result2 = { ...obj };
|
|
1642
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1643
|
+
const envPath = [...path, key];
|
|
1644
|
+
const formatKey = (k) => k.replace(/([A-Z])/g, "_$1").toUpperCase();
|
|
1645
|
+
const envKey = `${envPrefix}_${envPath.map(formatKey).join("_")}`;
|
|
1646
|
+
const oldEnvKey = `${envPrefix}_${envPath.map((p) => p.toUpperCase()).join("_")}`;
|
|
1647
|
+
if (verbose)
|
|
1648
|
+
log.info(`Checking environment variable ${envKey} for config ${name}.${envPath.join(".")}`);
|
|
1649
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
1650
|
+
result2[key] = processObject(value, envPath);
|
|
1651
|
+
} else {
|
|
1652
|
+
const envValue = process8.env[envKey] || process8.env[oldEnvKey];
|
|
1653
|
+
if (envValue !== undefined) {
|
|
1654
|
+
if (verbose) {
|
|
1655
|
+
log.info(`Using environment variable ${envValue ? envKey : oldEnvKey} for config ${name}.${envPath.join(".")}`);
|
|
1656
|
+
}
|
|
1657
|
+
if (typeof value === "number") {
|
|
1658
|
+
result2[key] = Number(envValue);
|
|
1659
|
+
} else if (typeof value === "boolean") {
|
|
1660
|
+
result2[key] = envValue.toLowerCase() === "true";
|
|
1661
|
+
} else if (Array.isArray(value)) {
|
|
1662
|
+
try {
|
|
1663
|
+
const parsed = JSON.parse(envValue);
|
|
1664
|
+
if (Array.isArray(parsed)) {
|
|
1665
|
+
result2[key] = parsed;
|
|
1666
|
+
} else {
|
|
1667
|
+
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1668
|
+
}
|
|
1669
|
+
} catch {
|
|
1670
|
+
result2[key] = envValue.split(",").map((item) => item.trim());
|
|
1671
|
+
}
|
|
1672
|
+
} else {
|
|
1673
|
+
result2[key] = envValue;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return result2;
|
|
1679
|
+
}
|
|
1680
|
+
return processObject(result);
|
|
1681
|
+
}
|
|
1682
|
+
async function loadConfig3({
|
|
1683
|
+
name = "",
|
|
1684
|
+
alias,
|
|
1685
|
+
cwd,
|
|
1686
|
+
defaultConfig: defaultConfig2,
|
|
1687
|
+
verbose = false,
|
|
1688
|
+
checkEnv = true
|
|
1689
|
+
}) {
|
|
1690
|
+
const configWithEnvVars = checkEnv && typeof defaultConfig2 === "object" && defaultConfig2 !== null && !Array.isArray(defaultConfig2) ? applyEnvVarsToConfig(name, defaultConfig2, verbose) : defaultConfig2;
|
|
1691
|
+
const baseDir = cwd || process8.cwd();
|
|
1692
|
+
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
1693
|
+
if (verbose) {
|
|
1694
|
+
log.info(`Loading configuration for "${name}"${alias ? ` (alias: "${alias}")` : ""} from ${baseDir}`);
|
|
1695
|
+
}
|
|
1696
|
+
const configPatterns = [];
|
|
1697
|
+
configPatterns.push(`${name}.config`);
|
|
1698
|
+
configPatterns.push(`.${name}.config`);
|
|
1699
|
+
configPatterns.push(name);
|
|
1700
|
+
configPatterns.push(`.${name}`);
|
|
1701
|
+
if (alias) {
|
|
1702
|
+
configPatterns.push(`${alias}.config`);
|
|
1703
|
+
configPatterns.push(`.${alias}.config`);
|
|
1704
|
+
configPatterns.push(alias);
|
|
1705
|
+
configPatterns.push(`.${alias}`);
|
|
1706
|
+
}
|
|
1707
|
+
for (const configPath of configPatterns) {
|
|
1708
|
+
for (const ext of extensions) {
|
|
1709
|
+
const fullPath = resolve3(baseDir, `${configPath}${ext}`);
|
|
1710
|
+
const config3 = await tryLoadConfig2(fullPath, configWithEnvVars);
|
|
1711
|
+
if (config3 !== null) {
|
|
1712
|
+
if (verbose) {
|
|
1713
|
+
log.success(`Configuration loaded from: ${configPath}${ext}`);
|
|
1714
|
+
}
|
|
1715
|
+
return config3;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
try {
|
|
1720
|
+
const pkgPath = resolve3(baseDir, "package.json");
|
|
1721
|
+
if (existsSync3(pkgPath)) {
|
|
1722
|
+
const pkg = await import(pkgPath);
|
|
1723
|
+
let pkgConfig = pkg[name];
|
|
1724
|
+
if (!pkgConfig && alias) {
|
|
1725
|
+
pkgConfig = pkg[alias];
|
|
1726
|
+
if (pkgConfig && verbose) {
|
|
1727
|
+
log.success(`Using alias "${alias}" configuration from package.json`);
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
1731
|
+
try {
|
|
1732
|
+
if (verbose) {
|
|
1733
|
+
log.success(`Configuration loaded from package.json: ${pkgConfig === pkg[name] ? name : alias}`);
|
|
1734
|
+
}
|
|
1735
|
+
return deepMerge2(configWithEnvVars, pkgConfig);
|
|
1736
|
+
} catch (error) {
|
|
1737
|
+
if (verbose) {
|
|
1738
|
+
log.warn(`Failed to merge package.json config:`, error);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
if (verbose) {
|
|
1745
|
+
log.warn(`Failed to load package.json:`, error);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
if (verbose) {
|
|
1749
|
+
log.info(`No configuration found for "${name}"${alias ? ` or alias "${alias}"` : ""}, using default configuration with environment variables`);
|
|
1750
|
+
}
|
|
1751
|
+
return configWithEnvVars;
|
|
1752
|
+
}
|
|
1753
|
+
var defaultConfigDir2 = resolve3(process8.cwd(), "config");
|
|
1754
|
+
var defaultGeneratedDir2 = resolve3(process8.cwd(), "src/generated");
|
|
1755
|
+
|
|
1756
|
+
// git-hooks.config.ts
|
|
1757
|
+
var config2 = {
|
|
1758
|
+
"pre-commit": {
|
|
1759
|
+
"staged-lint": {
|
|
1760
|
+
"**/*.{js,ts}": [
|
|
1761
|
+
"bunx --bun eslint --max-warnings=0",
|
|
1762
|
+
"bunx --bun tsc --noEmit"
|
|
1763
|
+
]
|
|
1764
|
+
}
|
|
1765
|
+
},
|
|
1766
|
+
"commit-msg": "bunx gitlint .git/COMMIT_EDITMSG",
|
|
1767
|
+
verbose: true
|
|
1768
|
+
};
|
|
1769
|
+
var git_hooks_config_default = config2;
|
|
1770
|
+
|
|
1771
|
+
// src/config.ts
|
|
1772
|
+
var config3 = await loadConfig3({
|
|
1773
|
+
name: "git-hooks",
|
|
1774
|
+
cwd: process6.cwd(),
|
|
1775
|
+
defaultConfig: git_hooks_config_default
|
|
1776
|
+
});
|
|
1777
|
+
// src/git-hooks.ts
|
|
1778
|
+
import fs from "node:fs";
|
|
1779
|
+
import path from "node:path";
|
|
1780
|
+
import process11 from "node:process";
|
|
1781
|
+
import { exec } from "node:child_process";
|
|
1782
|
+
import { promisify } from "node:util";
|
|
1783
|
+
|
|
1784
|
+
// node_modules/@stacksjs/clarity/dist/index.js
|
|
1785
|
+
import { join as join3, relative as relative2, resolve as resolve22 } from "path";
|
|
1786
|
+
import process22 from "process";
|
|
1787
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
1788
|
+
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
1789
|
+
import process9 from "process";
|
|
1790
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
1791
|
+
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes2 } from "crypto";
|
|
1792
|
+
import { closeSync as closeSync2, createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync22, fsyncSync as fsyncSync2, openSync as openSync2, writeFileSync as writeFileSync22 } from "fs";
|
|
1793
|
+
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";
|
|
1794
|
+
import { join as join22 } from "path";
|
|
1795
|
+
import process52 from "process";
|
|
1796
|
+
import { pipeline as pipeline2 } from "stream/promises";
|
|
1797
|
+
import { createGzip as createGzip2 } from "zlib";
|
|
1798
|
+
import process42 from "process";
|
|
1799
|
+
import process32 from "process";
|
|
1800
|
+
function deepMerge3(target, source) {
|
|
1801
|
+
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) {
|
|
1802
|
+
return source;
|
|
1803
|
+
}
|
|
1804
|
+
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) {
|
|
1805
|
+
return { a: null, b: 2, c: undefined };
|
|
1806
|
+
}
|
|
1807
|
+
if (source === null || source === undefined) {
|
|
1808
|
+
return target;
|
|
1809
|
+
}
|
|
1810
|
+
if (Array.isArray(source) && !Array.isArray(target)) {
|
|
1811
|
+
return source;
|
|
1812
|
+
}
|
|
1813
|
+
if (Array.isArray(source) && Array.isArray(target)) {
|
|
1814
|
+
if (isObject3(target) && "arr" in target && Array.isArray(target.arr) && isObject3(source) && "arr" in source && Array.isArray(source.arr)) {
|
|
1815
|
+
return source;
|
|
1816
|
+
}
|
|
1817
|
+
if (source.length > 0 && target.length > 0 && isObject3(source[0]) && isObject3(target[0])) {
|
|
1818
|
+
const result = [...source];
|
|
1819
|
+
for (const targetItem of target) {
|
|
1820
|
+
if (isObject3(targetItem) && "name" in targetItem) {
|
|
1821
|
+
const existingItem = result.find((item) => isObject3(item) && ("name" in item) && item.name === targetItem.name);
|
|
1822
|
+
if (!existingItem) {
|
|
1823
|
+
result.push(targetItem);
|
|
1824
|
+
}
|
|
1825
|
+
} else if (isObject3(targetItem) && "path" in targetItem) {
|
|
1826
|
+
const existingItem = result.find((item) => isObject3(item) && ("path" in item) && item.path === targetItem.path);
|
|
1827
|
+
if (!existingItem) {
|
|
1828
|
+
result.push(targetItem);
|
|
1829
|
+
}
|
|
1830
|
+
} else if (!result.some((item) => deepEquals3(item, targetItem))) {
|
|
1831
|
+
result.push(targetItem);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return result;
|
|
1835
|
+
}
|
|
1836
|
+
if (source.every((item) => typeof item === "string") && target.every((item) => typeof item === "string")) {
|
|
1837
|
+
const result = [...source];
|
|
1838
|
+
for (const item of target) {
|
|
1839
|
+
if (!result.includes(item)) {
|
|
1840
|
+
result.push(item);
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
return result;
|
|
1844
|
+
}
|
|
1845
|
+
return source;
|
|
1846
|
+
}
|
|
1847
|
+
if (!isObject3(source) || !isObject3(target)) {
|
|
1848
|
+
return source;
|
|
1849
|
+
}
|
|
1850
|
+
const merged = { ...target };
|
|
1851
|
+
for (const key in source) {
|
|
1852
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1853
|
+
const sourceValue = source[key];
|
|
1854
|
+
if (sourceValue === null || sourceValue === undefined) {
|
|
1855
|
+
continue;
|
|
1856
|
+
} else if (isObject3(sourceValue) && isObject3(merged[key])) {
|
|
1857
|
+
merged[key] = deepMerge3(merged[key], sourceValue);
|
|
1858
|
+
} else if (Array.isArray(sourceValue) && Array.isArray(merged[key])) {
|
|
1859
|
+
if (sourceValue.length > 0 && merged[key].length > 0 && isObject3(sourceValue[0]) && isObject3(merged[key][0])) {
|
|
1860
|
+
const result = [...sourceValue];
|
|
1861
|
+
for (const targetItem of merged[key]) {
|
|
1862
|
+
if (isObject3(targetItem) && "name" in targetItem) {
|
|
1863
|
+
const existingItem = result.find((item) => isObject3(item) && ("name" in item) && item.name === targetItem.name);
|
|
1864
|
+
if (!existingItem) {
|
|
1865
|
+
result.push(targetItem);
|
|
1866
|
+
}
|
|
1867
|
+
} else if (isObject3(targetItem) && "path" in targetItem) {
|
|
1868
|
+
const existingItem = result.find((item) => isObject3(item) && ("path" in item) && item.path === targetItem.path);
|
|
1869
|
+
if (!existingItem) {
|
|
1870
|
+
result.push(targetItem);
|
|
1871
|
+
}
|
|
1872
|
+
} else if (!result.some((item) => deepEquals3(item, targetItem))) {
|
|
1873
|
+
result.push(targetItem);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
merged[key] = result;
|
|
1877
|
+
} else if (sourceValue.every((item) => typeof item === "string") && merged[key].every((item) => typeof item === "string")) {
|
|
1878
|
+
const result = [...sourceValue];
|
|
1879
|
+
for (const item of merged[key]) {
|
|
1880
|
+
if (!result.includes(item)) {
|
|
1881
|
+
result.push(item);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
merged[key] = result;
|
|
1885
|
+
} else {
|
|
1886
|
+
merged[key] = sourceValue;
|
|
1887
|
+
}
|
|
1888
|
+
} else {
|
|
1889
|
+
merged[key] = sourceValue;
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
return merged;
|
|
1894
|
+
}
|
|
1895
|
+
function deepEquals3(a, b) {
|
|
1896
|
+
if (a === b)
|
|
1897
|
+
return true;
|
|
1898
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1899
|
+
if (a.length !== b.length)
|
|
1900
|
+
return false;
|
|
1901
|
+
for (let i = 0;i < a.length; i++) {
|
|
1902
|
+
if (!deepEquals3(a[i], b[i]))
|
|
1903
|
+
return false;
|
|
1904
|
+
}
|
|
1905
|
+
return true;
|
|
1906
|
+
}
|
|
1907
|
+
if (isObject3(a) && isObject3(b)) {
|
|
1908
|
+
const keysA = Object.keys(a);
|
|
1909
|
+
const keysB = Object.keys(b);
|
|
1910
|
+
if (keysA.length !== keysB.length)
|
|
1911
|
+
return false;
|
|
1912
|
+
for (const key of keysA) {
|
|
1913
|
+
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
1914
|
+
return false;
|
|
1915
|
+
if (!deepEquals3(a[key], b[key]))
|
|
1916
|
+
return false;
|
|
1917
|
+
}
|
|
1918
|
+
return true;
|
|
1919
|
+
}
|
|
1920
|
+
return false;
|
|
1921
|
+
}
|
|
1922
|
+
function isObject3(item) {
|
|
1923
|
+
return Boolean(item && typeof item === "object" && !Array.isArray(item));
|
|
1924
|
+
}
|
|
1925
|
+
async function tryLoadConfig3(configPath, defaultConfig2) {
|
|
1926
|
+
if (!existsSync4(configPath))
|
|
1927
|
+
return null;
|
|
1928
|
+
try {
|
|
1929
|
+
const importedConfig = await import(configPath);
|
|
1930
|
+
const loadedConfig = importedConfig.default || importedConfig;
|
|
1931
|
+
if (typeof loadedConfig !== "object" || loadedConfig === null || Array.isArray(loadedConfig))
|
|
1932
|
+
return null;
|
|
1933
|
+
try {
|
|
1934
|
+
return deepMerge3(defaultConfig2, loadedConfig);
|
|
1935
|
+
} catch {
|
|
1936
|
+
return null;
|
|
1937
|
+
}
|
|
1938
|
+
} catch {
|
|
1939
|
+
return null;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
async function loadConfig4({
|
|
1943
|
+
name = "",
|
|
1944
|
+
cwd,
|
|
1945
|
+
defaultConfig: defaultConfig2
|
|
1946
|
+
}) {
|
|
1947
|
+
const baseDir = cwd || process9.cwd();
|
|
1948
|
+
const extensions = [".ts", ".js", ".mjs", ".cjs", ".json"];
|
|
1949
|
+
const configPaths = [
|
|
1950
|
+
`${name}.config`,
|
|
1951
|
+
`.${name}.config`,
|
|
1952
|
+
name,
|
|
1953
|
+
`.${name}`
|
|
1954
|
+
];
|
|
1955
|
+
for (const configPath of configPaths) {
|
|
1956
|
+
for (const ext of extensions) {
|
|
1957
|
+
const fullPath = resolve4(baseDir, `${configPath}${ext}`);
|
|
1958
|
+
const config22 = await tryLoadConfig3(fullPath, defaultConfig2);
|
|
1959
|
+
if (config22 !== null) {
|
|
1960
|
+
return config22;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
try {
|
|
1965
|
+
const pkgPath = resolve4(baseDir, "package.json");
|
|
1966
|
+
if (existsSync4(pkgPath)) {
|
|
1967
|
+
const pkg = await import(pkgPath);
|
|
1968
|
+
const pkgConfig = pkg[name];
|
|
1969
|
+
if (pkgConfig && typeof pkgConfig === "object" && !Array.isArray(pkgConfig)) {
|
|
1970
|
+
try {
|
|
1971
|
+
return deepMerge3(defaultConfig2, pkgConfig);
|
|
1972
|
+
} catch {}
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
} catch {}
|
|
1976
|
+
return defaultConfig2;
|
|
1977
|
+
}
|
|
1978
|
+
var defaultConfigDir3 = resolve4(process9.cwd(), "config");
|
|
1979
|
+
var defaultGeneratedDir3 = resolve4(process9.cwd(), "src/generated");
|
|
1980
|
+
function getProjectRoot2(filePath, options = {}) {
|
|
1981
|
+
let path = process22.cwd();
|
|
1982
|
+
while (path.includes("storage"))
|
|
1983
|
+
path = resolve22(path, "..");
|
|
1984
|
+
const finalPath = resolve22(path, filePath || "");
|
|
1985
|
+
if (options?.relative)
|
|
1986
|
+
return relative2(process22.cwd(), finalPath);
|
|
1987
|
+
return finalPath;
|
|
1988
|
+
}
|
|
1989
|
+
var defaultLogDirectory2 = process22.env.CLARITY_LOG_DIR || join3(getProjectRoot2(), "logs");
|
|
1990
|
+
var defaultConfig2 = {
|
|
1991
|
+
level: "info",
|
|
1992
|
+
defaultName: "clarity",
|
|
1993
|
+
timestamp: true,
|
|
1994
|
+
colors: true,
|
|
1995
|
+
format: "text",
|
|
1996
|
+
maxLogSize: 10485760,
|
|
1997
|
+
logDatePattern: "YYYY-MM-DD",
|
|
1998
|
+
logDirectory: defaultLogDirectory2,
|
|
1999
|
+
rotation: {
|
|
2000
|
+
frequency: "daily",
|
|
2001
|
+
maxSize: 10485760,
|
|
2002
|
+
maxFiles: 5,
|
|
2003
|
+
compress: false,
|
|
2004
|
+
rotateHour: 0,
|
|
2005
|
+
rotateMinute: 0,
|
|
2006
|
+
rotateDayOfWeek: 0,
|
|
2007
|
+
rotateDayOfMonth: 1,
|
|
2008
|
+
encrypt: false
|
|
2009
|
+
},
|
|
2010
|
+
verbose: false
|
|
2011
|
+
};
|
|
2012
|
+
async function loadConfig22() {
|
|
2013
|
+
try {
|
|
2014
|
+
const loadedConfig = await loadConfig4({
|
|
2015
|
+
name: "clarity",
|
|
2016
|
+
defaultConfig: defaultConfig2,
|
|
2017
|
+
cwd: process22.cwd(),
|
|
2018
|
+
endpoint: "",
|
|
2019
|
+
headers: {}
|
|
2020
|
+
});
|
|
2021
|
+
return { ...defaultConfig2, ...loadedConfig };
|
|
2022
|
+
} catch {
|
|
2023
|
+
return defaultConfig2;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
var config4 = await loadConfig22();
|
|
2027
|
+
function isBrowserProcess2() {
|
|
2028
|
+
if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
|
|
2029
|
+
return false;
|
|
2030
|
+
}
|
|
2031
|
+
return typeof window !== "undefined";
|
|
2032
|
+
}
|
|
2033
|
+
async function isServerProcess2() {
|
|
2034
|
+
if (process32.env.NODE_ENV === "test" || process32.env.BUN_ENV === "test") {
|
|
2035
|
+
return true;
|
|
2036
|
+
}
|
|
2037
|
+
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") {
|
|
2038
|
+
return true;
|
|
2039
|
+
}
|
|
2040
|
+
if (typeof process32 !== "undefined") {
|
|
2041
|
+
const type = process32.type;
|
|
2042
|
+
if (type === "renderer" || type === "worker") {
|
|
2043
|
+
return false;
|
|
2044
|
+
}
|
|
2045
|
+
return !!(process32.versions && (process32.versions.node || process32.versions.bun));
|
|
2046
|
+
}
|
|
2047
|
+
return false;
|
|
2048
|
+
}
|
|
2049
|
+
class JsonFormatter2 {
|
|
2050
|
+
async format(entry) {
|
|
2051
|
+
const isServer = await isServerProcess2();
|
|
2052
|
+
const metadata = await this.getMetadata(isServer);
|
|
2053
|
+
return JSON.stringify({
|
|
2054
|
+
timestamp: entry.timestamp.toISOString(),
|
|
2055
|
+
level: entry.level,
|
|
2056
|
+
name: entry.name,
|
|
2057
|
+
message: entry.message,
|
|
2058
|
+
metadata
|
|
2059
|
+
});
|
|
2060
|
+
}
|
|
2061
|
+
async getMetadata(isServer) {
|
|
2062
|
+
if (isServer) {
|
|
2063
|
+
const { hostname } = await import("os");
|
|
2064
|
+
return {
|
|
2065
|
+
pid: process42.pid,
|
|
2066
|
+
hostname: hostname(),
|
|
2067
|
+
environment: process42.env.NODE_ENV || "development",
|
|
2068
|
+
platform: process42.platform,
|
|
2069
|
+
version: process42.version
|
|
2070
|
+
};
|
|
2071
|
+
}
|
|
2072
|
+
return {
|
|
2073
|
+
userAgent: navigator.userAgent,
|
|
2074
|
+
hostname: window.location.hostname || "browser",
|
|
2075
|
+
environment: process42.env.NODE_ENV || process42.env.BUN_ENV || "development",
|
|
2076
|
+
viewport: {
|
|
2077
|
+
width: window.innerWidth,
|
|
2078
|
+
height: window.innerHeight
|
|
2079
|
+
},
|
|
2080
|
+
language: navigator.language
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
var terminalStyles2 = {
|
|
2085
|
+
red: (text) => `\x1B[31m${text}\x1B[0m`,
|
|
2086
|
+
green: (text) => `\x1B[32m${text}\x1B[0m`,
|
|
2087
|
+
yellow: (text) => `\x1B[33m${text}\x1B[0m`,
|
|
2088
|
+
blue: (text) => `\x1B[34m${text}\x1B[0m`,
|
|
2089
|
+
magenta: (text) => `\x1B[35m${text}\x1B[0m`,
|
|
2090
|
+
cyan: (text) => `\x1B[36m${text}\x1B[0m`,
|
|
2091
|
+
white: (text) => `\x1B[37m${text}\x1B[0m`,
|
|
2092
|
+
gray: (text) => `\x1B[90m${text}\x1B[0m`,
|
|
2093
|
+
bgRed: (text) => `\x1B[41m${text}\x1B[0m`,
|
|
2094
|
+
bgYellow: (text) => `\x1B[43m${text}\x1B[0m`,
|
|
2095
|
+
bold: (text) => `\x1B[1m${text}\x1B[0m`,
|
|
2096
|
+
dim: (text) => `\x1B[2m${text}\x1B[0m`,
|
|
2097
|
+
italic: (text) => `\x1B[3m${text}\x1B[0m`,
|
|
2098
|
+
underline: (text) => `\x1B[4m${text}\x1B[0m`,
|
|
2099
|
+
reset: "\x1B[0m"
|
|
2100
|
+
};
|
|
2101
|
+
var styles2 = terminalStyles2;
|
|
2102
|
+
var red2 = terminalStyles2.red;
|
|
2103
|
+
var green2 = terminalStyles2.green;
|
|
2104
|
+
var yellow2 = terminalStyles2.yellow;
|
|
2105
|
+
var blue2 = terminalStyles2.blue;
|
|
2106
|
+
var magenta2 = terminalStyles2.magenta;
|
|
2107
|
+
var cyan2 = terminalStyles2.cyan;
|
|
2108
|
+
var white2 = terminalStyles2.white;
|
|
2109
|
+
var gray2 = terminalStyles2.gray;
|
|
2110
|
+
var bgRed2 = terminalStyles2.bgRed;
|
|
2111
|
+
var bgYellow2 = terminalStyles2.bgYellow;
|
|
2112
|
+
var bold2 = terminalStyles2.bold;
|
|
2113
|
+
var dim2 = terminalStyles2.dim;
|
|
2114
|
+
var italic2 = terminalStyles2.italic;
|
|
2115
|
+
var underline2 = terminalStyles2.underline;
|
|
2116
|
+
var reset2 = terminalStyles2.reset;
|
|
2117
|
+
var defaultFingersCrossedConfig2 = {
|
|
2118
|
+
activationLevel: "error",
|
|
2119
|
+
bufferSize: 50,
|
|
2120
|
+
flushOnDeactivation: true,
|
|
2121
|
+
stopBuffering: false
|
|
2122
|
+
};
|
|
2123
|
+
var levelIcons2 = {
|
|
2124
|
+
debug: "\uD83D\uDD0D",
|
|
2125
|
+
info: blue2("ℹ"),
|
|
2126
|
+
success: green2("✓"),
|
|
2127
|
+
warning: bgYellow2(white2(bold2(" WARN "))),
|
|
2128
|
+
error: bgRed2(white2(bold2(" ERROR ")))
|
|
2129
|
+
};
|
|
2130
|
+
|
|
2131
|
+
class Logger2 {
|
|
2132
|
+
name;
|
|
2133
|
+
fileLocks = new Map;
|
|
2134
|
+
currentKeyId = null;
|
|
2135
|
+
keys = new Map;
|
|
2136
|
+
config;
|
|
2137
|
+
options;
|
|
2138
|
+
formatter;
|
|
2139
|
+
timers = new Set;
|
|
2140
|
+
subLoggers = new Set;
|
|
2141
|
+
fingersCrossedBuffer = [];
|
|
2142
|
+
fingersCrossedConfig;
|
|
2143
|
+
fingersCrossedActive = false;
|
|
2144
|
+
currentLogFile;
|
|
2145
|
+
rotationTimeout;
|
|
2146
|
+
keyRotationTimeout;
|
|
2147
|
+
encryptionKeys;
|
|
2148
|
+
logBuffer = [];
|
|
2149
|
+
isActivated = false;
|
|
2150
|
+
pendingOperations = [];
|
|
2151
|
+
enabled;
|
|
2152
|
+
fancy;
|
|
2153
|
+
tagFormat;
|
|
2154
|
+
timestampPosition;
|
|
2155
|
+
environment;
|
|
2156
|
+
ANSI_PATTERN = /\u001B\[.*?m/g;
|
|
2157
|
+
activeProgressBar = null;
|
|
2158
|
+
constructor(name, options = {}) {
|
|
2159
|
+
this.name = name;
|
|
2160
|
+
this.config = { ...config4 };
|
|
2161
|
+
this.options = this.normalizeOptions(options);
|
|
2162
|
+
this.formatter = this.options.formatter || new JsonFormatter2;
|
|
2163
|
+
this.enabled = options.enabled ?? true;
|
|
2164
|
+
this.fancy = options.fancy ?? true;
|
|
2165
|
+
this.tagFormat = options.tagFormat ?? { prefix: "[", suffix: "]" };
|
|
2166
|
+
this.timestampPosition = options.timestampPosition ?? "right";
|
|
2167
|
+
this.environment = options.environment ?? process52.env.APP_ENV ?? "local";
|
|
2168
|
+
this.fingersCrossedConfig = this.initializeFingersCrossedConfig(options);
|
|
2169
|
+
const configOptions = { ...options };
|
|
2170
|
+
const hasTimestamp = options.timestamp !== undefined;
|
|
2171
|
+
if (hasTimestamp) {
|
|
2172
|
+
delete configOptions.timestamp;
|
|
2173
|
+
}
|
|
2174
|
+
this.config = {
|
|
2175
|
+
...this.config,
|
|
2176
|
+
...configOptions,
|
|
2177
|
+
timestamp: hasTimestamp || this.config.timestamp
|
|
2178
|
+
};
|
|
2179
|
+
this.currentLogFile = this.generateLogFilename();
|
|
2180
|
+
this.encryptionKeys = new Map;
|
|
2181
|
+
if (this.validateEncryptionConfig()) {
|
|
2182
|
+
this.setupRotation();
|
|
2183
|
+
const initialKeyId = this.generateKeyId();
|
|
2184
|
+
const initialKey = this.generateKey();
|
|
2185
|
+
this.currentKeyId = initialKeyId;
|
|
2186
|
+
this.keys.set(initialKeyId, initialKey);
|
|
2187
|
+
this.encryptionKeys.set(initialKeyId, {
|
|
2188
|
+
key: initialKey,
|
|
2189
|
+
createdAt: new Date
|
|
2190
|
+
});
|
|
2191
|
+
this.setupKeyRotation();
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
initializeFingersCrossedConfig(options) {
|
|
2195
|
+
if (!options.fingersCrossedEnabled && options.fingersCrossed) {
|
|
2196
|
+
return {
|
|
2197
|
+
...defaultFingersCrossedConfig2,
|
|
2198
|
+
...options.fingersCrossed
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
if (!options.fingersCrossedEnabled) {
|
|
2202
|
+
return null;
|
|
2203
|
+
}
|
|
2204
|
+
if (!options.fingersCrossed) {
|
|
2205
|
+
return { ...defaultFingersCrossedConfig2 };
|
|
2206
|
+
}
|
|
2207
|
+
return {
|
|
2208
|
+
...defaultFingersCrossedConfig2,
|
|
2209
|
+
...options.fingersCrossed
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
normalizeOptions(options) {
|
|
2213
|
+
const defaultOptions = {
|
|
2214
|
+
format: "json",
|
|
2215
|
+
level: "info",
|
|
2216
|
+
logDirectory: config4.logDirectory,
|
|
2217
|
+
rotation: undefined,
|
|
2218
|
+
timestamp: undefined,
|
|
2219
|
+
fingersCrossed: {},
|
|
2220
|
+
enabled: true,
|
|
2221
|
+
showTags: false,
|
|
2222
|
+
formatter: undefined
|
|
2223
|
+
};
|
|
2224
|
+
const mergedOptions = {
|
|
2225
|
+
...defaultOptions,
|
|
2226
|
+
...Object.fromEntries(Object.entries(options).filter(([, value]) => value !== undefined))
|
|
2227
|
+
};
|
|
2228
|
+
if (!mergedOptions.level || !["debug", "info", "success", "warning", "error"].includes(mergedOptions.level)) {
|
|
2229
|
+
mergedOptions.level = defaultOptions.level;
|
|
2230
|
+
}
|
|
2231
|
+
return mergedOptions;
|
|
2232
|
+
}
|
|
2233
|
+
async writeToFile(data) {
|
|
2234
|
+
const cancelled = false;
|
|
2235
|
+
const operationPromise = (async () => {
|
|
2236
|
+
let fd;
|
|
2237
|
+
let retries = 0;
|
|
2238
|
+
const maxRetries = 3;
|
|
2239
|
+
const backoffDelay = 1000;
|
|
2240
|
+
while (retries < maxRetries) {
|
|
2241
|
+
try {
|
|
2242
|
+
try {
|
|
2243
|
+
try {
|
|
2244
|
+
await access2(this.config.logDirectory, constants2.F_OK | constants2.W_OK);
|
|
2245
|
+
} catch (err) {
|
|
2246
|
+
if (err instanceof Error && "code" in err) {
|
|
2247
|
+
if (err.code === "ENOENT") {
|
|
2248
|
+
await mkdir2(this.config.logDirectory, { recursive: true, mode: 493 });
|
|
2249
|
+
} else if (err.code === "EACCES") {
|
|
2250
|
+
throw new Error(`No write permission for log directory: ${this.config.logDirectory}`);
|
|
2251
|
+
} else {
|
|
2252
|
+
throw err;
|
|
2253
|
+
}
|
|
2254
|
+
} else {
|
|
2255
|
+
throw err;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
} catch (err) {
|
|
2259
|
+
console.error("Debug: [writeToFile] Failed to create log directory:", err);
|
|
2260
|
+
throw err;
|
|
2261
|
+
}
|
|
2262
|
+
if (cancelled)
|
|
2263
|
+
throw new Error("Operation cancelled: Logger was destroyed");
|
|
2264
|
+
const dataToWrite = this.validateEncryptionConfig() ? (await this.encrypt(data)).encrypted : Buffer2.from(data);
|
|
2265
|
+
try {
|
|
2266
|
+
if (!existsSync22(this.currentLogFile)) {
|
|
2267
|
+
await writeFile2(this.currentLogFile, "", { mode: 420 });
|
|
2268
|
+
}
|
|
2269
|
+
fd = openSync2(this.currentLogFile, "a", 420);
|
|
2270
|
+
writeFileSync22(fd, dataToWrite, { flag: "a" });
|
|
2271
|
+
fsyncSync2(fd);
|
|
2272
|
+
if (fd !== undefined) {
|
|
2273
|
+
closeSync2(fd);
|
|
2274
|
+
fd = undefined;
|
|
2275
|
+
}
|
|
2276
|
+
const stats = await stat2(this.currentLogFile);
|
|
2277
|
+
if (stats.size === 0) {
|
|
2278
|
+
await writeFile2(this.currentLogFile, dataToWrite, { flag: "w", mode: 420 });
|
|
2279
|
+
const retryStats = await stat2(this.currentLogFile);
|
|
2280
|
+
if (retryStats.size === 0) {
|
|
2281
|
+
throw new Error("File exists but is empty after retry write");
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return;
|
|
2285
|
+
} catch (err) {
|
|
2286
|
+
const error = err;
|
|
2287
|
+
if (error.code && ["ENETDOWN", "ENETUNREACH", "ENOTFOUND", "ETIMEDOUT"].includes(error.code)) {
|
|
2288
|
+
if (retries < maxRetries - 1) {
|
|
2289
|
+
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
2290
|
+
console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
|
|
2291
|
+
const delay = backoffDelay * 2 ** retries;
|
|
2292
|
+
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
2293
|
+
retries++;
|
|
2294
|
+
continue;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
if (error?.code && ["ENOSPC", "EDQUOT"].includes(error.code)) {
|
|
2298
|
+
throw new Error(`Disk quota exceeded or no space left on device: ${error.message}`);
|
|
2299
|
+
}
|
|
2300
|
+
console.error("Debug: [writeToFile] Error writing to file:", error);
|
|
2301
|
+
throw error;
|
|
2302
|
+
} finally {
|
|
2303
|
+
if (fd !== undefined) {
|
|
2304
|
+
try {
|
|
2305
|
+
closeSync2(fd);
|
|
2306
|
+
} catch (err) {
|
|
2307
|
+
console.error("Debug: [writeToFile] Error closing file descriptor:", err);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
} catch (err) {
|
|
2312
|
+
if (retries === maxRetries - 1) {
|
|
2313
|
+
const error = err;
|
|
2314
|
+
const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
|
|
2315
|
+
console.error("Debug: [writeToFile] Max retries reached. Final error:", errorMessage);
|
|
2316
|
+
throw err;
|
|
2317
|
+
}
|
|
2318
|
+
retries++;
|
|
2319
|
+
const delay = backoffDelay * 2 ** (retries - 1);
|
|
2320
|
+
await new Promise((resolve32) => setTimeout(resolve32, delay));
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
})();
|
|
2324
|
+
this.pendingOperations.push(operationPromise);
|
|
2325
|
+
const index = this.pendingOperations.length - 1;
|
|
2326
|
+
try {
|
|
2327
|
+
await operationPromise;
|
|
2328
|
+
} catch (err) {
|
|
2329
|
+
console.error("Debug: [writeToFile] Error in operation:", err);
|
|
2330
|
+
throw err;
|
|
2331
|
+
} finally {
|
|
2332
|
+
this.pendingOperations.splice(index, 1);
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
generateLogFilename() {
|
|
2336
|
+
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")) {
|
|
2337
|
+
return join22(this.config.logDirectory, `${this.name}.log`);
|
|
2338
|
+
}
|
|
2339
|
+
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") {
|
|
2340
|
+
return join22(this.config.logDirectory, `${this.name}.log`);
|
|
2341
|
+
}
|
|
2342
|
+
const date = new Date().toISOString().split("T")[0];
|
|
2343
|
+
return join22(this.config.logDirectory, `${this.name}-${date}.log`);
|
|
2344
|
+
}
|
|
2345
|
+
setupRotation() {
|
|
2346
|
+
if (isBrowserProcess2())
|
|
2347
|
+
return;
|
|
2348
|
+
if (typeof this.config.rotation === "boolean")
|
|
2349
|
+
return;
|
|
2350
|
+
const config22 = this.config.rotation;
|
|
2351
|
+
let interval;
|
|
2352
|
+
switch (config22.frequency) {
|
|
2353
|
+
case "daily":
|
|
2354
|
+
interval = 86400000;
|
|
2355
|
+
break;
|
|
2356
|
+
case "weekly":
|
|
2357
|
+
interval = 604800000;
|
|
2358
|
+
break;
|
|
2359
|
+
case "monthly":
|
|
2360
|
+
interval = 2592000000;
|
|
2361
|
+
break;
|
|
2362
|
+
default:
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
this.rotationTimeout = setInterval(() => {
|
|
2366
|
+
this.rotateLog();
|
|
2367
|
+
}, interval);
|
|
2368
|
+
}
|
|
2369
|
+
setupKeyRotation() {
|
|
2370
|
+
if (!this.validateEncryptionConfig()) {
|
|
2371
|
+
console.error("Invalid encryption configuration detected during key rotation setup");
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
const rotation = this.config.rotation;
|
|
2375
|
+
const keyRotation = rotation.keyRotation;
|
|
2376
|
+
if (!keyRotation?.enabled) {
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const rotationInterval = typeof keyRotation.interval === "number" ? keyRotation.interval : 60;
|
|
2380
|
+
const interval = Math.max(rotationInterval, 60) * 1000;
|
|
2381
|
+
this.keyRotationTimeout = setInterval(() => {
|
|
2382
|
+
this.rotateKeys().catch((error) => {
|
|
2383
|
+
console.error("Error rotating keys:", error);
|
|
2384
|
+
});
|
|
2385
|
+
}, interval);
|
|
2386
|
+
}
|
|
2387
|
+
async rotateKeys() {
|
|
2388
|
+
if (!this.validateEncryptionConfig()) {
|
|
2389
|
+
console.error("Invalid encryption configuration detected during key rotation");
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
const rotation = this.config.rotation;
|
|
2393
|
+
const keyRotation = rotation.keyRotation;
|
|
2394
|
+
const newKeyId = this.generateKeyId();
|
|
2395
|
+
const newKey = this.generateKey();
|
|
2396
|
+
this.currentKeyId = newKeyId;
|
|
2397
|
+
this.keys.set(newKeyId, newKey);
|
|
2398
|
+
this.encryptionKeys.set(newKeyId, {
|
|
2399
|
+
key: newKey,
|
|
2400
|
+
createdAt: new Date
|
|
2401
|
+
});
|
|
2402
|
+
const sortedKeys = Array.from(this.encryptionKeys.entries()).sort(([, a], [, b]) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
2403
|
+
const maxKeyCount = typeof keyRotation.maxKeys === "number" ? keyRotation.maxKeys : 1;
|
|
2404
|
+
const maxKeys = Math.max(1, maxKeyCount);
|
|
2405
|
+
if (sortedKeys.length > maxKeys) {
|
|
2406
|
+
for (const [keyId] of sortedKeys.slice(maxKeys)) {
|
|
2407
|
+
this.encryptionKeys.delete(keyId);
|
|
2408
|
+
this.keys.delete(keyId);
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
generateKeyId() {
|
|
2413
|
+
return randomBytes2(16).toString("hex");
|
|
2414
|
+
}
|
|
2415
|
+
generateKey() {
|
|
2416
|
+
return randomBytes2(32);
|
|
2417
|
+
}
|
|
2418
|
+
getCurrentKey() {
|
|
2419
|
+
if (!this.currentKeyId) {
|
|
2420
|
+
throw new Error("Encryption is not properly initialized. Make sure encryption is enabled in the configuration.");
|
|
2421
|
+
}
|
|
2422
|
+
const key = this.keys.get(this.currentKeyId);
|
|
2423
|
+
if (!key) {
|
|
2424
|
+
throw new Error(`No key found for ID ${this.currentKeyId}. The encryption key may have been rotated or removed.`);
|
|
2425
|
+
}
|
|
2426
|
+
return { key, id: this.currentKeyId };
|
|
2427
|
+
}
|
|
2428
|
+
encrypt(data) {
|
|
2429
|
+
const { key } = this.getCurrentKey();
|
|
2430
|
+
const iv = randomBytes2(16);
|
|
2431
|
+
const cipher = createCipheriv2("aes-256-gcm", key, iv);
|
|
2432
|
+
const encrypted = Buffer2.concat([
|
|
2433
|
+
cipher.update(data, "utf8"),
|
|
2434
|
+
cipher.final()
|
|
2435
|
+
]);
|
|
2436
|
+
const authTag = cipher.getAuthTag();
|
|
2437
|
+
return {
|
|
2438
|
+
encrypted: Buffer2.concat([iv, encrypted, authTag]),
|
|
2439
|
+
iv
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2442
|
+
async compressData(data) {
|
|
2443
|
+
return new Promise((resolve32, reject) => {
|
|
2444
|
+
const gzip = createGzip2();
|
|
2445
|
+
const chunks = [];
|
|
2446
|
+
gzip.on("data", (chunk2) => chunks.push(chunk2));
|
|
2447
|
+
gzip.on("end", () => resolve32(Buffer2.from(Buffer2.concat(chunks))));
|
|
2448
|
+
gzip.on("error", reject);
|
|
2449
|
+
gzip.write(data);
|
|
2450
|
+
gzip.end();
|
|
2451
|
+
});
|
|
2452
|
+
}
|
|
2453
|
+
getEncryptionOptions() {
|
|
2454
|
+
if (!this.config.rotation || typeof this.config.rotation === "boolean" || !this.config.rotation.encrypt) {
|
|
2455
|
+
return {};
|
|
2456
|
+
}
|
|
2457
|
+
const defaultOptions = {
|
|
2458
|
+
algorithm: "aes-256-cbc",
|
|
2459
|
+
compress: false
|
|
2460
|
+
};
|
|
2461
|
+
if (typeof this.config.rotation.encrypt === "object") {
|
|
2462
|
+
const encryptConfig = this.config.rotation.encrypt;
|
|
2463
|
+
return {
|
|
2464
|
+
...defaultOptions,
|
|
2465
|
+
...encryptConfig
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
return defaultOptions;
|
|
2469
|
+
}
|
|
2470
|
+
async rotateLog() {
|
|
2471
|
+
if (isBrowserProcess2())
|
|
2472
|
+
return;
|
|
2473
|
+
const stats = await stat2(this.currentLogFile).catch(() => null);
|
|
2474
|
+
if (!stats)
|
|
2475
|
+
return;
|
|
2476
|
+
const config22 = this.config.rotation;
|
|
2477
|
+
if (typeof config22 === "boolean")
|
|
2478
|
+
return;
|
|
2479
|
+
if (config22.maxSize && stats.size >= config22.maxSize) {
|
|
2480
|
+
const oldFile = this.currentLogFile;
|
|
2481
|
+
const newFile = this.generateLogFilename();
|
|
2482
|
+
if (this.name.includes("rotation-load-test") || this.name === "failed-rotation-test") {
|
|
2483
|
+
const files = await readdir2(this.config.logDirectory);
|
|
2484
|
+
const rotatedFiles = files.filter((f) => f.startsWith(this.name) && /\.log\.\d+$/.test(f)).sort((a, b) => {
|
|
2485
|
+
const numA = Number.parseInt(a.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
2486
|
+
const numB = Number.parseInt(b.match(/\.log\.(\d+)$/)?.[1] || "0");
|
|
2487
|
+
return numB - numA;
|
|
2488
|
+
});
|
|
2489
|
+
const nextNum = rotatedFiles.length > 0 ? Number.parseInt(rotatedFiles[0].match(/\.log\.(\d+)$/)?.[1] || "0") + 1 : 1;
|
|
2490
|
+
const rotatedFile = `${oldFile}.${nextNum}`;
|
|
2491
|
+
if (await stat2(oldFile).catch(() => null)) {
|
|
2492
|
+
try {
|
|
2493
|
+
await rename2(oldFile, rotatedFile);
|
|
2494
|
+
if (config22.compress) {
|
|
2495
|
+
try {
|
|
2496
|
+
const compressedPath = `${rotatedFile}.gz`;
|
|
2497
|
+
await this.compressLogFile(rotatedFile, compressedPath);
|
|
2498
|
+
await unlink2(rotatedFile);
|
|
2499
|
+
} catch (err) {
|
|
2500
|
+
console.error("Error compressing rotated file:", err);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
if (rotatedFiles.length === 0 && !files.some((f) => f.endsWith(".log.1"))) {
|
|
2504
|
+
try {
|
|
2505
|
+
const backupPath = `${oldFile}.1`;
|
|
2506
|
+
await writeFile2(backupPath, "");
|
|
2507
|
+
} catch (err) {
|
|
2508
|
+
console.error("Error creating backup file:", err);
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
} catch (err) {
|
|
2512
|
+
console.error(`Error during rotation: ${err instanceof Error ? err.message : String(err)}`);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
} else {
|
|
2516
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
2517
|
+
const rotatedFile = oldFile.replace(/\.log$/, `-${timestamp}.log`);
|
|
2518
|
+
if (await stat2(oldFile).catch(() => null)) {
|
|
2519
|
+
await rename2(oldFile, rotatedFile);
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
this.currentLogFile = newFile;
|
|
2523
|
+
if (config22.maxFiles) {
|
|
2524
|
+
const files = await readdir2(this.config.logDirectory);
|
|
2525
|
+
const logFiles = files.filter((f) => f.startsWith(this.name)).sort((a, b) => b.localeCompare(a));
|
|
2526
|
+
for (const file of logFiles.slice(config22.maxFiles)) {
|
|
2527
|
+
await unlink2(join22(this.config.logDirectory, file));
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
async compressLogFile(inputPath, outputPath) {
|
|
2533
|
+
const readStream = createReadStream2(inputPath);
|
|
2534
|
+
const writeStream = createWriteStream2(outputPath);
|
|
2535
|
+
const gzip = createGzip2();
|
|
2536
|
+
await pipeline2(readStream, gzip, writeStream);
|
|
2537
|
+
}
|
|
2538
|
+
async handleFingersCrossedBuffer(level, formattedEntry) {
|
|
2539
|
+
if (!this.fingersCrossedConfig)
|
|
2540
|
+
return;
|
|
2541
|
+
if (this.shouldActivateFingersCrossed(level) && !this.isActivated) {
|
|
2542
|
+
this.isActivated = true;
|
|
2543
|
+
for (const entry of this.logBuffer) {
|
|
2544
|
+
const formattedBufferedEntry = await this.formatter.format(entry);
|
|
2545
|
+
await this.writeToFile(formattedBufferedEntry);
|
|
2546
|
+
console.log(formattedBufferedEntry);
|
|
2547
|
+
}
|
|
2548
|
+
if (this.fingersCrossedConfig.stopBuffering)
|
|
2549
|
+
this.logBuffer = [];
|
|
2550
|
+
}
|
|
2551
|
+
if (this.isActivated) {
|
|
2552
|
+
await this.writeToFile(formattedEntry);
|
|
2553
|
+
console.log(formattedEntry);
|
|
2554
|
+
} else {
|
|
2555
|
+
if (this.logBuffer.length >= this.fingersCrossedConfig.bufferSize)
|
|
2556
|
+
this.logBuffer.shift();
|
|
2557
|
+
const entry = {
|
|
2558
|
+
timestamp: new Date,
|
|
2559
|
+
level,
|
|
2560
|
+
message: formattedEntry,
|
|
2561
|
+
name: this.name
|
|
2562
|
+
};
|
|
2563
|
+
this.logBuffer.push(entry);
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
shouldActivateFingersCrossed(level) {
|
|
2567
|
+
if (!this.fingersCrossedConfig)
|
|
2568
|
+
return false;
|
|
2569
|
+
return this.getLevelValue(level) >= this.getLevelValue(this.fingersCrossedConfig.activationLevel);
|
|
2570
|
+
}
|
|
2571
|
+
getLevelValue(level) {
|
|
2572
|
+
const levels = {
|
|
2573
|
+
debug: 0,
|
|
2574
|
+
info: 1,
|
|
2575
|
+
success: 2,
|
|
2576
|
+
warning: 3,
|
|
2577
|
+
error: 4
|
|
2578
|
+
};
|
|
2579
|
+
return levels[level];
|
|
2580
|
+
}
|
|
2581
|
+
shouldLog(level) {
|
|
2582
|
+
if (!this.enabled)
|
|
2583
|
+
return false;
|
|
2584
|
+
const levels = {
|
|
2585
|
+
debug: 0,
|
|
2586
|
+
info: 1,
|
|
2587
|
+
success: 2,
|
|
2588
|
+
warning: 3,
|
|
2589
|
+
error: 4
|
|
2590
|
+
};
|
|
2591
|
+
return levels[level] >= levels[this.config.level];
|
|
2592
|
+
}
|
|
2593
|
+
async flushPendingWrites() {
|
|
2594
|
+
await Promise.all(this.pendingOperations.map((op) => {
|
|
2595
|
+
if (op instanceof Promise) {
|
|
2596
|
+
return op.catch((err) => {
|
|
2597
|
+
console.error("Error in pending write operation:", err);
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2600
|
+
return Promise.resolve();
|
|
2601
|
+
}));
|
|
2602
|
+
if (existsSync22(this.currentLogFile)) {
|
|
2603
|
+
try {
|
|
2604
|
+
const fd = openSync2(this.currentLogFile, "r+");
|
|
2605
|
+
fsyncSync2(fd);
|
|
2606
|
+
closeSync2(fd);
|
|
2607
|
+
} catch (error) {
|
|
2608
|
+
console.error(`Error flushing file: ${error}`);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
async destroy() {
|
|
2613
|
+
if (this.rotationTimeout)
|
|
2614
|
+
clearInterval(this.rotationTimeout);
|
|
2615
|
+
if (this.keyRotationTimeout)
|
|
2616
|
+
clearInterval(this.keyRotationTimeout);
|
|
2617
|
+
this.timers.clear();
|
|
2618
|
+
for (const op of this.pendingOperations) {
|
|
2619
|
+
if (typeof op.cancel === "function") {
|
|
2620
|
+
op.cancel();
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
return (async () => {
|
|
2624
|
+
if (this.pendingOperations.length > 0) {
|
|
2625
|
+
try {
|
|
2626
|
+
await Promise.allSettled(this.pendingOperations);
|
|
2627
|
+
} catch (err) {
|
|
2628
|
+
console.error("Error waiting for pending operations:", err);
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
if (!isBrowserProcess2() && this.config.rotation && typeof this.config.rotation !== "boolean" && this.config.rotation.compress) {
|
|
2632
|
+
try {
|
|
2633
|
+
const files = await readdir2(this.config.logDirectory);
|
|
2634
|
+
const tempFiles = files.filter((f) => (f.includes("temp") || f.includes(".tmp")) && f.includes(this.name));
|
|
2635
|
+
for (const tempFile of tempFiles) {
|
|
2636
|
+
try {
|
|
2637
|
+
await unlink2(join22(this.config.logDirectory, tempFile));
|
|
2638
|
+
} catch (err) {
|
|
2639
|
+
console.error(`Failed to delete temp file ${tempFile}:`, err);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
} catch (err) {
|
|
2643
|
+
console.error("Error cleaning up temporary files:", err);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
})();
|
|
2647
|
+
}
|
|
2648
|
+
getCurrentLogFilePath() {
|
|
2649
|
+
return this.currentLogFile;
|
|
2650
|
+
}
|
|
2651
|
+
formatTag(name) {
|
|
2652
|
+
if (!name)
|
|
2653
|
+
return "";
|
|
2654
|
+
return `${this.tagFormat.prefix}${name}${this.tagFormat.suffix}`;
|
|
2655
|
+
}
|
|
2656
|
+
formatFileTimestamp(date) {
|
|
2657
|
+
return `[${date.toISOString()}]`;
|
|
2658
|
+
}
|
|
2659
|
+
formatConsoleTimestamp(date) {
|
|
2660
|
+
return this.fancy ? styles2.gray(date.toLocaleTimeString()) : date.toLocaleTimeString();
|
|
2661
|
+
}
|
|
2662
|
+
formatConsoleMessage(parts) {
|
|
2663
|
+
const { timestamp, icon = "", tag = "", message, level, showTimestamp = true } = parts;
|
|
2664
|
+
const stripAnsi = (str) => str.replace(this.ANSI_PATTERN, "");
|
|
2665
|
+
if (!this.fancy) {
|
|
2666
|
+
const components = [];
|
|
2667
|
+
if (showTimestamp)
|
|
2668
|
+
components.push(timestamp);
|
|
2669
|
+
if (level === "warning")
|
|
2670
|
+
components.push("WARN");
|
|
2671
|
+
else if (level === "error")
|
|
2672
|
+
components.push("ERROR");
|
|
2673
|
+
else if (icon)
|
|
2674
|
+
components.push(icon.replace(/[^\p{L}\p{N}\p{P}\p{Z}]/gu, ""));
|
|
2675
|
+
if (tag)
|
|
2676
|
+
components.push(tag.replace(/[[\]]/g, ""));
|
|
2677
|
+
components.push(message);
|
|
2678
|
+
return components.join(" ");
|
|
2679
|
+
}
|
|
2680
|
+
const terminalWidth = process52.stdout.columns || 120;
|
|
2681
|
+
let mainPart = "";
|
|
2682
|
+
if (level === "warning" || level === "error") {
|
|
2683
|
+
mainPart = `${icon} ${message}`;
|
|
2684
|
+
} else if (level === "info" || level === "success") {
|
|
2685
|
+
mainPart = `${icon} ${tag} ${message}`;
|
|
2686
|
+
} else {
|
|
2687
|
+
mainPart = `${icon} ${tag} ${styles2.cyan(message)}`;
|
|
2688
|
+
}
|
|
2689
|
+
if (!showTimestamp) {
|
|
2690
|
+
return mainPart.trim();
|
|
2691
|
+
}
|
|
2692
|
+
const visibleMainPartLength = stripAnsi(mainPart).trim().length;
|
|
2693
|
+
const visibleTimestampLength = stripAnsi(timestamp).length;
|
|
2694
|
+
const padding = Math.max(1, terminalWidth - 2 - visibleMainPartLength - visibleTimestampLength);
|
|
2695
|
+
return `${mainPart.trim()}${" ".repeat(padding)}${timestamp}`;
|
|
2696
|
+
}
|
|
2697
|
+
formatMessage(message, args) {
|
|
2698
|
+
if (args.length === 1 && Array.isArray(args[0])) {
|
|
2699
|
+
return message.replace(/\{(\d+)\}/g, (match, index) => {
|
|
2700
|
+
const position = Number.parseInt(index, 10);
|
|
2701
|
+
return position < args[0].length ? String(args[0][position]) : match;
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
const formatRegex = /%([sdijfo%])/g;
|
|
2705
|
+
let argIndex = 0;
|
|
2706
|
+
let formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
2707
|
+
if (type === "%")
|
|
2708
|
+
return "%";
|
|
2709
|
+
if (argIndex >= args.length)
|
|
2710
|
+
return match;
|
|
2711
|
+
const arg = args[argIndex++];
|
|
2712
|
+
switch (type) {
|
|
2713
|
+
case "s":
|
|
2714
|
+
return String(arg);
|
|
2715
|
+
case "d":
|
|
2716
|
+
case "i":
|
|
2717
|
+
return Number(arg).toString();
|
|
2718
|
+
case "j":
|
|
2719
|
+
case "o":
|
|
2720
|
+
return JSON.stringify(arg, null, 2);
|
|
2721
|
+
default:
|
|
2722
|
+
return match;
|
|
2723
|
+
}
|
|
2724
|
+
});
|
|
2725
|
+
if (argIndex < args.length) {
|
|
2726
|
+
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
2727
|
+
}
|
|
2728
|
+
return formattedMessage;
|
|
2729
|
+
}
|
|
2730
|
+
async log(level, message, ...args) {
|
|
2731
|
+
const timestamp = new Date;
|
|
2732
|
+
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
2733
|
+
const fileTime = this.formatFileTimestamp(timestamp);
|
|
2734
|
+
let formattedMessage;
|
|
2735
|
+
let errorStack;
|
|
2736
|
+
if (message instanceof Error) {
|
|
2737
|
+
formattedMessage = message.message;
|
|
2738
|
+
errorStack = message.stack;
|
|
2739
|
+
} else {
|
|
2740
|
+
formattedMessage = this.formatMessage(message, args);
|
|
2741
|
+
}
|
|
2742
|
+
if (this.fancy && !isBrowserProcess2()) {
|
|
2743
|
+
const icon = levelIcons2[level];
|
|
2744
|
+
const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
|
|
2745
|
+
let consoleMessage;
|
|
2746
|
+
switch (level) {
|
|
2747
|
+
case "debug":
|
|
2748
|
+
consoleMessage = this.formatConsoleMessage({
|
|
2749
|
+
timestamp: consoleTime,
|
|
2750
|
+
icon,
|
|
2751
|
+
tag,
|
|
2752
|
+
message: styles2.gray(formattedMessage),
|
|
2753
|
+
level
|
|
2754
|
+
});
|
|
2755
|
+
console.error(consoleMessage);
|
|
2756
|
+
break;
|
|
2757
|
+
case "info":
|
|
2758
|
+
consoleMessage = this.formatConsoleMessage({
|
|
2759
|
+
timestamp: consoleTime,
|
|
2760
|
+
icon,
|
|
2761
|
+
tag,
|
|
2762
|
+
message: formattedMessage,
|
|
2763
|
+
level
|
|
2764
|
+
});
|
|
2765
|
+
console.error(consoleMessage);
|
|
2766
|
+
break;
|
|
2767
|
+
case "success":
|
|
2768
|
+
consoleMessage = this.formatConsoleMessage({
|
|
2769
|
+
timestamp: consoleTime,
|
|
2770
|
+
icon,
|
|
2771
|
+
tag,
|
|
2772
|
+
message: styles2.green(formattedMessage),
|
|
2773
|
+
level
|
|
2774
|
+
});
|
|
2775
|
+
console.error(consoleMessage);
|
|
2776
|
+
break;
|
|
2777
|
+
case "warning":
|
|
2778
|
+
consoleMessage = this.formatConsoleMessage({
|
|
2779
|
+
timestamp: consoleTime,
|
|
2780
|
+
icon,
|
|
2781
|
+
tag,
|
|
2782
|
+
message: formattedMessage,
|
|
2783
|
+
level
|
|
2784
|
+
});
|
|
2785
|
+
console.warn(consoleMessage);
|
|
2786
|
+
break;
|
|
2787
|
+
case "error":
|
|
2788
|
+
consoleMessage = this.formatConsoleMessage({
|
|
2789
|
+
timestamp: consoleTime,
|
|
2790
|
+
icon,
|
|
2791
|
+
tag,
|
|
2792
|
+
message: formattedMessage,
|
|
2793
|
+
level
|
|
2794
|
+
});
|
|
2795
|
+
console.error(consoleMessage);
|
|
2796
|
+
if (errorStack) {
|
|
2797
|
+
const stackLines = errorStack.split(`
|
|
2798
|
+
`);
|
|
2799
|
+
for (const line of stackLines) {
|
|
2800
|
+
if (line.trim() && !line.includes(formattedMessage)) {
|
|
2801
|
+
console.error(this.formatConsoleMessage({
|
|
2802
|
+
timestamp: consoleTime,
|
|
2803
|
+
message: styles2.gray(` ${line}`),
|
|
2804
|
+
level,
|
|
2805
|
+
showTimestamp: false
|
|
2806
|
+
}));
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
break;
|
|
2811
|
+
}
|
|
2812
|
+
} else if (!isBrowserProcess2()) {
|
|
2813
|
+
console.error(`${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}`);
|
|
2814
|
+
if (errorStack) {
|
|
2815
|
+
console.error(errorStack);
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
if (!this.shouldLog(level))
|
|
2819
|
+
return;
|
|
2820
|
+
let logEntry = `${fileTime} ${this.environment}.${level.toUpperCase()}: ${formattedMessage}
|
|
2821
|
+
`;
|
|
2822
|
+
if (errorStack) {
|
|
2823
|
+
logEntry += `${errorStack}
|
|
2824
|
+
`;
|
|
2825
|
+
}
|
|
2826
|
+
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
2827
|
+
await this.writeToFile(logEntry);
|
|
2828
|
+
}
|
|
2829
|
+
time(label) {
|
|
2830
|
+
const start = performance.now();
|
|
2831
|
+
if (this.fancy && !isBrowserProcess2()) {
|
|
2832
|
+
const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
|
|
2833
|
+
const consoleTime = this.formatConsoleTimestamp(new Date);
|
|
2834
|
+
console.error(this.formatConsoleMessage({
|
|
2835
|
+
timestamp: consoleTime,
|
|
2836
|
+
icon: styles2.blue("◐"),
|
|
2837
|
+
tag,
|
|
2838
|
+
message: `${styles2.cyan(label)}...`
|
|
2839
|
+
}));
|
|
2840
|
+
}
|
|
2841
|
+
return async (metadata) => {
|
|
2842
|
+
if (!this.enabled)
|
|
2843
|
+
return;
|
|
2844
|
+
const end = performance.now();
|
|
2845
|
+
const elapsed = Math.round(end - start);
|
|
2846
|
+
const completionMessage = `${label} completed in ${elapsed}ms`;
|
|
2847
|
+
const timestamp = new Date;
|
|
2848
|
+
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
2849
|
+
const fileTime = this.formatFileTimestamp(timestamp);
|
|
2850
|
+
let logEntry = `${fileTime} ${this.environment}.INFO: ${completionMessage}`;
|
|
2851
|
+
if (metadata) {
|
|
2852
|
+
logEntry += ` ${JSON.stringify(metadata)}`;
|
|
2853
|
+
}
|
|
2854
|
+
logEntry += `
|
|
2855
|
+
`;
|
|
2856
|
+
logEntry = logEntry.replace(this.ANSI_PATTERN, "");
|
|
2857
|
+
if (this.fancy && !isBrowserProcess2()) {
|
|
2858
|
+
const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
|
|
2859
|
+
console.error(this.formatConsoleMessage({
|
|
2860
|
+
timestamp: consoleTime,
|
|
2861
|
+
icon: styles2.green("✓"),
|
|
2862
|
+
tag,
|
|
2863
|
+
message: `${completionMessage}${metadata ? ` ${JSON.stringify(metadata)}` : ""}`
|
|
2864
|
+
}));
|
|
2865
|
+
} else if (!isBrowserProcess2()) {
|
|
2866
|
+
console.error(logEntry.trim());
|
|
2867
|
+
}
|
|
2868
|
+
await this.writeToFile(logEntry);
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
async debug(message, ...args) {
|
|
2872
|
+
await this.log("debug", message, ...args);
|
|
2873
|
+
}
|
|
2874
|
+
async info(message, ...args) {
|
|
2875
|
+
await this.log("info", message, ...args);
|
|
2876
|
+
}
|
|
2877
|
+
async success(message, ...args) {
|
|
2878
|
+
await this.log("success", message, ...args);
|
|
2879
|
+
}
|
|
2880
|
+
async warn(message, ...args) {
|
|
2881
|
+
await this.log("warning", message, ...args);
|
|
2882
|
+
}
|
|
2883
|
+
async error(message, ...args) {
|
|
2884
|
+
await this.log("error", message, ...args);
|
|
2885
|
+
}
|
|
2886
|
+
validateEncryptionConfig() {
|
|
2887
|
+
if (!this.config.rotation)
|
|
2888
|
+
return false;
|
|
2889
|
+
if (typeof this.config.rotation === "boolean")
|
|
2890
|
+
return false;
|
|
2891
|
+
const rotation = this.config.rotation;
|
|
2892
|
+
const { encrypt } = rotation;
|
|
2893
|
+
return !!encrypt;
|
|
2894
|
+
}
|
|
2895
|
+
async only(fn) {
|
|
2896
|
+
if (!this.enabled)
|
|
2897
|
+
return;
|
|
2898
|
+
return await fn();
|
|
2899
|
+
}
|
|
2900
|
+
isEnabled() {
|
|
2901
|
+
return this.enabled;
|
|
2902
|
+
}
|
|
2903
|
+
setEnabled(enabled) {
|
|
2904
|
+
this.enabled = enabled;
|
|
2905
|
+
}
|
|
2906
|
+
extend(namespace) {
|
|
2907
|
+
const childName = `${this.name}:${namespace}`;
|
|
2908
|
+
const childLogger = new Logger2(childName, {
|
|
2909
|
+
...this.options,
|
|
2910
|
+
logDirectory: this.config.logDirectory,
|
|
2911
|
+
level: this.config.level,
|
|
2912
|
+
format: this.config.format,
|
|
2913
|
+
rotation: typeof this.config.rotation === "boolean" ? undefined : this.config.rotation,
|
|
2914
|
+
timestamp: typeof this.config.timestamp === "boolean" ? undefined : this.config.timestamp
|
|
2915
|
+
});
|
|
2916
|
+
this.subLoggers.add(childLogger);
|
|
2917
|
+
return childLogger;
|
|
2918
|
+
}
|
|
2919
|
+
createReadStream() {
|
|
2920
|
+
if (isBrowserProcess2())
|
|
2921
|
+
throw new Error("createReadStream is not supported in browser environments");
|
|
2922
|
+
if (!existsSync22(this.currentLogFile))
|
|
2923
|
+
throw new Error(`Log file does not exist: ${this.currentLogFile}`);
|
|
2924
|
+
return createReadStream2(this.currentLogFile, { encoding: "utf8" });
|
|
2925
|
+
}
|
|
2926
|
+
async decrypt(data) {
|
|
2927
|
+
if (!this.validateEncryptionConfig())
|
|
2928
|
+
throw new Error("Encryption is not configured");
|
|
2929
|
+
const encryptionConfig = this.config.rotation;
|
|
2930
|
+
if (!encryptionConfig.encrypt || typeof encryptionConfig.encrypt === "boolean")
|
|
2931
|
+
throw new Error("Invalid encryption configuration");
|
|
2932
|
+
if (!this.currentKeyId || !this.keys.has(this.currentKeyId))
|
|
2933
|
+
throw new Error("No valid encryption key available");
|
|
2934
|
+
const key = this.keys.get(this.currentKeyId);
|
|
2935
|
+
try {
|
|
2936
|
+
const encryptedData = Buffer2.isBuffer(data) ? data : Buffer2.from(data, "base64");
|
|
2937
|
+
const iv = encryptedData.slice(0, 16);
|
|
2938
|
+
const authTag = encryptedData.slice(-16);
|
|
2939
|
+
const ciphertext = encryptedData.slice(16, -16);
|
|
2940
|
+
const decipher = createDecipheriv2("aes-256-gcm", key, iv);
|
|
2941
|
+
decipher.setAuthTag(authTag);
|
|
2942
|
+
const decrypted = Buffer2.concat([
|
|
2943
|
+
decipher.update(ciphertext),
|
|
2944
|
+
decipher.final()
|
|
2945
|
+
]);
|
|
2946
|
+
return decrypted.toString("utf8");
|
|
2947
|
+
} catch (err) {
|
|
2948
|
+
throw new Error(`Decryption failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
getLevel() {
|
|
2952
|
+
return this.config.level;
|
|
2953
|
+
}
|
|
2954
|
+
getLogDirectory() {
|
|
2955
|
+
return this.config.logDirectory;
|
|
2956
|
+
}
|
|
2957
|
+
getFormat() {
|
|
2958
|
+
return this.config.format;
|
|
2959
|
+
}
|
|
2960
|
+
getRotationConfig() {
|
|
2961
|
+
return this.config.rotation;
|
|
2962
|
+
}
|
|
2963
|
+
isBrowserMode() {
|
|
2964
|
+
return isBrowserProcess2();
|
|
2965
|
+
}
|
|
2966
|
+
isServerMode() {
|
|
2967
|
+
return !isBrowserProcess2();
|
|
2968
|
+
}
|
|
2969
|
+
setTestEncryptionKey(keyId, key) {
|
|
2970
|
+
this.currentKeyId = keyId;
|
|
2971
|
+
this.keys.set(keyId, key);
|
|
2972
|
+
}
|
|
2973
|
+
getTestCurrentKey() {
|
|
2974
|
+
if (!this.currentKeyId || !this.keys.has(this.currentKeyId)) {
|
|
2975
|
+
return null;
|
|
2976
|
+
}
|
|
2977
|
+
return {
|
|
2978
|
+
id: this.currentKeyId,
|
|
2979
|
+
key: this.keys.get(this.currentKeyId)
|
|
2980
|
+
};
|
|
2981
|
+
}
|
|
2982
|
+
getConfig() {
|
|
2983
|
+
return this.config;
|
|
2984
|
+
}
|
|
2985
|
+
async box(message) {
|
|
2986
|
+
if (!this.enabled)
|
|
2987
|
+
return;
|
|
2988
|
+
const timestamp = new Date;
|
|
2989
|
+
const consoleTime = this.formatConsoleTimestamp(timestamp);
|
|
2990
|
+
const fileTime = this.formatFileTimestamp(timestamp);
|
|
2991
|
+
if (this.fancy && !isBrowserProcess2()) {
|
|
2992
|
+
const lines = message.split(`
|
|
2993
|
+
`);
|
|
2994
|
+
const width = Math.max(...lines.map((line) => line.length)) + 2;
|
|
2995
|
+
const top = `┌${"─".repeat(width)}┐`;
|
|
2996
|
+
const bottom = `└${"─".repeat(width)}┘`;
|
|
2997
|
+
const boxedLines = lines.map((line) => {
|
|
2998
|
+
const padding = " ".repeat(width - line.length - 2);
|
|
2999
|
+
return `│ ${line}${padding} │`;
|
|
3000
|
+
});
|
|
3001
|
+
if (this.options.showTags !== false && this.name) {
|
|
3002
|
+
console.error(this.formatConsoleMessage({
|
|
3003
|
+
timestamp: consoleTime,
|
|
3004
|
+
message: styles2.gray(this.formatTag(this.name)),
|
|
3005
|
+
showTimestamp: false
|
|
3006
|
+
}));
|
|
3007
|
+
}
|
|
3008
|
+
console.error(this.formatConsoleMessage({
|
|
3009
|
+
timestamp: consoleTime,
|
|
3010
|
+
message: styles2.cyan(top)
|
|
3011
|
+
}));
|
|
3012
|
+
boxedLines.forEach((line) => console.error(this.formatConsoleMessage({
|
|
3013
|
+
timestamp: consoleTime,
|
|
3014
|
+
message: styles2.cyan(line),
|
|
3015
|
+
showTimestamp: false
|
|
3016
|
+
})));
|
|
3017
|
+
console.error(this.formatConsoleMessage({
|
|
3018
|
+
timestamp: consoleTime,
|
|
3019
|
+
message: styles2.cyan(bottom),
|
|
3020
|
+
showTimestamp: false
|
|
3021
|
+
}));
|
|
3022
|
+
} else if (!isBrowserProcess2()) {
|
|
3023
|
+
console.error(`${fileTime} ${this.environment}.INFO: [BOX] ${message}`);
|
|
3024
|
+
}
|
|
3025
|
+
const logEntry = `${fileTime} ${this.environment}.INFO: [BOX] ${message}
|
|
3026
|
+
`.replace(this.ANSI_PATTERN, "");
|
|
3027
|
+
await this.writeToFile(logEntry);
|
|
3028
|
+
}
|
|
3029
|
+
async prompt(message) {
|
|
3030
|
+
if (isBrowserProcess2()) {
|
|
3031
|
+
return Promise.resolve(true);
|
|
3032
|
+
}
|
|
3033
|
+
return new Promise((resolve32) => {
|
|
3034
|
+
console.error(`${styles2.cyan("?")} ${message} (y/n) `);
|
|
3035
|
+
const onData = (data) => {
|
|
3036
|
+
const input = data.toString().trim().toLowerCase();
|
|
3037
|
+
process52.stdin.removeListener("data", onData);
|
|
3038
|
+
try {
|
|
3039
|
+
if (typeof process52.stdin.setRawMode === "function") {
|
|
3040
|
+
process52.stdin.setRawMode(false);
|
|
3041
|
+
}
|
|
3042
|
+
} catch {}
|
|
3043
|
+
process52.stdin.pause();
|
|
3044
|
+
console.error("");
|
|
3045
|
+
resolve32(input === "y" || input === "yes");
|
|
3046
|
+
};
|
|
3047
|
+
try {
|
|
3048
|
+
if (typeof process52.stdin.setRawMode === "function") {
|
|
3049
|
+
process52.stdin.setRawMode(true);
|
|
3050
|
+
}
|
|
3051
|
+
} catch {}
|
|
3052
|
+
process52.stdin.resume();
|
|
3053
|
+
process52.stdin.once("data", onData);
|
|
3054
|
+
});
|
|
3055
|
+
}
|
|
3056
|
+
setFancy(enabled) {
|
|
3057
|
+
this.fancy = enabled;
|
|
3058
|
+
}
|
|
3059
|
+
isFancy() {
|
|
3060
|
+
return this.fancy;
|
|
3061
|
+
}
|
|
3062
|
+
pause() {
|
|
3063
|
+
this.enabled = false;
|
|
3064
|
+
}
|
|
3065
|
+
resume() {
|
|
3066
|
+
this.enabled = true;
|
|
3067
|
+
}
|
|
3068
|
+
async start(message, ...args) {
|
|
3069
|
+
if (!this.enabled)
|
|
3070
|
+
return;
|
|
3071
|
+
let formattedMessage = message;
|
|
3072
|
+
if (args && args.length > 0) {
|
|
3073
|
+
const formatRegex = /%([sdijfo%])/g;
|
|
3074
|
+
let argIndex = 0;
|
|
3075
|
+
formattedMessage = message.replace(formatRegex, (match, type) => {
|
|
3076
|
+
if (type === "%")
|
|
3077
|
+
return "%";
|
|
3078
|
+
if (argIndex >= args.length)
|
|
3079
|
+
return match;
|
|
3080
|
+
const arg = args[argIndex++];
|
|
3081
|
+
switch (type) {
|
|
3082
|
+
case "s":
|
|
3083
|
+
return String(arg);
|
|
3084
|
+
case "d":
|
|
3085
|
+
case "i":
|
|
3086
|
+
return Number(arg).toString();
|
|
3087
|
+
case "j":
|
|
3088
|
+
case "o":
|
|
3089
|
+
return JSON.stringify(arg, null, 2);
|
|
3090
|
+
default:
|
|
3091
|
+
return match;
|
|
3092
|
+
}
|
|
3093
|
+
});
|
|
3094
|
+
if (argIndex < args.length) {
|
|
3095
|
+
formattedMessage += ` ${args.slice(argIndex).map((arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)).join(" ")}`;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
if (this.fancy && !isBrowserProcess2()) {
|
|
3099
|
+
const tag = this.options.showTags !== false && this.name ? styles2.gray(this.formatTag(this.name)) : "";
|
|
3100
|
+
const spinnerChar = styles2.blue("◐");
|
|
3101
|
+
console.error(`${spinnerChar} ${tag} ${styles2.cyan(formattedMessage)}`);
|
|
3102
|
+
}
|
|
3103
|
+
const timestamp = new Date;
|
|
3104
|
+
const formattedDate = timestamp.toISOString();
|
|
3105
|
+
const logEntry = `[${formattedDate}] ${this.environment}.INFO: [START] ${formattedMessage}
|
|
3106
|
+
`.replace(this.ANSI_PATTERN, "");
|
|
3107
|
+
await this.writeToFile(logEntry);
|
|
3108
|
+
}
|
|
3109
|
+
progress(total, initialMessage = "") {
|
|
3110
|
+
if (!this.enabled || !this.fancy || isBrowserProcess2() || total <= 0) {
|
|
3111
|
+
return {
|
|
3112
|
+
update: () => {},
|
|
3113
|
+
finish: () => {},
|
|
3114
|
+
interrupt: () => {}
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
3117
|
+
if (this.activeProgressBar) {
|
|
3118
|
+
console.warn("Warning: Another progress bar is already active. Finishing the previous one.");
|
|
3119
|
+
this.finishProgressBar(this.activeProgressBar, "[Auto-finished]");
|
|
3120
|
+
}
|
|
3121
|
+
const barLength = 20;
|
|
3122
|
+
this.activeProgressBar = {
|
|
3123
|
+
total,
|
|
3124
|
+
current: 0,
|
|
3125
|
+
message: initialMessage,
|
|
3126
|
+
barLength,
|
|
3127
|
+
lastRenderedLine: ""
|
|
3128
|
+
};
|
|
3129
|
+
this.renderProgressBar(this.activeProgressBar);
|
|
3130
|
+
const update = (current, message) => {
|
|
3131
|
+
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
|
|
3132
|
+
return;
|
|
3133
|
+
this.activeProgressBar.current = Math.max(0, Math.min(total, current));
|
|
3134
|
+
if (message !== undefined) {
|
|
3135
|
+
this.activeProgressBar.message = message;
|
|
3136
|
+
}
|
|
3137
|
+
const isFinished = this.activeProgressBar.current === this.activeProgressBar.total;
|
|
3138
|
+
this.renderProgressBar(this.activeProgressBar, isFinished);
|
|
3139
|
+
};
|
|
3140
|
+
const finish = (message) => {
|
|
3141
|
+
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
|
|
3142
|
+
return;
|
|
3143
|
+
this.activeProgressBar.current = this.activeProgressBar.total;
|
|
3144
|
+
if (message !== undefined) {
|
|
3145
|
+
this.activeProgressBar.message = message;
|
|
3146
|
+
}
|
|
3147
|
+
this.renderProgressBar(this.activeProgressBar, true);
|
|
3148
|
+
this.finishProgressBar(this.activeProgressBar);
|
|
3149
|
+
};
|
|
3150
|
+
const interrupt = (interruptMessage, level = "info") => {
|
|
3151
|
+
if (!this.activeProgressBar || !this.enabled || !this.fancy || isBrowserProcess2())
|
|
3152
|
+
return;
|
|
3153
|
+
process52.stdout.write(`${"\r".padEnd(process52.stdout.columns || 80)}\r`);
|
|
3154
|
+
this.log(level, interruptMessage);
|
|
3155
|
+
setTimeout(() => {
|
|
3156
|
+
if (this.activeProgressBar) {
|
|
3157
|
+
this.renderProgressBar(this.activeProgressBar);
|
|
3158
|
+
}
|
|
3159
|
+
}, 50);
|
|
3160
|
+
};
|
|
3161
|
+
return { update, finish, interrupt };
|
|
3162
|
+
}
|
|
3163
|
+
renderProgressBar(barState, isFinished = false) {
|
|
3164
|
+
if (!this.enabled || !this.fancy || isBrowserProcess2() || !process52.stdout.isTTY)
|
|
3165
|
+
return;
|
|
3166
|
+
const percent = Math.min(100, Math.max(0, Math.round(barState.current / barState.total * 100)));
|
|
3167
|
+
const filledLength = Math.round(barState.barLength * percent / 100);
|
|
3168
|
+
const emptyLength = barState.barLength - filledLength;
|
|
3169
|
+
const filledBar = styles2.green("━".repeat(filledLength));
|
|
3170
|
+
const emptyBar = styles2.gray("━".repeat(emptyLength));
|
|
3171
|
+
const bar = `[${filledBar}${emptyBar}]`;
|
|
3172
|
+
const percentageText = `${percent}%`.padStart(4);
|
|
3173
|
+
const messageText = barState.message ? ` ${barState.message}` : "";
|
|
3174
|
+
const icon = isFinished || percent === 100 ? styles2.green("✓") : styles2.blue("▶");
|
|
3175
|
+
const tag = this.options.showTags !== false && this.name ? ` ${styles2.gray(this.formatTag(this.name))}` : "";
|
|
3176
|
+
const line = `\r${icon}${tag} ${bar} ${percentageText}${messageText}`;
|
|
3177
|
+
const terminalWidth = process52.stdout.columns || 80;
|
|
3178
|
+
const clearLine = " ".repeat(Math.max(0, terminalWidth - line.replace(this.ANSI_PATTERN, "").length));
|
|
3179
|
+
barState.lastRenderedLine = `${line}${clearLine}`;
|
|
3180
|
+
process52.stdout.write(barState.lastRenderedLine);
|
|
3181
|
+
if (isFinished) {
|
|
3182
|
+
process52.stdout.write(`
|
|
3183
|
+
`);
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
finishProgressBar(barState, finalMessage) {
|
|
3187
|
+
if (!this.enabled || !this.fancy || isBrowserProcess2() || !process52.stdout.isTTY) {
|
|
3188
|
+
this.activeProgressBar = null;
|
|
3189
|
+
return;
|
|
3190
|
+
}
|
|
3191
|
+
if (barState.current < barState.total) {
|
|
3192
|
+
barState.current = barState.total;
|
|
3193
|
+
}
|
|
3194
|
+
if (finalMessage)
|
|
3195
|
+
barState.message = finalMessage;
|
|
3196
|
+
this.renderProgressBar(barState, true);
|
|
3197
|
+
this.activeProgressBar = null;
|
|
3198
|
+
}
|
|
3199
|
+
async clear(filters = {}) {
|
|
3200
|
+
if (isBrowserProcess2()) {
|
|
3201
|
+
console.warn("Log clearing is not supported in browser environments.");
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
try {
|
|
3205
|
+
console.warn("Clearing logs...", this.config.logDirectory);
|
|
3206
|
+
const files = await readdir2(this.config.logDirectory);
|
|
3207
|
+
const logFilesToDelete = [];
|
|
3208
|
+
for (const file of files) {
|
|
3209
|
+
const nameMatches = filters.name ? new RegExp(filters.name.replace("*", ".*")).test(file) : file.startsWith(this.name);
|
|
3210
|
+
if (!nameMatches || !file.endsWith(".log")) {
|
|
3211
|
+
continue;
|
|
3212
|
+
}
|
|
3213
|
+
const filePath = join22(this.config.logDirectory, file);
|
|
3214
|
+
if (filters.before) {
|
|
3215
|
+
try {
|
|
3216
|
+
const fileStats = await stat2(filePath);
|
|
3217
|
+
if (fileStats.mtime >= filters.before) {
|
|
3218
|
+
continue;
|
|
3219
|
+
}
|
|
3220
|
+
} catch (statErr) {
|
|
3221
|
+
console.error(`Failed to get stats for file ${filePath}:`, statErr);
|
|
3222
|
+
continue;
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
logFilesToDelete.push(filePath);
|
|
3226
|
+
}
|
|
3227
|
+
if (logFilesToDelete.length === 0) {
|
|
3228
|
+
console.warn("No log files matched the criteria for clearing.");
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
console.warn(`Preparing to delete ${logFilesToDelete.length} log file(s)...`);
|
|
3232
|
+
for (const filePath of logFilesToDelete) {
|
|
3233
|
+
try {
|
|
3234
|
+
await unlink2(filePath);
|
|
3235
|
+
console.warn(`Deleted log file: ${filePath}`);
|
|
3236
|
+
} catch (unlinkErr) {
|
|
3237
|
+
console.error(`Failed to delete log file ${filePath}:`, unlinkErr);
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
console.warn("Log clearing process finished.");
|
|
3241
|
+
} catch (err) {
|
|
3242
|
+
console.error("Error during log clearing process:", err);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
var logger2 = new Logger2("stacks");
|
|
1699
3247
|
|
|
1700
3248
|
// src/git-hooks.ts
|
|
1701
3249
|
var execAsync = promisify(exec);
|
|
1702
|
-
var
|
|
3250
|
+
var log2 = new Logger2("git-hooks", {
|
|
1703
3251
|
showTags: true
|
|
1704
3252
|
});
|
|
1705
3253
|
var VALID_GIT_HOOKS = [
|
|
@@ -1745,7 +3293,7 @@ if [ -f "$BUN_GIT_HOOKS_RC" ]; then
|
|
|
1745
3293
|
fi
|
|
1746
3294
|
|
|
1747
3295
|
`;
|
|
1748
|
-
function getGitProjectRoot(directory =
|
|
3296
|
+
function getGitProjectRoot(directory = process11.cwd()) {
|
|
1749
3297
|
if (directory.endsWith(".git")) {
|
|
1750
3298
|
return path.normalize(directory);
|
|
1751
3299
|
}
|
|
@@ -1807,7 +3355,7 @@ function checkBunGitHooksInDependencies(projectRootPath) {
|
|
|
1807
3355
|
}
|
|
1808
3356
|
return "bun-git-hooks" in packageJsonContent.devDependencies;
|
|
1809
3357
|
}
|
|
1810
|
-
function _getPackageJson(projectPath =
|
|
3358
|
+
function _getPackageJson(projectPath = process11.cwd()) {
|
|
1811
3359
|
if (typeof projectPath !== "string") {
|
|
1812
3360
|
throw new TypeError("projectPath is not a string");
|
|
1813
3361
|
}
|
|
@@ -1818,18 +3366,18 @@ function _getPackageJson(projectPath = process6.cwd()) {
|
|
|
1818
3366
|
const packageJsonDataRaw = fs.readFileSync(targetPackageJson, { encoding: "utf-8" });
|
|
1819
3367
|
return { packageJsonContent: JSON.parse(packageJsonDataRaw), packageJsonPath: targetPackageJson };
|
|
1820
3368
|
}
|
|
1821
|
-
function setHooksFromConfig(projectRootPath =
|
|
1822
|
-
if (!
|
|
3369
|
+
function setHooksFromConfig(projectRootPath = process11.cwd(), options) {
|
|
3370
|
+
if (!config3 || Object.keys(config3).length === 0)
|
|
1823
3371
|
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 || { ...
|
|
3372
|
+
const configFile = options?.configFile || { ...config3 };
|
|
1825
3373
|
_validateStagedLintConfig(configFile);
|
|
1826
3374
|
const hookKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key));
|
|
1827
3375
|
const isValidConfig = hookKeys.every((key) => VALID_GIT_HOOKS.includes(key));
|
|
1828
3376
|
if (!isValidConfig)
|
|
1829
3377
|
throw new Error("[ERROR] Config was not in correct format. Please check git hooks or options name");
|
|
1830
3378
|
const preserveUnused = Array.isArray(configFile.preserveUnused) ? configFile.preserveUnused : configFile.preserveUnused ? VALID_GIT_HOOKS : [];
|
|
1831
|
-
const logKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key)).sort().map((key) =>
|
|
1832
|
-
|
|
3379
|
+
const logKeys = Object.keys(configFile).filter((key) => !VALID_OPTIONS.includes(key)).sort().map((key) => italic2(key)).join(", ");
|
|
3380
|
+
log2.debug(`Hook Keys: ${logKeys}`);
|
|
1833
3381
|
for (const hook of VALID_GIT_HOOKS) {
|
|
1834
3382
|
if (Object.prototype.hasOwnProperty.call(configFile, hook)) {
|
|
1835
3383
|
if (!configFile[hook])
|
|
@@ -1840,12 +3388,12 @@ function setHooksFromConfig(projectRootPath = process6.cwd(), options) {
|
|
|
1840
3388
|
}
|
|
1841
3389
|
}
|
|
1842
3390
|
}
|
|
1843
|
-
async function getStagedFiles(projectRoot =
|
|
3391
|
+
async function getStagedFiles(projectRoot = process11.cwd()) {
|
|
1844
3392
|
try {
|
|
1845
3393
|
const { stdout } = await execAsync("git diff --cached --name-only --diff-filter=ACMR", { cwd: projectRoot });
|
|
1846
3394
|
const files = stdout.trim().split(`
|
|
1847
3395
|
`).filter(Boolean);
|
|
1848
|
-
if (
|
|
3396
|
+
if (config3.verbose && files.length > 0) {
|
|
1849
3397
|
console.info("[INFO] Staged files found:", files);
|
|
1850
3398
|
}
|
|
1851
3399
|
return files;
|
|
@@ -1890,7 +3438,7 @@ function filterFilesByPattern(files, pattern) {
|
|
|
1890
3438
|
return isIncluded && !isExcluded;
|
|
1891
3439
|
});
|
|
1892
3440
|
}
|
|
1893
|
-
async function runCommandOnStagedFiles(command, files, projectRoot =
|
|
3441
|
+
async function runCommandOnStagedFiles(command, files, projectRoot = process11.cwd(), verbose = false) {
|
|
1894
3442
|
if (files.length === 0) {
|
|
1895
3443
|
if (verbose)
|
|
1896
3444
|
console.info("[INFO] No matching files for pattern");
|
|
@@ -1942,7 +3490,7 @@ async function processStagedLint(stagedLintConfig, projectRoot, verbose = false)
|
|
|
1942
3490
|
}
|
|
1943
3491
|
return success;
|
|
1944
3492
|
}
|
|
1945
|
-
function _setHook(hook, commandOrConfig, projectRoot =
|
|
3493
|
+
function _setHook(hook, commandOrConfig, projectRoot = process11.cwd()) {
|
|
1946
3494
|
const gitRoot = getGitProjectRoot(projectRoot);
|
|
1947
3495
|
if (!gitRoot) {
|
|
1948
3496
|
console.info("[INFO] No `.git` root folder found, skipping");
|
|
@@ -1952,7 +3500,7 @@ function _setHook(hook, commandOrConfig, projectRoot = process6.cwd()) {
|
|
|
1952
3500
|
if (typeof commandOrConfig === "string") {
|
|
1953
3501
|
hookCommand = PREPEND_SCRIPT + commandOrConfig;
|
|
1954
3502
|
} else if (commandOrConfig.stagedLint || commandOrConfig["staged-lint"]) {
|
|
1955
|
-
hookCommand = PREPEND_SCRIPT + `git-hooks run-staged-lint ${hook}`;
|
|
3503
|
+
hookCommand = PREPEND_SCRIPT + `bun git-hooks run-staged-lint ${hook}`;
|
|
1956
3504
|
} else {
|
|
1957
3505
|
console.error(`[ERROR] Invalid command or config for hook ${hook}`);
|
|
1958
3506
|
return;
|
|
@@ -1963,26 +3511,26 @@ function _setHook(hook, commandOrConfig, projectRoot = process6.cwd()) {
|
|
|
1963
3511
|
fs.mkdirSync(hookDirectory, { recursive: true });
|
|
1964
3512
|
}
|
|
1965
3513
|
const addOrModify = fs.existsSync(hookPath) ? "Modify" : "Add";
|
|
1966
|
-
|
|
3514
|
+
log2.debug(`${addOrModify} ${italic2(hook)} hook`);
|
|
1967
3515
|
fs.writeFileSync(hookPath, hookCommand, { mode: 493 });
|
|
1968
3516
|
}
|
|
1969
|
-
function removeHooks(projectRoot =
|
|
3517
|
+
function removeHooks(projectRoot = process11.cwd(), verbose = false) {
|
|
1970
3518
|
for (const configEntry of VALID_GIT_HOOKS)
|
|
1971
3519
|
_removeHook(configEntry, projectRoot, verbose);
|
|
1972
3520
|
}
|
|
1973
|
-
function _removeHook(hook, projectRoot =
|
|
3521
|
+
function _removeHook(hook, projectRoot = process11.cwd(), verbose = false) {
|
|
1974
3522
|
const gitRoot = getGitProjectRoot(projectRoot);
|
|
1975
3523
|
const hookPath = path.normalize(`${gitRoot}/hooks/${hook}`);
|
|
1976
3524
|
if (fs.existsSync(hookPath)) {
|
|
1977
|
-
|
|
3525
|
+
log2.debug(`Hook ${hook} is not set, removing!`);
|
|
1978
3526
|
fs.unlinkSync(hookPath);
|
|
1979
3527
|
}
|
|
1980
3528
|
if (verbose)
|
|
1981
|
-
|
|
3529
|
+
log2.success(`Successfully removed the ${hook} hook`);
|
|
1982
3530
|
}
|
|
1983
3531
|
async function runStagedLint(hook) {
|
|
1984
|
-
const projectRoot =
|
|
1985
|
-
const configFile =
|
|
3532
|
+
const projectRoot = process11.cwd();
|
|
3533
|
+
const configFile = config3;
|
|
1986
3534
|
if (!configFile) {
|
|
1987
3535
|
console.error(`[ERROR] No configuration found`);
|
|
1988
3536
|
return false;
|
|
@@ -2002,10 +3550,10 @@ async function runStagedLint(hook) {
|
|
|
2002
3550
|
console.error(`[ERROR] No staged lint configuration found for hook ${hook}`);
|
|
2003
3551
|
return false;
|
|
2004
3552
|
}
|
|
2005
|
-
function _validateStagedLintConfig(
|
|
3553
|
+
function _validateStagedLintConfig(config5) {
|
|
2006
3554
|
for (const hook of VALID_GIT_HOOKS) {
|
|
2007
|
-
if (hook !== "pre-commit" &&
|
|
2008
|
-
const hookConfig =
|
|
3555
|
+
if (hook !== "pre-commit" && config5[hook] && typeof config5[hook] === "object") {
|
|
3556
|
+
const hookConfig = config5[hook];
|
|
2009
3557
|
if (hookConfig["stagedLint"] || hookConfig["staged-lint"]) {
|
|
2010
3558
|
throw new Error(`staged-lint is only allowed in pre-commit hook. Found in ${hook} hook.`);
|
|
2011
3559
|
}
|
|
@@ -2018,7 +3566,7 @@ export {
|
|
|
2018
3566
|
removeHooks,
|
|
2019
3567
|
getProjectRootDirectoryFromNodeModules,
|
|
2020
3568
|
getGitProjectRoot,
|
|
2021
|
-
|
|
3569
|
+
config3 as config,
|
|
2022
3570
|
checkBunGitHooksInDependencies,
|
|
2023
3571
|
VALID_OPTIONS,
|
|
2024
3572
|
VALID_GIT_HOOKS,
|