@ankurhalder/codebase-snapshot 4.0.0 → 4.0.2
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.js +463 -289
- package/dist/{chunk-FM4OOQPF.js → chunk-CY3XU5TS.js} +301 -127
- package/dist/cli.cjs +427 -253
- package/dist/cli.d.cts +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +9 -6
- package/dist/index.cjs +299 -125
- package/dist/index.d.cts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +1 -1
- package/dist/{types-BdpT_4b8.d.cts → types-LSfwsKE-.d.cts} +1 -0
- package/dist/{types-BdpT_4b8.d.ts → types-LSfwsKE-.d.ts} +1 -0
- package/docs/cli.md +5 -3
- package/docs/troubleshooting.md +1 -1
- package/package.json +1 -1
|
@@ -2188,11 +2188,15 @@ function isSensitivePath(relativePath) {
|
|
|
2188
2188
|
}
|
|
2189
2189
|
return matchesSensitiveList(posixPath, base);
|
|
2190
2190
|
}
|
|
2191
|
-
function
|
|
2191
|
+
function pathScanRules(extraRules) {
|
|
2192
|
+
const fallback = extraRules ?? [];
|
|
2193
|
+
return [...DEFAULT_SECRET_PATTERNS, ...fallback];
|
|
2194
|
+
}
|
|
2195
|
+
function findSecretInPath(relativePath, extraRules) {
|
|
2192
2196
|
const posixPath = relativePath.replace(/\\/g, "/");
|
|
2193
2197
|
const spans = [];
|
|
2194
2198
|
const rules = [];
|
|
2195
|
-
for (const { rule, pattern } of
|
|
2199
|
+
for (const { rule, pattern } of pathScanRules(extraRules)) {
|
|
2196
2200
|
const scan = new RegExp(pattern.source, `${pattern.flags.replace(/[gy]/g, "")}g`);
|
|
2197
2201
|
let match;
|
|
2198
2202
|
while ((match = scan.exec(posixPath)) !== null) {
|
|
@@ -2200,24 +2204,39 @@ function findSecretInPath(relativePath) {
|
|
|
2200
2204
|
scan.lastIndex += 1;
|
|
2201
2205
|
continue;
|
|
2202
2206
|
}
|
|
2203
|
-
spans.push({ start: match.index, end: match.index + match[0].length
|
|
2207
|
+
spans.push({ start: match.index, end: match.index + match[0].length });
|
|
2204
2208
|
if (!rules.includes(rule)) rules.push(rule);
|
|
2205
2209
|
}
|
|
2206
2210
|
}
|
|
2207
2211
|
if (spans.length === 0) return null;
|
|
2208
2212
|
spans.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
2213
|
+
const merged = [];
|
|
2214
|
+
for (const span of spans) {
|
|
2215
|
+
const last = merged[merged.length - 1];
|
|
2216
|
+
if (last && span.start <= last.end) last.end = Math.max(last.end, span.end);
|
|
2217
|
+
else merged.push({ start: span.start, end: span.end });
|
|
2218
|
+
}
|
|
2209
2219
|
let out = "";
|
|
2210
2220
|
let cursor = 0;
|
|
2211
|
-
for (const span of
|
|
2212
|
-
|
|
2213
|
-
const start = Math.max(span.start, cursor);
|
|
2214
|
-
out += posixPath.slice(cursor, start);
|
|
2221
|
+
for (const span of merged) {
|
|
2222
|
+
out += posixPath.slice(cursor, span.start);
|
|
2215
2223
|
out += REDACTION_MARKER;
|
|
2216
|
-
cursor =
|
|
2224
|
+
cursor = span.end;
|
|
2217
2225
|
}
|
|
2218
2226
|
out += posixPath.slice(cursor);
|
|
2219
2227
|
return { rules, masked: out };
|
|
2220
2228
|
}
|
|
2229
|
+
function maskSkipPaths(records, extraRules) {
|
|
2230
|
+
return records.map((record) => {
|
|
2231
|
+
const hit = findSecretInPath(record.path, extraRules);
|
|
2232
|
+
const detail = record.detail ? findSecretInPath(record.detail, extraRules) : null;
|
|
2233
|
+
return {
|
|
2234
|
+
...record,
|
|
2235
|
+
path: hit ? hit.masked : record.path,
|
|
2236
|
+
...detail ? { detail: detail.masked } : {}
|
|
2237
|
+
};
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2221
2240
|
function globToRegExp(glob) {
|
|
2222
2241
|
const normalized = glob.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
2223
2242
|
const anchored = normalized.startsWith("/");
|
|
@@ -2448,6 +2467,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2448
2467
|
const includePatterns = options.includePatterns ?? [];
|
|
2449
2468
|
const excludePatterns = options.excludePatterns ?? [];
|
|
2450
2469
|
const includeSensitiveFiles = options.includeSensitiveFiles ?? false;
|
|
2470
|
+
const pathRules = options.secretRules;
|
|
2451
2471
|
const isToolOwned = makeToolOwnedDecider(cwd);
|
|
2452
2472
|
let candidates;
|
|
2453
2473
|
const skipped = [];
|
|
@@ -2483,7 +2503,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2483
2503
|
}
|
|
2484
2504
|
}
|
|
2485
2505
|
} catch {
|
|
2486
|
-
const walked = walkDirectory(cwd, cwd, /* @__PURE__ */ new Set(), true);
|
|
2506
|
+
const walked = walkDirectory(cwd, cwd, rootRealFor(cwd), /* @__PURE__ */ new Set(), true);
|
|
2487
2507
|
candidates = walked.files;
|
|
2488
2508
|
skipped.push(...walked.skipped);
|
|
2489
2509
|
}
|
|
@@ -2521,7 +2541,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2521
2541
|
});
|
|
2522
2542
|
return false;
|
|
2523
2543
|
}
|
|
2524
|
-
const secret = findSecretInPath(file);
|
|
2544
|
+
const secret = findSecretInPath(file, pathRules);
|
|
2525
2545
|
if (secret) {
|
|
2526
2546
|
skipped.push({
|
|
2527
2547
|
path: secret.masked,
|
|
@@ -2532,30 +2552,29 @@ function collectFiles(cwd, options = {}) {
|
|
|
2532
2552
|
}
|
|
2533
2553
|
return true;
|
|
2534
2554
|
}).sort();
|
|
2535
|
-
return { files, skipped };
|
|
2555
|
+
return { files, skipped: maskSkipPaths(skipped, pathRules) };
|
|
2536
2556
|
}
|
|
2537
|
-
function
|
|
2538
|
-
const results = { files: [], skipped: [] };
|
|
2539
|
-
let realDir;
|
|
2557
|
+
function rootRealFor(root) {
|
|
2540
2558
|
try {
|
|
2541
|
-
|
|
2559
|
+
return fs9.realpathSync(root);
|
|
2542
2560
|
} catch {
|
|
2543
|
-
|
|
2544
|
-
}
|
|
2545
|
-
if (visited.has(realDir)) return results;
|
|
2546
|
-
visited.add(realDir);
|
|
2547
|
-
let rootReal;
|
|
2548
|
-
try {
|
|
2549
|
-
rootReal = fs9.realpathSync(baseDir);
|
|
2550
|
-
} catch {
|
|
2551
|
-
rootReal = baseDir;
|
|
2561
|
+
return root;
|
|
2552
2562
|
}
|
|
2563
|
+
}
|
|
2564
|
+
function walkDirectory(dir, baseDir, rootReal, visited, isRoot = false) {
|
|
2565
|
+
const results = { files: [], skipped: [] };
|
|
2566
|
+
if (visited.has(dir)) return results;
|
|
2567
|
+
visited.add(dir);
|
|
2553
2568
|
const ignoredByGitignore = isRoot ? readGitignoreMatcher(baseDir) : () => false;
|
|
2554
2569
|
let entries;
|
|
2555
2570
|
try {
|
|
2556
2571
|
entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
2557
2572
|
} catch {
|
|
2558
|
-
results.skipped.push({
|
|
2573
|
+
results.skipped.push({
|
|
2574
|
+
path: path10.relative(baseDir, dir).replace(/\\/g, "/") || ".",
|
|
2575
|
+
reason: "read-error",
|
|
2576
|
+
detail: "directory unreadable"
|
|
2577
|
+
});
|
|
2559
2578
|
return results;
|
|
2560
2579
|
}
|
|
2561
2580
|
for (const entry of entries) {
|
|
@@ -2634,7 +2653,7 @@ function walkDirectory(dir, baseDir, visited, isRoot = false) {
|
|
|
2634
2653
|
isFile = true;
|
|
2635
2654
|
}
|
|
2636
2655
|
if (isDirectory) {
|
|
2637
|
-
const nested = walkDirectory(fullPath, baseDir, visited);
|
|
2656
|
+
const nested = walkDirectory(fullPath, baseDir, rootReal, visited);
|
|
2638
2657
|
results.files.push(...nested.files);
|
|
2639
2658
|
results.skipped.push(...nested.skipped);
|
|
2640
2659
|
} else if (isFile) {
|
|
@@ -2905,6 +2924,9 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
2905
2924
|
}
|
|
2906
2925
|
async function loadConfigFile(cwd) {
|
|
2907
2926
|
const loaded = await loadConfigFileDetailed(cwd);
|
|
2927
|
+
if (loaded.errors.length > 0) {
|
|
2928
|
+
throw new Error(`The config file could not be read: ${loaded.errors.join("; ")}`);
|
|
2929
|
+
}
|
|
2908
2930
|
return loaded.config;
|
|
2909
2931
|
}
|
|
2910
2932
|
var MIN_MAX_PART_BYTES = 4096;
|
|
@@ -3333,7 +3355,8 @@ function defineConfig(config) {
|
|
|
3333
3355
|
}
|
|
3334
3356
|
|
|
3335
3357
|
// src/generator/audit.ts
|
|
3336
|
-
function generateAuditReport(manifest, secretFindings) {
|
|
3358
|
+
function generateAuditReport(manifest, secretFindings, secretRules) {
|
|
3359
|
+
const mask = (value) => findSecretInPath(value, secretRules)?.masked ?? value;
|
|
3337
3360
|
const lines = [
|
|
3338
3361
|
"# Codebase Health & Security Audit",
|
|
3339
3362
|
"",
|
|
@@ -3368,7 +3391,7 @@ function generateAuditReport(manifest, secretFindings) {
|
|
|
3368
3391
|
"| :--- | :--- | :--- |"
|
|
3369
3392
|
);
|
|
3370
3393
|
for (const finding of secretFindings) {
|
|
3371
|
-
lines.push(`| \`${finding.path ?? "unknown"}\` | ${finding.line} | \`${finding.rule}\` |`);
|
|
3394
|
+
lines.push(`| \`${mask(finding.path ?? "unknown")}\` | ${finding.line} | \`${finding.rule}\` |`);
|
|
3372
3395
|
}
|
|
3373
3396
|
lines.push("", "### Matches by rule", "", "| Rule | Matches |", "| :--- | :--- |");
|
|
3374
3397
|
for (const [rule, count] of Array.from(byRule.entries()).sort((a, b) => b[1] - a[1])) {
|
|
@@ -3390,7 +3413,7 @@ function generateAuditReport(manifest, secretFindings) {
|
|
|
3390
3413
|
for (const file of largeFiles) {
|
|
3391
3414
|
const sizeKb = (file.sizeBytes / 1024).toFixed(1);
|
|
3392
3415
|
const status = file.isPreviewTruncated ? "Truncated Head/Tail" : "Full";
|
|
3393
|
-
lines.push(`| \`${file.relativePath}\` | ${sizeKb} KB | ${file.lines} | ${status} |`);
|
|
3416
|
+
lines.push(`| \`${mask(file.relativePath)}\` | ${sizeKb} KB | ${file.lines} | ${status} |`);
|
|
3394
3417
|
}
|
|
3395
3418
|
lines.push("");
|
|
3396
3419
|
}
|
|
@@ -3432,7 +3455,7 @@ function generateAuditReport(manifest, secretFindings) {
|
|
|
3432
3455
|
"| :--- | :--- | :--- |"
|
|
3433
3456
|
);
|
|
3434
3457
|
for (const skip of manifest.skipped) {
|
|
3435
|
-
lines.push(`| \`${skip.path}\` | \`${skip.reason}\` | ${skip.detail ?? "-"} |`);
|
|
3458
|
+
lines.push(`| \`${mask(skip.path)}\` | \`${skip.reason}\` | ${skip.detail ?? "-"} |`);
|
|
3436
3459
|
}
|
|
3437
3460
|
lines.push("");
|
|
3438
3461
|
}
|
|
@@ -4094,6 +4117,9 @@ function detectLanguage(filePath) {
|
|
|
4094
4117
|
const ext = path10.posix.extname(base).toLowerCase();
|
|
4095
4118
|
return LANGUAGE_BY_EXTENSION[ext] ?? "text";
|
|
4096
4119
|
}
|
|
4120
|
+
function maskedPath(value, secretRules) {
|
|
4121
|
+
return findSecretInPath(value, secretRules)?.masked ?? value;
|
|
4122
|
+
}
|
|
4097
4123
|
function emptyDrift() {
|
|
4098
4124
|
return {
|
|
4099
4125
|
missingInSnapshot: [],
|
|
@@ -4164,15 +4190,20 @@ function validateSnapshot(configInput) {
|
|
|
4164
4190
|
const skippedSet = new Set(
|
|
4165
4191
|
manifest.skipped.filter((entry) => entry && typeof entry.path === "string").map((entry) => entry.path)
|
|
4166
4192
|
);
|
|
4193
|
+
const isSkippedOnDisk = (diskFile) => {
|
|
4194
|
+
if (skippedSet.has(diskFile)) return true;
|
|
4195
|
+
return skippedSet.has(maskedPath(diskFile, config.secretRules));
|
|
4196
|
+
};
|
|
4167
4197
|
const collection = collectFiles(config.cwd, {
|
|
4168
4198
|
includePatterns: config.include,
|
|
4169
4199
|
excludePatterns: [...config.excludePatterns, ...config.presetExclude],
|
|
4170
|
-
includeSensitiveFiles: config.includeSensitiveFiles
|
|
4200
|
+
includeSensitiveFiles: config.includeSensitiveFiles,
|
|
4201
|
+
secretRules: config.secretRules
|
|
4171
4202
|
});
|
|
4172
4203
|
for (const diskFile of collection.files) {
|
|
4173
4204
|
const snapshotHash = manifestFileMap.get(diskFile);
|
|
4174
4205
|
if (!snapshotHash) {
|
|
4175
|
-
if (
|
|
4206
|
+
if (isSkippedOnDisk(diskFile) && !wouldNowBeIncluded(config.cwd, diskFile)) continue;
|
|
4176
4207
|
drift.missingInSnapshot.push(diskFile);
|
|
4177
4208
|
continue;
|
|
4178
4209
|
}
|
|
@@ -4441,10 +4472,19 @@ function validateSnapshot(configInput) {
|
|
|
4441
4472
|
`${drift.configMismatches.length} configuration mismatch(es) between the manifest and this run.`
|
|
4442
4473
|
);
|
|
4443
4474
|
}
|
|
4475
|
+
const maskedDrift = {
|
|
4476
|
+
...drift,
|
|
4477
|
+
missingInSnapshot: drift.missingInSnapshot.map((value) => maskedPath(value, config.secretRules)),
|
|
4478
|
+
missingOnDisk: drift.missingOnDisk.map((value) => maskedPath(value, config.secretRules)),
|
|
4479
|
+
hashMismatches: drift.hashMismatches.map((mismatch) => ({
|
|
4480
|
+
...mismatch,
|
|
4481
|
+
path: maskedPath(mismatch.path, config.secretRules)
|
|
4482
|
+
}))
|
|
4483
|
+
};
|
|
4444
4484
|
return {
|
|
4445
4485
|
valid: errors.length === 0,
|
|
4446
4486
|
manifestPresent: true,
|
|
4447
|
-
drift,
|
|
4487
|
+
drift: maskedDrift,
|
|
4448
4488
|
errors,
|
|
4449
4489
|
warnings
|
|
4450
4490
|
};
|
|
@@ -4479,18 +4519,22 @@ function readManifest2(config) {
|
|
|
4479
4519
|
function explainPath(config, target) {
|
|
4480
4520
|
const relative4 = normalizeTarget(config.cwd, target);
|
|
4481
4521
|
const absolute = path10.join(config.cwd, relative4);
|
|
4522
|
+
const maskedPath2 = findSecretInPath(relative4, config.secretRules)?.masked ?? relative4;
|
|
4482
4523
|
const result = {
|
|
4483
|
-
path:
|
|
4524
|
+
path: maskedPath2,
|
|
4484
4525
|
exists: fs9.existsSync(absolute),
|
|
4485
4526
|
included: false
|
|
4486
4527
|
};
|
|
4487
4528
|
const collection = collectFiles(config.cwd, {
|
|
4488
4529
|
includePatterns: config.include,
|
|
4489
4530
|
excludePatterns: [...config.excludePatterns, ...config.presetExclude],
|
|
4490
|
-
includeSensitiveFiles: config.includeSensitiveFiles
|
|
4531
|
+
includeSensitiveFiles: config.includeSensitiveFiles,
|
|
4532
|
+
secretRules: config.secretRules
|
|
4491
4533
|
});
|
|
4492
4534
|
if (!collection.files.includes(relative4)) {
|
|
4493
|
-
const record = collection.skipped.find(
|
|
4535
|
+
const record = collection.skipped.find(
|
|
4536
|
+
(entry2) => entry2.path === relative4 || entry2.path === maskedPath2
|
|
4537
|
+
);
|
|
4494
4538
|
if (record) {
|
|
4495
4539
|
result.reason = record.reason;
|
|
4496
4540
|
result.detail = record.detail;
|
|
@@ -4527,7 +4571,7 @@ function explainPath(config, target) {
|
|
|
4527
4571
|
result.secrets = findings.slice(0, 20).map((finding) => ({ rule: finding.rule, line: finding.line }));
|
|
4528
4572
|
}
|
|
4529
4573
|
const manifest = readManifest2(config);
|
|
4530
|
-
const entry = manifest?.files.find((file) => file.relativePath === relative4);
|
|
4574
|
+
const entry = Array.isArray(manifest?.files) ? manifest.files.find((file) => file.relativePath === relative4) : void 0;
|
|
4531
4575
|
result.part = entry?.part ?? null;
|
|
4532
4576
|
result.inclusionMode = entry?.inclusionMode;
|
|
4533
4577
|
return result;
|
|
@@ -4632,12 +4676,13 @@ function compareManifests(before, after) {
|
|
|
4632
4676
|
if (!right.has(filePath)) removed.push(filePath);
|
|
4633
4677
|
}
|
|
4634
4678
|
const sort = (values) => values.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
4679
|
+
const mask = (values) => values.map((value) => findSecretInPath(value)?.masked ?? value);
|
|
4635
4680
|
return {
|
|
4636
4681
|
before: side(before),
|
|
4637
4682
|
after: side(after),
|
|
4638
|
-
added: sort(added),
|
|
4639
|
-
removed: sort(removed),
|
|
4640
|
-
changed: sort(changed),
|
|
4683
|
+
added: mask(sort(added)),
|
|
4684
|
+
removed: mask(sort(removed)),
|
|
4685
|
+
changed: mask(sort(changed)),
|
|
4641
4686
|
unchanged
|
|
4642
4687
|
};
|
|
4643
4688
|
}
|
|
@@ -5362,7 +5407,7 @@ async function runInit(options) {
|
|
|
5362
5407
|
|
|
5363
5408
|
// src/index.ts
|
|
5364
5409
|
var GENERATOR_NAME = "@ankurhalder/codebase-snapshot";
|
|
5365
|
-
var GENERATOR_VERSION = "4.0.
|
|
5410
|
+
var GENERATOR_VERSION = "4.0.2";
|
|
5366
5411
|
var SCHEMA_VERSION = "3.0.0";
|
|
5367
5412
|
function sha256Hex2(input) {
|
|
5368
5413
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
@@ -5399,7 +5444,6 @@ function bump(counts, key) {
|
|
|
5399
5444
|
}
|
|
5400
5445
|
var RELATIVE_SPECIFIER = /^\.{1,2}\//;
|
|
5401
5446
|
var IMPORT_CANDIDATE_SUFFIXES = [
|
|
5402
|
-
"",
|
|
5403
5447
|
".ts",
|
|
5404
5448
|
".tsx",
|
|
5405
5449
|
".mts",
|
|
@@ -5413,23 +5457,59 @@ var IMPORT_CANDIDATE_SUFFIXES = [
|
|
|
5413
5457
|
"/index.js",
|
|
5414
5458
|
"/index.mjs"
|
|
5415
5459
|
];
|
|
5416
|
-
|
|
5460
|
+
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
5461
|
+
".ts",
|
|
5462
|
+
".tsx",
|
|
5463
|
+
".mts",
|
|
5464
|
+
".cts",
|
|
5465
|
+
".js",
|
|
5466
|
+
".jsx",
|
|
5467
|
+
".mjs",
|
|
5468
|
+
".cjs"
|
|
5469
|
+
]);
|
|
5470
|
+
function buildImportResolver(files) {
|
|
5471
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
5472
|
+
const byPathFolded = /* @__PURE__ */ new Map();
|
|
5473
|
+
const byStem = /* @__PURE__ */ new Map();
|
|
5474
|
+
const byStemFolded = /* @__PURE__ */ new Map();
|
|
5475
|
+
const remember = (map, key, value) => {
|
|
5476
|
+
if (!map.has(key)) map.set(key, value);
|
|
5477
|
+
};
|
|
5478
|
+
for (const file of files) {
|
|
5479
|
+
const relativePath = file.relativePath;
|
|
5480
|
+
remember(byPath, relativePath, relativePath);
|
|
5481
|
+
remember(byPathFolded, relativePath.toLowerCase(), relativePath);
|
|
5482
|
+
const extension = path10.posix.extname(relativePath);
|
|
5483
|
+
if (!SOURCE_EXTENSIONS.has(extension)) continue;
|
|
5484
|
+
const stem = relativePath.slice(0, -extension.length);
|
|
5485
|
+
remember(byStem, stem, relativePath);
|
|
5486
|
+
remember(byStemFolded, stem.toLowerCase(), relativePath);
|
|
5487
|
+
if (path10.posix.basename(stem) === "index") {
|
|
5488
|
+
const directory = path10.posix.dirname(stem);
|
|
5489
|
+
remember(byStem, directory, relativePath);
|
|
5490
|
+
remember(byStemFolded, directory.toLowerCase(), relativePath);
|
|
5491
|
+
}
|
|
5492
|
+
}
|
|
5493
|
+
return { byPath, byPathFolded, byStem, byStemFolded };
|
|
5494
|
+
}
|
|
5495
|
+
function resolveSpecifier(fromFile, specifier, resolver) {
|
|
5417
5496
|
if (!RELATIVE_SPECIFIER.test(specifier)) return null;
|
|
5418
|
-
const
|
|
5419
|
-
|
|
5420
|
-
|
|
5497
|
+
const joined = path10.posix.normalize(
|
|
5498
|
+
path10.posix.join(path10.posix.dirname(fromFile), specifier)
|
|
5499
|
+
);
|
|
5500
|
+
const exact = (key) => resolver.byPath.get(key) ?? resolver.byPathFolded.get(key.toLowerCase()) ?? null;
|
|
5501
|
+
const direct = exact(joined);
|
|
5502
|
+
if (direct) return direct;
|
|
5421
5503
|
for (const suffix of IMPORT_CANDIDATE_SUFFIXES) {
|
|
5422
|
-
const
|
|
5423
|
-
if (
|
|
5504
|
+
const hit = exact(`${joined}${suffix}`);
|
|
5505
|
+
if (hit) return hit;
|
|
5424
5506
|
}
|
|
5425
|
-
const
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
}
|
|
5429
|
-
return null;
|
|
5507
|
+
const stem = joined.replace(/\.(?:js|mjs|cjs|jsx)$/, "");
|
|
5508
|
+
const byStem = (key) => resolver.byStem.get(key) ?? resolver.byStemFolded.get(key.toLowerCase()) ?? null;
|
|
5509
|
+
return byStem(joined) ?? byStem(stem);
|
|
5430
5510
|
}
|
|
5431
5511
|
function buildIndexes(files) {
|
|
5432
|
-
const
|
|
5512
|
+
const resolver = buildImportResolver(files);
|
|
5433
5513
|
const importerCounts = /* @__PURE__ */ new Map();
|
|
5434
5514
|
const byFile = files.filter((file) => isSourceSummary(file.summary)).map((file) => {
|
|
5435
5515
|
const summary = file.summary;
|
|
@@ -5441,7 +5521,7 @@ function buildIndexes(files) {
|
|
|
5441
5521
|
});
|
|
5442
5522
|
for (const entry of byFile) {
|
|
5443
5523
|
for (const specifier of entry.imports) {
|
|
5444
|
-
const resolved = resolveSpecifier(entry.path, specifier,
|
|
5524
|
+
const resolved = resolveSpecifier(entry.path, specifier, resolver);
|
|
5445
5525
|
if (resolved) importerCounts.set(resolved, (importerCounts.get(resolved) ?? 0) + 1);
|
|
5446
5526
|
}
|
|
5447
5527
|
}
|
|
@@ -5532,15 +5612,22 @@ function resolveSafeOutputDirs(config) {
|
|
|
5532
5612
|
return { outDir, tmpDir };
|
|
5533
5613
|
}
|
|
5534
5614
|
var PLACEHOLDER_ENTRIES = /* @__PURE__ */ new Set([".gitkeep", ".gitignore", ".DS_Store"]);
|
|
5535
|
-
var
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5542
|
-
|
|
5543
|
-
|
|
5615
|
+
var RUN_DIR_PREFIX = "run-";
|
|
5616
|
+
var STALE_RUN_MS = 60 * 60 * 1e3;
|
|
5617
|
+
function maskPathText(value, secretRules) {
|
|
5618
|
+
return findSecretInPath(value, secretRules)?.masked ?? value;
|
|
5619
|
+
}
|
|
5620
|
+
function maskSkipRecords(records, secretRules) {
|
|
5621
|
+
return maskSkipPaths(records, secretRules);
|
|
5622
|
+
}
|
|
5623
|
+
function isProcessAlive(pid) {
|
|
5624
|
+
try {
|
|
5625
|
+
process.kill(pid, 0);
|
|
5626
|
+
return true;
|
|
5627
|
+
} catch (err) {
|
|
5628
|
+
return err.code !== "ESRCH";
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5544
5631
|
var OWNERSHIP_MARKER = ".codebase-snapshot";
|
|
5545
5632
|
var SUPPORTED_MARKER_SCHEMAS = /* @__PURE__ */ new Set([SCHEMA_VERSION]);
|
|
5546
5633
|
var SNAPSHOT_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -5570,6 +5657,7 @@ function markerPayload(dir, state, id, createdAt) {
|
|
|
5570
5657
|
createdAt,
|
|
5571
5658
|
state,
|
|
5572
5659
|
id,
|
|
5660
|
+
pid: process.pid,
|
|
5573
5661
|
entries: listEntries(dir)
|
|
5574
5662
|
};
|
|
5575
5663
|
const manifestPath = path10.join(dir, "manifest.json");
|
|
@@ -5633,6 +5721,7 @@ function readOwnershipMarker(dir) {
|
|
|
5633
5721
|
createdAt: typeof candidate.createdAt === "string" ? candidate.createdAt : "unknown",
|
|
5634
5722
|
state: candidate.state,
|
|
5635
5723
|
id: candidate.id,
|
|
5724
|
+
pid: typeof candidate.pid === "number" ? candidate.pid : void 0,
|
|
5636
5725
|
manifestSha256: typeof candidate.manifestSha256 === "string" ? candidate.manifestSha256 : void 0,
|
|
5637
5726
|
entries: Array.isArray(candidate.entries) && candidate.entries.every((entry) => typeof entry === "string") ? candidate.entries : void 0
|
|
5638
5727
|
},
|
|
@@ -5740,7 +5829,7 @@ function describeEntries(entries, limit = 5) {
|
|
|
5740
5829
|
const shown = entries.slice(0, limit).join(", ");
|
|
5741
5830
|
return entries.length > limit ? `${shown}, and ${entries.length - limit} more` : shown;
|
|
5742
5831
|
}
|
|
5743
|
-
function assertReplaceable(target, label) {
|
|
5832
|
+
function assertReplaceable(target, label, secretRules) {
|
|
5744
5833
|
if (!fs9.existsSync(target)) return;
|
|
5745
5834
|
if (!fs9.statSync(target).isDirectory()) {
|
|
5746
5835
|
throw new Error(
|
|
@@ -5749,34 +5838,89 @@ function assertReplaceable(target, label) {
|
|
|
5749
5838
|
}
|
|
5750
5839
|
const entries = fs9.readdirSync(target);
|
|
5751
5840
|
if (entries.length === 0) return;
|
|
5752
|
-
if (
|
|
5753
|
-
const {
|
|
5754
|
-
if (label === "tmpDir") {
|
|
5755
|
-
if (!marker2) {
|
|
5756
|
-
throw new Error(
|
|
5757
|
-
`Refusing to replace tmpDir ${target}: ${problem ?? "it does not carry this generator's marker"}. This generator only clears a staging directory it wrote. Point tmpDir at a new or empty directory, or remove ${target} yourself.`
|
|
5758
|
-
);
|
|
5759
|
-
}
|
|
5760
|
-
const unexpected = entries.filter((name) => !STAGING_ENTRIES.has(name));
|
|
5761
|
-
if (unexpected.length > 0) {
|
|
5762
|
-
throw new Error(
|
|
5763
|
-
`Refusing to replace tmpDir ${target}: it holds ${describeEntries(unexpected)}, which this generator did not write. Point tmpDir at a new or empty directory, or remove those files yourself.`
|
|
5764
|
-
);
|
|
5765
|
-
}
|
|
5766
|
-
return;
|
|
5767
|
-
}
|
|
5841
|
+
if (entries.every((name) => PLACEHOLDER_ENTRIES.has(name))) return;
|
|
5842
|
+
const { problem } = readOwnershipMarker(target);
|
|
5768
5843
|
const verdict = assessSnapshotDirectory(target);
|
|
5769
5844
|
if (verdict.owned) return;
|
|
5845
|
+
const shownForeign = verdict.foreignEntries.map((name) => maskPathText(name, secretRules));
|
|
5846
|
+
const shownEntries = entries.map((name) => maskPathText(name, secretRules));
|
|
5770
5847
|
if (verdict.foreignEntries.length > 0) {
|
|
5771
5848
|
throw new Error(
|
|
5772
|
-
`Refusing to replace ${label} ${target}: it carries this generator's ownership marker, but these entries are not part of the snapshot it recorded: ${describeEntries(
|
|
5849
|
+
`Refusing to replace ${label} ${target}: it carries this generator's ownership marker, but these entries are not part of the snapshot it recorded: ${describeEntries(shownForeign)}. Remove them yourself, or point ${label} at a new or empty directory.`
|
|
5773
5850
|
);
|
|
5774
5851
|
}
|
|
5775
5852
|
const reason = verdict.problem ?? problem ?? "it does not look like a snapshot this generator wrote";
|
|
5776
5853
|
throw new Error(
|
|
5777
|
-
`Refusing to replace ${label} ${target}: ${reason} (found ${describeEntries(
|
|
5854
|
+
`Refusing to replace ${label} ${target}: ${reason} (found ${describeEntries(shownEntries)}). Remove the directory yourself, or point ${label} at a new or empty directory.`
|
|
5778
5855
|
);
|
|
5779
5856
|
}
|
|
5857
|
+
function assertStagingRootUsable(tmpDir, secretRules) {
|
|
5858
|
+
if (!fs9.existsSync(tmpDir)) return;
|
|
5859
|
+
if (!fs9.statSync(tmpDir).isDirectory()) {
|
|
5860
|
+
throw new Error(`Refusing to write into tmpDir ${tmpDir}: it exists but is not a directory.`);
|
|
5861
|
+
}
|
|
5862
|
+
const entries = fs9.readdirSync(tmpDir);
|
|
5863
|
+
if (entries.length === 0) return;
|
|
5864
|
+
const foreign = entries.filter((name) => {
|
|
5865
|
+
const full = path10.join(tmpDir, name);
|
|
5866
|
+
if (!name.startsWith(RUN_DIR_PREFIX)) return true;
|
|
5867
|
+
let stats;
|
|
5868
|
+
try {
|
|
5869
|
+
stats = fs9.statSync(full);
|
|
5870
|
+
} catch {
|
|
5871
|
+
return true;
|
|
5872
|
+
}
|
|
5873
|
+
if (!stats.isDirectory()) return true;
|
|
5874
|
+
const { marker: marker2 } = readOwnershipMarker(full);
|
|
5875
|
+
if (marker2) return false;
|
|
5876
|
+
try {
|
|
5877
|
+
return fs9.readdirSync(full).length > 0;
|
|
5878
|
+
} catch {
|
|
5879
|
+
return true;
|
|
5880
|
+
}
|
|
5881
|
+
});
|
|
5882
|
+
if (foreign.length > 0) {
|
|
5883
|
+
const shown = describeEntries(foreign.map((name) => maskPathText(name, secretRules)));
|
|
5884
|
+
throw new Error(
|
|
5885
|
+
`Refusing to replace tmpDir ${tmpDir}: it holds ${shown}, which this generator did not write. Point tmpDir at a new or empty directory, or remove those files yourself.`
|
|
5886
|
+
);
|
|
5887
|
+
}
|
|
5888
|
+
}
|
|
5889
|
+
function cleanStaleRunDirs(tmpDir) {
|
|
5890
|
+
let entries;
|
|
5891
|
+
try {
|
|
5892
|
+
entries = fs9.readdirSync(tmpDir);
|
|
5893
|
+
} catch {
|
|
5894
|
+
return;
|
|
5895
|
+
}
|
|
5896
|
+
for (const name of entries) {
|
|
5897
|
+
if (!name.startsWith(RUN_DIR_PREFIX)) continue;
|
|
5898
|
+
const full = path10.join(tmpDir, name);
|
|
5899
|
+
const { marker: marker2 } = readOwnershipMarker(full);
|
|
5900
|
+
if (marker2) {
|
|
5901
|
+
const created = Date.parse(marker2.createdAt);
|
|
5902
|
+
const aged = !Number.isFinite(created) || Date.now() - created > STALE_RUN_MS;
|
|
5903
|
+
const abandoned = typeof marker2.pid === "number" && !isProcessAlive(marker2.pid);
|
|
5904
|
+
if (aged || abandoned) {
|
|
5905
|
+
try {
|
|
5906
|
+
fs9.rmSync(full, { recursive: true, force: true });
|
|
5907
|
+
} catch {
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
continue;
|
|
5911
|
+
}
|
|
5912
|
+
try {
|
|
5913
|
+
if (fs9.readdirSync(full).length === 0) fs9.rmSync(full, { recursive: true, force: true });
|
|
5914
|
+
} catch {
|
|
5915
|
+
}
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5918
|
+
function removeIfEmpty(dir) {
|
|
5919
|
+
try {
|
|
5920
|
+
if (fs9.readdirSync(dir).length === 0) fs9.rmSync(dir, { recursive: true, force: true });
|
|
5921
|
+
} catch {
|
|
5922
|
+
}
|
|
5923
|
+
}
|
|
5780
5924
|
function ensureParentDirectory(target, label) {
|
|
5781
5925
|
const parent = path10.dirname(target);
|
|
5782
5926
|
if (fs9.existsSync(parent) && !fs9.statSync(parent).isDirectory()) {
|
|
@@ -5792,14 +5936,12 @@ function ensureParentDirectory(target, label) {
|
|
|
5792
5936
|
);
|
|
5793
5937
|
}
|
|
5794
5938
|
}
|
|
5795
|
-
function acquireRunLock(
|
|
5796
|
-
const
|
|
5797
|
-
|
|
5798
|
-
`codebase-snapshot-${sha256Hex2(outDir).slice(0, 16)}.lock`
|
|
5799
|
-
);
|
|
5939
|
+
function acquireRunLock(stagingRoot) {
|
|
5940
|
+
const key = lockKeyFor(stagingRoot);
|
|
5941
|
+
const lockPath = path10.join(os.tmpdir(), `codebase-snapshot-${key}.lock`);
|
|
5800
5942
|
const payload = `${JSON.stringify({
|
|
5801
5943
|
pid: process.pid,
|
|
5802
|
-
|
|
5944
|
+
stagingRoot,
|
|
5803
5945
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5804
5946
|
})}
|
|
5805
5947
|
`;
|
|
@@ -5824,11 +5966,20 @@ function acquireRunLock(outDir) {
|
|
|
5824
5966
|
continue;
|
|
5825
5967
|
}
|
|
5826
5968
|
throw new Error(
|
|
5827
|
-
`Another generate run is already
|
|
5969
|
+
`Another generate run is already using the staging directory ${stagingRoot}. Wait for it to finish, or delete ${lockPath} if no other run is active.`
|
|
5828
5970
|
);
|
|
5829
5971
|
}
|
|
5830
5972
|
}
|
|
5831
|
-
throw new Error(`Could not acquire the generate lock for ${
|
|
5973
|
+
throw new Error(`Could not acquire the generate lock for ${stagingRoot}.`);
|
|
5974
|
+
}
|
|
5975
|
+
function lockKeyFor(stagingRoot) {
|
|
5976
|
+
let key = stagingRoot;
|
|
5977
|
+
try {
|
|
5978
|
+
key = fs9.realpathSync(stagingRoot);
|
|
5979
|
+
} catch {
|
|
5980
|
+
}
|
|
5981
|
+
if (process.platform === "win32" || process.platform === "darwin") key = key.toLowerCase();
|
|
5982
|
+
return sha256Hex2(key).slice(0, 16);
|
|
5832
5983
|
}
|
|
5833
5984
|
function lockOwnerIsGone(lockPath) {
|
|
5834
5985
|
let raw;
|
|
@@ -5864,18 +6015,32 @@ function writeManifestAtomically(manifestPath, manifest) {
|
|
|
5864
6015
|
throw err;
|
|
5865
6016
|
}
|
|
5866
6017
|
}
|
|
5867
|
-
function swapIntoPlace(
|
|
6018
|
+
function swapIntoPlace(stagingDir, outDir) {
|
|
5868
6019
|
ensureParentDirectory(outDir, "outDir");
|
|
6020
|
+
const deadline = Date.now() + 3e3;
|
|
6021
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
6022
|
+
try {
|
|
6023
|
+
swapOnce(stagingDir, outDir);
|
|
6024
|
+
return;
|
|
6025
|
+
} catch (err) {
|
|
6026
|
+
const code = err.code;
|
|
6027
|
+
const racy = code === "ENOENT" || code === "ENOTEMPTY" || code === "EEXIST" || code === "EPERM";
|
|
6028
|
+
if (!racy || attempt >= 10 || Date.now() > deadline) throw err;
|
|
6029
|
+
sleepSync(50);
|
|
6030
|
+
}
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
function swapOnce(stagingDir, outDir) {
|
|
5869
6034
|
const backupDir = `${outDir}.backup-${process.pid}-${Date.now()}`;
|
|
5870
6035
|
const hadPrevious = fs9.existsSync(outDir);
|
|
5871
6036
|
if (hadPrevious) fs9.renameSync(outDir, backupDir);
|
|
5872
6037
|
try {
|
|
5873
6038
|
try {
|
|
5874
|
-
fs9.renameSync(
|
|
6039
|
+
fs9.renameSync(stagingDir, outDir);
|
|
5875
6040
|
} catch (err) {
|
|
5876
6041
|
if (err.code === "EXDEV") {
|
|
5877
|
-
fs9.cpSync(
|
|
5878
|
-
fs9.rmSync(
|
|
6042
|
+
fs9.cpSync(stagingDir, outDir, { recursive: true });
|
|
6043
|
+
fs9.rmSync(stagingDir, { recursive: true, force: true });
|
|
5879
6044
|
} else {
|
|
5880
6045
|
throw err;
|
|
5881
6046
|
}
|
|
@@ -5889,6 +6054,10 @@ function swapIntoPlace(tmpDir, outDir) {
|
|
|
5889
6054
|
throw err;
|
|
5890
6055
|
}
|
|
5891
6056
|
}
|
|
6057
|
+
function sleepSync(milliseconds) {
|
|
6058
|
+
const buffer = new Int32Array(new SharedArrayBuffer(4));
|
|
6059
|
+
Atomics.wait(buffer, 0, 0, milliseconds);
|
|
6060
|
+
}
|
|
5892
6061
|
function artifactWarnings(artifacts) {
|
|
5893
6062
|
const messages = [];
|
|
5894
6063
|
if (!artifacts.manifest) {
|
|
@@ -5951,11 +6120,12 @@ function generateSnapshot(configInput, options) {
|
|
|
5951
6120
|
const collection = collectFiles(config.cwd, {
|
|
5952
6121
|
includePatterns: config.include,
|
|
5953
6122
|
excludePatterns: [...config.excludePatterns, ...config.presetExclude],
|
|
5954
|
-
includeSensitiveFiles: config.includeSensitiveFiles
|
|
6123
|
+
includeSensitiveFiles: config.includeSensitiveFiles,
|
|
6124
|
+
secretRules: config.secretRules
|
|
5955
6125
|
});
|
|
5956
6126
|
const files = [];
|
|
5957
6127
|
const monolithBodies = /* @__PURE__ */ new Map();
|
|
5958
|
-
const skipped = [...collection.skipped];
|
|
6128
|
+
const skipped = maskSkipRecords([...collection.skipped], config.secretRules);
|
|
5959
6129
|
const secretFindings = [];
|
|
5960
6130
|
const warnings = [];
|
|
5961
6131
|
const layerCounts = {};
|
|
@@ -6029,12 +6199,12 @@ function generateSnapshot(configInput, options) {
|
|
|
6029
6199
|
summaryQuality = outcome?.quality;
|
|
6030
6200
|
if (isSourceSummary(summary) && summary.parseErrors) {
|
|
6031
6201
|
warnings.push(
|
|
6032
|
-
`Parse errors in ${relativePath} (${summary.parseErrors}); its summary is incomplete.`
|
|
6202
|
+
`Parse errors in ${maskPathText(relativePath, config.secretRules)} (${summary.parseErrors}); its summary is incomplete.`
|
|
6033
6203
|
);
|
|
6034
6204
|
}
|
|
6035
6205
|
} catch (err) {
|
|
6036
6206
|
warnings.push(
|
|
6037
|
-
`Summary skipped for ${relativePath}: ${err.message}`.replace(/\s+/g, " ")
|
|
6207
|
+
`Summary skipped for ${maskPathText(relativePath, config.secretRules)}: ${err.message}`.replace(/\s+/g, " ")
|
|
6038
6208
|
);
|
|
6039
6209
|
}
|
|
6040
6210
|
files.push({
|
|
@@ -6078,6 +6248,7 @@ function generateSnapshot(configInput, options) {
|
|
|
6078
6248
|
const truncatedPreviewCount = files.filter((file) => file.isPreviewTruncated).length;
|
|
6079
6249
|
const validationErrors = verifyInMemory(files, parts, maxEffectiveBudget);
|
|
6080
6250
|
const totalContentBytes = files.reduce((total, file) => total + file.includedBytes, 0);
|
|
6251
|
+
const maskName = (value) => maskPathText(value, config.secretRules);
|
|
6081
6252
|
const manifest = {
|
|
6082
6253
|
schemaVersion: SCHEMA_VERSION,
|
|
6083
6254
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6098,13 +6269,13 @@ function generateSnapshot(configInput, options) {
|
|
|
6098
6269
|
includeMonolith: config.includeMonolith,
|
|
6099
6270
|
includeSensitiveFiles: config.includeSensitiveFiles,
|
|
6100
6271
|
artifacts: { ...config.artifacts },
|
|
6101
|
-
include: [...config.include],
|
|
6272
|
+
include: [...config.include].map(maskName),
|
|
6102
6273
|
preset: config.preset,
|
|
6103
6274
|
layersMode: config.layersMode,
|
|
6104
6275
|
budgets: { default: config.budgets.default, byLayer: { ...config.budgets.byLayer } },
|
|
6105
|
-
excludePatterns: [...config.excludePatterns],
|
|
6106
|
-
layers: config.layers.map((layer2) => layer2.name),
|
|
6107
|
-
kinds: config.kinds.map((kind) => kind.kind)
|
|
6276
|
+
excludePatterns: [...config.excludePatterns].map(maskName),
|
|
6277
|
+
layers: config.layers.map((layer2) => maskName(layer2.name)),
|
|
6278
|
+
kinds: config.kinds.map((kind) => maskName(kind.kind))
|
|
6108
6279
|
},
|
|
6109
6280
|
counts: {
|
|
6110
6281
|
totalFiles: files.length,
|
|
@@ -6143,12 +6314,12 @@ function generateSnapshot(configInput, options) {
|
|
|
6143
6314
|
const { content: _content, ...rest } = file;
|
|
6144
6315
|
return rest;
|
|
6145
6316
|
}),
|
|
6146
|
-
skipped,
|
|
6317
|
+
skipped: maskSkipRecords(skipped, config.secretRules),
|
|
6147
6318
|
warnings
|
|
6148
6319
|
};
|
|
6149
6320
|
manifest.warnings = [
|
|
6150
6321
|
...warnings,
|
|
6151
|
-
...secretFindings.map((finding) => `${finding.rule} at ${finding.path ?? "unknown"}:${finding.line}`)
|
|
6322
|
+
...secretFindings.map((finding) => `${finding.rule} at ${maskPathText(finding.path ?? "unknown", config.secretRules)}:${finding.line}`)
|
|
6152
6323
|
];
|
|
6153
6324
|
manifest.totals.warningCount = manifest.warnings.length;
|
|
6154
6325
|
let monolithJson = null;
|
|
@@ -6194,31 +6365,33 @@ function generateSnapshot(configInput, options) {
|
|
|
6194
6365
|
manifest.totals.warningCount = manifest.warnings.length;
|
|
6195
6366
|
const { outDir, tmpDir } = resolveSafeOutputDirs(config);
|
|
6196
6367
|
const { artifacts } = config;
|
|
6197
|
-
assertReplaceable(
|
|
6198
|
-
|
|
6368
|
+
assertReplaceable(outDir, "outDir", config.secretRules);
|
|
6369
|
+
assertStagingRootUsable(tmpDir, config.secretRules);
|
|
6199
6370
|
if (dryRun) {
|
|
6200
6371
|
runAfterGenerate(config, manifest);
|
|
6201
6372
|
return manifest;
|
|
6202
6373
|
}
|
|
6203
|
-
const releaseLock = acquireRunLock(
|
|
6204
|
-
let
|
|
6374
|
+
const releaseLock = acquireRunLock(tmpDir);
|
|
6375
|
+
let stagingDir = null;
|
|
6205
6376
|
try {
|
|
6206
6377
|
ensureParentDirectory(outDir, "outDir");
|
|
6207
|
-
fs9.rmSync(tmpDir, { recursive: true, force: true });
|
|
6208
6378
|
fs9.mkdirSync(tmpDir, { recursive: true });
|
|
6209
|
-
|
|
6379
|
+
cleanStaleRunDirs(tmpDir);
|
|
6210
6380
|
const snapshotId = crypto.randomUUID();
|
|
6211
6381
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6212
|
-
|
|
6382
|
+
stagingDir = path10.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
|
|
6383
|
+
fs9.mkdirSync(stagingDir);
|
|
6384
|
+
writeOwnershipMarker(stagingDir, {
|
|
6213
6385
|
generator: GENERATOR_NAME,
|
|
6214
6386
|
version: GENERATOR_VERSION,
|
|
6215
6387
|
schemaVersion: SCHEMA_VERSION,
|
|
6216
6388
|
createdAt,
|
|
6217
6389
|
state: "staging",
|
|
6218
|
-
id: snapshotId
|
|
6390
|
+
id: snapshotId,
|
|
6391
|
+
pid: process.pid
|
|
6219
6392
|
});
|
|
6220
|
-
const partsDir = path10.join(
|
|
6221
|
-
const reportsDir = path10.join(
|
|
6393
|
+
const partsDir = path10.join(stagingDir, "parts");
|
|
6394
|
+
const reportsDir = path10.join(stagingDir, "reports");
|
|
6222
6395
|
if (artifacts.parts) fs9.mkdirSync(partsDir, { recursive: true });
|
|
6223
6396
|
if (artifacts.navigation || artifacts.projectTree || artifacts.audit) {
|
|
6224
6397
|
fs9.mkdirSync(reportsDir, { recursive: true });
|
|
@@ -6238,25 +6411,25 @@ function generateSnapshot(configInput, options) {
|
|
|
6238
6411
|
if (artifacts.audit) {
|
|
6239
6412
|
fs9.writeFileSync(
|
|
6240
6413
|
path10.join(reportsDir, "audit.md"),
|
|
6241
|
-
generateAuditReport(manifest, secretFindings),
|
|
6414
|
+
generateAuditReport(manifest, secretFindings, config.secretRules),
|
|
6242
6415
|
"utf8"
|
|
6243
6416
|
);
|
|
6244
6417
|
}
|
|
6245
6418
|
if (artifacts.readme) {
|
|
6246
|
-
fs9.writeFileSync(path10.join(
|
|
6419
|
+
fs9.writeFileSync(path10.join(stagingDir, "README.md"), generateReadme(manifest), "utf8");
|
|
6247
6420
|
}
|
|
6248
6421
|
if (artifacts.manifest) {
|
|
6249
|
-
fs9.writeFileSync(path10.join(
|
|
6422
|
+
fs9.writeFileSync(path10.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
6250
6423
|
}
|
|
6251
6424
|
if (monolithJson !== null) {
|
|
6252
|
-
fs9.writeFileSync(path10.join(
|
|
6425
|
+
fs9.writeFileSync(path10.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
|
|
6253
6426
|
}
|
|
6254
6427
|
if (monolithMarkdown !== null) {
|
|
6255
|
-
fs9.writeFileSync(path10.join(
|
|
6428
|
+
fs9.writeFileSync(path10.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
|
|
6256
6429
|
}
|
|
6257
|
-
writeOwnershipMarker(
|
|
6258
|
-
swapIntoPlace(
|
|
6259
|
-
|
|
6430
|
+
writeOwnershipMarker(stagingDir, markerPayload(stagingDir, "complete", snapshotId, createdAt));
|
|
6431
|
+
swapIntoPlace(stagingDir, outDir);
|
|
6432
|
+
stagingDir = null;
|
|
6260
6433
|
const warningsBeforeHook = manifest.warnings.length;
|
|
6261
6434
|
runAfterGenerate(config, manifest);
|
|
6262
6435
|
if (artifacts.manifest && manifest.warnings.length !== warningsBeforeHook) {
|
|
@@ -6265,14 +6438,15 @@ function generateSnapshot(configInput, options) {
|
|
|
6265
6438
|
writeOwnershipMarker(outDir, markerPayload(outDir, "complete", snapshotId, createdAt));
|
|
6266
6439
|
return manifest;
|
|
6267
6440
|
} catch (err) {
|
|
6268
|
-
if (
|
|
6441
|
+
if (stagingDir !== null) {
|
|
6269
6442
|
try {
|
|
6270
|
-
fs9.rmSync(
|
|
6443
|
+
fs9.rmSync(stagingDir, { recursive: true, force: true });
|
|
6271
6444
|
} catch {
|
|
6272
6445
|
}
|
|
6273
6446
|
}
|
|
6274
6447
|
throw err;
|
|
6275
6448
|
} finally {
|
|
6449
|
+
removeIfEmpty(tmpDir);
|
|
6276
6450
|
releaseLock();
|
|
6277
6451
|
}
|
|
6278
6452
|
}
|
|
@@ -6281,5 +6455,5 @@ async function generateSnapshotAsync(configInput, options) {
|
|
|
6281
6455
|
}
|
|
6282
6456
|
|
|
6283
6457
|
export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countLines, defineConfig, detectLanguage, detectPreset, explainPath, fenceForContent, fenceForText, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, globToRegExp, isBinaryBuffer, isBinaryExtension, isBinaryFile, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, profileForPath, renderConfig, renderDiffText, renderExplainText, renderMinimalConfig, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, unknownPresetMessage, validateSnapshot };
|
|
6284
|
-
//# sourceMappingURL=chunk-
|
|
6285
|
-
//# sourceMappingURL=chunk-
|
|
6458
|
+
//# sourceMappingURL=chunk-CY3XU5TS.js.map
|
|
6459
|
+
//# sourceMappingURL=chunk-CY3XU5TS.js.map
|