codebase-snapshot 0.9.0 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +229 -1
- package/README.md +141 -127
- package/SECURITY.md +6 -2
- package/dist/bin.js +2544 -507
- package/dist/chunk-EWZYK3VX.js +2577 -0
- package/dist/{chunk-FJ4RQYY2.js → chunk-FCWD4LY7.js} +493 -362
- package/dist/cli.cjs +2451 -436
- package/dist/cli.d.cts +11 -1
- package/dist/cli.d.ts +11 -1
- package/dist/cli.js +68 -750
- package/dist/index.cjs +481 -360
- package/dist/index.d.cts +111 -5
- package/dist/index.d.ts +111 -5
- package/dist/index.js +1 -1
- package/dist/mcp.cjs +9398 -0
- package/dist/mcp.d.cts +399 -0
- package/dist/mcp.d.ts +399 -0
- package/dist/mcp.js +4 -0
- package/docs/agent.md +36 -0
- package/docs/cli.md +85 -14
- package/docs/codebase-token-budget.md +98 -0
- package/docs/configuration.md +12 -2
- package/docs/how-to-feed-a-repo-to-claude.md +4 -2
- package/docs/install.md +39 -11
- package/docs/mcp.md +149 -0
- package/docs/stale-context-is-your-bug.md +118 -0
- package/docs/troubleshooting.md +13 -0
- package/docs/vs-repomix.md +4 -2
- package/package.json +32 -16
package/dist/index.cjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
4
|
var async_hooks = require('async_hooks');
|
|
5
|
-
var
|
|
5
|
+
var fs11 = require('fs');
|
|
6
6
|
var os = require('os');
|
|
7
|
-
var
|
|
7
|
+
var path12 = require('path');
|
|
8
8
|
var ts = require('typescript');
|
|
9
9
|
var module$1 = require('module');
|
|
10
10
|
var url = require('url');
|
|
@@ -32,9 +32,9 @@ function _interopNamespace(e) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
35
|
-
var
|
|
35
|
+
var fs11__namespace = /*#__PURE__*/_interopNamespace(fs11);
|
|
36
36
|
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
37
|
-
var
|
|
37
|
+
var path12__namespace = /*#__PURE__*/_interopNamespace(path12);
|
|
38
38
|
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
|
39
39
|
var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
|
|
40
40
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
@@ -263,9 +263,9 @@ var JAVA_METHOD = /^\s+(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)
|
|
|
263
263
|
var jvmProfile = {
|
|
264
264
|
id: "jvm",
|
|
265
265
|
extensions: [".java", ".kt", ".kts", ".scala"],
|
|
266
|
-
summarize(
|
|
266
|
+
summarize(path13, content) {
|
|
267
267
|
const summary = emptySummary();
|
|
268
|
-
const lower =
|
|
268
|
+
const lower = path13.toLowerCase();
|
|
269
269
|
const isJava = lower.endsWith(".java");
|
|
270
270
|
const isKotlin = lower.endsWith(".kt") || lower.endsWith(".kts");
|
|
271
271
|
eachLine(content, (line) => {
|
|
@@ -718,16 +718,16 @@ function summarizeTypeScriptSource(relativePath, content) {
|
|
|
718
718
|
// src/ast/profiles/sfc.ts
|
|
719
719
|
var SCRIPT_BLOCK = /<script[^>]*>([\s\S]*?)<\/script>/gi;
|
|
720
720
|
var ASTRO_FRONTMATTER = /^\uFEFF?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?=\r?\n|$)/;
|
|
721
|
-
function componentName(
|
|
722
|
-
const base =
|
|
721
|
+
function componentName(path13) {
|
|
722
|
+
const base = path13.split("/").pop() ?? path13;
|
|
723
723
|
return base.replace(/\.[^.]+$/, "");
|
|
724
724
|
}
|
|
725
725
|
var sfcProfile = {
|
|
726
726
|
id: "sfc",
|
|
727
727
|
extensions: [".vue", ".svelte", ".astro"],
|
|
728
|
-
summarize(
|
|
728
|
+
summarize(path13, content) {
|
|
729
729
|
let script = "";
|
|
730
|
-
if (
|
|
730
|
+
if (path13.toLowerCase().endsWith(".astro")) {
|
|
731
731
|
const frontmatter = ASTRO_FRONTMATTER.exec(content);
|
|
732
732
|
if (frontmatter) script += `${frontmatter[1]}
|
|
733
733
|
`;
|
|
@@ -736,7 +736,7 @@ var sfcProfile = {
|
|
|
736
736
|
script += `${match[1]}
|
|
737
737
|
`;
|
|
738
738
|
}
|
|
739
|
-
const name = componentName(
|
|
739
|
+
const name = componentName(path13);
|
|
740
740
|
if (!script.trim()) {
|
|
741
741
|
const summary2 = emptySummary();
|
|
742
742
|
if (name) {
|
|
@@ -770,15 +770,15 @@ for (const profile of LANGUAGE_PROFILES) {
|
|
|
770
770
|
BY_EXTENSION.set(extension.toLowerCase(), profile);
|
|
771
771
|
}
|
|
772
772
|
}
|
|
773
|
-
function profileForPath(
|
|
774
|
-
const lower =
|
|
773
|
+
function profileForPath(path13) {
|
|
774
|
+
const lower = path13.toLowerCase();
|
|
775
775
|
const dot = lower.lastIndexOf(".");
|
|
776
776
|
if (dot === -1) return null;
|
|
777
777
|
return BY_EXTENSION.get(lower.slice(dot)) ?? null;
|
|
778
778
|
}
|
|
779
|
-
function summarizeWithProfile(
|
|
780
|
-
const profile = profileForPath(
|
|
781
|
-
return profile ? profile.summarize(
|
|
779
|
+
function summarizeWithProfile(path13, content) {
|
|
780
|
+
const profile = profileForPath(path13);
|
|
781
|
+
return profile ? profile.summarize(path13, content) : null;
|
|
782
782
|
}
|
|
783
783
|
|
|
784
784
|
// src/ast/structured.ts
|
|
@@ -949,15 +949,15 @@ var SKIPPED_WALK_DIRS = /* @__PURE__ */ new Set([
|
|
|
949
949
|
]);
|
|
950
950
|
function readSmallFile(fullPath) {
|
|
951
951
|
try {
|
|
952
|
-
const stats =
|
|
952
|
+
const stats = fs11__namespace.statSync(fullPath);
|
|
953
953
|
if (!stats.isFile() || stats.size > MANIFEST_MAX_BYTES) return null;
|
|
954
|
-
return
|
|
954
|
+
return fs11__namespace.readFileSync(fullPath, "utf8");
|
|
955
955
|
} catch {
|
|
956
956
|
return null;
|
|
957
957
|
}
|
|
958
958
|
}
|
|
959
959
|
function readManifest(cwd, name) {
|
|
960
|
-
return readSmallFile(
|
|
960
|
+
return readSmallFile(path12__namespace.join(cwd, name));
|
|
961
961
|
}
|
|
962
962
|
function dependenciesFromPackageJson(raw) {
|
|
963
963
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -1017,7 +1017,7 @@ function pnpmWorkspacePatterns(raw) {
|
|
|
1017
1017
|
function childDirectories(cwd, parent) {
|
|
1018
1018
|
let entries;
|
|
1019
1019
|
try {
|
|
1020
|
-
entries =
|
|
1020
|
+
entries = fs11__namespace.readdirSync(path12__namespace.join(cwd, parent), { withFileTypes: true });
|
|
1021
1021
|
} catch {
|
|
1022
1022
|
return [];
|
|
1023
1023
|
}
|
|
@@ -1052,13 +1052,13 @@ function workspacePackageDirs(cwd, patterns) {
|
|
|
1052
1052
|
function scanWorkspacePackages(cwd, patterns) {
|
|
1053
1053
|
const files = /* @__PURE__ */ new Set();
|
|
1054
1054
|
const dependencies = /* @__PURE__ */ new Set();
|
|
1055
|
-
for (const
|
|
1056
|
-
const full =
|
|
1055
|
+
for (const relative7 of workspacePackageDirs(cwd, patterns)) {
|
|
1056
|
+
const full = path12__namespace.join(cwd, relative7);
|
|
1057
1057
|
try {
|
|
1058
|
-
for (const entry of
|
|
1058
|
+
for (const entry of fs11__namespace.readdirSync(full, { withFileTypes: true })) files.add(entry.name);
|
|
1059
1059
|
} catch {
|
|
1060
1060
|
}
|
|
1061
|
-
const raw = readSmallFile(
|
|
1061
|
+
const raw = readSmallFile(path12__namespace.join(full, "package.json"));
|
|
1062
1062
|
if (raw !== null) {
|
|
1063
1063
|
for (const name of dependenciesFromPackageJson(raw)) dependencies.add(name);
|
|
1064
1064
|
}
|
|
@@ -1075,7 +1075,7 @@ function countMarkdownFiles(cwd) {
|
|
|
1075
1075
|
directoriesSeen += 1;
|
|
1076
1076
|
let entries;
|
|
1077
1077
|
try {
|
|
1078
|
-
entries =
|
|
1078
|
+
entries = fs11__namespace.readdirSync(current.dir, { withFileTypes: true });
|
|
1079
1079
|
} catch {
|
|
1080
1080
|
continue;
|
|
1081
1081
|
}
|
|
@@ -1086,7 +1086,7 @@ function countMarkdownFiles(cwd) {
|
|
|
1086
1086
|
}
|
|
1087
1087
|
if (!entry.isDirectory() || current.depth >= 2) continue;
|
|
1088
1088
|
if (entry.name.startsWith(".") || SKIPPED_WALK_DIRS.has(entry.name)) continue;
|
|
1089
|
-
queue.push({ dir:
|
|
1089
|
+
queue.push({ dir: path12__namespace.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
1090
1090
|
}
|
|
1091
1091
|
}
|
|
1092
1092
|
return count;
|
|
@@ -1095,7 +1095,7 @@ function buildPresetContext(cwd) {
|
|
|
1095
1095
|
const files = /* @__PURE__ */ new Set();
|
|
1096
1096
|
const dirs = /* @__PURE__ */ new Set();
|
|
1097
1097
|
try {
|
|
1098
|
-
for (const entry of
|
|
1098
|
+
for (const entry of fs11__namespace.readdirSync(cwd, { withFileTypes: true })) {
|
|
1099
1099
|
if (entry.isDirectory()) dirs.add(entry.name);
|
|
1100
1100
|
else if (entry.isFile()) files.add(entry.name);
|
|
1101
1101
|
}
|
|
@@ -1112,7 +1112,7 @@ function buildPresetContext(cwd) {
|
|
|
1112
1112
|
const isWorkspace = files.has("pnpm-workspace.yaml") || files.has("nx.json") || files.has("turbo.json") || files.has("lerna.json") || packageJson !== void 0 && packageJson.includes('"workspaces"') || declaredWorkspaces.length > 0;
|
|
1113
1113
|
let workspace = { files: /* @__PURE__ */ new Set(), dependencies: /* @__PURE__ */ new Set() };
|
|
1114
1114
|
if (isWorkspace) {
|
|
1115
|
-
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(
|
|
1115
|
+
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(path12__namespace.join(cwd, "pnpm-workspace.yaml")) : null;
|
|
1116
1116
|
const declared = pnpmRaw === null ? [] : pnpmWorkspacePatterns(pnpmRaw);
|
|
1117
1117
|
const patterns = declared.length > 0 ? declared : declaredWorkspaces.length > 0 ? declaredWorkspaces : DEFAULT_WORKSPACE_PATTERNS;
|
|
1118
1118
|
workspace = scanWorkspacePackages(cwd, patterns);
|
|
@@ -1130,25 +1130,41 @@ function buildPresetContext(cwd) {
|
|
|
1130
1130
|
markdownCount: files.has("package.json") ? 0 : countMarkdownFiles(cwd)
|
|
1131
1131
|
};
|
|
1132
1132
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1133
|
+
|
|
1134
|
+
// src/presets/evidence.ts
|
|
1135
|
+
function fileEvidence(context, name) {
|
|
1136
|
+
return context.files.has(name) ? name : null;
|
|
1135
1137
|
}
|
|
1136
|
-
function
|
|
1138
|
+
function fileStartingWithEvidence(context, prefix) {
|
|
1137
1139
|
for (const file of context.files) {
|
|
1138
|
-
if (file.startsWith(prefix)) return
|
|
1140
|
+
if (file.startsWith(prefix)) return file;
|
|
1139
1141
|
}
|
|
1140
1142
|
for (const file of context.workspaceFiles) {
|
|
1141
|
-
if (file.startsWith(prefix)) return
|
|
1143
|
+
if (file.startsWith(prefix)) return file;
|
|
1142
1144
|
}
|
|
1143
|
-
return
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
function dependencyEvidence(context, ...names) {
|
|
1148
|
+
for (const name of names) {
|
|
1149
|
+
if (context.dependencies.has(name)) return `depends on ${name}`;
|
|
1150
|
+
}
|
|
1151
|
+
return null;
|
|
1144
1152
|
}
|
|
1145
|
-
function
|
|
1153
|
+
function manifestEvidence(context, manifest, needle) {
|
|
1146
1154
|
const content = context.manifests[manifest];
|
|
1147
|
-
if (!content) return
|
|
1148
|
-
|
|
1155
|
+
if (!content) return null;
|
|
1156
|
+
if (!content.toLowerCase().includes(needle.toLowerCase())) return null;
|
|
1157
|
+
return `${needle} in ${manifest}`;
|
|
1149
1158
|
}
|
|
1150
|
-
function
|
|
1151
|
-
|
|
1159
|
+
function suffixEvidence(context, suffix) {
|
|
1160
|
+
for (const file of context.files) {
|
|
1161
|
+
if (file.endsWith(suffix)) return file;
|
|
1162
|
+
}
|
|
1163
|
+
return null;
|
|
1164
|
+
}
|
|
1165
|
+
function markdownEvidence(context) {
|
|
1166
|
+
if (context.markdownCount < 3 || context.files.has("package.json")) return null;
|
|
1167
|
+
return `${context.markdownCount} markdown files, no package.json`;
|
|
1152
1168
|
}
|
|
1153
1169
|
|
|
1154
1170
|
// src/presets/helpers.ts
|
|
@@ -1356,7 +1372,7 @@ var JS_PRESETS = [
|
|
|
1356
1372
|
{
|
|
1357
1373
|
name: "nextjs",
|
|
1358
1374
|
priority: 100,
|
|
1359
|
-
detect: (context) =>
|
|
1375
|
+
detect: (context) => fileStartingWithEvidence(context, "next.config") ?? dependencyEvidence(context, "next"),
|
|
1360
1376
|
layers: NEXTJS_LAYERS,
|
|
1361
1377
|
kinds: NEXTJS_KINDS,
|
|
1362
1378
|
exclude: NEXT_LIKE_EXCLUDES,
|
|
@@ -1365,7 +1381,7 @@ var JS_PRESETS = [
|
|
|
1365
1381
|
{
|
|
1366
1382
|
name: "nuxt",
|
|
1367
1383
|
priority: 98,
|
|
1368
|
-
detect: (context) =>
|
|
1384
|
+
detect: (context) => fileStartingWithEvidence(context, "nuxt.config") ?? dependencyEvidence(context, "nuxt", "nuxt3"),
|
|
1369
1385
|
layers: [
|
|
1370
1386
|
layer("pages", "pages/", "src/pages/"),
|
|
1371
1387
|
layer("components", "components/", "src/components/"),
|
|
@@ -1389,7 +1405,7 @@ var JS_PRESETS = [
|
|
|
1389
1405
|
{
|
|
1390
1406
|
name: "sveltekit",
|
|
1391
1407
|
priority: 96,
|
|
1392
|
-
detect: (context) =>
|
|
1408
|
+
detect: (context) => fileStartingWithEvidence(context, "svelte.config") ?? dependencyEvidence(context, "@sveltejs/kit", "svelte"),
|
|
1393
1409
|
layers: [
|
|
1394
1410
|
layer("routes", "src/routes/", "routes/"),
|
|
1395
1411
|
layer("lib", "src/lib/", "lib/"),
|
|
@@ -1410,7 +1426,7 @@ var JS_PRESETS = [
|
|
|
1410
1426
|
{
|
|
1411
1427
|
name: "remix",
|
|
1412
1428
|
priority: 94,
|
|
1413
|
-
detect: (context) =>
|
|
1429
|
+
detect: (context) => dependencyEvidence(context, "@remix-run/react", "@remix-run/node", "@remix-run/dev"),
|
|
1414
1430
|
layers: [
|
|
1415
1431
|
layer("routes", "app/routes/", "routes/"),
|
|
1416
1432
|
layer("components", "app/components/"),
|
|
@@ -1424,7 +1440,7 @@ var JS_PRESETS = [
|
|
|
1424
1440
|
{
|
|
1425
1441
|
name: "astro",
|
|
1426
1442
|
priority: 92,
|
|
1427
|
-
detect: (context) =>
|
|
1443
|
+
detect: (context) => fileStartingWithEvidence(context, "astro.config") ?? dependencyEvidence(context, "astro"),
|
|
1428
1444
|
layers: [
|
|
1429
1445
|
layer("pages", "src/pages/"),
|
|
1430
1446
|
layer("layouts", "src/layouts/"),
|
|
@@ -1439,7 +1455,7 @@ var JS_PRESETS = [
|
|
|
1439
1455
|
{
|
|
1440
1456
|
name: "angular",
|
|
1441
1457
|
priority: 90,
|
|
1442
|
-
detect: (context) =>
|
|
1458
|
+
detect: (context) => fileEvidence(context, "angular.json") ?? dependencyEvidence(context, "@angular/core"),
|
|
1443
1459
|
layers: [
|
|
1444
1460
|
layer("app", "src/app/"),
|
|
1445
1461
|
layer("features", "src/app/features/"),
|
|
@@ -1463,7 +1479,7 @@ var JS_PRESETS = [
|
|
|
1463
1479
|
{
|
|
1464
1480
|
name: "solid",
|
|
1465
1481
|
priority: 88,
|
|
1466
|
-
detect: (context) =>
|
|
1482
|
+
detect: (context) => dependencyEvidence(context, "solid-js", "solid-start"),
|
|
1467
1483
|
layers: [
|
|
1468
1484
|
layer("pages", "src/routes/", "src/pages/"),
|
|
1469
1485
|
layer("components", "src/components/"),
|
|
@@ -1476,7 +1492,15 @@ var JS_PRESETS = [
|
|
|
1476
1492
|
{
|
|
1477
1493
|
name: "vue-vite",
|
|
1478
1494
|
priority: 86,
|
|
1479
|
-
|
|
1495
|
+
// `vue` is the decisive signal; `vite` (or its config file) only says the app is
|
|
1496
|
+
// built with Vite rather than shipped pre-compiled, so it is required but not what
|
|
1497
|
+
// gets reported.
|
|
1498
|
+
detect: (context) => {
|
|
1499
|
+
const framework = dependencyEvidence(context, "vue");
|
|
1500
|
+
if (framework === null) return null;
|
|
1501
|
+
const build = dependencyEvidence(context, "vite") ?? fileStartingWithEvidence(context, "vite.config");
|
|
1502
|
+
return build === null ? null : framework;
|
|
1503
|
+
},
|
|
1480
1504
|
layers: [
|
|
1481
1505
|
layer("pages", "src/pages/", "src/views/"),
|
|
1482
1506
|
layer("components", "src/components/"),
|
|
@@ -1501,7 +1525,12 @@ var JS_PRESETS = [
|
|
|
1501
1525
|
{
|
|
1502
1526
|
name: "react-vite",
|
|
1503
1527
|
priority: 84,
|
|
1504
|
-
detect: (context) =>
|
|
1528
|
+
detect: (context) => {
|
|
1529
|
+
const framework = dependencyEvidence(context, "react");
|
|
1530
|
+
if (framework === null) return null;
|
|
1531
|
+
const build = dependencyEvidence(context, "vite") ?? fileStartingWithEvidence(context, "vite.config");
|
|
1532
|
+
return build === null ? null : framework;
|
|
1533
|
+
},
|
|
1505
1534
|
layers: VITE_LAYERS,
|
|
1506
1535
|
kinds: VITE_KINDS,
|
|
1507
1536
|
exclude: [".vite", "dist"],
|
|
@@ -1510,7 +1539,7 @@ var JS_PRESETS = [
|
|
|
1510
1539
|
{
|
|
1511
1540
|
name: "nest",
|
|
1512
1541
|
priority: 80,
|
|
1513
|
-
detect: (context) =>
|
|
1542
|
+
detect: (context) => dependencyEvidence(context, "@nestjs/core"),
|
|
1514
1543
|
layers: [
|
|
1515
1544
|
layer("modules", "src/modules/", "modules/"),
|
|
1516
1545
|
layer("controllers", "src/controllers/", "controllers/"),
|
|
@@ -1536,7 +1565,7 @@ var JS_PRESETS = [
|
|
|
1536
1565
|
{
|
|
1537
1566
|
name: "node-express",
|
|
1538
1567
|
priority: 78,
|
|
1539
|
-
detect: (context) =>
|
|
1568
|
+
detect: (context) => dependencyEvidence(context, "express", "fastify", "koa", "@hapi/hapi"),
|
|
1540
1569
|
layers: NODE_LAYERS,
|
|
1541
1570
|
kinds: NODE_KINDS,
|
|
1542
1571
|
exclude: ["dist"],
|
|
@@ -1547,7 +1576,7 @@ var JS_PRESETS = [
|
|
|
1547
1576
|
// A bare package.json is often just tooling around a non-JS project, so it
|
|
1548
1577
|
// ranks below every definitive language manifest.
|
|
1549
1578
|
priority: 45,
|
|
1550
|
-
detect: (context) =>
|
|
1579
|
+
detect: (context) => fileEvidence(context, "package.json"),
|
|
1551
1580
|
layers: [
|
|
1552
1581
|
layer("src", "src/"),
|
|
1553
1582
|
layer("lib", "lib/"),
|
|
@@ -1561,13 +1590,12 @@ var JS_PRESETS = [
|
|
|
1561
1590
|
];
|
|
1562
1591
|
|
|
1563
1592
|
// src/presets/lang-presets.ts
|
|
1564
|
-
var anyFileEndingWith = (context, suffix) => Array.from(context.files).some((file) => file.endsWith(suffix));
|
|
1565
1593
|
var DIR = (name) => `${name}/`;
|
|
1566
1594
|
var LANGUAGE_PRESETS = [
|
|
1567
1595
|
{
|
|
1568
1596
|
name: "python-django",
|
|
1569
1597
|
priority: 56,
|
|
1570
|
-
detect: (context) =>
|
|
1598
|
+
detect: (context) => fileEvidence(context, "manage.py") ?? manifestEvidence(context, "pyproject.toml", "django") ?? manifestEvidence(context, "requirements.txt", "django"),
|
|
1571
1599
|
layers: [
|
|
1572
1600
|
layer("views", DIR("views"), DIR("app/views"), DIR("apps/views")),
|
|
1573
1601
|
layer("models", DIR("models"), DIR("app/models"), DIR("apps/models")),
|
|
@@ -1593,7 +1621,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1593
1621
|
{
|
|
1594
1622
|
name: "python-fastapi",
|
|
1595
1623
|
priority: 54,
|
|
1596
|
-
detect: (context) =>
|
|
1624
|
+
detect: (context) => manifestEvidence(context, "requirements.txt", "fastapi") ?? manifestEvidence(context, "requirements.txt", "flask") ?? manifestEvidence(context, "pyproject.toml", "fastapi") ?? manifestEvidence(context, "pyproject.toml", "flask"),
|
|
1597
1625
|
layers: [
|
|
1598
1626
|
layer("routers", DIR("routers"), DIR("routes"), DIR("api")),
|
|
1599
1627
|
layer("models", DIR("models"), DIR("db")),
|
|
@@ -1617,7 +1645,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1617
1645
|
name: "python-lib",
|
|
1618
1646
|
// Below node-lib: a Node repo with a stray .py file is still a Node repo.
|
|
1619
1647
|
priority: 30,
|
|
1620
|
-
detect: (context) =>
|
|
1648
|
+
detect: (context) => fileEvidence(context, "pyproject.toml") ?? fileEvidence(context, "setup.py") ?? fileEvidence(context, "requirements.txt") ?? suffixEvidence(context, ".py"),
|
|
1621
1649
|
layers: [
|
|
1622
1650
|
layer("package", DIR("src"), DIR("lib")),
|
|
1623
1651
|
layer("tests", DIR("tests"), DIR("test")),
|
|
@@ -1630,7 +1658,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1630
1658
|
{
|
|
1631
1659
|
name: "go",
|
|
1632
1660
|
priority: 50,
|
|
1633
|
-
detect: (context) =>
|
|
1661
|
+
detect: (context) => fileEvidence(context, "go.mod"),
|
|
1634
1662
|
layers: [
|
|
1635
1663
|
layer("cmd", "cmd/"),
|
|
1636
1664
|
layer("internal", "internal/"),
|
|
@@ -1654,7 +1682,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1654
1682
|
{
|
|
1655
1683
|
name: "rust",
|
|
1656
1684
|
priority: 48,
|
|
1657
|
-
detect: (context) =>
|
|
1685
|
+
detect: (context) => fileEvidence(context, "Cargo.toml"),
|
|
1658
1686
|
layers: [
|
|
1659
1687
|
layer("src", "src/"),
|
|
1660
1688
|
layer("crates", "crates/"),
|
|
@@ -1670,7 +1698,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1670
1698
|
{
|
|
1671
1699
|
name: "java-spring",
|
|
1672
1700
|
priority: 46,
|
|
1673
|
-
detect: (context) =>
|
|
1701
|
+
detect: (context) => fileEvidence(context, "pom.xml") ?? fileEvidence(context, "build.gradle") ?? fileEvidence(context, "build.gradle.kts"),
|
|
1674
1702
|
layers: [
|
|
1675
1703
|
layer("api", "src/main/java/"),
|
|
1676
1704
|
layer("test", "src/test/java/"),
|
|
@@ -1693,7 +1721,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1693
1721
|
{
|
|
1694
1722
|
name: "dotnet",
|
|
1695
1723
|
priority: 44,
|
|
1696
|
-
detect: (context) =>
|
|
1724
|
+
detect: (context) => suffixEvidence(context, ".csproj") ?? suffixEvidence(context, ".sln") ?? fileEvidence(context, "global.json"),
|
|
1697
1725
|
layers: [
|
|
1698
1726
|
layer("web", "src/", "Web/"),
|
|
1699
1727
|
layer("domain", "Domain/", "Core/"),
|
|
@@ -1716,7 +1744,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1716
1744
|
{
|
|
1717
1745
|
name: "php-laravel",
|
|
1718
1746
|
priority: 42,
|
|
1719
|
-
detect: (context) =>
|
|
1747
|
+
detect: (context) => fileEvidence(context, "artisan") ?? manifestEvidence(context, "composer.json", "laravel") ?? fileEvidence(context, "composer.json"),
|
|
1720
1748
|
layers: [
|
|
1721
1749
|
layer("app", "app/"),
|
|
1722
1750
|
layer("routes", "routes/"),
|
|
@@ -1742,7 +1770,7 @@ var LANGUAGE_PRESETS = [
|
|
|
1742
1770
|
{
|
|
1743
1771
|
name: "ruby-rails",
|
|
1744
1772
|
priority: 40,
|
|
1745
|
-
detect: (context) =>
|
|
1773
|
+
detect: (context) => fileEvidence(context, "Gemfile") ?? fileEvidence(context, "config.ru") ?? fileEvidence(context, "Rakefile"),
|
|
1746
1774
|
layers: [
|
|
1747
1775
|
layer("app", "app/"),
|
|
1748
1776
|
layer("controllers", "app/controllers/"),
|
|
@@ -1815,7 +1843,7 @@ var SHAPE_PRESETS = [
|
|
|
1815
1843
|
{
|
|
1816
1844
|
name: "monorepo",
|
|
1817
1845
|
priority: 70,
|
|
1818
|
-
detect: (context) =>
|
|
1846
|
+
detect: (context) => fileEvidence(context, "pnpm-workspace.yaml") ?? fileEvidence(context, "nx.json") ?? fileEvidence(context, "turbo.json") ?? fileEvidence(context, "lerna.json") ?? manifestEvidence(context, "package.json", '"workspaces"'),
|
|
1819
1847
|
layers: [
|
|
1820
1848
|
layer("apps", "apps/"),
|
|
1821
1849
|
layer("packages", "packages/"),
|
|
@@ -1829,7 +1857,7 @@ var SHAPE_PRESETS = [
|
|
|
1829
1857
|
{
|
|
1830
1858
|
name: "infra",
|
|
1831
1859
|
priority: 24,
|
|
1832
|
-
detect: (context) =>
|
|
1860
|
+
detect: (context) => suffixEvidence(context, ".tf") ?? fileEvidence(context, "Chart.yaml") ?? fileEvidence(context, "kustomization.yaml") ?? fileEvidence(context, "docker-compose.yml") ?? fileEvidence(context, "docker-compose.yaml"),
|
|
1833
1861
|
layers: [
|
|
1834
1862
|
layer("modules", "modules/"),
|
|
1835
1863
|
layer("environments", "env/", "environments/"),
|
|
@@ -1851,7 +1879,7 @@ var SHAPE_PRESETS = [
|
|
|
1851
1879
|
// up to two directories down (bounded in the context builder). Counting
|
|
1852
1880
|
// only the root turned every real documentation repository — README.md plus
|
|
1853
1881
|
// the pages under `docs/` — into `generic`.
|
|
1854
|
-
detect: (context) =>
|
|
1882
|
+
detect: (context) => markdownEvidence(context),
|
|
1855
1883
|
layers: [
|
|
1856
1884
|
layer("content", "content/", "docs/"),
|
|
1857
1885
|
layer("assets", "assets/", "static/", "public/"),
|
|
@@ -1864,7 +1892,10 @@ var SHAPE_PRESETS = [
|
|
|
1864
1892
|
{
|
|
1865
1893
|
name: "generic",
|
|
1866
1894
|
priority: 0,
|
|
1867
|
-
|
|
1895
|
+
// No detector: this is the fallback, and `detectPresetFromContext` reaches it only
|
|
1896
|
+
// when every other preset reported no evidence. `fallback: true` is what lets the
|
|
1897
|
+
// wizard tell "I recognised this" apart from "I gave up".
|
|
1898
|
+
fallback: true,
|
|
1868
1899
|
layers: DEFAULT_LAYERS,
|
|
1869
1900
|
kinds: DEFAULT_KINDS,
|
|
1870
1901
|
exclude: [],
|
|
@@ -1896,20 +1927,27 @@ function detectPresetFromContext(context, forced) {
|
|
|
1896
1927
|
if (forced !== void 0) {
|
|
1897
1928
|
const preset = BY_NAME.get(forced);
|
|
1898
1929
|
if (!preset) throw new Error(unknownPresetMessage(forced));
|
|
1899
|
-
return toDetected(preset);
|
|
1930
|
+
return toDetected(preset, null);
|
|
1900
1931
|
}
|
|
1901
1932
|
for (const preset of PRESETS) {
|
|
1902
|
-
|
|
1933
|
+
const reason = preset.detect?.(context) ?? null;
|
|
1934
|
+
if (reason !== null) return toDetected(preset, reason);
|
|
1935
|
+
}
|
|
1936
|
+
const fallback = PRESETS.find((preset) => preset.fallback === true);
|
|
1937
|
+
if (fallback === void 0) {
|
|
1938
|
+
throw new Error("No fallback preset is defined. Exactly one preset must set `fallback: true`.");
|
|
1903
1939
|
}
|
|
1904
|
-
return toDetected(
|
|
1940
|
+
return toDetected(fallback, null, true);
|
|
1905
1941
|
}
|
|
1906
|
-
function toDetected(preset) {
|
|
1942
|
+
function toDetected(preset, reason, fallback = false) {
|
|
1907
1943
|
return {
|
|
1908
1944
|
presetName: preset.name,
|
|
1909
1945
|
layers: preset.layers,
|
|
1910
1946
|
kinds: preset.kinds,
|
|
1911
1947
|
exclude: preset.exclude ? [...preset.exclude] : [],
|
|
1912
|
-
recommendedBudget: preset.recommendedBudget ?? null
|
|
1948
|
+
recommendedBudget: preset.recommendedBudget ?? null,
|
|
1949
|
+
reason,
|
|
1950
|
+
fallback
|
|
1913
1951
|
};
|
|
1914
1952
|
}
|
|
1915
1953
|
function detectPreset(cwd, forced) {
|
|
@@ -2349,14 +2387,14 @@ var PRESET_IGNORES = new Set(
|
|
|
2349
2387
|
);
|
|
2350
2388
|
function readLinkTarget(linkPath, fallback) {
|
|
2351
2389
|
try {
|
|
2352
|
-
return
|
|
2390
|
+
return fs11__namespace.readlinkSync(linkPath);
|
|
2353
2391
|
} catch {
|
|
2354
2392
|
return fallback;
|
|
2355
2393
|
}
|
|
2356
2394
|
}
|
|
2357
2395
|
function isInside(root, candidate) {
|
|
2358
|
-
const
|
|
2359
|
-
return
|
|
2396
|
+
const relative7 = path12__namespace.relative(root, candidate);
|
|
2397
|
+
return relative7 === "" || !relative7.startsWith(`..${path12__namespace.sep}`) && relative7 !== ".." && !path12__namespace.isAbsolute(relative7);
|
|
2360
2398
|
}
|
|
2361
2399
|
function getGitInfo(cwd, fallbackBranch = "main") {
|
|
2362
2400
|
try {
|
|
@@ -2561,10 +2599,10 @@ function trimUnescapedTrailingSpaces(line) {
|
|
|
2561
2599
|
return line.slice(0, end);
|
|
2562
2600
|
}
|
|
2563
2601
|
function readGitignoreRules(dir) {
|
|
2564
|
-
const gitignorePath =
|
|
2602
|
+
const gitignorePath = path12__namespace.join(dir, ".gitignore");
|
|
2565
2603
|
let raw;
|
|
2566
2604
|
try {
|
|
2567
|
-
raw =
|
|
2605
|
+
raw = fs11__namespace.readFileSync(gitignorePath, "utf8");
|
|
2568
2606
|
} catch {
|
|
2569
2607
|
return [];
|
|
2570
2608
|
}
|
|
@@ -2691,7 +2729,7 @@ function isToolOwnedDirName(name) {
|
|
|
2691
2729
|
}
|
|
2692
2730
|
function hasSnapshotMarker(target) {
|
|
2693
2731
|
try {
|
|
2694
|
-
return
|
|
2732
|
+
return fs11__namespace.statSync(target).isDirectory() && fs11__namespace.existsSync(path12__namespace.join(target, ".codebase-snapshot"));
|
|
2695
2733
|
} catch {
|
|
2696
2734
|
return false;
|
|
2697
2735
|
}
|
|
@@ -2705,7 +2743,7 @@ function makeToolOwnedDecider(cwd, toolOwnedPaths) {
|
|
|
2705
2743
|
const prefix = parts.slice(0, depth).join("/");
|
|
2706
2744
|
let hasMarker = markers.get(prefix);
|
|
2707
2745
|
if (hasMarker === void 0) {
|
|
2708
|
-
hasMarker =
|
|
2746
|
+
hasMarker = fs11__namespace.existsSync(path12__namespace.join(cwd, prefix, ".codebase-snapshot"));
|
|
2709
2747
|
markers.set(prefix, hasMarker);
|
|
2710
2748
|
}
|
|
2711
2749
|
if (hasMarker) return true;
|
|
@@ -2720,7 +2758,7 @@ function makeLinkProbe() {
|
|
|
2720
2758
|
let known = cache.get(absolutePath);
|
|
2721
2759
|
if (known === void 0) {
|
|
2722
2760
|
try {
|
|
2723
|
-
known =
|
|
2761
|
+
known = fs11__namespace.lstatSync(absolutePath).isSymbolicLink();
|
|
2724
2762
|
} catch {
|
|
2725
2763
|
known = false;
|
|
2726
2764
|
}
|
|
@@ -2733,7 +2771,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2733
2771
|
const isLink = makeLinkProbe();
|
|
2734
2772
|
let rootReal = cwd;
|
|
2735
2773
|
try {
|
|
2736
|
-
rootReal =
|
|
2774
|
+
rootReal = fs11__namespace.realpathSync(cwd);
|
|
2737
2775
|
} catch {
|
|
2738
2776
|
}
|
|
2739
2777
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -2743,7 +2781,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2743
2781
|
let linkedDir = null;
|
|
2744
2782
|
for (let depth = 1; depth <= parts.length; depth += 1) {
|
|
2745
2783
|
const prefix = parts.slice(0, depth).join("/");
|
|
2746
|
-
if (isLink(
|
|
2784
|
+
if (isLink(path12__namespace.join(cwd, prefix))) {
|
|
2747
2785
|
linkedDir = prefix;
|
|
2748
2786
|
break;
|
|
2749
2787
|
}
|
|
@@ -2754,10 +2792,10 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2754
2792
|
}
|
|
2755
2793
|
if (reported.has(linkedDir)) continue;
|
|
2756
2794
|
reported.add(linkedDir);
|
|
2757
|
-
const absolute =
|
|
2795
|
+
const absolute = path12__namespace.join(cwd, linkedDir);
|
|
2758
2796
|
let targetReal = absolute;
|
|
2759
2797
|
try {
|
|
2760
|
-
targetReal =
|
|
2798
|
+
targetReal = fs11__namespace.realpathSync(absolute);
|
|
2761
2799
|
} catch {
|
|
2762
2800
|
}
|
|
2763
2801
|
const target = readLinkTarget(absolute, targetReal);
|
|
@@ -2834,7 +2872,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2834
2872
|
"Discovery mode is `git`, but git could not list this directory's files. Run inside a working repository, or pass --discovery walk (or auto) to scan the tree directly."
|
|
2835
2873
|
);
|
|
2836
2874
|
}
|
|
2837
|
-
if (
|
|
2875
|
+
if (fs11__namespace.existsSync(path12__namespace.join(cwd, ".git"))) {
|
|
2838
2876
|
throw new Error(
|
|
2839
2877
|
"This directory is a git repository, but git could not list its files. A plain walk honours .gitignore files, but git also applies .git/info/exclude and your global excludes file, includes files that are tracked although a .gitignore now matches them, and treats a submodule as a single entry. Fix the repository (git status should work), run outside git, or pass --discovery walk to accept those differences."
|
|
2840
2878
|
);
|
|
@@ -2893,7 +2931,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2893
2931
|
}
|
|
2894
2932
|
function rootRealFor(root) {
|
|
2895
2933
|
try {
|
|
2896
|
-
return
|
|
2934
|
+
return fs11__namespace.realpathSync(root);
|
|
2897
2935
|
} catch {
|
|
2898
2936
|
return root;
|
|
2899
2937
|
}
|
|
@@ -2901,18 +2939,18 @@ function rootRealFor(root) {
|
|
|
2901
2939
|
function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PURE__ */ new Set(), parentGitignoreLayers = []) {
|
|
2902
2940
|
const results = { files: [], skipped: [] };
|
|
2903
2941
|
const stack = [];
|
|
2904
|
-
const relativeToBase = (target) =>
|
|
2942
|
+
const relativeToBase = (target) => path12__namespace.relative(baseDir, target).replace(/\\/g, "/") || ".";
|
|
2905
2943
|
const enter = (current, layers) => {
|
|
2906
2944
|
if (visited.has(current)) return false;
|
|
2907
2945
|
visited.add(current);
|
|
2908
2946
|
const localRules = readGitignoreRules(current);
|
|
2909
2947
|
const gitignoreLayers = localRules.length === 0 ? layers : [
|
|
2910
2948
|
...layers,
|
|
2911
|
-
{ prefix:
|
|
2949
|
+
{ prefix: path12__namespace.relative(baseDir, current).replace(/\\/g, "/"), rules: localRules }
|
|
2912
2950
|
];
|
|
2913
2951
|
let entries;
|
|
2914
2952
|
try {
|
|
2915
|
-
entries =
|
|
2953
|
+
entries = fs11__namespace.readdirSync(current, { withFileTypes: true });
|
|
2916
2954
|
} catch {
|
|
2917
2955
|
results.skipped.push({
|
|
2918
2956
|
path: relativeToBase(current),
|
|
@@ -2934,8 +2972,8 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2934
2972
|
}
|
|
2935
2973
|
const entry = frame.entries[frame.index];
|
|
2936
2974
|
frame.index += 1;
|
|
2937
|
-
const fullPath =
|
|
2938
|
-
const relPath =
|
|
2975
|
+
const fullPath = path12__namespace.join(frame.dir, entry.name);
|
|
2976
|
+
const relPath = path12__namespace.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
2939
2977
|
if (isToolOwnedDirName(entry.name) && reservedPaths.has(relPath)) continue;
|
|
2940
2978
|
if (DEFAULT_IGNORED_DIRS.includes(entry.name)) {
|
|
2941
2979
|
results.skipped.push({
|
|
@@ -2968,14 +3006,14 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2968
3006
|
if (entry.isSymbolicLink()) {
|
|
2969
3007
|
let targetReal;
|
|
2970
3008
|
try {
|
|
2971
|
-
targetReal =
|
|
3009
|
+
targetReal = fs11__namespace.realpathSync(fullPath);
|
|
2972
3010
|
} catch {
|
|
2973
3011
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "broken symlink" });
|
|
2974
3012
|
continue;
|
|
2975
3013
|
}
|
|
2976
3014
|
let stats;
|
|
2977
3015
|
try {
|
|
2978
|
-
stats =
|
|
3016
|
+
stats = fs11__namespace.statSync(fullPath);
|
|
2979
3017
|
} catch {
|
|
2980
3018
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "unreadable symlink" });
|
|
2981
3019
|
continue;
|
|
@@ -3273,11 +3311,11 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
3273
3311
|
const warnings = [];
|
|
3274
3312
|
const errors = [];
|
|
3275
3313
|
for (const filename of CONFIG_FILENAMES) {
|
|
3276
|
-
const fullPath =
|
|
3277
|
-
if (!
|
|
3314
|
+
const fullPath = path12__namespace.join(cwd, filename);
|
|
3315
|
+
if (!fs11__namespace.existsSync(fullPath)) continue;
|
|
3278
3316
|
if (filename.endsWith(".json") || filename === ".snapshotrc") {
|
|
3279
3317
|
try {
|
|
3280
|
-
const config = parseJsonish(
|
|
3318
|
+
const config = parseJsonish(fs11__namespace.readFileSync(fullPath, "utf8"), fullPath);
|
|
3281
3319
|
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
3282
3320
|
throw new Error(
|
|
3283
3321
|
`${fullPath} does not hold a configuration object (received ${describeValue2(config)}).`
|
|
@@ -3311,10 +3349,10 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
3311
3349
|
continue;
|
|
3312
3350
|
}
|
|
3313
3351
|
}
|
|
3314
|
-
const pkgJsonPath =
|
|
3315
|
-
if (
|
|
3352
|
+
const pkgJsonPath = path12__namespace.join(cwd, "package.json");
|
|
3353
|
+
if (fs11__namespace.existsSync(pkgJsonPath)) {
|
|
3316
3354
|
try {
|
|
3317
|
-
const parsed = parseJsonish(
|
|
3355
|
+
const parsed = parseJsonish(fs11__namespace.readFileSync(pkgJsonPath, "utf8"), pkgJsonPath);
|
|
3318
3356
|
const snapshotKey = parsed.snapshot;
|
|
3319
3357
|
if (snapshotKey && typeof snapshotKey === "object" && !Array.isArray(snapshotKey)) {
|
|
3320
3358
|
return { config: snapshotKey, file: pkgJsonPath, warnings, errors };
|
|
@@ -3337,7 +3375,7 @@ async function loadConfigFile(cwd) {
|
|
|
3337
3375
|
const loaded = await loadConfigFileDetailed(cwd);
|
|
3338
3376
|
if (loaded.config && loaded.file && typeof loaded.config === "object") {
|
|
3339
3377
|
Object.defineProperty(loaded.config, CONFIG_DIR_SYMBOL, {
|
|
3340
|
-
value:
|
|
3378
|
+
value: path12__namespace.dirname(loaded.file),
|
|
3341
3379
|
enumerable: false,
|
|
3342
3380
|
configurable: true
|
|
3343
3381
|
});
|
|
@@ -3496,12 +3534,12 @@ function resolveKindRules(value) {
|
|
|
3496
3534
|
function outputExcludePatterns(cwd, outDir, tmpDir) {
|
|
3497
3535
|
const patterns = [];
|
|
3498
3536
|
for (const dir of [outDir, tmpDir]) {
|
|
3499
|
-
const absolute =
|
|
3500
|
-
const
|
|
3501
|
-
if (!
|
|
3537
|
+
const absolute = path12__namespace.resolve(cwd, dir);
|
|
3538
|
+
const relative7 = path12__namespace.relative(cwd, absolute);
|
|
3539
|
+
if (!relative7 || relative7 === ".." || relative7.startsWith(`..${path12__namespace.sep}`) || path12__namespace.isAbsolute(relative7)) {
|
|
3502
3540
|
continue;
|
|
3503
3541
|
}
|
|
3504
|
-
patterns.push(`${
|
|
3542
|
+
patterns.push(`${relative7.replace(/\\/g, "/")}/**`);
|
|
3505
3543
|
}
|
|
3506
3544
|
return patterns;
|
|
3507
3545
|
}
|
|
@@ -3617,11 +3655,11 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
|
|
|
3617
3655
|
);
|
|
3618
3656
|
}
|
|
3619
3657
|
const candidate = cliOptions?.cwd || userConfig?.cwd || baseDir || process.cwd();
|
|
3620
|
-
const resolved =
|
|
3621
|
-
if (!
|
|
3658
|
+
const resolved = path12__namespace.resolve(candidate);
|
|
3659
|
+
if (!fs11__namespace.existsSync(resolved)) {
|
|
3622
3660
|
throw new Error(`Working directory does not exist: ${resolved}`);
|
|
3623
3661
|
}
|
|
3624
|
-
if (!
|
|
3662
|
+
if (!fs11__namespace.statSync(resolved).isDirectory()) {
|
|
3625
3663
|
throw new Error(`Working directory is not a directory: ${resolved}`);
|
|
3626
3664
|
}
|
|
3627
3665
|
return resolved;
|
|
@@ -4645,7 +4683,7 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4645
4683
|
".so"
|
|
4646
4684
|
]);
|
|
4647
4685
|
function isBinaryExtension(filePath) {
|
|
4648
|
-
const ext =
|
|
4686
|
+
const ext = path12__namespace.extname(filePath).toLowerCase();
|
|
4649
4687
|
return BINARY_EXTENSIONS.has(ext);
|
|
4650
4688
|
}
|
|
4651
4689
|
function isBinaryBuffer(buffer) {
|
|
@@ -4815,13 +4853,13 @@ function isBinaryFile(absolutePath) {
|
|
|
4815
4853
|
if (isBinaryExtension(absolutePath)) return true;
|
|
4816
4854
|
let fd;
|
|
4817
4855
|
try {
|
|
4818
|
-
fd =
|
|
4856
|
+
fd = fs11__namespace.openSync(absolutePath, "r");
|
|
4819
4857
|
const buffer = Buffer.alloc(CHUNK);
|
|
4820
4858
|
let sample;
|
|
4821
4859
|
let position = 0;
|
|
4822
4860
|
while (position < BINARY_SCAN_BYTES) {
|
|
4823
4861
|
const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
|
|
4824
|
-
const bytesRead =
|
|
4862
|
+
const bytesRead = fs11__namespace.readSync(fd, buffer, 0, wanted, position);
|
|
4825
4863
|
if (bytesRead === 0) return false;
|
|
4826
4864
|
const chunk = buffer.subarray(0, bytesRead);
|
|
4827
4865
|
if (sample === void 0) {
|
|
@@ -4839,7 +4877,7 @@ function isBinaryFile(absolutePath) {
|
|
|
4839
4877
|
} finally {
|
|
4840
4878
|
if (fd !== void 0) {
|
|
4841
4879
|
try {
|
|
4842
|
-
|
|
4880
|
+
fs11__namespace.closeSync(fd);
|
|
4843
4881
|
} catch {
|
|
4844
4882
|
}
|
|
4845
4883
|
}
|
|
@@ -4899,10 +4937,10 @@ var LANGUAGE_BY_BASENAME = {
|
|
|
4899
4937
|
};
|
|
4900
4938
|
function detectLanguage(filePath) {
|
|
4901
4939
|
const normalized = filePath.replace(/\\/g, "/");
|
|
4902
|
-
const base =
|
|
4940
|
+
const base = path12__namespace.posix.basename(normalized);
|
|
4903
4941
|
if (LANGUAGE_BY_BASENAME[base]) return LANGUAGE_BY_BASENAME[base];
|
|
4904
4942
|
if (base === ".env" || base.startsWith(".env.")) return "dotenv";
|
|
4905
|
-
const ext =
|
|
4943
|
+
const ext = path12__namespace.posix.extname(base).toLowerCase();
|
|
4906
4944
|
return LANGUAGE_BY_EXTENSION[ext] ?? "text";
|
|
4907
4945
|
}
|
|
4908
4946
|
function maskedPath(value, secretRules) {
|
|
@@ -4910,33 +4948,33 @@ function maskedPath(value, secretRules) {
|
|
|
4910
4948
|
}
|
|
4911
4949
|
function confineToDirectory(directory, filename) {
|
|
4912
4950
|
if (filename.includes("\0")) return null;
|
|
4913
|
-
if (
|
|
4914
|
-
const base =
|
|
4915
|
-
const resolved =
|
|
4951
|
+
if (path12__namespace.isAbsolute(filename)) return null;
|
|
4952
|
+
const base = path12__namespace.resolve(directory);
|
|
4953
|
+
const resolved = path12__namespace.resolve(base, filename);
|
|
4916
4954
|
const caseInsensitive = process.platform === "win32" || process.platform === "darwin";
|
|
4917
|
-
const prefix = caseInsensitive ? `${base}${
|
|
4955
|
+
const prefix = caseInsensitive ? `${base}${path12__namespace.sep}`.toLowerCase() : `${base}${path12__namespace.sep}`;
|
|
4918
4956
|
const candidate = caseInsensitive ? resolved.toLowerCase() : resolved;
|
|
4919
4957
|
return candidate.startsWith(prefix) ? resolved : null;
|
|
4920
4958
|
}
|
|
4921
4959
|
function findStagingDirectory(config) {
|
|
4922
|
-
const tmpDir =
|
|
4960
|
+
const tmpDir = path12__namespace.resolve(config.cwd, config.tmpDir);
|
|
4923
4961
|
let entries;
|
|
4924
4962
|
try {
|
|
4925
|
-
entries =
|
|
4963
|
+
entries = fs11__namespace.readdirSync(tmpDir);
|
|
4926
4964
|
} catch {
|
|
4927
4965
|
return null;
|
|
4928
4966
|
}
|
|
4929
4967
|
const runs = entries.filter((name) => name.startsWith("run-")).sort();
|
|
4930
4968
|
const newest = runs[runs.length - 1];
|
|
4931
|
-
return newest ?
|
|
4969
|
+
return newest ? path12__namespace.join(tmpDir, newest) : null;
|
|
4932
4970
|
}
|
|
4933
4971
|
function describeMissingManifest(config, manifestPath) {
|
|
4934
|
-
const outDir =
|
|
4935
|
-
const markerPath =
|
|
4972
|
+
const outDir = path12__namespace.resolve(config.cwd, config.outDir);
|
|
4973
|
+
const markerPath = path12__namespace.join(outDir, ".codebase-snapshot");
|
|
4936
4974
|
let marker2 = null;
|
|
4937
4975
|
try {
|
|
4938
|
-
if (
|
|
4939
|
-
const parsed = JSON.parse(
|
|
4976
|
+
if (fs11__namespace.existsSync(markerPath)) {
|
|
4977
|
+
const parsed = JSON.parse(fs11__namespace.readFileSync(markerPath, "utf8"));
|
|
4940
4978
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4941
4979
|
marker2 = parsed;
|
|
4942
4980
|
}
|
|
@@ -4972,14 +5010,14 @@ function sha256Hex(buffer) {
|
|
|
4972
5010
|
}
|
|
4973
5011
|
var VERIFY_SNIFF_MAX_BYTES = 8 * 1024 * 1024;
|
|
4974
5012
|
function wouldNowBeIncluded(cwd, relativePath, reason) {
|
|
4975
|
-
const absolutePath =
|
|
5013
|
+
const absolutePath = path12__namespace.join(cwd, relativePath);
|
|
4976
5014
|
try {
|
|
4977
|
-
const stats =
|
|
5015
|
+
const stats = fs11__namespace.statSync(absolutePath);
|
|
4978
5016
|
if (!stats.isFile()) return false;
|
|
4979
5017
|
if (isBinaryFile(absolutePath)) return false;
|
|
4980
5018
|
if (reason !== "binary") return true;
|
|
4981
5019
|
if (stats.size > VERIFY_SNIFF_MAX_BYTES) return false;
|
|
4982
|
-
return !decodeText(
|
|
5020
|
+
return !decodeText(fs11__namespace.readFileSync(absolutePath)).binary;
|
|
4983
5021
|
} catch {
|
|
4984
5022
|
return false;
|
|
4985
5023
|
}
|
|
@@ -5037,8 +5075,8 @@ function describeManifestShapeProblem(value) {
|
|
|
5037
5075
|
function validateSnapshot(configInput) {
|
|
5038
5076
|
assertUsableConfigInput(configInput);
|
|
5039
5077
|
const config = isResolvedConfig(configInput) ? normalizeResolvedConfig(configInput) : resolveConfig(configInput);
|
|
5040
|
-
const manifestPath =
|
|
5041
|
-
if (!
|
|
5078
|
+
const manifestPath = path12__namespace.resolve(config.cwd, config.outDir, "manifest.json");
|
|
5079
|
+
if (!fs11__namespace.existsSync(manifestPath)) {
|
|
5042
5080
|
return {
|
|
5043
5081
|
valid: false,
|
|
5044
5082
|
manifestPresent: false,
|
|
@@ -5049,7 +5087,7 @@ function validateSnapshot(configInput) {
|
|
|
5049
5087
|
}
|
|
5050
5088
|
let manifest;
|
|
5051
5089
|
try {
|
|
5052
|
-
manifest = JSON.parse(
|
|
5090
|
+
manifest = JSON.parse(fs11__namespace.readFileSync(manifestPath, "utf8"));
|
|
5053
5091
|
} catch (err) {
|
|
5054
5092
|
return {
|
|
5055
5093
|
valid: false,
|
|
@@ -5071,7 +5109,7 @@ function validateSnapshot(configInput) {
|
|
|
5071
5109
|
}
|
|
5072
5110
|
const drift = emptyDrift();
|
|
5073
5111
|
const warnings = [];
|
|
5074
|
-
const snapshotDir =
|
|
5112
|
+
const snapshotDir = path12__namespace.resolve(config.cwd, config.outDir);
|
|
5075
5113
|
const manifestFileMap = /* @__PURE__ */ new Map();
|
|
5076
5114
|
for (const file of manifest.files) {
|
|
5077
5115
|
if (file && typeof file.relativePath === "string") {
|
|
@@ -5105,7 +5143,7 @@ function validateSnapshot(configInput) {
|
|
|
5105
5143
|
}
|
|
5106
5144
|
let diskHash;
|
|
5107
5145
|
try {
|
|
5108
|
-
diskHash = sha256Hex(
|
|
5146
|
+
diskHash = sha256Hex(fs11__namespace.readFileSync(path12__namespace.join(config.cwd, diskFile)));
|
|
5109
5147
|
} catch (err) {
|
|
5110
5148
|
if (err.code === "ENOENT") {
|
|
5111
5149
|
drift.missingOnDisk.push(diskFile);
|
|
@@ -5129,7 +5167,7 @@ function validateSnapshot(configInput) {
|
|
|
5129
5167
|
}
|
|
5130
5168
|
let statFailure = null;
|
|
5131
5169
|
try {
|
|
5132
|
-
|
|
5170
|
+
fs11__namespace.statSync(confined);
|
|
5133
5171
|
} catch (err) {
|
|
5134
5172
|
statFailure = err;
|
|
5135
5173
|
}
|
|
@@ -5149,7 +5187,7 @@ function validateSnapshot(configInput) {
|
|
|
5149
5187
|
...Object.values(config.budgets.byLayer)
|
|
5150
5188
|
);
|
|
5151
5189
|
const partNames = /* @__PURE__ */ new Set();
|
|
5152
|
-
const partsDir =
|
|
5190
|
+
const partsDir = path12__namespace.join(snapshotDir, "parts");
|
|
5153
5191
|
for (const part of manifest.parts) {
|
|
5154
5192
|
if (!part || typeof part.filename !== "string") continue;
|
|
5155
5193
|
partNames.add(part.filename);
|
|
@@ -5164,7 +5202,7 @@ function validateSnapshot(configInput) {
|
|
|
5164
5202
|
}
|
|
5165
5203
|
let buffer;
|
|
5166
5204
|
try {
|
|
5167
|
-
buffer =
|
|
5205
|
+
buffer = fs11__namespace.readFileSync(partPath);
|
|
5168
5206
|
} catch {
|
|
5169
5207
|
drift.partIssues.push({ part: part.filename, issue: "missing from snapshot/parts" });
|
|
5170
5208
|
continue;
|
|
@@ -5378,9 +5416,9 @@ function validateSnapshot(configInput) {
|
|
|
5378
5416
|
["full-codebase.md", manifest.artifacts?.fullMarkdown]
|
|
5379
5417
|
]) {
|
|
5380
5418
|
if (!artifact) continue;
|
|
5381
|
-
const artifactPath =
|
|
5419
|
+
const artifactPath = path12__namespace.join(snapshotDir, key);
|
|
5382
5420
|
try {
|
|
5383
|
-
const buffer =
|
|
5421
|
+
const buffer = fs11__namespace.readFileSync(artifactPath);
|
|
5384
5422
|
if (sha256Hex(buffer) !== artifact.sha256 || buffer.length !== artifact.byteSize) {
|
|
5385
5423
|
drift.partIssues.push({ part: key, issue: "artifact does not match its recorded digest" });
|
|
5386
5424
|
}
|
|
@@ -5450,7 +5488,7 @@ function validateSnapshot(configInput) {
|
|
|
5450
5488
|
|
|
5451
5489
|
// src/version.ts
|
|
5452
5490
|
var GENERATOR_NAME = "codebase-snapshot";
|
|
5453
|
-
var GENERATOR_VERSION = "0.9.
|
|
5491
|
+
var GENERATOR_VERSION = "0.9.4";
|
|
5454
5492
|
var LEGACY_GENERATOR_NAMES = ["@ankurhalder/codebase-snapshot"];
|
|
5455
5493
|
function isOurGeneratorName(name) {
|
|
5456
5494
|
if (typeof name !== "string") return false;
|
|
@@ -5465,42 +5503,42 @@ function describeMatcher(matcher) {
|
|
|
5465
5503
|
return String(matcher);
|
|
5466
5504
|
}
|
|
5467
5505
|
function normalizeTarget(cwd, target) {
|
|
5468
|
-
const absolute =
|
|
5469
|
-
const
|
|
5470
|
-
if (
|
|
5471
|
-
return
|
|
5506
|
+
const absolute = path12__namespace.resolve(cwd, target);
|
|
5507
|
+
const relative7 = path12__namespace.relative(cwd, absolute);
|
|
5508
|
+
if (relative7.startsWith("..") || path12__namespace.isAbsolute(relative7)) return target;
|
|
5509
|
+
return relative7.split(path12__namespace.sep).join("/");
|
|
5472
5510
|
}
|
|
5473
5511
|
function findRuleMatch(rules, relativePath) {
|
|
5474
5512
|
return rules.find(
|
|
5475
5513
|
(rule) => matchRule(relativePath, rule.match)
|
|
5476
5514
|
);
|
|
5477
5515
|
}
|
|
5478
|
-
function findRecordedAncestor(skipped,
|
|
5516
|
+
function findRecordedAncestor(skipped, relative7, maskedPath2) {
|
|
5479
5517
|
let nearest;
|
|
5480
5518
|
for (const record of skipped) {
|
|
5481
5519
|
const ancestorPath = record.path;
|
|
5482
5520
|
if (ancestorPath.length === 0) continue;
|
|
5483
|
-
const isAncestor =
|
|
5521
|
+
const isAncestor = relative7.startsWith(`${ancestorPath}/`) || maskedPath2.startsWith(`${ancestorPath}/`);
|
|
5484
5522
|
if (!isAncestor) continue;
|
|
5485
5523
|
if (!nearest || ancestorPath.length > nearest.path.length) nearest = record;
|
|
5486
5524
|
}
|
|
5487
5525
|
return nearest;
|
|
5488
5526
|
}
|
|
5489
5527
|
function readManifest2(config) {
|
|
5490
|
-
const manifestPath =
|
|
5528
|
+
const manifestPath = path12__namespace.resolve(config.cwd, config.outDir, "manifest.json");
|
|
5491
5529
|
try {
|
|
5492
|
-
return JSON.parse(
|
|
5530
|
+
return JSON.parse(fs11__namespace.readFileSync(manifestPath, "utf8"));
|
|
5493
5531
|
} catch {
|
|
5494
5532
|
return null;
|
|
5495
5533
|
}
|
|
5496
5534
|
}
|
|
5497
5535
|
function explainPath(config, target) {
|
|
5498
|
-
const
|
|
5499
|
-
const absolute =
|
|
5500
|
-
const maskedPath2 = findSecretInPath(
|
|
5536
|
+
const relative7 = normalizeTarget(config.cwd, target);
|
|
5537
|
+
const absolute = path12__namespace.join(config.cwd, relative7);
|
|
5538
|
+
const maskedPath2 = findSecretInPath(relative7, config.secretRules)?.masked ?? relative7;
|
|
5501
5539
|
const result = {
|
|
5502
5540
|
path: maskedPath2,
|
|
5503
|
-
exists:
|
|
5541
|
+
exists: fs11__namespace.existsSync(absolute),
|
|
5504
5542
|
included: false
|
|
5505
5543
|
};
|
|
5506
5544
|
const collection = collectFiles(config.cwd, {
|
|
@@ -5511,12 +5549,12 @@ function explainPath(config, target) {
|
|
|
5511
5549
|
// Same exclusion `generate` applies, so `explain` never says "not-discovered" about a file
|
|
5512
5550
|
// that is only missing because the walker dropped the tool's own output directory.
|
|
5513
5551
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
5514
|
-
(directory) =>
|
|
5515
|
-
).filter((
|
|
5552
|
+
(directory) => path12__namespace.relative(config.cwd, path12__namespace.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
5553
|
+
).filter((relative8) => relative8.length > 0 && !relative8.startsWith(".."))
|
|
5516
5554
|
});
|
|
5517
|
-
if (!collection.files.includes(
|
|
5555
|
+
if (!collection.files.includes(relative7)) {
|
|
5518
5556
|
const record = collection.skipped.find(
|
|
5519
|
-
(entry2) => entry2.path ===
|
|
5557
|
+
(entry2) => entry2.path === relative7 || entry2.path === maskedPath2
|
|
5520
5558
|
);
|
|
5521
5559
|
if (record) {
|
|
5522
5560
|
result.reason = record.reason;
|
|
@@ -5525,7 +5563,7 @@ function explainPath(config, target) {
|
|
|
5525
5563
|
result.reason = "missing";
|
|
5526
5564
|
result.detail = "no such file or directory, relative to the configured cwd";
|
|
5527
5565
|
} else {
|
|
5528
|
-
const ancestor = findRecordedAncestor(collection.skipped,
|
|
5566
|
+
const ancestor = findRecordedAncestor(collection.skipped, relative7, maskedPath2);
|
|
5529
5567
|
if (ancestor) {
|
|
5530
5568
|
result.reason = ancestor.reason;
|
|
5531
5569
|
result.detail = ancestor.detail ? `${ancestor.detail} \u2014 inherited from the skipped directory \`${ancestor.path}\`` : `inside the skipped directory \`${ancestor.path}\``;
|
|
@@ -5543,15 +5581,15 @@ function explainPath(config, target) {
|
|
|
5543
5581
|
result.detail = "binary content; generate skips it and records `binary` in manifest.skipped[]";
|
|
5544
5582
|
return result;
|
|
5545
5583
|
}
|
|
5546
|
-
result.layer = classifyLayer(
|
|
5547
|
-
result.kind = classifyKind(
|
|
5548
|
-
result.language = detectLanguage(
|
|
5549
|
-
const layerRule = findRuleMatch(config.layers,
|
|
5584
|
+
result.layer = classifyLayer(relative7, config.layers);
|
|
5585
|
+
result.kind = classifyKind(relative7, config.kinds);
|
|
5586
|
+
result.language = detectLanguage(relative7);
|
|
5587
|
+
const layerRule = findRuleMatch(config.layers, relative7);
|
|
5550
5588
|
if (layerRule) result.layerMatch = describeMatcher(layerRule.match);
|
|
5551
|
-
const kindRule = findRuleMatch(config.kinds,
|
|
5589
|
+
const kindRule = findRuleMatch(config.kinds, relative7);
|
|
5552
5590
|
if (kindRule) result.kindMatch = describeMatcher(kindRule.match);
|
|
5553
|
-
if (
|
|
5554
|
-
const buffer =
|
|
5591
|
+
if (fs11__namespace.existsSync(absolute) && fs11__namespace.statSync(absolute).isFile()) {
|
|
5592
|
+
const buffer = fs11__namespace.readFileSync(absolute);
|
|
5555
5593
|
const decoded = decodeText(buffer);
|
|
5556
5594
|
if (decoded.binary) {
|
|
5557
5595
|
result.included = false;
|
|
@@ -5563,12 +5601,12 @@ function explainPath(config, target) {
|
|
|
5563
5601
|
result.bytes = buffer.length;
|
|
5564
5602
|
result.lines = countLines(text2);
|
|
5565
5603
|
if (decoded.encoding !== "utf-8") result.encoding = decoded.encoding;
|
|
5566
|
-
const { findings } = scanAndRedactSecrets(text2, config.secretRules,
|
|
5604
|
+
const { findings } = scanAndRedactSecrets(text2, config.secretRules, relative7);
|
|
5567
5605
|
result.secretCount = findings.length;
|
|
5568
5606
|
result.secrets = findings.slice(0, 20).map((finding) => ({ rules: finding.rules, line: finding.line }));
|
|
5569
5607
|
}
|
|
5570
5608
|
const manifest = readManifest2(config);
|
|
5571
|
-
const entry = Array.isArray(manifest?.files) ? manifest.files.find((file) => file.relativePath ===
|
|
5609
|
+
const entry = Array.isArray(manifest?.files) ? manifest.files.find((file) => file.relativePath === relative7) : void 0;
|
|
5572
5610
|
result.part = entry?.part ?? null;
|
|
5573
5611
|
result.inclusionMode = entry?.inclusionMode;
|
|
5574
5612
|
return result;
|
|
@@ -5799,14 +5837,14 @@ function compareManifests(before, after) {
|
|
|
5799
5837
|
function loadManifest(target) {
|
|
5800
5838
|
let isDirectory;
|
|
5801
5839
|
try {
|
|
5802
|
-
isDirectory =
|
|
5840
|
+
isDirectory = fs11__namespace.statSync(target).isDirectory();
|
|
5803
5841
|
} catch {
|
|
5804
5842
|
throw new Error(`No snapshot found at ${target}: the path does not exist.`);
|
|
5805
5843
|
}
|
|
5806
|
-
const manifestPath = isDirectory ?
|
|
5844
|
+
const manifestPath = isDirectory ? path12__namespace.join(target, "manifest.json") : target;
|
|
5807
5845
|
let raw;
|
|
5808
5846
|
try {
|
|
5809
|
-
raw =
|
|
5847
|
+
raw = fs11__namespace.readFileSync(manifestPath, "utf8");
|
|
5810
5848
|
} catch {
|
|
5811
5849
|
throw new Error(`Could not read a manifest at ${manifestPath}.`);
|
|
5812
5850
|
}
|
|
@@ -5863,15 +5901,15 @@ function renderDiffText(diff) {
|
|
|
5863
5901
|
function appendGitignoreEntries(cwd, entries) {
|
|
5864
5902
|
const wanted = [...new Set(entries)].filter((entry) => entry.trim().length > 0);
|
|
5865
5903
|
if (wanted.length === 0) return { added: [], note: null };
|
|
5866
|
-
const ignorePath =
|
|
5904
|
+
const ignorePath = path12__namespace.join(cwd, ".gitignore");
|
|
5867
5905
|
const manual = `Add ${wanted.map((entry) => `"${entry}"`).join(" and ")} to your .gitignore yourself.`;
|
|
5868
5906
|
let existing = "";
|
|
5869
5907
|
try {
|
|
5870
|
-
if (
|
|
5871
|
-
if (
|
|
5908
|
+
if (fs11__namespace.existsSync(ignorePath)) {
|
|
5909
|
+
if (fs11__namespace.statSync(ignorePath).isDirectory()) {
|
|
5872
5910
|
return { added: [], note: `${ignorePath} is a directory, so it was not updated. ${manual}` };
|
|
5873
5911
|
}
|
|
5874
|
-
existing =
|
|
5912
|
+
existing = fs11__namespace.readFileSync(ignorePath, "utf8");
|
|
5875
5913
|
}
|
|
5876
5914
|
} catch (err) {
|
|
5877
5915
|
return {
|
|
@@ -5884,7 +5922,7 @@ function appendGitignoreEntries(cwd, entries) {
|
|
|
5884
5922
|
if (added.length === 0) return { added: [], note: null };
|
|
5885
5923
|
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
5886
5924
|
try {
|
|
5887
|
-
|
|
5925
|
+
fs11__namespace.writeFileSync(ignorePath, `${existing}${prefix}${added.join("\n")}
|
|
5888
5926
|
`, "utf8");
|
|
5889
5927
|
} catch (err) {
|
|
5890
5928
|
return { added: [], note: `${err.message}. ${manual}` };
|
|
@@ -6277,10 +6315,10 @@ var CONFIG_CANDIDATES = [
|
|
|
6277
6315
|
];
|
|
6278
6316
|
function chooseConfigFileName(cwd) {
|
|
6279
6317
|
if (!supportsTypeScriptImports()) return "snapshot.config.mjs";
|
|
6280
|
-
const pkgPath =
|
|
6281
|
-
if (!
|
|
6318
|
+
const pkgPath = path12__namespace.join(cwd, "package.json");
|
|
6319
|
+
if (!fs11__namespace.existsSync(pkgPath)) return "snapshot.config.mjs";
|
|
6282
6320
|
try {
|
|
6283
|
-
const parsed = JSON.parse(
|
|
6321
|
+
const parsed = JSON.parse(fs11__namespace.readFileSync(pkgPath, "utf8"));
|
|
6284
6322
|
return parsed.type === "module" ? "snapshot.config.ts" : "snapshot.config.mjs";
|
|
6285
6323
|
} catch {
|
|
6286
6324
|
return "snapshot.config.mjs";
|
|
@@ -6294,7 +6332,7 @@ var SIZE_CHOICES = [
|
|
|
6294
6332
|
];
|
|
6295
6333
|
function packageJsonHasConfig(cwd) {
|
|
6296
6334
|
try {
|
|
6297
|
-
const parsed = JSON.parse(
|
|
6335
|
+
const parsed = JSON.parse(fs11__namespace.readFileSync(path12__namespace.join(cwd, "package.json"), "utf8"));
|
|
6298
6336
|
return typeof parsed.snapshot === "object" && parsed.snapshot !== null && !Array.isArray(parsed.snapshot);
|
|
6299
6337
|
} catch {
|
|
6300
6338
|
return false;
|
|
@@ -6315,7 +6353,7 @@ function artifactAnswers(options) {
|
|
|
6315
6353
|
}
|
|
6316
6354
|
function topLevelDirs(cwd) {
|
|
6317
6355
|
try {
|
|
6318
|
-
return
|
|
6356
|
+
return fs11__namespace.readdirSync(cwd, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules").map((entry) => entry.name).sort();
|
|
6319
6357
|
} catch {
|
|
6320
6358
|
return [];
|
|
6321
6359
|
}
|
|
@@ -6328,7 +6366,7 @@ function describeJsonValue(value) {
|
|
|
6328
6366
|
}
|
|
6329
6367
|
function writeFileOrExplain(target, content) {
|
|
6330
6368
|
try {
|
|
6331
|
-
|
|
6369
|
+
fs11__namespace.writeFileSync(target, content, "utf8");
|
|
6332
6370
|
} catch (err) {
|
|
6333
6371
|
const code = err.code;
|
|
6334
6372
|
const reason = code === "EACCES" || code === "EPERM" || code === "EROFS" ? `permission denied (${code})` : code === "EISDIR" ? "it is a directory" : `${err.message}`;
|
|
@@ -6339,7 +6377,7 @@ function canWriteModuleConfig(name, cwd) {
|
|
|
6339
6377
|
if (name.endsWith(".mjs") || name.endsWith(".ts")) return true;
|
|
6340
6378
|
if (!name.endsWith(".js")) return false;
|
|
6341
6379
|
try {
|
|
6342
|
-
const parsed = JSON.parse(
|
|
6380
|
+
const parsed = JSON.parse(fs11__namespace.readFileSync(path12__namespace.join(cwd, "package.json"), "utf8"));
|
|
6343
6381
|
return parsed.type === "module";
|
|
6344
6382
|
} catch {
|
|
6345
6383
|
return false;
|
|
@@ -6374,19 +6412,19 @@ function serializePackageJson(raw, value) {
|
|
|
6374
6412
|
return `${text2}${raw.endsWith("\n") ? crlf ? "\r\n" : "\n" : ""}`;
|
|
6375
6413
|
}
|
|
6376
6414
|
function updatePackageJson(cwd, notes) {
|
|
6377
|
-
const packagePath =
|
|
6415
|
+
const packagePath = path12__namespace.join(cwd, "package.json");
|
|
6378
6416
|
const unchanged = {
|
|
6379
6417
|
scripts: [],
|
|
6380
6418
|
dependency: { name: GENERATOR_NAME, range: null, added: false }
|
|
6381
6419
|
};
|
|
6382
|
-
if (!
|
|
6420
|
+
if (!fs11__namespace.existsSync(packagePath)) {
|
|
6383
6421
|
notes.push("No package.json found, so npm scripts and the devDependency were not added.");
|
|
6384
6422
|
return unchanged;
|
|
6385
6423
|
}
|
|
6386
6424
|
let raw;
|
|
6387
6425
|
let parsed;
|
|
6388
6426
|
try {
|
|
6389
|
-
raw =
|
|
6427
|
+
raw = fs11__namespace.readFileSync(packagePath, "utf8");
|
|
6390
6428
|
parsed = JSON.parse(raw);
|
|
6391
6429
|
} catch {
|
|
6392
6430
|
notes.push("Could not parse package.json; npm scripts and the devDependency were not added.");
|
|
@@ -6449,16 +6487,18 @@ function updatePackageJson(cwd, notes) {
|
|
|
6449
6487
|
return { scripts: added, dependency };
|
|
6450
6488
|
}
|
|
6451
6489
|
var GITIGNORE_ENTRIES = ["snapshot/", "snapshot.tmp/"];
|
|
6452
|
-
function resolvePresetChoice(
|
|
6490
|
+
function resolvePresetChoice(detectedName, presetName) {
|
|
6453
6491
|
return {
|
|
6454
6492
|
value: presetName,
|
|
6455
6493
|
label: presetName,
|
|
6456
|
-
hint: presetName ===
|
|
6494
|
+
hint: presetName === detectedName ? "detected" : void 0
|
|
6457
6495
|
};
|
|
6458
6496
|
}
|
|
6459
6497
|
async function runInit(options) {
|
|
6460
6498
|
const io = options.io ?? defaultIO();
|
|
6461
6499
|
const detected = detectPreset(options.cwd, options.preset);
|
|
6500
|
+
let reason = detected.reason;
|
|
6501
|
+
let fallback = detected.fallback;
|
|
6462
6502
|
const notes = [];
|
|
6463
6503
|
const answers = {
|
|
6464
6504
|
preset: detected.presetName,
|
|
@@ -6480,117 +6520,148 @@ async function runInit(options) {
|
|
|
6480
6520
|
if (interactive) {
|
|
6481
6521
|
io.output.write("\n codebase-snapshot\n");
|
|
6482
6522
|
io.output.write(" Turn this repository into an LLM-ready, redacted, byte-bounded snapshot.\n\n");
|
|
6483
|
-
|
|
6523
|
+
if (fallback) {
|
|
6524
|
+
io.output.write(" \u26A0 Could not tell what kind of project this is.\n");
|
|
6525
|
+
io.output.write(" No package.json, go.mod, Cargo.toml, pyproject.toml, Gemfile,\n");
|
|
6526
|
+
io.output.write(" composer.json, pom.xml, *.csproj, next.config.*, vite.config.*, *.tf\n");
|
|
6527
|
+
io.output.write(" or workspace marker was found here.\n\n");
|
|
6528
|
+
} else {
|
|
6529
|
+
io.output.write(` Detected ${detected.presetName}
|
|
6530
|
+
`);
|
|
6531
|
+
io.output.write(` Because ${reason}
|
|
6532
|
+
|
|
6484
6533
|
`);
|
|
6534
|
+
}
|
|
6485
6535
|
io.output.write(` Directory ${options.cwd}
|
|
6486
6536
|
|
|
6487
6537
|
`);
|
|
6488
|
-
const
|
|
6489
|
-
|
|
6538
|
+
const paceChoices = fallback ? [
|
|
6539
|
+
{ value: "choose", label: "Pick the closest preset", hint: "then generate with the defaults" },
|
|
6540
|
+
{ value: "recommended", label: "Use the defaults", hint: "generic \xB7 everything the scanner finds" },
|
|
6541
|
+
{ value: "walk", label: "Go through each setting", hint: "every question starts on its default" }
|
|
6542
|
+
] : [
|
|
6543
|
+
{
|
|
6544
|
+
value: "recommended",
|
|
6545
|
+
label: "Use the recommended setup",
|
|
6546
|
+
hint: `${detected.presetName} \xB7 config \xB7 npm scripts \xB7 install \xB7 generate`
|
|
6547
|
+
},
|
|
6548
|
+
{ value: "walk", label: "Go through each setting", hint: "every question starts on its default" },
|
|
6549
|
+
{ value: "choose", label: "Pick a different preset", hint: "everything else stays at the defaults" }
|
|
6550
|
+
];
|
|
6551
|
+
const pace = await select(io, "How should I set this up?", paceChoices, {
|
|
6552
|
+
defaultValue: fallback ? "choose" : "recommended"
|
|
6490
6553
|
});
|
|
6491
|
-
if (
|
|
6554
|
+
if (pace === "choose") {
|
|
6492
6555
|
answers.preset = await select(
|
|
6493
6556
|
io,
|
|
6494
6557
|
"What kind of project is this?",
|
|
6495
|
-
listPresetNames().map(
|
|
6558
|
+
listPresetNames().map(
|
|
6559
|
+
(name) => resolvePresetChoice(fallback ? null : detected.presetName, name)
|
|
6560
|
+
),
|
|
6561
|
+
{ defaultValue: answers.preset }
|
|
6496
6562
|
);
|
|
6497
6563
|
const chosen = detectPreset(options.cwd, answers.preset);
|
|
6498
6564
|
answers.preset = chosen.presetName;
|
|
6565
|
+
reason = null;
|
|
6566
|
+
fallback = false;
|
|
6499
6567
|
}
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6568
|
+
if (pace === "walk") {
|
|
6569
|
+
const scope = await select(
|
|
6570
|
+
io,
|
|
6571
|
+
"What should go into the snapshot?",
|
|
6572
|
+
[
|
|
6573
|
+
{ value: "all", label: "Everything the scanner finds", hint: "recommended \xB7 respects .gitignore" },
|
|
6574
|
+
{ value: "folders", label: "Only specific folders\u2026" },
|
|
6575
|
+
{ value: "no-tests", label: "Everything, but skip tests" },
|
|
6576
|
+
{ value: "custom", label: "Let me write glob patterns" }
|
|
6577
|
+
],
|
|
6578
|
+
{ defaultValue: "all" }
|
|
6579
|
+
);
|
|
6580
|
+
if (scope === "folders") {
|
|
6581
|
+
const dirs = topLevelDirs(options.cwd).slice(0, 40);
|
|
6582
|
+
if (dirs.length === 0) {
|
|
6583
|
+
notes.push("No top-level directories found; the snapshot will include everything.");
|
|
6584
|
+
} else {
|
|
6585
|
+
const chosen = await multiSelect(
|
|
6586
|
+
io,
|
|
6587
|
+
"Select folders",
|
|
6588
|
+
dirs.map((name) => ({ value: name, label: `${name}/` })),
|
|
6589
|
+
{ defaults: dirs }
|
|
6590
|
+
);
|
|
6591
|
+
answers.include = chosen.map((name) => `${name}/**`);
|
|
6592
|
+
}
|
|
6593
|
+
} else if (scope === "no-tests") {
|
|
6594
|
+
answers.excludePatterns = [
|
|
6595
|
+
...answers.excludePatterns,
|
|
6596
|
+
"**/*.test.*",
|
|
6597
|
+
"**/*.spec.*",
|
|
6598
|
+
"tests",
|
|
6599
|
+
"test"
|
|
6600
|
+
];
|
|
6601
|
+
} else if (scope === "custom") {
|
|
6602
|
+
const raw = await text(io, "Glob patterns to include (comma separated)", {
|
|
6603
|
+
defaultValue: ""
|
|
6604
|
+
});
|
|
6605
|
+
answers.include = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
6606
|
+
}
|
|
6607
|
+
const currentBudget = String(answers.maxPartBytes);
|
|
6608
|
+
const sizeChoice = await select(io, "How large should each part be?", SIZE_CHOICES, {
|
|
6609
|
+
defaultValue: SIZE_CHOICES.some((choice) => choice.value === currentBudget) ? currentBudget : "120k"
|
|
6610
|
+
});
|
|
6611
|
+
if (sizeChoice === "custom") {
|
|
6612
|
+
const raw = await text(io, "Part size (e.g. 150k, 1.5mb, 900000)", {
|
|
6613
|
+
defaultValue: String(answers.maxPartBytes),
|
|
6614
|
+
validate: (value) => parseByteSize(value) === void 0 ? "Not a valid size." : null
|
|
6615
|
+
});
|
|
6616
|
+
answers.maxPartBytes = parseByteSize(raw) ?? answers.maxPartBytes;
|
|
6515
6617
|
} else {
|
|
6516
|
-
|
|
6517
|
-
io,
|
|
6518
|
-
"Select folders",
|
|
6519
|
-
dirs.map((name) => ({ value: name, label: `${name}/` })),
|
|
6520
|
-
{ defaults: dirs }
|
|
6521
|
-
);
|
|
6522
|
-
answers.include = chosen.map((name) => `${name}/**`);
|
|
6618
|
+
answers.maxPartBytes = sizeChoice;
|
|
6523
6619
|
}
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
"
|
|
6528
|
-
"
|
|
6529
|
-
"
|
|
6530
|
-
"
|
|
6620
|
+
const artifactChoices = [
|
|
6621
|
+
{ value: "readme", label: "README.md", hint: "orientation page" },
|
|
6622
|
+
{ value: "manifest", label: "manifest.json", hint: "required by validate and report" },
|
|
6623
|
+
{ value: "parts", label: "parts/", hint: "the code payload" },
|
|
6624
|
+
{ value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
|
|
6625
|
+
{ value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
|
|
6626
|
+
{ value: "audit", label: "reports/audit.md", hint: "security and health findings" },
|
|
6627
|
+
{ value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
|
|
6531
6628
|
];
|
|
6532
|
-
|
|
6533
|
-
const
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
answers.maxPartBytes = sizeChoice;
|
|
6549
|
-
}
|
|
6550
|
-
const artifactChoices = [
|
|
6551
|
-
{ value: "readme", label: "README.md", hint: "orientation page" },
|
|
6552
|
-
{ value: "manifest", label: "manifest.json", hint: "required by validate and report" },
|
|
6553
|
-
{ value: "parts", label: "parts/", hint: "the code payload" },
|
|
6554
|
-
{ value: "navigation", label: "reports/navigation.md", hint: "file \u2192 part index" },
|
|
6555
|
-
{ value: "projectTree", label: "reports/project-tree.md", hint: "ASCII tree" },
|
|
6556
|
-
{ value: "audit", label: "reports/audit.md", hint: "security and health findings" },
|
|
6557
|
-
{ value: "monolith", label: "full-codebase.json + .md", hint: "roughly doubles output" }
|
|
6558
|
-
];
|
|
6559
|
-
const presetEnabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
|
|
6560
|
-
const selectedArtifacts = await multiSelect(
|
|
6561
|
-
io,
|
|
6562
|
-
"Which artifacts should be generated?",
|
|
6563
|
-
artifactChoices,
|
|
6564
|
-
{ defaults: presetEnabled }
|
|
6565
|
-
);
|
|
6566
|
-
for (const name of ARTIFACT_NAMES) answers.artifacts[name] = selectedArtifacts.includes(name);
|
|
6567
|
-
const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
|
|
6568
|
-
answers.includeSensitiveFiles = await confirm(
|
|
6569
|
-
io,
|
|
6570
|
-
"Include credential files (.env, *.pem, .npmrc, .ssh/)?",
|
|
6571
|
-
{ defaultValue: false }
|
|
6572
|
-
);
|
|
6573
|
-
io.output.write("\n Review\n\n");
|
|
6574
|
-
io.output.write(` project ${answers.preset}
|
|
6629
|
+
const presetEnabled = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]);
|
|
6630
|
+
const selectedArtifacts = await multiSelect(
|
|
6631
|
+
io,
|
|
6632
|
+
"Which artifacts should be generated?",
|
|
6633
|
+
artifactChoices,
|
|
6634
|
+
{ defaults: presetEnabled }
|
|
6635
|
+
);
|
|
6636
|
+
for (const name of ARTIFACT_NAMES) answers.artifacts[name] = selectedArtifacts.includes(name);
|
|
6637
|
+
const enabledCount = ARTIFACT_NAMES.filter((name) => answers.artifacts[name]).length;
|
|
6638
|
+
answers.includeSensitiveFiles = await confirm(
|
|
6639
|
+
io,
|
|
6640
|
+
"Include credential files (.env, *.pem, .npmrc, .ssh/)?",
|
|
6641
|
+
{ defaultValue: false }
|
|
6642
|
+
);
|
|
6643
|
+
io.output.write("\n Review\n\n");
|
|
6644
|
+
io.output.write(` project ${answers.preset}
|
|
6575
6645
|
`);
|
|
6576
|
-
|
|
6646
|
+
io.output.write(` include ${answers.include.length ? answers.include.join(", ") : "everything"}
|
|
6577
6647
|
`);
|
|
6578
|
-
|
|
6648
|
+
io.output.write(` part size ${String(answers.maxPartBytes)}
|
|
6579
6649
|
`);
|
|
6580
|
-
|
|
6650
|
+
io.output.write(` artifacts ${enabledCount} of ${ARTIFACT_NAMES.length}
|
|
6581
6651
|
`);
|
|
6582
|
-
|
|
6652
|
+
io.output.write(` credentials ${answers.includeSensitiveFiles ? "included" : "skipped"}
|
|
6583
6653
|
|
|
6584
6654
|
`);
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6655
|
+
io.output.write(" Will write snapshot.config with your answers, plus every other setting\n");
|
|
6656
|
+
io.output.write(" at its default \u2014 so nothing is hidden behind the docs.\n\n");
|
|
6657
|
+
const proceed = await confirm(io, "Write this and continue?", { defaultValue: true });
|
|
6658
|
+
if (!proceed) throw new PromptCancelled();
|
|
6659
|
+
}
|
|
6589
6660
|
}
|
|
6590
6661
|
const configText = renderConfig(answers);
|
|
6591
6662
|
const preferredName = chooseConfigFileName(options.cwd);
|
|
6592
6663
|
const presentConfigs = CONFIG_CANDIDATES.filter(
|
|
6593
|
-
(name) =>
|
|
6664
|
+
(name) => fs11__namespace.existsSync(path12__namespace.join(options.cwd, name))
|
|
6594
6665
|
);
|
|
6595
6666
|
const present = presentConfigs[0] ?? null;
|
|
6596
6667
|
if (presentConfigs.length > 1) {
|
|
@@ -6599,7 +6670,7 @@ async function runInit(options) {
|
|
|
6599
6670
|
);
|
|
6600
6671
|
}
|
|
6601
6672
|
const configName = present !== null && options.force ? present : preferredName;
|
|
6602
|
-
const configPath =
|
|
6673
|
+
const configPath = path12__namespace.join(options.cwd, configName);
|
|
6603
6674
|
const reused = present !== null && options.force !== true && options.reuseConfig === true;
|
|
6604
6675
|
if (reused) notes.push(`Kept the existing ${present} instead of writing a new one.`);
|
|
6605
6676
|
if (options.dryRun) {
|
|
@@ -6609,6 +6680,8 @@ async function runInit(options) {
|
|
|
6609
6680
|
written: false,
|
|
6610
6681
|
reused,
|
|
6611
6682
|
preset: answers.preset,
|
|
6683
|
+
reason,
|
|
6684
|
+
fallback,
|
|
6612
6685
|
scripts: [],
|
|
6613
6686
|
gitignoreEntries: [],
|
|
6614
6687
|
dependency: { name: GENERATOR_NAME, range: `^${GENERATOR_VERSION}`, added: false },
|
|
@@ -6630,7 +6703,7 @@ async function runInit(options) {
|
|
|
6630
6703
|
'package.json already defines a "snapshot" config. Remove that key, or re-run with --force to write a config file that takes precedence over it.'
|
|
6631
6704
|
);
|
|
6632
6705
|
}
|
|
6633
|
-
if (
|
|
6706
|
+
if (fs11__namespace.existsSync(configPath) && !options.force && !reused) {
|
|
6634
6707
|
throw new Error(`${configName} already exists. Re-run with --force to replace it.`);
|
|
6635
6708
|
}
|
|
6636
6709
|
if (!reused) writeFileOrExplain(configPath, configText);
|
|
@@ -6643,12 +6716,56 @@ async function runInit(options) {
|
|
|
6643
6716
|
written: true,
|
|
6644
6717
|
reused,
|
|
6645
6718
|
preset: answers.preset,
|
|
6719
|
+
reason,
|
|
6720
|
+
fallback,
|
|
6646
6721
|
scripts,
|
|
6647
6722
|
gitignoreEntries: ignore.added,
|
|
6648
6723
|
dependency,
|
|
6649
6724
|
notes
|
|
6650
6725
|
};
|
|
6651
6726
|
}
|
|
6727
|
+
function describeTarget(cwd) {
|
|
6728
|
+
const relative7 = path12__namespace.relative(process.cwd(), cwd);
|
|
6729
|
+
if (relative7 === "") return "this directory";
|
|
6730
|
+
if (relative7.startsWith("..") || path12__namespace.isAbsolute(relative7)) return cwd;
|
|
6731
|
+
return relative7;
|
|
6732
|
+
}
|
|
6733
|
+
function firstRunMessage(reason, cwd) {
|
|
6734
|
+
const where = describeTarget(cwd);
|
|
6735
|
+
if (reason === "empty") {
|
|
6736
|
+
return `Nothing to snapshot: ${where} has no files. Run this inside the repository you want to snapshot, or pass --cwd.`;
|
|
6737
|
+
}
|
|
6738
|
+
return `No configuration found in ${where} and this session is not interactive, so nothing was generated.
|
|
6739
|
+
Choose one:
|
|
6740
|
+
${GENERATOR_NAME} --autopilot detect the project, set it up and generate, no questions
|
|
6741
|
+
${GENERATOR_NAME} init --yes write a config from the detected defaults, then generate
|
|
6742
|
+
${GENERATOR_NAME} init write a config interactively`;
|
|
6743
|
+
}
|
|
6744
|
+
function planFirstRun(facts) {
|
|
6745
|
+
if (facts.emptyTarget) return { action: "refuse", exitCode: 1, reason: "empty" };
|
|
6746
|
+
if (facts.autopilot) return { action: "setup", interactive: false };
|
|
6747
|
+
if (facts.hasConfig || facts.hasPriorSnapshot) return { action: "generate" };
|
|
6748
|
+
if (facts.interactive) return { action: "setup", interactive: true };
|
|
6749
|
+
return { action: "refuse", exitCode: 2, reason: "undecided" };
|
|
6750
|
+
}
|
|
6751
|
+
var NOT_CONTENT = /* @__PURE__ */ new Set([".git", ".hg", ".svn", ".bzr", ".DS_Store", "Thumbs.db"]);
|
|
6752
|
+
function isEffectivelyEmpty(cwd) {
|
|
6753
|
+
try {
|
|
6754
|
+
return fs11__namespace.readdirSync(cwd).every((entry) => NOT_CONTENT.has(entry));
|
|
6755
|
+
} catch {
|
|
6756
|
+
return false;
|
|
6757
|
+
}
|
|
6758
|
+
}
|
|
6759
|
+
function hasPriorSnapshot(cwd, outDir) {
|
|
6760
|
+
let parsed;
|
|
6761
|
+
try {
|
|
6762
|
+
parsed = JSON.parse(fs11__namespace.readFileSync(path12__namespace.join(cwd, outDir, ".codebase-snapshot"), "utf8"));
|
|
6763
|
+
} catch {
|
|
6764
|
+
return false;
|
|
6765
|
+
}
|
|
6766
|
+
if (parsed === null || typeof parsed !== "object") return false;
|
|
6767
|
+
return isOurGeneratorName(parsed.generator);
|
|
6768
|
+
}
|
|
6652
6769
|
|
|
6653
6770
|
// src/index.ts
|
|
6654
6771
|
var SCHEMA_VERSION = "3.0.0";
|
|
@@ -6730,13 +6847,13 @@ function buildImportResolver(files) {
|
|
|
6730
6847
|
const relativePath = file.relativePath;
|
|
6731
6848
|
remember(byPath, relativePath, relativePath);
|
|
6732
6849
|
remember(byPathFolded, relativePath.toLowerCase(), relativePath);
|
|
6733
|
-
const extension =
|
|
6850
|
+
const extension = path12__namespace.posix.extname(relativePath);
|
|
6734
6851
|
if (!SOURCE_EXTENSIONS.has(extension)) continue;
|
|
6735
6852
|
const stem = relativePath.slice(0, -extension.length);
|
|
6736
6853
|
remember(byStem, stem, relativePath);
|
|
6737
6854
|
remember(byStemFolded, stem.toLowerCase(), relativePath);
|
|
6738
|
-
if (
|
|
6739
|
-
const directory =
|
|
6855
|
+
if (path12__namespace.posix.basename(stem) === "index") {
|
|
6856
|
+
const directory = path12__namespace.posix.dirname(stem);
|
|
6740
6857
|
remember(byStem, directory, relativePath);
|
|
6741
6858
|
remember(byStemFolded, directory.toLowerCase(), relativePath);
|
|
6742
6859
|
}
|
|
@@ -6745,8 +6862,8 @@ function buildImportResolver(files) {
|
|
|
6745
6862
|
}
|
|
6746
6863
|
function resolveSpecifier(fromFile, specifier, resolver) {
|
|
6747
6864
|
if (!RELATIVE_SPECIFIER.test(specifier)) return null;
|
|
6748
|
-
const joined =
|
|
6749
|
-
|
|
6865
|
+
const joined = path12__namespace.posix.normalize(
|
|
6866
|
+
path12__namespace.posix.join(path12__namespace.posix.dirname(fromFile), specifier)
|
|
6750
6867
|
);
|
|
6751
6868
|
const exact = (key) => resolver.byPath.get(key) ?? resolver.byPathFolded.get(key.toLowerCase()) ?? null;
|
|
6752
6869
|
const direct = exact(joined);
|
|
@@ -6839,11 +6956,11 @@ function verifyInMemory(files, parts, maxPartBytes) {
|
|
|
6839
6956
|
return errors;
|
|
6840
6957
|
}
|
|
6841
6958
|
function resolveSafeOutputDirs(config) {
|
|
6842
|
-
const cwd =
|
|
6843
|
-
const outDir =
|
|
6844
|
-
const tmpDir =
|
|
6845
|
-
const root =
|
|
6846
|
-
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${
|
|
6959
|
+
const cwd = path12__namespace.resolve(config.cwd);
|
|
6960
|
+
const outDir = path12__namespace.resolve(cwd, config.outDir);
|
|
6961
|
+
const tmpDir = path12__namespace.resolve(cwd, config.tmpDir);
|
|
6962
|
+
const root = path12__namespace.parse(cwd).root;
|
|
6963
|
+
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path12__namespace.sep}`);
|
|
6847
6964
|
const reject = (reason) => {
|
|
6848
6965
|
throw new Error(
|
|
6849
6966
|
`Refusing to generate: ${reason}. outDir=${outDir} tmpDir=${tmpDir} cwd=${cwd}`
|
|
@@ -6899,14 +7016,14 @@ function listEntries(dir) {
|
|
|
6899
7016
|
const walk = (absolute, prefix) => {
|
|
6900
7017
|
let children;
|
|
6901
7018
|
try {
|
|
6902
|
-
children =
|
|
7019
|
+
children = fs11__namespace.readdirSync(absolute, { withFileTypes: true });
|
|
6903
7020
|
} catch {
|
|
6904
7021
|
return;
|
|
6905
7022
|
}
|
|
6906
7023
|
for (const child of children) {
|
|
6907
|
-
const
|
|
6908
|
-
entries.push(
|
|
6909
|
-
if (child.isDirectory()) walk(
|
|
7024
|
+
const relative7 = prefix === "" ? child.name : `${prefix}/${child.name}`;
|
|
7025
|
+
entries.push(relative7);
|
|
7026
|
+
if (child.isDirectory()) walk(path12__namespace.join(absolute, child.name), relative7);
|
|
6910
7027
|
}
|
|
6911
7028
|
};
|
|
6912
7029
|
walk(dir, "");
|
|
@@ -6923,28 +7040,28 @@ function markerPayload(dir, state, id, createdAt) {
|
|
|
6923
7040
|
pid: process.pid,
|
|
6924
7041
|
entries: listEntries(dir)
|
|
6925
7042
|
};
|
|
6926
|
-
const manifestPath =
|
|
6927
|
-
if (
|
|
6928
|
-
marker2.manifestSha256 = sha256Hex2(
|
|
7043
|
+
const manifestPath = path12__namespace.join(dir, "manifest.json");
|
|
7044
|
+
if (fs11__namespace.existsSync(manifestPath)) {
|
|
7045
|
+
marker2.manifestSha256 = sha256Hex2(fs11__namespace.readFileSync(manifestPath));
|
|
6929
7046
|
}
|
|
6930
7047
|
return marker2;
|
|
6931
7048
|
}
|
|
6932
7049
|
function writeOwnershipMarker(dir, marker2) {
|
|
6933
|
-
|
|
6934
|
-
|
|
7050
|
+
fs11__namespace.writeFileSync(
|
|
7051
|
+
path12__namespace.join(dir, OWNERSHIP_MARKER),
|
|
6935
7052
|
`${JSON.stringify(marker2, null, 2)}
|
|
6936
7053
|
`,
|
|
6937
7054
|
"utf8"
|
|
6938
7055
|
);
|
|
6939
7056
|
}
|
|
6940
7057
|
function readOwnershipMarker(dir) {
|
|
6941
|
-
const markerPath =
|
|
6942
|
-
if (!
|
|
7058
|
+
const markerPath = path12__namespace.join(dir, OWNERSHIP_MARKER);
|
|
7059
|
+
if (!fs11__namespace.existsSync(markerPath)) {
|
|
6943
7060
|
return { marker: null, problem: "it holds no .codebase-snapshot marker" };
|
|
6944
7061
|
}
|
|
6945
7062
|
let raw;
|
|
6946
7063
|
try {
|
|
6947
|
-
raw =
|
|
7064
|
+
raw = fs11__namespace.readFileSync(markerPath, "utf8");
|
|
6948
7065
|
} catch {
|
|
6949
7066
|
return { marker: null, problem: "its .codebase-snapshot marker could not be read" };
|
|
6950
7067
|
}
|
|
@@ -7012,11 +7129,11 @@ function assessSnapshotDirectory(dir) {
|
|
|
7012
7129
|
marker: marker2
|
|
7013
7130
|
};
|
|
7014
7131
|
}
|
|
7015
|
-
const manifestPath =
|
|
7016
|
-
if (
|
|
7132
|
+
const manifestPath = path12__namespace.join(dir, "manifest.json");
|
|
7133
|
+
if (fs11__namespace.existsSync(manifestPath)) {
|
|
7017
7134
|
let raw;
|
|
7018
7135
|
try {
|
|
7019
|
-
raw =
|
|
7136
|
+
raw = fs11__namespace.readFileSync(manifestPath, "utf8");
|
|
7020
7137
|
} catch {
|
|
7021
7138
|
return {
|
|
7022
7139
|
owned: false,
|
|
@@ -7098,13 +7215,13 @@ function containsNoFiles(dir) {
|
|
|
7098
7215
|
const current = pending.pop();
|
|
7099
7216
|
let entries;
|
|
7100
7217
|
try {
|
|
7101
|
-
entries =
|
|
7218
|
+
entries = fs11__namespace.readdirSync(current, { withFileTypes: true });
|
|
7102
7219
|
} catch {
|
|
7103
7220
|
return false;
|
|
7104
7221
|
}
|
|
7105
7222
|
for (const entry of entries) {
|
|
7106
7223
|
if (entry.isDirectory()) {
|
|
7107
|
-
pending.push(
|
|
7224
|
+
pending.push(path12__namespace.join(current, entry.name));
|
|
7108
7225
|
} else if (!IGNORABLE_ENTRIES.has(entry.name)) {
|
|
7109
7226
|
return false;
|
|
7110
7227
|
}
|
|
@@ -7113,13 +7230,13 @@ function containsNoFiles(dir) {
|
|
|
7113
7230
|
return true;
|
|
7114
7231
|
}
|
|
7115
7232
|
function assertReplaceable(target, label, secretRules) {
|
|
7116
|
-
if (!
|
|
7117
|
-
if (!
|
|
7233
|
+
if (!fs11__namespace.existsSync(target)) return;
|
|
7234
|
+
if (!fs11__namespace.statSync(target).isDirectory()) {
|
|
7118
7235
|
throw new Error(
|
|
7119
7236
|
`Refusing to write into ${label} ${target}: it exists but is not a directory.`
|
|
7120
7237
|
);
|
|
7121
7238
|
}
|
|
7122
|
-
const entries =
|
|
7239
|
+
const entries = fs11__namespace.readdirSync(target);
|
|
7123
7240
|
if (entries.length === 0) return;
|
|
7124
7241
|
if (entries.every((name) => IGNORABLE_ENTRIES.has(name))) return;
|
|
7125
7242
|
if (containsNoFiles(target)) return;
|
|
@@ -7139,18 +7256,18 @@ function assertReplaceable(target, label, secretRules) {
|
|
|
7139
7256
|
);
|
|
7140
7257
|
}
|
|
7141
7258
|
function assertStagingRootUsable(tmpDir, secretRules) {
|
|
7142
|
-
if (!
|
|
7143
|
-
if (!
|
|
7259
|
+
if (!fs11__namespace.existsSync(tmpDir)) return;
|
|
7260
|
+
if (!fs11__namespace.statSync(tmpDir).isDirectory()) {
|
|
7144
7261
|
throw new Error(`Refusing to write into tmpDir ${tmpDir}: it exists but is not a directory.`);
|
|
7145
7262
|
}
|
|
7146
|
-
const entries =
|
|
7263
|
+
const entries = fs11__namespace.readdirSync(tmpDir);
|
|
7147
7264
|
if (entries.length === 0) return;
|
|
7148
7265
|
const foreign = entries.filter((name) => {
|
|
7149
|
-
const full =
|
|
7266
|
+
const full = path12__namespace.join(tmpDir, name);
|
|
7150
7267
|
if (!name.startsWith(RUN_DIR_PREFIX)) return true;
|
|
7151
7268
|
let stats;
|
|
7152
7269
|
try {
|
|
7153
|
-
stats =
|
|
7270
|
+
stats = fs11__namespace.statSync(full);
|
|
7154
7271
|
} catch {
|
|
7155
7272
|
return true;
|
|
7156
7273
|
}
|
|
@@ -7158,7 +7275,7 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7158
7275
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7159
7276
|
if (marker2) return false;
|
|
7160
7277
|
try {
|
|
7161
|
-
return
|
|
7278
|
+
return fs11__namespace.readdirSync(full).length > 0;
|
|
7162
7279
|
} catch {
|
|
7163
7280
|
return true;
|
|
7164
7281
|
}
|
|
@@ -7173,13 +7290,13 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7173
7290
|
function cleanStaleRunDirs(tmpDir) {
|
|
7174
7291
|
let entries;
|
|
7175
7292
|
try {
|
|
7176
|
-
entries =
|
|
7293
|
+
entries = fs11__namespace.readdirSync(tmpDir);
|
|
7177
7294
|
} catch {
|
|
7178
7295
|
return;
|
|
7179
7296
|
}
|
|
7180
7297
|
for (const name of entries) {
|
|
7181
7298
|
if (!name.startsWith(RUN_DIR_PREFIX)) continue;
|
|
7182
|
-
const full =
|
|
7299
|
+
const full = path12__namespace.join(tmpDir, name);
|
|
7183
7300
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7184
7301
|
if (marker2) {
|
|
7185
7302
|
const created = Date.parse(marker2.createdAt);
|
|
@@ -7187,33 +7304,33 @@ function cleanStaleRunDirs(tmpDir) {
|
|
|
7187
7304
|
const abandoned = typeof marker2.pid === "number" && !isProcessAlive(marker2.pid);
|
|
7188
7305
|
if (aged || abandoned) {
|
|
7189
7306
|
try {
|
|
7190
|
-
|
|
7307
|
+
fs11__namespace.rmSync(full, { recursive: true, force: true });
|
|
7191
7308
|
} catch {
|
|
7192
7309
|
}
|
|
7193
7310
|
}
|
|
7194
7311
|
continue;
|
|
7195
7312
|
}
|
|
7196
7313
|
try {
|
|
7197
|
-
if (
|
|
7314
|
+
if (fs11__namespace.readdirSync(full).length === 0) fs11__namespace.rmSync(full, { recursive: true, force: true });
|
|
7198
7315
|
} catch {
|
|
7199
7316
|
}
|
|
7200
7317
|
}
|
|
7201
7318
|
}
|
|
7202
7319
|
function removeIfEmpty(dir) {
|
|
7203
7320
|
try {
|
|
7204
|
-
if (
|
|
7321
|
+
if (fs11__namespace.readdirSync(dir).length === 0) fs11__namespace.rmSync(dir, { recursive: true, force: true });
|
|
7205
7322
|
} catch {
|
|
7206
7323
|
}
|
|
7207
7324
|
}
|
|
7208
7325
|
function ensureParentDirectory(target, label) {
|
|
7209
|
-
const parent =
|
|
7210
|
-
if (
|
|
7326
|
+
const parent = path12__namespace.dirname(target);
|
|
7327
|
+
if (fs11__namespace.existsSync(parent) && !fs11__namespace.statSync(parent).isDirectory()) {
|
|
7211
7328
|
throw new Error(
|
|
7212
7329
|
`Refusing to create ${label} ${target}: ${parent} exists but is not a directory.`
|
|
7213
7330
|
);
|
|
7214
7331
|
}
|
|
7215
7332
|
try {
|
|
7216
|
-
|
|
7333
|
+
fs11__namespace.mkdirSync(parent, { recursive: true });
|
|
7217
7334
|
} catch (err) {
|
|
7218
7335
|
throw new Error(
|
|
7219
7336
|
`Refusing to create ${label} ${target}: its parent ${parent} could not be created (${err.message}).`
|
|
@@ -7222,7 +7339,7 @@ function ensureParentDirectory(target, label) {
|
|
|
7222
7339
|
}
|
|
7223
7340
|
function acquireRunLock(stagingRoot) {
|
|
7224
7341
|
const key = lockKeyFor(stagingRoot);
|
|
7225
|
-
const lockPath =
|
|
7342
|
+
const lockPath = path12__namespace.join(os__namespace.tmpdir(), `codebase-snapshot-${key}.lock`);
|
|
7226
7343
|
const payload = `${JSON.stringify({
|
|
7227
7344
|
pid: process.pid,
|
|
7228
7345
|
stagingRoot,
|
|
@@ -7231,22 +7348,22 @@ function acquireRunLock(stagingRoot) {
|
|
|
7231
7348
|
`;
|
|
7232
7349
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
7233
7350
|
try {
|
|
7234
|
-
const handle =
|
|
7351
|
+
const handle = fs11__namespace.openSync(lockPath, "wx");
|
|
7235
7352
|
try {
|
|
7236
|
-
|
|
7353
|
+
fs11__namespace.writeSync(handle, payload);
|
|
7237
7354
|
} finally {
|
|
7238
|
-
|
|
7355
|
+
fs11__namespace.closeSync(handle);
|
|
7239
7356
|
}
|
|
7240
7357
|
return () => {
|
|
7241
7358
|
try {
|
|
7242
|
-
|
|
7359
|
+
fs11__namespace.rmSync(lockPath, { force: true });
|
|
7243
7360
|
} catch {
|
|
7244
7361
|
}
|
|
7245
7362
|
};
|
|
7246
7363
|
} catch (err) {
|
|
7247
7364
|
if (err.code !== "EEXIST") throw err;
|
|
7248
7365
|
if (attempt === 0 && lockOwnerIsGone(lockPath)) {
|
|
7249
|
-
|
|
7366
|
+
fs11__namespace.rmSync(lockPath, { force: true });
|
|
7250
7367
|
continue;
|
|
7251
7368
|
}
|
|
7252
7369
|
throw new Error(
|
|
@@ -7259,7 +7376,7 @@ function acquireRunLock(stagingRoot) {
|
|
|
7259
7376
|
function lockKeyFor(stagingRoot) {
|
|
7260
7377
|
let key = stagingRoot;
|
|
7261
7378
|
try {
|
|
7262
|
-
key =
|
|
7379
|
+
key = fs11__namespace.realpathSync(stagingRoot);
|
|
7263
7380
|
} catch {
|
|
7264
7381
|
}
|
|
7265
7382
|
if (process.platform === "win32" || process.platform === "darwin") key = key.toLowerCase();
|
|
@@ -7268,7 +7385,7 @@ function lockKeyFor(stagingRoot) {
|
|
|
7268
7385
|
function lockOwnerIsGone(lockPath) {
|
|
7269
7386
|
let raw;
|
|
7270
7387
|
try {
|
|
7271
|
-
raw =
|
|
7388
|
+
raw = fs11__namespace.readFileSync(lockPath, "utf8");
|
|
7272
7389
|
} catch {
|
|
7273
7390
|
return false;
|
|
7274
7391
|
}
|
|
@@ -7288,12 +7405,12 @@ function lockOwnerIsGone(lockPath) {
|
|
|
7288
7405
|
}
|
|
7289
7406
|
function writeManifestAtomically(manifestPath, manifest) {
|
|
7290
7407
|
const tempPath = `${manifestPath}.${process.pid}.tmp`;
|
|
7291
|
-
|
|
7408
|
+
fs11__namespace.writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
7292
7409
|
try {
|
|
7293
|
-
|
|
7410
|
+
fs11__namespace.renameSync(tempPath, manifestPath);
|
|
7294
7411
|
} catch (err) {
|
|
7295
7412
|
try {
|
|
7296
|
-
|
|
7413
|
+
fs11__namespace.rmSync(tempPath, { force: true });
|
|
7297
7414
|
} catch {
|
|
7298
7415
|
}
|
|
7299
7416
|
throw err;
|
|
@@ -7316,31 +7433,31 @@ function swapIntoPlace(stagingDir, outDir) {
|
|
|
7316
7433
|
}
|
|
7317
7434
|
function swapOnce(stagingDir, outDir) {
|
|
7318
7435
|
const backupDir = `${outDir}.backup-${process.pid}-${Date.now()}`;
|
|
7319
|
-
const hadPrevious =
|
|
7320
|
-
if (hadPrevious)
|
|
7436
|
+
const hadPrevious = fs11__namespace.existsSync(outDir);
|
|
7437
|
+
if (hadPrevious) fs11__namespace.renameSync(outDir, backupDir);
|
|
7321
7438
|
try {
|
|
7322
7439
|
try {
|
|
7323
|
-
|
|
7440
|
+
fs11__namespace.renameSync(stagingDir, outDir);
|
|
7324
7441
|
} catch (err) {
|
|
7325
7442
|
if (err.code !== "EXDEV") throw err;
|
|
7326
7443
|
const partialDir = `${outDir}.partial-${process.pid}-${Date.now()}`;
|
|
7327
7444
|
try {
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7445
|
+
fs11__namespace.cpSync(stagingDir, partialDir, { recursive: true });
|
|
7446
|
+
fs11__namespace.renameSync(partialDir, outDir);
|
|
7447
|
+
fs11__namespace.rmSync(stagingDir, { recursive: true, force: true });
|
|
7331
7448
|
} catch (copyErr) {
|
|
7332
7449
|
try {
|
|
7333
|
-
|
|
7450
|
+
fs11__namespace.rmSync(partialDir, { recursive: true, force: true });
|
|
7334
7451
|
} catch {
|
|
7335
7452
|
}
|
|
7336
7453
|
throw copyErr;
|
|
7337
7454
|
}
|
|
7338
7455
|
}
|
|
7339
|
-
if (hadPrevious)
|
|
7456
|
+
if (hadPrevious) fs11__namespace.rmSync(backupDir, { recursive: true, force: true });
|
|
7340
7457
|
} catch (err) {
|
|
7341
|
-
if (hadPrevious &&
|
|
7342
|
-
if (
|
|
7343
|
-
|
|
7458
|
+
if (hadPrevious && fs11__namespace.existsSync(backupDir)) {
|
|
7459
|
+
if (fs11__namespace.existsSync(outDir)) fs11__namespace.rmSync(outDir, { recursive: true, force: true });
|
|
7460
|
+
fs11__namespace.renameSync(backupDir, outDir);
|
|
7344
7461
|
}
|
|
7345
7462
|
throw err;
|
|
7346
7463
|
}
|
|
@@ -7435,8 +7552,8 @@ function generateSnapshot(configInput, options) {
|
|
|
7435
7552
|
// first run cannot have marked them yet, so the name alone keeps a run from recording its own
|
|
7436
7553
|
// output — but only at these exact paths, not at every directory that shares the name.
|
|
7437
7554
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
7438
|
-
(directory) =>
|
|
7439
|
-
).filter((
|
|
7555
|
+
(directory) => path12__namespace.relative(config.cwd, path12__namespace.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
7556
|
+
).filter((relative7) => relative7.length > 0 && !relative7.startsWith(".."))
|
|
7440
7557
|
});
|
|
7441
7558
|
const files = [];
|
|
7442
7559
|
const monolithBodies = /* @__PURE__ */ new Map();
|
|
@@ -7456,12 +7573,12 @@ function generateSnapshot(configInput, options) {
|
|
|
7456
7573
|
let totalSizeBytes = 0;
|
|
7457
7574
|
let largeFileCount = 0;
|
|
7458
7575
|
for (const relativePath of collection.files) {
|
|
7459
|
-
const absolutePath =
|
|
7576
|
+
const absolutePath = path12__namespace.join(config.cwd, relativePath);
|
|
7460
7577
|
let stats;
|
|
7461
7578
|
try {
|
|
7462
|
-
stats =
|
|
7579
|
+
stats = fs11__namespace.statSync(absolutePath);
|
|
7463
7580
|
if (!stats.isFile()) {
|
|
7464
|
-
const nestedRepository = stats.isDirectory() &&
|
|
7581
|
+
const nestedRepository = stats.isDirectory() && fs11__namespace.existsSync(path12__namespace.join(absolutePath, ".git"));
|
|
7465
7582
|
skipped.push(
|
|
7466
7583
|
nestedRepository ? {
|
|
7467
7584
|
path: relativePath,
|
|
@@ -7481,7 +7598,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7481
7598
|
}
|
|
7482
7599
|
let buffer;
|
|
7483
7600
|
try {
|
|
7484
|
-
buffer =
|
|
7601
|
+
buffer = fs11__namespace.readFileSync(absolutePath);
|
|
7485
7602
|
} catch {
|
|
7486
7603
|
skipped.push({ path: relativePath, reason: "read-error" });
|
|
7487
7604
|
continue;
|
|
@@ -7811,12 +7928,12 @@ function generateSnapshot(configInput, options) {
|
|
|
7811
7928
|
let stagingDir = null;
|
|
7812
7929
|
try {
|
|
7813
7930
|
ensureParentDirectory(outDir, "outDir");
|
|
7814
|
-
|
|
7931
|
+
fs11__namespace.mkdirSync(tmpDir, { recursive: true });
|
|
7815
7932
|
cleanStaleRunDirs(tmpDir);
|
|
7816
7933
|
const snapshotId = crypto__namespace.randomUUID();
|
|
7817
7934
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7818
|
-
stagingDir =
|
|
7819
|
-
|
|
7935
|
+
stagingDir = path12__namespace.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
|
|
7936
|
+
fs11__namespace.mkdirSync(stagingDir);
|
|
7820
7937
|
writeOwnershipMarker(stagingDir, {
|
|
7821
7938
|
generator: GENERATOR_NAME,
|
|
7822
7939
|
version: GENERATOR_VERSION,
|
|
@@ -7826,41 +7943,41 @@ function generateSnapshot(configInput, options) {
|
|
|
7826
7943
|
id: snapshotId,
|
|
7827
7944
|
pid: process.pid
|
|
7828
7945
|
});
|
|
7829
|
-
const partsDir =
|
|
7830
|
-
const reportsDir =
|
|
7831
|
-
if (artifacts.parts)
|
|
7946
|
+
const partsDir = path12__namespace.join(stagingDir, "parts");
|
|
7947
|
+
const reportsDir = path12__namespace.join(stagingDir, "reports");
|
|
7948
|
+
if (artifacts.parts) fs11__namespace.mkdirSync(partsDir, { recursive: true });
|
|
7832
7949
|
if (artifacts.navigation || artifacts.projectTree || artifacts.audit) {
|
|
7833
|
-
|
|
7950
|
+
fs11__namespace.mkdirSync(reportsDir, { recursive: true });
|
|
7834
7951
|
}
|
|
7835
7952
|
if (artifacts.parts) {
|
|
7836
7953
|
for (const part of parts) {
|
|
7837
|
-
|
|
7954
|
+
fs11__namespace.writeFileSync(path12__namespace.join(partsDir, part.filename), part.markdown, "utf8");
|
|
7838
7955
|
}
|
|
7839
7956
|
}
|
|
7840
7957
|
if (projectTree !== null) {
|
|
7841
|
-
|
|
7958
|
+
fs11__namespace.writeFileSync(path12__namespace.join(reportsDir, "project-tree.md"), projectTree, "utf8");
|
|
7842
7959
|
}
|
|
7843
7960
|
if (artifacts.navigation) {
|
|
7844
|
-
|
|
7961
|
+
fs11__namespace.writeFileSync(path12__namespace.join(reportsDir, "navigation.md"), generateNavigation(manifest), "utf8");
|
|
7845
7962
|
}
|
|
7846
7963
|
if (artifacts.audit) {
|
|
7847
|
-
|
|
7848
|
-
|
|
7964
|
+
fs11__namespace.writeFileSync(
|
|
7965
|
+
path12__namespace.join(reportsDir, "audit.md"),
|
|
7849
7966
|
generateAuditReport(manifest, secretFindings, config.secretRules),
|
|
7850
7967
|
"utf8"
|
|
7851
7968
|
);
|
|
7852
7969
|
}
|
|
7853
7970
|
if (artifacts.readme) {
|
|
7854
|
-
|
|
7971
|
+
fs11__namespace.writeFileSync(path12__namespace.join(stagingDir, "README.md"), generateReadme(manifest, artifacts), "utf8");
|
|
7855
7972
|
}
|
|
7856
7973
|
if (artifacts.manifest) {
|
|
7857
|
-
|
|
7974
|
+
fs11__namespace.writeFileSync(path12__namespace.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
7858
7975
|
}
|
|
7859
7976
|
if (monolithJson !== null) {
|
|
7860
|
-
|
|
7977
|
+
fs11__namespace.writeFileSync(path12__namespace.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
|
|
7861
7978
|
}
|
|
7862
7979
|
if (monolithMarkdown !== null) {
|
|
7863
|
-
|
|
7980
|
+
fs11__namespace.writeFileSync(path12__namespace.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
|
|
7864
7981
|
}
|
|
7865
7982
|
writeOwnershipMarker(stagingDir, markerPayload(stagingDir, "complete", snapshotId, createdAt));
|
|
7866
7983
|
swapIntoPlace(stagingDir, outDir);
|
|
@@ -7869,7 +7986,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7869
7986
|
const pendingHook = runAfterGenerate(config, manifest);
|
|
7870
7987
|
const shipHookState = () => {
|
|
7871
7988
|
if (artifacts.manifest && manifest.warnings.length !== warningsBeforeHook) {
|
|
7872
|
-
writeManifestAtomically(
|
|
7989
|
+
writeManifestAtomically(path12__namespace.join(outDir, "manifest.json"), manifest);
|
|
7873
7990
|
}
|
|
7874
7991
|
writeOwnershipMarker(outDir, markerPayload(outDir, "complete", snapshotId, createdAt));
|
|
7875
7992
|
};
|
|
@@ -7892,7 +8009,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7892
8009
|
} catch (err) {
|
|
7893
8010
|
if (stagingDir !== null) {
|
|
7894
8011
|
try {
|
|
7895
|
-
|
|
8012
|
+
fs11__namespace.rmSync(stagingDir, { recursive: true, force: true });
|
|
7896
8013
|
} catch {
|
|
7897
8014
|
}
|
|
7898
8015
|
}
|
|
@@ -7930,14 +8047,17 @@ exports.detectPreset = detectPreset;
|
|
|
7930
8047
|
exports.explainPath = explainPath;
|
|
7931
8048
|
exports.fenceForContent = fenceForContent;
|
|
7932
8049
|
exports.fenceForText = fenceForText;
|
|
8050
|
+
exports.firstRunMessage = firstRunMessage;
|
|
7933
8051
|
exports.generateProjectTree = generateProjectTree;
|
|
7934
8052
|
exports.generateSnapshot = generateSnapshot;
|
|
7935
8053
|
exports.generateSnapshotAsync = generateSnapshotAsync;
|
|
7936
8054
|
exports.getPreset = getPreset;
|
|
7937
8055
|
exports.globToRegExp = globToRegExp;
|
|
8056
|
+
exports.hasPriorSnapshot = hasPriorSnapshot;
|
|
7938
8057
|
exports.isBinaryBuffer = isBinaryBuffer;
|
|
7939
8058
|
exports.isBinaryExtension = isBinaryExtension;
|
|
7940
8059
|
exports.isBinaryFile = isBinaryFile;
|
|
8060
|
+
exports.isEffectivelyEmpty = isEffectivelyEmpty;
|
|
7941
8061
|
exports.isInteractive = isInteractive;
|
|
7942
8062
|
exports.isResolvedConfig = isResolvedConfig;
|
|
7943
8063
|
exports.isSensitivePath = isSensitivePath;
|
|
@@ -7951,6 +8071,7 @@ exports.matchesExclude = matchesExclude;
|
|
|
7951
8071
|
exports.normalizeResolvedConfig = normalizeResolvedConfig;
|
|
7952
8072
|
exports.parseByteSize = parseByteSize;
|
|
7953
8073
|
exports.partitionFiles = partitionFiles;
|
|
8074
|
+
exports.planFirstRun = planFirstRun;
|
|
7954
8075
|
exports.profileForPath = profileForPath;
|
|
7955
8076
|
exports.renderConfig = renderConfig;
|
|
7956
8077
|
exports.renderDiffText = renderDiffText;
|