codebase-snapshot 0.9.5 → 0.9.6
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 +46 -0
- package/README.md +4 -1
- package/dist/bin.js +405 -203
- package/dist/{chunk-B336MMNC.js → chunk-3KUL3QRH.js} +379 -222
- package/dist/{chunk-4AHHSNGG.js → chunk-ZKZOGGM3.js} +33 -7
- package/dist/cli.cjs +508 -310
- package/dist/cli.d.cts +7 -1
- package/dist/cli.d.ts +7 -1
- package/dist/cli.js +16 -2
- package/dist/index.cjs +384 -215
- package/dist/index.d.cts +54 -2
- package/dist/index.d.ts +54 -2
- package/dist/index.js +1 -1
- package/dist/mcp.cjs +31 -4
- package/dist/mcp.d.cts +14 -1
- package/dist/mcp.d.ts +14 -1
- package/dist/mcp.js +2 -2
- package/docs/cli.md +19 -2
- package/docs/mcp.md +3 -3
- package/package.json +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as crypto from 'crypto';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
3
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
4
|
-
import * as
|
|
4
|
+
import * as fs12 from 'fs';
|
|
5
5
|
import * as os from 'os';
|
|
6
|
-
import * as
|
|
6
|
+
import * as path13 from 'path';
|
|
7
7
|
import ts from 'typescript';
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
9
|
import { pathToFileURL } from 'url';
|
|
10
10
|
import * as childProcess from 'child_process';
|
|
11
|
+
import * as https from 'https';
|
|
11
12
|
import * as readline from 'readline';
|
|
12
13
|
|
|
13
14
|
// src/index.ts
|
|
@@ -234,9 +235,9 @@ var JAVA_METHOD = /^\s+(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)
|
|
|
234
235
|
var jvmProfile = {
|
|
235
236
|
id: "jvm",
|
|
236
237
|
extensions: [".java", ".kt", ".kts", ".scala"],
|
|
237
|
-
summarize(
|
|
238
|
+
summarize(path14, content) {
|
|
238
239
|
const summary = emptySummary();
|
|
239
|
-
const lower =
|
|
240
|
+
const lower = path14.toLowerCase();
|
|
240
241
|
const isJava = lower.endsWith(".java");
|
|
241
242
|
const isKotlin = lower.endsWith(".kt") || lower.endsWith(".kts");
|
|
242
243
|
eachLine(content, (line) => {
|
|
@@ -689,16 +690,16 @@ function summarizeTypeScriptSource(relativePath, content) {
|
|
|
689
690
|
// src/ast/profiles/sfc.ts
|
|
690
691
|
var SCRIPT_BLOCK = /<script[^>]*>([\s\S]*?)<\/script>/gi;
|
|
691
692
|
var ASTRO_FRONTMATTER = /^\uFEFF?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?=\r?\n|$)/;
|
|
692
|
-
function componentName(
|
|
693
|
-
const base =
|
|
693
|
+
function componentName(path14) {
|
|
694
|
+
const base = path14.split("/").pop() ?? path14;
|
|
694
695
|
return base.replace(/\.[^.]+$/, "");
|
|
695
696
|
}
|
|
696
697
|
var sfcProfile = {
|
|
697
698
|
id: "sfc",
|
|
698
699
|
extensions: [".vue", ".svelte", ".astro"],
|
|
699
|
-
summarize(
|
|
700
|
+
summarize(path14, content) {
|
|
700
701
|
let script = "";
|
|
701
|
-
if (
|
|
702
|
+
if (path14.toLowerCase().endsWith(".astro")) {
|
|
702
703
|
const frontmatter = ASTRO_FRONTMATTER.exec(content);
|
|
703
704
|
if (frontmatter) script += `${frontmatter[1]}
|
|
704
705
|
`;
|
|
@@ -707,7 +708,7 @@ var sfcProfile = {
|
|
|
707
708
|
script += `${match[1]}
|
|
708
709
|
`;
|
|
709
710
|
}
|
|
710
|
-
const name = componentName(
|
|
711
|
+
const name = componentName(path14);
|
|
711
712
|
if (!script.trim()) {
|
|
712
713
|
const summary2 = emptySummary();
|
|
713
714
|
if (name) {
|
|
@@ -741,15 +742,15 @@ for (const profile of LANGUAGE_PROFILES) {
|
|
|
741
742
|
BY_EXTENSION.set(extension.toLowerCase(), profile);
|
|
742
743
|
}
|
|
743
744
|
}
|
|
744
|
-
function profileForPath(
|
|
745
|
-
const lower =
|
|
745
|
+
function profileForPath(path14) {
|
|
746
|
+
const lower = path14.toLowerCase();
|
|
746
747
|
const dot = lower.lastIndexOf(".");
|
|
747
748
|
if (dot === -1) return null;
|
|
748
749
|
return BY_EXTENSION.get(lower.slice(dot)) ?? null;
|
|
749
750
|
}
|
|
750
|
-
function summarizeWithProfile(
|
|
751
|
-
const profile = profileForPath(
|
|
752
|
-
return profile ? profile.summarize(
|
|
751
|
+
function summarizeWithProfile(path14, content) {
|
|
752
|
+
const profile = profileForPath(path14);
|
|
753
|
+
return profile ? profile.summarize(path14, content) : null;
|
|
753
754
|
}
|
|
754
755
|
|
|
755
756
|
// src/ast/structured.ts
|
|
@@ -920,15 +921,15 @@ var SKIPPED_WALK_DIRS = /* @__PURE__ */ new Set([
|
|
|
920
921
|
]);
|
|
921
922
|
function readSmallFile(fullPath) {
|
|
922
923
|
try {
|
|
923
|
-
const stats =
|
|
924
|
+
const stats = fs12.statSync(fullPath);
|
|
924
925
|
if (!stats.isFile() || stats.size > MANIFEST_MAX_BYTES) return null;
|
|
925
|
-
return
|
|
926
|
+
return fs12.readFileSync(fullPath, "utf8");
|
|
926
927
|
} catch {
|
|
927
928
|
return null;
|
|
928
929
|
}
|
|
929
930
|
}
|
|
930
931
|
function readManifest(cwd, name) {
|
|
931
|
-
return readSmallFile(
|
|
932
|
+
return readSmallFile(path13.join(cwd, name));
|
|
932
933
|
}
|
|
933
934
|
function dependenciesFromPackageJson(raw) {
|
|
934
935
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -988,7 +989,7 @@ function pnpmWorkspacePatterns(raw) {
|
|
|
988
989
|
function childDirectories(cwd, parent) {
|
|
989
990
|
let entries;
|
|
990
991
|
try {
|
|
991
|
-
entries =
|
|
992
|
+
entries = fs12.readdirSync(path13.join(cwd, parent), { withFileTypes: true });
|
|
992
993
|
} catch {
|
|
993
994
|
return [];
|
|
994
995
|
}
|
|
@@ -1024,12 +1025,12 @@ function scanWorkspacePackages(cwd, patterns) {
|
|
|
1024
1025
|
const files = /* @__PURE__ */ new Set();
|
|
1025
1026
|
const dependencies = /* @__PURE__ */ new Set();
|
|
1026
1027
|
for (const relative7 of workspacePackageDirs(cwd, patterns)) {
|
|
1027
|
-
const full =
|
|
1028
|
+
const full = path13.join(cwd, relative7);
|
|
1028
1029
|
try {
|
|
1029
|
-
for (const entry of
|
|
1030
|
+
for (const entry of fs12.readdirSync(full, { withFileTypes: true })) files.add(entry.name);
|
|
1030
1031
|
} catch {
|
|
1031
1032
|
}
|
|
1032
|
-
const raw = readSmallFile(
|
|
1033
|
+
const raw = readSmallFile(path13.join(full, "package.json"));
|
|
1033
1034
|
if (raw !== null) {
|
|
1034
1035
|
for (const name of dependenciesFromPackageJson(raw)) dependencies.add(name);
|
|
1035
1036
|
}
|
|
@@ -1046,7 +1047,7 @@ function countMarkdownFiles(cwd) {
|
|
|
1046
1047
|
directoriesSeen += 1;
|
|
1047
1048
|
let entries;
|
|
1048
1049
|
try {
|
|
1049
|
-
entries =
|
|
1050
|
+
entries = fs12.readdirSync(current.dir, { withFileTypes: true });
|
|
1050
1051
|
} catch {
|
|
1051
1052
|
continue;
|
|
1052
1053
|
}
|
|
@@ -1057,7 +1058,7 @@ function countMarkdownFiles(cwd) {
|
|
|
1057
1058
|
}
|
|
1058
1059
|
if (!entry.isDirectory() || current.depth >= 2) continue;
|
|
1059
1060
|
if (entry.name.startsWith(".") || SKIPPED_WALK_DIRS.has(entry.name)) continue;
|
|
1060
|
-
queue.push({ dir:
|
|
1061
|
+
queue.push({ dir: path13.join(current.dir, entry.name), depth: current.depth + 1 });
|
|
1061
1062
|
}
|
|
1062
1063
|
}
|
|
1063
1064
|
return count;
|
|
@@ -1066,7 +1067,7 @@ function buildPresetContext(cwd) {
|
|
|
1066
1067
|
const files = /* @__PURE__ */ new Set();
|
|
1067
1068
|
const dirs = /* @__PURE__ */ new Set();
|
|
1068
1069
|
try {
|
|
1069
|
-
for (const entry of
|
|
1070
|
+
for (const entry of fs12.readdirSync(cwd, { withFileTypes: true })) {
|
|
1070
1071
|
if (entry.isDirectory()) dirs.add(entry.name);
|
|
1071
1072
|
else if (entry.isFile()) files.add(entry.name);
|
|
1072
1073
|
}
|
|
@@ -1083,7 +1084,7 @@ function buildPresetContext(cwd) {
|
|
|
1083
1084
|
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;
|
|
1084
1085
|
let workspace = { files: /* @__PURE__ */ new Set(), dependencies: /* @__PURE__ */ new Set() };
|
|
1085
1086
|
if (isWorkspace) {
|
|
1086
|
-
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(
|
|
1087
|
+
const pnpmRaw = files.has("pnpm-workspace.yaml") ? readSmallFile(path13.join(cwd, "pnpm-workspace.yaml")) : null;
|
|
1087
1088
|
const declared = pnpmRaw === null ? [] : pnpmWorkspacePatterns(pnpmRaw);
|
|
1088
1089
|
const patterns = declared.length > 0 ? declared : declaredWorkspaces.length > 0 ? declaredWorkspaces : DEFAULT_WORKSPACE_PATTERNS;
|
|
1089
1090
|
workspace = scanWorkspacePackages(cwd, patterns);
|
|
@@ -2358,14 +2359,14 @@ var PRESET_IGNORES = new Set(
|
|
|
2358
2359
|
);
|
|
2359
2360
|
function readLinkTarget(linkPath, fallback) {
|
|
2360
2361
|
try {
|
|
2361
|
-
return
|
|
2362
|
+
return fs12.readlinkSync(linkPath);
|
|
2362
2363
|
} catch {
|
|
2363
2364
|
return fallback;
|
|
2364
2365
|
}
|
|
2365
2366
|
}
|
|
2366
2367
|
function isInside(root, candidate) {
|
|
2367
|
-
const relative7 =
|
|
2368
|
-
return relative7 === "" || !relative7.startsWith(`..${
|
|
2368
|
+
const relative7 = path13.relative(root, candidate);
|
|
2369
|
+
return relative7 === "" || !relative7.startsWith(`..${path13.sep}`) && relative7 !== ".." && !path13.isAbsolute(relative7);
|
|
2369
2370
|
}
|
|
2370
2371
|
function getGitInfo(cwd, fallbackBranch = "main") {
|
|
2371
2372
|
try {
|
|
@@ -2570,10 +2571,10 @@ function trimUnescapedTrailingSpaces(line) {
|
|
|
2570
2571
|
return line.slice(0, end);
|
|
2571
2572
|
}
|
|
2572
2573
|
function readGitignoreRules(dir) {
|
|
2573
|
-
const gitignorePath2 =
|
|
2574
|
+
const gitignorePath2 = path13.join(dir, ".gitignore");
|
|
2574
2575
|
let raw;
|
|
2575
2576
|
try {
|
|
2576
|
-
raw =
|
|
2577
|
+
raw = fs12.readFileSync(gitignorePath2, "utf8");
|
|
2577
2578
|
} catch {
|
|
2578
2579
|
return [];
|
|
2579
2580
|
}
|
|
@@ -2700,7 +2701,7 @@ function isToolOwnedDirName(name) {
|
|
|
2700
2701
|
}
|
|
2701
2702
|
function hasSnapshotMarker(target) {
|
|
2702
2703
|
try {
|
|
2703
|
-
return
|
|
2704
|
+
return fs12.statSync(target).isDirectory() && fs12.existsSync(path13.join(target, ".codebase-snapshot"));
|
|
2704
2705
|
} catch {
|
|
2705
2706
|
return false;
|
|
2706
2707
|
}
|
|
@@ -2714,7 +2715,7 @@ function makeToolOwnedDecider(cwd, toolOwnedPaths) {
|
|
|
2714
2715
|
const prefix = parts.slice(0, depth).join("/");
|
|
2715
2716
|
let hasMarker = markers.get(prefix);
|
|
2716
2717
|
if (hasMarker === void 0) {
|
|
2717
|
-
hasMarker =
|
|
2718
|
+
hasMarker = fs12.existsSync(path13.join(cwd, prefix, ".codebase-snapshot"));
|
|
2718
2719
|
markers.set(prefix, hasMarker);
|
|
2719
2720
|
}
|
|
2720
2721
|
if (hasMarker) return true;
|
|
@@ -2729,7 +2730,7 @@ function makeLinkProbe() {
|
|
|
2729
2730
|
let known = cache.get(absolutePath);
|
|
2730
2731
|
if (known === void 0) {
|
|
2731
2732
|
try {
|
|
2732
|
-
known =
|
|
2733
|
+
known = fs12.lstatSync(absolutePath).isSymbolicLink();
|
|
2733
2734
|
} catch {
|
|
2734
2735
|
known = false;
|
|
2735
2736
|
}
|
|
@@ -2742,7 +2743,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2742
2743
|
const isLink = makeLinkProbe();
|
|
2743
2744
|
let rootReal = cwd;
|
|
2744
2745
|
try {
|
|
2745
|
-
rootReal =
|
|
2746
|
+
rootReal = fs12.realpathSync(cwd);
|
|
2746
2747
|
} catch {
|
|
2747
2748
|
}
|
|
2748
2749
|
const reported = /* @__PURE__ */ new Set();
|
|
@@ -2752,7 +2753,7 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2752
2753
|
let linkedDir = null;
|
|
2753
2754
|
for (let depth = 1; depth <= parts.length; depth += 1) {
|
|
2754
2755
|
const prefix = parts.slice(0, depth).join("/");
|
|
2755
|
-
if (isLink(
|
|
2756
|
+
if (isLink(path13.join(cwd, prefix))) {
|
|
2756
2757
|
linkedDir = prefix;
|
|
2757
2758
|
break;
|
|
2758
2759
|
}
|
|
@@ -2763,10 +2764,10 @@ function dropLinkedDirectories(cwd, candidates, skipped) {
|
|
|
2763
2764
|
}
|
|
2764
2765
|
if (reported.has(linkedDir)) continue;
|
|
2765
2766
|
reported.add(linkedDir);
|
|
2766
|
-
const absolute =
|
|
2767
|
+
const absolute = path13.join(cwd, linkedDir);
|
|
2767
2768
|
let targetReal = absolute;
|
|
2768
2769
|
try {
|
|
2769
|
-
targetReal =
|
|
2770
|
+
targetReal = fs12.realpathSync(absolute);
|
|
2770
2771
|
} catch {
|
|
2771
2772
|
}
|
|
2772
2773
|
const target = readLinkTarget(absolute, targetReal);
|
|
@@ -2843,7 +2844,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2843
2844
|
"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."
|
|
2844
2845
|
);
|
|
2845
2846
|
}
|
|
2846
|
-
if (
|
|
2847
|
+
if (fs12.existsSync(path13.join(cwd, ".git"))) {
|
|
2847
2848
|
throw new Error(
|
|
2848
2849
|
"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."
|
|
2849
2850
|
);
|
|
@@ -2902,7 +2903,7 @@ function collectFiles(cwd, options = {}) {
|
|
|
2902
2903
|
}
|
|
2903
2904
|
function rootRealFor(root) {
|
|
2904
2905
|
try {
|
|
2905
|
-
return
|
|
2906
|
+
return fs12.realpathSync(root);
|
|
2906
2907
|
} catch {
|
|
2907
2908
|
return root;
|
|
2908
2909
|
}
|
|
@@ -2910,18 +2911,18 @@ function rootRealFor(root) {
|
|
|
2910
2911
|
function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PURE__ */ new Set(), parentGitignoreLayers = []) {
|
|
2911
2912
|
const results = { files: [], skipped: [] };
|
|
2912
2913
|
const stack = [];
|
|
2913
|
-
const relativeToBase = (target) =>
|
|
2914
|
+
const relativeToBase = (target) => path13.relative(baseDir, target).replace(/\\/g, "/") || ".";
|
|
2914
2915
|
const enter = (current, layers) => {
|
|
2915
2916
|
if (visited.has(current)) return false;
|
|
2916
2917
|
visited.add(current);
|
|
2917
2918
|
const localRules = readGitignoreRules(current);
|
|
2918
2919
|
const gitignoreLayers = localRules.length === 0 ? layers : [
|
|
2919
2920
|
...layers,
|
|
2920
|
-
{ prefix:
|
|
2921
|
+
{ prefix: path13.relative(baseDir, current).replace(/\\/g, "/"), rules: localRules }
|
|
2921
2922
|
];
|
|
2922
2923
|
let entries;
|
|
2923
2924
|
try {
|
|
2924
|
-
entries =
|
|
2925
|
+
entries = fs12.readdirSync(current, { withFileTypes: true });
|
|
2925
2926
|
} catch {
|
|
2926
2927
|
results.skipped.push({
|
|
2927
2928
|
path: relativeToBase(current),
|
|
@@ -2943,8 +2944,8 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2943
2944
|
}
|
|
2944
2945
|
const entry = frame.entries[frame.index];
|
|
2945
2946
|
frame.index += 1;
|
|
2946
|
-
const fullPath =
|
|
2947
|
-
const relPath =
|
|
2947
|
+
const fullPath = path13.join(frame.dir, entry.name);
|
|
2948
|
+
const relPath = path13.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
2948
2949
|
if (isToolOwnedDirName(entry.name) && reservedPaths.has(relPath)) continue;
|
|
2949
2950
|
if (DEFAULT_IGNORED_DIRS.includes(entry.name)) {
|
|
2950
2951
|
results.skipped.push({
|
|
@@ -2977,14 +2978,14 @@ function walkDirectory(dir, baseDir, rootReal, visited, reservedPaths = /* @__PU
|
|
|
2977
2978
|
if (entry.isSymbolicLink()) {
|
|
2978
2979
|
let targetReal;
|
|
2979
2980
|
try {
|
|
2980
|
-
targetReal =
|
|
2981
|
+
targetReal = fs12.realpathSync(fullPath);
|
|
2981
2982
|
} catch {
|
|
2982
2983
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "broken symlink" });
|
|
2983
2984
|
continue;
|
|
2984
2985
|
}
|
|
2985
2986
|
let stats;
|
|
2986
2987
|
try {
|
|
2987
|
-
stats =
|
|
2988
|
+
stats = fs12.statSync(fullPath);
|
|
2988
2989
|
} catch {
|
|
2989
2990
|
results.skipped.push({ path: relPath, reason: "read-error", detail: "unreadable symlink" });
|
|
2990
2991
|
continue;
|
|
@@ -3039,13 +3040,13 @@ var CONFIG_FILENAMES = [
|
|
|
3039
3040
|
];
|
|
3040
3041
|
function findConfigFile(cwd) {
|
|
3041
3042
|
for (const filename of CONFIG_FILENAMES) {
|
|
3042
|
-
const fullPath =
|
|
3043
|
-
if (
|
|
3043
|
+
const fullPath = path13.join(cwd, filename);
|
|
3044
|
+
if (fs12.existsSync(fullPath)) return fullPath;
|
|
3044
3045
|
}
|
|
3045
|
-
const pkgJsonPath =
|
|
3046
|
-
if (!
|
|
3046
|
+
const pkgJsonPath = path13.join(cwd, "package.json");
|
|
3047
|
+
if (!fs12.existsSync(pkgJsonPath)) return null;
|
|
3047
3048
|
try {
|
|
3048
|
-
const parsed = JSON.parse(
|
|
3049
|
+
const parsed = JSON.parse(fs12.readFileSync(pkgJsonPath, "utf8"));
|
|
3049
3050
|
return parsed.snapshot === void 0 ? null : pkgJsonPath;
|
|
3050
3051
|
} catch {
|
|
3051
3052
|
return null;
|
|
@@ -3296,11 +3297,11 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
3296
3297
|
const warnings = [];
|
|
3297
3298
|
const errors = [];
|
|
3298
3299
|
for (const filename of CONFIG_FILENAMES) {
|
|
3299
|
-
const fullPath =
|
|
3300
|
-
if (!
|
|
3300
|
+
const fullPath = path13.join(cwd, filename);
|
|
3301
|
+
if (!fs12.existsSync(fullPath)) continue;
|
|
3301
3302
|
if (filename.endsWith(".json") || filename === ".snapshotrc") {
|
|
3302
3303
|
try {
|
|
3303
|
-
const config = parseJsonish(
|
|
3304
|
+
const config = parseJsonish(fs12.readFileSync(fullPath, "utf8"), fullPath);
|
|
3304
3305
|
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
3305
3306
|
throw new Error(
|
|
3306
3307
|
`${fullPath} does not hold a configuration object (received ${describeValue2(config)}).`
|
|
@@ -3334,10 +3335,10 @@ async function loadConfigFileDetailed(cwd) {
|
|
|
3334
3335
|
continue;
|
|
3335
3336
|
}
|
|
3336
3337
|
}
|
|
3337
|
-
const pkgJsonPath =
|
|
3338
|
-
if (
|
|
3338
|
+
const pkgJsonPath = path13.join(cwd, "package.json");
|
|
3339
|
+
if (fs12.existsSync(pkgJsonPath)) {
|
|
3339
3340
|
try {
|
|
3340
|
-
const parsed = parseJsonish(
|
|
3341
|
+
const parsed = parseJsonish(fs12.readFileSync(pkgJsonPath, "utf8"), pkgJsonPath);
|
|
3341
3342
|
const snapshotKey = parsed.snapshot;
|
|
3342
3343
|
if (snapshotKey && typeof snapshotKey === "object" && !Array.isArray(snapshotKey)) {
|
|
3343
3344
|
return { config: snapshotKey, file: pkgJsonPath, warnings, errors };
|
|
@@ -3360,7 +3361,7 @@ async function loadConfigFile(cwd) {
|
|
|
3360
3361
|
const loaded = await loadConfigFileDetailed(cwd);
|
|
3361
3362
|
if (loaded.config && loaded.file && typeof loaded.config === "object") {
|
|
3362
3363
|
Object.defineProperty(loaded.config, CONFIG_DIR_SYMBOL, {
|
|
3363
|
-
value:
|
|
3364
|
+
value: path13.dirname(loaded.file),
|
|
3364
3365
|
enumerable: false,
|
|
3365
3366
|
configurable: true
|
|
3366
3367
|
});
|
|
@@ -3519,9 +3520,9 @@ function resolveKindRules(value) {
|
|
|
3519
3520
|
function outputExcludePatterns(cwd, outDir, tmpDir) {
|
|
3520
3521
|
const patterns = [];
|
|
3521
3522
|
for (const dir of [outDir, tmpDir]) {
|
|
3522
|
-
const absolute =
|
|
3523
|
-
const relative7 =
|
|
3524
|
-
if (!relative7 || relative7 === ".." || relative7.startsWith(`..${
|
|
3523
|
+
const absolute = path13.resolve(cwd, dir);
|
|
3524
|
+
const relative7 = path13.relative(cwd, absolute);
|
|
3525
|
+
if (!relative7 || relative7 === ".." || relative7.startsWith(`..${path13.sep}`) || path13.isAbsolute(relative7)) {
|
|
3525
3526
|
continue;
|
|
3526
3527
|
}
|
|
3527
3528
|
patterns.push(`${relative7.replace(/\\/g, "/")}/**`);
|
|
@@ -3640,11 +3641,11 @@ function resolveCandidateCwd(userConfig, cliOptions, baseDir) {
|
|
|
3640
3641
|
);
|
|
3641
3642
|
}
|
|
3642
3643
|
const candidate = cliOptions?.cwd || userConfig?.cwd || baseDir || process.cwd();
|
|
3643
|
-
const resolved =
|
|
3644
|
-
if (!
|
|
3644
|
+
const resolved = path13.resolve(candidate);
|
|
3645
|
+
if (!fs12.existsSync(resolved)) {
|
|
3645
3646
|
throw new Error(`Working directory does not exist: ${resolved}`);
|
|
3646
3647
|
}
|
|
3647
|
-
if (!
|
|
3648
|
+
if (!fs12.statSync(resolved).isDirectory()) {
|
|
3648
3649
|
throw new Error(`Working directory is not a directory: ${resolved}`);
|
|
3649
3650
|
}
|
|
3650
3651
|
return resolved;
|
|
@@ -4668,7 +4669,7 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
4668
4669
|
".so"
|
|
4669
4670
|
]);
|
|
4670
4671
|
function isBinaryExtension(filePath) {
|
|
4671
|
-
const ext =
|
|
4672
|
+
const ext = path13.extname(filePath).toLowerCase();
|
|
4672
4673
|
return BINARY_EXTENSIONS.has(ext);
|
|
4673
4674
|
}
|
|
4674
4675
|
function isBinaryBuffer(buffer) {
|
|
@@ -4838,13 +4839,13 @@ function isBinaryFile(absolutePath) {
|
|
|
4838
4839
|
if (isBinaryExtension(absolutePath)) return true;
|
|
4839
4840
|
let fd;
|
|
4840
4841
|
try {
|
|
4841
|
-
fd =
|
|
4842
|
+
fd = fs12.openSync(absolutePath, "r");
|
|
4842
4843
|
const buffer = Buffer.alloc(CHUNK);
|
|
4843
4844
|
let sample;
|
|
4844
4845
|
let position = 0;
|
|
4845
4846
|
while (position < BINARY_SCAN_BYTES) {
|
|
4846
4847
|
const wanted = Math.min(CHUNK, BINARY_SCAN_BYTES - position);
|
|
4847
|
-
const bytesRead =
|
|
4848
|
+
const bytesRead = fs12.readSync(fd, buffer, 0, wanted, position);
|
|
4848
4849
|
if (bytesRead === 0) return false;
|
|
4849
4850
|
const chunk = buffer.subarray(0, bytesRead);
|
|
4850
4851
|
if (sample === void 0) {
|
|
@@ -4862,7 +4863,7 @@ function isBinaryFile(absolutePath) {
|
|
|
4862
4863
|
} finally {
|
|
4863
4864
|
if (fd !== void 0) {
|
|
4864
4865
|
try {
|
|
4865
|
-
|
|
4866
|
+
fs12.closeSync(fd);
|
|
4866
4867
|
} catch {
|
|
4867
4868
|
}
|
|
4868
4869
|
}
|
|
@@ -4922,10 +4923,10 @@ var LANGUAGE_BY_BASENAME = {
|
|
|
4922
4923
|
};
|
|
4923
4924
|
function detectLanguage(filePath) {
|
|
4924
4925
|
const normalized = filePath.replace(/\\/g, "/");
|
|
4925
|
-
const base =
|
|
4926
|
+
const base = path13.posix.basename(normalized);
|
|
4926
4927
|
if (LANGUAGE_BY_BASENAME[base]) return LANGUAGE_BY_BASENAME[base];
|
|
4927
4928
|
if (base === ".env" || base.startsWith(".env.")) return "dotenv";
|
|
4928
|
-
const ext =
|
|
4929
|
+
const ext = path13.posix.extname(base).toLowerCase();
|
|
4929
4930
|
return LANGUAGE_BY_EXTENSION[ext] ?? "text";
|
|
4930
4931
|
}
|
|
4931
4932
|
function maskedPath(value, secretRules) {
|
|
@@ -4933,33 +4934,33 @@ function maskedPath(value, secretRules) {
|
|
|
4933
4934
|
}
|
|
4934
4935
|
function confineToDirectory(directory, filename) {
|
|
4935
4936
|
if (filename.includes("\0")) return null;
|
|
4936
|
-
if (
|
|
4937
|
-
const base =
|
|
4938
|
-
const resolved =
|
|
4937
|
+
if (path13.isAbsolute(filename)) return null;
|
|
4938
|
+
const base = path13.resolve(directory);
|
|
4939
|
+
const resolved = path13.resolve(base, filename);
|
|
4939
4940
|
const caseInsensitive = process.platform === "win32" || process.platform === "darwin";
|
|
4940
|
-
const prefix = caseInsensitive ? `${base}${
|
|
4941
|
+
const prefix = caseInsensitive ? `${base}${path13.sep}`.toLowerCase() : `${base}${path13.sep}`;
|
|
4941
4942
|
const candidate = caseInsensitive ? resolved.toLowerCase() : resolved;
|
|
4942
4943
|
return candidate.startsWith(prefix) ? resolved : null;
|
|
4943
4944
|
}
|
|
4944
4945
|
function findStagingDirectory(config) {
|
|
4945
|
-
const tmpDir =
|
|
4946
|
+
const tmpDir = path13.resolve(config.cwd, config.tmpDir);
|
|
4946
4947
|
let entries;
|
|
4947
4948
|
try {
|
|
4948
|
-
entries =
|
|
4949
|
+
entries = fs12.readdirSync(tmpDir);
|
|
4949
4950
|
} catch {
|
|
4950
4951
|
return null;
|
|
4951
4952
|
}
|
|
4952
4953
|
const runs = entries.filter((name) => name.startsWith("run-")).sort();
|
|
4953
4954
|
const newest = runs[runs.length - 1];
|
|
4954
|
-
return newest ?
|
|
4955
|
+
return newest ? path13.join(tmpDir, newest) : null;
|
|
4955
4956
|
}
|
|
4956
4957
|
function describeMissingManifest(config, manifestPath) {
|
|
4957
|
-
const outDir =
|
|
4958
|
-
const markerPath =
|
|
4958
|
+
const outDir = path13.resolve(config.cwd, config.outDir);
|
|
4959
|
+
const markerPath = path13.join(outDir, ".codebase-snapshot");
|
|
4959
4960
|
let marker2 = null;
|
|
4960
4961
|
try {
|
|
4961
|
-
if (
|
|
4962
|
-
const parsed = JSON.parse(
|
|
4962
|
+
if (fs12.existsSync(markerPath)) {
|
|
4963
|
+
const parsed = JSON.parse(fs12.readFileSync(markerPath, "utf8"));
|
|
4963
4964
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
4964
4965
|
marker2 = parsed;
|
|
4965
4966
|
}
|
|
@@ -4995,14 +4996,14 @@ function sha256Hex(buffer) {
|
|
|
4995
4996
|
}
|
|
4996
4997
|
var VERIFY_SNIFF_MAX_BYTES = 8 * 1024 * 1024;
|
|
4997
4998
|
function wouldNowBeIncluded(cwd, relativePath, reason) {
|
|
4998
|
-
const absolutePath =
|
|
4999
|
+
const absolutePath = path13.join(cwd, relativePath);
|
|
4999
5000
|
try {
|
|
5000
|
-
const stats =
|
|
5001
|
+
const stats = fs12.statSync(absolutePath);
|
|
5001
5002
|
if (!stats.isFile()) return false;
|
|
5002
5003
|
if (isBinaryFile(absolutePath)) return false;
|
|
5003
5004
|
if (reason !== "binary") return true;
|
|
5004
5005
|
if (stats.size > VERIFY_SNIFF_MAX_BYTES) return false;
|
|
5005
|
-
return !decodeText(
|
|
5006
|
+
return !decodeText(fs12.readFileSync(absolutePath)).binary;
|
|
5006
5007
|
} catch {
|
|
5007
5008
|
return false;
|
|
5008
5009
|
}
|
|
@@ -5060,8 +5061,8 @@ function describeManifestShapeProblem(value) {
|
|
|
5060
5061
|
function validateSnapshot(configInput) {
|
|
5061
5062
|
assertUsableConfigInput(configInput);
|
|
5062
5063
|
const config = isResolvedConfig(configInput) ? normalizeResolvedConfig(configInput) : resolveConfig(configInput);
|
|
5063
|
-
const manifestPath =
|
|
5064
|
-
if (!
|
|
5064
|
+
const manifestPath = path13.resolve(config.cwd, config.outDir, "manifest.json");
|
|
5065
|
+
if (!fs12.existsSync(manifestPath)) {
|
|
5065
5066
|
return {
|
|
5066
5067
|
valid: false,
|
|
5067
5068
|
manifestPresent: false,
|
|
@@ -5072,7 +5073,7 @@ function validateSnapshot(configInput) {
|
|
|
5072
5073
|
}
|
|
5073
5074
|
let manifest;
|
|
5074
5075
|
try {
|
|
5075
|
-
manifest = JSON.parse(
|
|
5076
|
+
manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf8"));
|
|
5076
5077
|
} catch (err) {
|
|
5077
5078
|
return {
|
|
5078
5079
|
valid: false,
|
|
@@ -5094,7 +5095,7 @@ function validateSnapshot(configInput) {
|
|
|
5094
5095
|
}
|
|
5095
5096
|
const drift = emptyDrift();
|
|
5096
5097
|
const warnings = [];
|
|
5097
|
-
const snapshotDir =
|
|
5098
|
+
const snapshotDir = path13.resolve(config.cwd, config.outDir);
|
|
5098
5099
|
const manifestFileMap = /* @__PURE__ */ new Map();
|
|
5099
5100
|
for (const file of manifest.files) {
|
|
5100
5101
|
if (file && typeof file.relativePath === "string") {
|
|
@@ -5128,7 +5129,7 @@ function validateSnapshot(configInput) {
|
|
|
5128
5129
|
}
|
|
5129
5130
|
let diskHash;
|
|
5130
5131
|
try {
|
|
5131
|
-
diskHash = sha256Hex(
|
|
5132
|
+
diskHash = sha256Hex(fs12.readFileSync(path13.join(config.cwd, diskFile)));
|
|
5132
5133
|
} catch (err) {
|
|
5133
5134
|
if (err.code === "ENOENT") {
|
|
5134
5135
|
drift.missingOnDisk.push(diskFile);
|
|
@@ -5152,7 +5153,7 @@ function validateSnapshot(configInput) {
|
|
|
5152
5153
|
}
|
|
5153
5154
|
let statFailure = null;
|
|
5154
5155
|
try {
|
|
5155
|
-
|
|
5156
|
+
fs12.statSync(confined);
|
|
5156
5157
|
} catch (err) {
|
|
5157
5158
|
statFailure = err;
|
|
5158
5159
|
}
|
|
@@ -5172,7 +5173,7 @@ function validateSnapshot(configInput) {
|
|
|
5172
5173
|
...Object.values(config.budgets.byLayer)
|
|
5173
5174
|
);
|
|
5174
5175
|
const partNames = /* @__PURE__ */ new Set();
|
|
5175
|
-
const partsDir =
|
|
5176
|
+
const partsDir = path13.join(snapshotDir, "parts");
|
|
5176
5177
|
for (const part of manifest.parts) {
|
|
5177
5178
|
if (!part || typeof part.filename !== "string") continue;
|
|
5178
5179
|
partNames.add(part.filename);
|
|
@@ -5187,7 +5188,7 @@ function validateSnapshot(configInput) {
|
|
|
5187
5188
|
}
|
|
5188
5189
|
let buffer;
|
|
5189
5190
|
try {
|
|
5190
|
-
buffer =
|
|
5191
|
+
buffer = fs12.readFileSync(partPath);
|
|
5191
5192
|
} catch {
|
|
5192
5193
|
drift.partIssues.push({ part: part.filename, issue: "missing from snapshot/parts" });
|
|
5193
5194
|
continue;
|
|
@@ -5401,9 +5402,9 @@ function validateSnapshot(configInput) {
|
|
|
5401
5402
|
["full-codebase.md", manifest.artifacts?.fullMarkdown]
|
|
5402
5403
|
]) {
|
|
5403
5404
|
if (!artifact) continue;
|
|
5404
|
-
const artifactPath =
|
|
5405
|
+
const artifactPath = path13.join(snapshotDir, key);
|
|
5405
5406
|
try {
|
|
5406
|
-
const buffer =
|
|
5407
|
+
const buffer = fs12.readFileSync(artifactPath);
|
|
5407
5408
|
if (sha256Hex(buffer) !== artifact.sha256 || buffer.length !== artifact.byteSize) {
|
|
5408
5409
|
drift.partIssues.push({ part: key, issue: "artifact does not match its recorded digest" });
|
|
5409
5410
|
}
|
|
@@ -5473,12 +5474,168 @@ function validateSnapshot(configInput) {
|
|
|
5473
5474
|
|
|
5474
5475
|
// src/version.ts
|
|
5475
5476
|
var GENERATOR_NAME = "codebase-snapshot";
|
|
5476
|
-
var GENERATOR_VERSION = "0.9.
|
|
5477
|
+
var GENERATOR_VERSION = "0.9.6";
|
|
5477
5478
|
var LEGACY_GENERATOR_NAMES = ["@ankurhalder/codebase-snapshot"];
|
|
5478
5479
|
function isOurGeneratorName(name) {
|
|
5479
5480
|
if (typeof name !== "string") return false;
|
|
5480
5481
|
return name === GENERATOR_NAME || LEGACY_GENERATOR_NAMES.includes(name);
|
|
5481
5482
|
}
|
|
5483
|
+
var PACKAGE_LATEST_URL = "https://registry.npmjs.org/codebase-snapshot/latest";
|
|
5484
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
5485
|
+
var FAILURE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
5486
|
+
var REQUEST_TIMEOUT_MS = 1200;
|
|
5487
|
+
function versionParts(value) {
|
|
5488
|
+
const core = value.trim().replace(/^v/i, "").split("-")[0];
|
|
5489
|
+
return core.split(".").map((part) => {
|
|
5490
|
+
const parsed = Number(part);
|
|
5491
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
5492
|
+
});
|
|
5493
|
+
}
|
|
5494
|
+
function isNewer(candidate, current) {
|
|
5495
|
+
const left = versionParts(candidate);
|
|
5496
|
+
const right = versionParts(current);
|
|
5497
|
+
const length = Math.max(left.length, right.length);
|
|
5498
|
+
for (let index = 0; index < length; index += 1) {
|
|
5499
|
+
const a = left[index] ?? 0;
|
|
5500
|
+
const b = right[index] ?? 0;
|
|
5501
|
+
if (a !== b) return a > b;
|
|
5502
|
+
}
|
|
5503
|
+
return false;
|
|
5504
|
+
}
|
|
5505
|
+
function cacheDirectory(env = process.env, platform = process.platform) {
|
|
5506
|
+
if (platform === "win32") {
|
|
5507
|
+
const base2 = env.LOCALAPPDATA ?? path13.join(os.homedir(), "AppData", "Local");
|
|
5508
|
+
return path13.join(base2, "codebase-snapshot");
|
|
5509
|
+
}
|
|
5510
|
+
if (platform === "darwin") {
|
|
5511
|
+
return path13.join(os.homedir(), "Library", "Caches", "codebase-snapshot");
|
|
5512
|
+
}
|
|
5513
|
+
const base = env.XDG_CACHE_HOME ?? path13.join(os.homedir(), ".cache");
|
|
5514
|
+
return path13.join(base, "codebase-snapshot");
|
|
5515
|
+
}
|
|
5516
|
+
function cacheFilePath(env = process.env) {
|
|
5517
|
+
return path13.join(cacheDirectory(env), "update-check.json");
|
|
5518
|
+
}
|
|
5519
|
+
function shouldCheck(argv, env) {
|
|
5520
|
+
const disabled = ["1", "true", "yes"].includes(
|
|
5521
|
+
String(env.CODEBASE_SNAPSHOT_NO_UPDATE_CHECK ?? "").toLowerCase()
|
|
5522
|
+
);
|
|
5523
|
+
if (disabled) return false;
|
|
5524
|
+
if (env.CI !== void 0 && env.CI !== "" && env.CI !== "false" && env.CI !== "0") return false;
|
|
5525
|
+
const args = argv.map((argument) => argument.toLowerCase());
|
|
5526
|
+
if (args.includes("--no-update-check")) return false;
|
|
5527
|
+
for (const skip of ["mcp", "describe", "skill", "--version", "-v", "--help", "-h"]) {
|
|
5528
|
+
if (args.includes(skip)) return false;
|
|
5529
|
+
}
|
|
5530
|
+
if (args.some((argument) => argument.includes("json"))) return false;
|
|
5531
|
+
return true;
|
|
5532
|
+
}
|
|
5533
|
+
function readCache(file) {
|
|
5534
|
+
let raw;
|
|
5535
|
+
try {
|
|
5536
|
+
raw = fs12.readFileSync(file, "utf8");
|
|
5537
|
+
} catch {
|
|
5538
|
+
return null;
|
|
5539
|
+
}
|
|
5540
|
+
try {
|
|
5541
|
+
const parsed = JSON.parse(raw);
|
|
5542
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
5543
|
+
const candidate = parsed;
|
|
5544
|
+
if (typeof candidate.checkedAt !== "number") return null;
|
|
5545
|
+
const latest = typeof candidate.latest === "string" ? candidate.latest : null;
|
|
5546
|
+
return { checkedAt: candidate.checkedAt, latest };
|
|
5547
|
+
} catch {
|
|
5548
|
+
return null;
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
function writeCache(file, entry) {
|
|
5552
|
+
try {
|
|
5553
|
+
fs12.mkdirSync(path13.dirname(file), { recursive: true });
|
|
5554
|
+
fs12.writeFileSync(file, `${JSON.stringify(entry)}
|
|
5555
|
+
`, "utf8");
|
|
5556
|
+
} catch {
|
|
5557
|
+
}
|
|
5558
|
+
}
|
|
5559
|
+
function fetchLatestVersion(url = PACKAGE_LATEST_URL, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
5560
|
+
return new Promise((resolve5) => {
|
|
5561
|
+
let settled = false;
|
|
5562
|
+
const finish = (value) => {
|
|
5563
|
+
if (settled) return;
|
|
5564
|
+
settled = true;
|
|
5565
|
+
resolve5(value);
|
|
5566
|
+
};
|
|
5567
|
+
const request = https.get(
|
|
5568
|
+
url,
|
|
5569
|
+
{
|
|
5570
|
+
headers: {
|
|
5571
|
+
accept: "application/json",
|
|
5572
|
+
"user-agent": "codebase-snapshot (update check)"
|
|
5573
|
+
}
|
|
5574
|
+
},
|
|
5575
|
+
(response) => {
|
|
5576
|
+
if (response.statusCode !== 200) {
|
|
5577
|
+
response.resume();
|
|
5578
|
+
finish(null);
|
|
5579
|
+
return;
|
|
5580
|
+
}
|
|
5581
|
+
let body = "";
|
|
5582
|
+
response.setEncoding("utf8");
|
|
5583
|
+
response.on("data", (chunk) => {
|
|
5584
|
+
body += chunk;
|
|
5585
|
+
if (body.length > 64 * 1024) {
|
|
5586
|
+
request.destroy();
|
|
5587
|
+
finish(null);
|
|
5588
|
+
}
|
|
5589
|
+
});
|
|
5590
|
+
response.on("end", () => {
|
|
5591
|
+
try {
|
|
5592
|
+
const parsed = JSON.parse(body);
|
|
5593
|
+
finish(typeof parsed.version === "string" ? parsed.version : null);
|
|
5594
|
+
} catch {
|
|
5595
|
+
finish(null);
|
|
5596
|
+
}
|
|
5597
|
+
});
|
|
5598
|
+
}
|
|
5599
|
+
);
|
|
5600
|
+
request.on("error", () => finish(null));
|
|
5601
|
+
request.setTimeout(timeoutMs, () => {
|
|
5602
|
+
request.destroy();
|
|
5603
|
+
finish(null);
|
|
5604
|
+
});
|
|
5605
|
+
});
|
|
5606
|
+
}
|
|
5607
|
+
async function checkForUpdate(options) {
|
|
5608
|
+
if (options.enabled === false) return null;
|
|
5609
|
+
const now = options.now ?? (() => Date.now());
|
|
5610
|
+
const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
|
|
5611
|
+
let latest = null;
|
|
5612
|
+
try {
|
|
5613
|
+
const cached = readCache(options.cacheFile);
|
|
5614
|
+
let needsFetch = cached === null;
|
|
5615
|
+
if (cached) {
|
|
5616
|
+
const age = now() - cached.checkedAt;
|
|
5617
|
+
if (cached.latest === null) {
|
|
5618
|
+
needsFetch = age >= FAILURE_INTERVAL_MS;
|
|
5619
|
+
} else {
|
|
5620
|
+
latest = cached.latest;
|
|
5621
|
+
needsFetch = age >= CHECK_INTERVAL_MS;
|
|
5622
|
+
}
|
|
5623
|
+
}
|
|
5624
|
+
if (needsFetch) {
|
|
5625
|
+
const fetched = await fetchLatest(PACKAGE_LATEST_URL, REQUEST_TIMEOUT_MS);
|
|
5626
|
+
writeCache(options.cacheFile, { checkedAt: now(), latest: fetched });
|
|
5627
|
+
latest = fetched;
|
|
5628
|
+
}
|
|
5629
|
+
} catch {
|
|
5630
|
+
return null;
|
|
5631
|
+
}
|
|
5632
|
+
if (!latest) return null;
|
|
5633
|
+
return isNewer(latest, options.current) ? { current: options.current, latest } : null;
|
|
5634
|
+
}
|
|
5635
|
+
function formatUpdateNotice(notice) {
|
|
5636
|
+
return `\u2191 codebase-snapshot ${notice.latest} is available \u2014 you have ${notice.current}.
|
|
5637
|
+
npm install -g codebase-snapshot`;
|
|
5638
|
+
}
|
|
5482
5639
|
function describeMatcher(matcher) {
|
|
5483
5640
|
if (typeof matcher === "string") return matcher;
|
|
5484
5641
|
if (matcher instanceof RegExp) return String(matcher);
|
|
@@ -5488,10 +5645,10 @@ function describeMatcher(matcher) {
|
|
|
5488
5645
|
return String(matcher);
|
|
5489
5646
|
}
|
|
5490
5647
|
function normalizeTarget(cwd, target) {
|
|
5491
|
-
const absolute =
|
|
5492
|
-
const relative7 =
|
|
5493
|
-
if (relative7.startsWith("..") ||
|
|
5494
|
-
return relative7.split(
|
|
5648
|
+
const absolute = path13.resolve(cwd, target);
|
|
5649
|
+
const relative7 = path13.relative(cwd, absolute);
|
|
5650
|
+
if (relative7.startsWith("..") || path13.isAbsolute(relative7)) return target;
|
|
5651
|
+
return relative7.split(path13.sep).join("/");
|
|
5495
5652
|
}
|
|
5496
5653
|
function findRuleMatch(rules, relativePath) {
|
|
5497
5654
|
return rules.find(
|
|
@@ -5510,20 +5667,20 @@ function findRecordedAncestor(skipped, relative7, maskedPath2) {
|
|
|
5510
5667
|
return nearest;
|
|
5511
5668
|
}
|
|
5512
5669
|
function readManifest2(config) {
|
|
5513
|
-
const manifestPath =
|
|
5670
|
+
const manifestPath = path13.resolve(config.cwd, config.outDir, "manifest.json");
|
|
5514
5671
|
try {
|
|
5515
|
-
return JSON.parse(
|
|
5672
|
+
return JSON.parse(fs12.readFileSync(manifestPath, "utf8"));
|
|
5516
5673
|
} catch {
|
|
5517
5674
|
return null;
|
|
5518
5675
|
}
|
|
5519
5676
|
}
|
|
5520
5677
|
function explainPath(config, target) {
|
|
5521
5678
|
const relative7 = normalizeTarget(config.cwd, target);
|
|
5522
|
-
const absolute =
|
|
5679
|
+
const absolute = path13.join(config.cwd, relative7);
|
|
5523
5680
|
const maskedPath2 = findSecretInPath(relative7, config.secretRules)?.masked ?? relative7;
|
|
5524
5681
|
const result = {
|
|
5525
5682
|
path: maskedPath2,
|
|
5526
|
-
exists:
|
|
5683
|
+
exists: fs12.existsSync(absolute),
|
|
5527
5684
|
included: false
|
|
5528
5685
|
};
|
|
5529
5686
|
const collection = collectFiles(config.cwd, {
|
|
@@ -5534,7 +5691,7 @@ function explainPath(config, target) {
|
|
|
5534
5691
|
// Same exclusion `generate` applies, so `explain` never says "not-discovered" about a file
|
|
5535
5692
|
// that is only missing because the walker dropped the tool's own output directory.
|
|
5536
5693
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
5537
|
-
(directory) =>
|
|
5694
|
+
(directory) => path13.relative(config.cwd, path13.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
5538
5695
|
).filter((relative8) => relative8.length > 0 && !relative8.startsWith(".."))
|
|
5539
5696
|
});
|
|
5540
5697
|
if (!collection.files.includes(relative7)) {
|
|
@@ -5573,8 +5730,8 @@ function explainPath(config, target) {
|
|
|
5573
5730
|
if (layerRule) result.layerMatch = describeMatcher(layerRule.match);
|
|
5574
5731
|
const kindRule = findRuleMatch(config.kinds, relative7);
|
|
5575
5732
|
if (kindRule) result.kindMatch = describeMatcher(kindRule.match);
|
|
5576
|
-
if (
|
|
5577
|
-
const buffer =
|
|
5733
|
+
if (fs12.existsSync(absolute) && fs12.statSync(absolute).isFile()) {
|
|
5734
|
+
const buffer = fs12.readFileSync(absolute);
|
|
5578
5735
|
const decoded = decodeText(buffer);
|
|
5579
5736
|
if (decoded.binary) {
|
|
5580
5737
|
result.included = false;
|
|
@@ -5822,14 +5979,14 @@ function compareManifests(before, after) {
|
|
|
5822
5979
|
function loadManifest(target) {
|
|
5823
5980
|
let isDirectory;
|
|
5824
5981
|
try {
|
|
5825
|
-
isDirectory =
|
|
5982
|
+
isDirectory = fs12.statSync(target).isDirectory();
|
|
5826
5983
|
} catch {
|
|
5827
5984
|
throw new Error(`No snapshot found at ${target}: the path does not exist.`);
|
|
5828
5985
|
}
|
|
5829
|
-
const manifestPath = isDirectory ?
|
|
5986
|
+
const manifestPath = isDirectory ? path13.join(target, "manifest.json") : target;
|
|
5830
5987
|
let raw;
|
|
5831
5988
|
try {
|
|
5832
|
-
raw =
|
|
5989
|
+
raw = fs12.readFileSync(manifestPath, "utf8");
|
|
5833
5990
|
} catch {
|
|
5834
5991
|
throw new Error(`Could not read a manifest at ${manifestPath}.`);
|
|
5835
5992
|
}
|
|
@@ -5886,15 +6043,15 @@ function renderDiffText(diff) {
|
|
|
5886
6043
|
function appendGitignoreEntries(cwd, entries) {
|
|
5887
6044
|
const wanted = [...new Set(entries)].filter((entry) => entry.trim().length > 0);
|
|
5888
6045
|
if (wanted.length === 0) return { added: [], note: null };
|
|
5889
|
-
const ignorePath =
|
|
6046
|
+
const ignorePath = path13.join(cwd, ".gitignore");
|
|
5890
6047
|
const manual = `Add ${wanted.map((entry) => `"${entry}"`).join(" and ")} to your .gitignore yourself.`;
|
|
5891
6048
|
let existing = "";
|
|
5892
6049
|
try {
|
|
5893
|
-
if (
|
|
5894
|
-
if (
|
|
6050
|
+
if (fs12.existsSync(ignorePath)) {
|
|
6051
|
+
if (fs12.statSync(ignorePath).isDirectory()) {
|
|
5895
6052
|
return { added: [], note: `${ignorePath} is a directory, so it was not updated. ${manual}` };
|
|
5896
6053
|
}
|
|
5897
|
-
existing =
|
|
6054
|
+
existing = fs12.readFileSync(ignorePath, "utf8");
|
|
5898
6055
|
}
|
|
5899
6056
|
} catch (err) {
|
|
5900
6057
|
return {
|
|
@@ -5907,7 +6064,7 @@ function appendGitignoreEntries(cwd, entries) {
|
|
|
5907
6064
|
if (added.length === 0) return { added: [], note: null };
|
|
5908
6065
|
const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
5909
6066
|
try {
|
|
5910
|
-
|
|
6067
|
+
fs12.writeFileSync(ignorePath, `${existing}${prefix}${added.join("\n")}
|
|
5911
6068
|
`, "utf8");
|
|
5912
6069
|
} catch (err) {
|
|
5913
6070
|
return { added: [], note: `${err.message}. ${manual}` };
|
|
@@ -5915,7 +6072,7 @@ function appendGitignoreEntries(cwd, entries) {
|
|
|
5915
6072
|
return { added, note: null };
|
|
5916
6073
|
}
|
|
5917
6074
|
function gitignorePath(cwd, filePath) {
|
|
5918
|
-
return
|
|
6075
|
+
return path13.relative(cwd, filePath).split(path13.sep).join("/");
|
|
5919
6076
|
}
|
|
5920
6077
|
|
|
5921
6078
|
// src/wizard/config-template.ts
|
|
@@ -6337,10 +6494,10 @@ var CONFIG_CANDIDATES = [
|
|
|
6337
6494
|
];
|
|
6338
6495
|
function chooseConfigFileName(cwd) {
|
|
6339
6496
|
if (!supportsTypeScriptImports()) return "snapshot.config.mjs";
|
|
6340
|
-
const pkgPath =
|
|
6341
|
-
if (!
|
|
6497
|
+
const pkgPath = path13.join(cwd, "package.json");
|
|
6498
|
+
if (!fs12.existsSync(pkgPath)) return "snapshot.config.mjs";
|
|
6342
6499
|
try {
|
|
6343
|
-
const parsed = JSON.parse(
|
|
6500
|
+
const parsed = JSON.parse(fs12.readFileSync(pkgPath, "utf8"));
|
|
6344
6501
|
return parsed.type === "module" ? "snapshot.config.ts" : "snapshot.config.mjs";
|
|
6345
6502
|
} catch {
|
|
6346
6503
|
return "snapshot.config.mjs";
|
|
@@ -6354,7 +6511,7 @@ var SIZE_CHOICES = [
|
|
|
6354
6511
|
];
|
|
6355
6512
|
function packageJsonHasConfig(cwd) {
|
|
6356
6513
|
try {
|
|
6357
|
-
const parsed = JSON.parse(
|
|
6514
|
+
const parsed = JSON.parse(fs12.readFileSync(path13.join(cwd, "package.json"), "utf8"));
|
|
6358
6515
|
return typeof parsed.snapshot === "object" && parsed.snapshot !== null && !Array.isArray(parsed.snapshot);
|
|
6359
6516
|
} catch {
|
|
6360
6517
|
return false;
|
|
@@ -6375,7 +6532,7 @@ function artifactAnswers(options) {
|
|
|
6375
6532
|
}
|
|
6376
6533
|
function topLevelDirs(cwd) {
|
|
6377
6534
|
try {
|
|
6378
|
-
return
|
|
6535
|
+
return fs12.readdirSync(cwd, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules").map((entry) => entry.name).sort();
|
|
6379
6536
|
} catch {
|
|
6380
6537
|
return [];
|
|
6381
6538
|
}
|
|
@@ -6388,7 +6545,7 @@ function describeJsonValue(value) {
|
|
|
6388
6545
|
}
|
|
6389
6546
|
function writeFileOrExplain(target, content) {
|
|
6390
6547
|
try {
|
|
6391
|
-
|
|
6548
|
+
fs12.writeFileSync(target, content, "utf8");
|
|
6392
6549
|
} catch (err) {
|
|
6393
6550
|
const code = err.code;
|
|
6394
6551
|
const reason = code === "EACCES" || code === "EPERM" || code === "EROFS" ? `permission denied (${code})` : code === "EISDIR" ? "it is a directory" : `${err.message}`;
|
|
@@ -6399,7 +6556,7 @@ function canWriteModuleConfig(name, cwd) {
|
|
|
6399
6556
|
if (name.endsWith(".mjs") || name.endsWith(".ts")) return true;
|
|
6400
6557
|
if (!name.endsWith(".js")) return false;
|
|
6401
6558
|
try {
|
|
6402
|
-
const parsed = JSON.parse(
|
|
6559
|
+
const parsed = JSON.parse(fs12.readFileSync(path13.join(cwd, "package.json"), "utf8"));
|
|
6403
6560
|
return parsed.type === "module";
|
|
6404
6561
|
} catch {
|
|
6405
6562
|
return false;
|
|
@@ -6434,19 +6591,19 @@ function serializePackageJson(raw, value) {
|
|
|
6434
6591
|
return `${text2}${raw.endsWith("\n") ? crlf ? "\r\n" : "\n" : ""}`;
|
|
6435
6592
|
}
|
|
6436
6593
|
function updatePackageJson(cwd, notes) {
|
|
6437
|
-
const packagePath =
|
|
6594
|
+
const packagePath = path13.join(cwd, "package.json");
|
|
6438
6595
|
const unchanged = {
|
|
6439
6596
|
scripts: [],
|
|
6440
6597
|
dependency: { name: GENERATOR_NAME, range: null, added: false }
|
|
6441
6598
|
};
|
|
6442
|
-
if (!
|
|
6599
|
+
if (!fs12.existsSync(packagePath)) {
|
|
6443
6600
|
notes.push("No package.json found, so npm scripts and the devDependency were not added.");
|
|
6444
6601
|
return unchanged;
|
|
6445
6602
|
}
|
|
6446
6603
|
let raw;
|
|
6447
6604
|
let parsed;
|
|
6448
6605
|
try {
|
|
6449
|
-
raw =
|
|
6606
|
+
raw = fs12.readFileSync(packagePath, "utf8");
|
|
6450
6607
|
parsed = JSON.parse(raw);
|
|
6451
6608
|
} catch {
|
|
6452
6609
|
notes.push("Could not parse package.json; npm scripts and the devDependency were not added.");
|
|
@@ -6738,7 +6895,7 @@ async function runInit(options) {
|
|
|
6738
6895
|
const configText = renderConfig(answers);
|
|
6739
6896
|
const preferredName = chooseConfigFileName(options.cwd);
|
|
6740
6897
|
const presentConfigs = CONFIG_CANDIDATES.filter(
|
|
6741
|
-
(name) =>
|
|
6898
|
+
(name) => fs12.existsSync(path13.join(options.cwd, name))
|
|
6742
6899
|
);
|
|
6743
6900
|
const present = presentConfigs[0] ?? null;
|
|
6744
6901
|
if (presentConfigs.length > 1) {
|
|
@@ -6747,7 +6904,7 @@ async function runInit(options) {
|
|
|
6747
6904
|
);
|
|
6748
6905
|
}
|
|
6749
6906
|
const configName = present !== null && options.force ? present : preferredName;
|
|
6750
|
-
const configPath =
|
|
6907
|
+
const configPath = path13.join(options.cwd, configName);
|
|
6751
6908
|
const reused = present !== null && options.force !== true && options.reuseConfig === true;
|
|
6752
6909
|
if (reused) notes.push(`Kept the existing ${present} instead of writing a new one.`);
|
|
6753
6910
|
if (options.dryRun) {
|
|
@@ -6780,7 +6937,7 @@ async function runInit(options) {
|
|
|
6780
6937
|
'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.'
|
|
6781
6938
|
);
|
|
6782
6939
|
}
|
|
6783
|
-
if (
|
|
6940
|
+
if (fs12.existsSync(configPath) && !options.force && !reused) {
|
|
6784
6941
|
throw new Error(`${configName} already exists. Re-run with --force to replace it.`);
|
|
6785
6942
|
}
|
|
6786
6943
|
if (!reused) writeFileOrExplain(configPath, configText);
|
|
@@ -6802,9 +6959,9 @@ async function runInit(options) {
|
|
|
6802
6959
|
};
|
|
6803
6960
|
}
|
|
6804
6961
|
function describeTarget(cwd) {
|
|
6805
|
-
const relative7 =
|
|
6962
|
+
const relative7 = path13.relative(process.cwd(), cwd);
|
|
6806
6963
|
if (relative7 === "") return "this directory";
|
|
6807
|
-
if (relative7.startsWith("..") ||
|
|
6964
|
+
if (relative7.startsWith("..") || path13.isAbsolute(relative7)) return cwd;
|
|
6808
6965
|
return relative7;
|
|
6809
6966
|
}
|
|
6810
6967
|
function firstRunMessage(reason, cwd) {
|
|
@@ -6828,7 +6985,7 @@ function planFirstRun(facts) {
|
|
|
6828
6985
|
var NOT_CONTENT = /* @__PURE__ */ new Set([".git", ".hg", ".svn", ".bzr", ".DS_Store", "Thumbs.db"]);
|
|
6829
6986
|
function isEffectivelyEmpty(cwd) {
|
|
6830
6987
|
try {
|
|
6831
|
-
return
|
|
6988
|
+
return fs12.readdirSync(cwd).every((entry) => NOT_CONTENT.has(entry));
|
|
6832
6989
|
} catch {
|
|
6833
6990
|
return false;
|
|
6834
6991
|
}
|
|
@@ -6836,7 +6993,7 @@ function isEffectivelyEmpty(cwd) {
|
|
|
6836
6993
|
function hasPriorSnapshot(cwd, outDir) {
|
|
6837
6994
|
let parsed;
|
|
6838
6995
|
try {
|
|
6839
|
-
parsed = JSON.parse(
|
|
6996
|
+
parsed = JSON.parse(fs12.readFileSync(path13.join(cwd, outDir, ".codebase-snapshot"), "utf8"));
|
|
6840
6997
|
} catch {
|
|
6841
6998
|
return false;
|
|
6842
6999
|
}
|
|
@@ -6924,13 +7081,13 @@ function buildImportResolver(files) {
|
|
|
6924
7081
|
const relativePath = file.relativePath;
|
|
6925
7082
|
remember(byPath, relativePath, relativePath);
|
|
6926
7083
|
remember(byPathFolded, relativePath.toLowerCase(), relativePath);
|
|
6927
|
-
const extension =
|
|
7084
|
+
const extension = path13.posix.extname(relativePath);
|
|
6928
7085
|
if (!SOURCE_EXTENSIONS.has(extension)) continue;
|
|
6929
7086
|
const stem = relativePath.slice(0, -extension.length);
|
|
6930
7087
|
remember(byStem, stem, relativePath);
|
|
6931
7088
|
remember(byStemFolded, stem.toLowerCase(), relativePath);
|
|
6932
|
-
if (
|
|
6933
|
-
const directory =
|
|
7089
|
+
if (path13.posix.basename(stem) === "index") {
|
|
7090
|
+
const directory = path13.posix.dirname(stem);
|
|
6934
7091
|
remember(byStem, directory, relativePath);
|
|
6935
7092
|
remember(byStemFolded, directory.toLowerCase(), relativePath);
|
|
6936
7093
|
}
|
|
@@ -6939,8 +7096,8 @@ function buildImportResolver(files) {
|
|
|
6939
7096
|
}
|
|
6940
7097
|
function resolveSpecifier(fromFile, specifier, resolver) {
|
|
6941
7098
|
if (!RELATIVE_SPECIFIER.test(specifier)) return null;
|
|
6942
|
-
const joined =
|
|
6943
|
-
|
|
7099
|
+
const joined = path13.posix.normalize(
|
|
7100
|
+
path13.posix.join(path13.posix.dirname(fromFile), specifier)
|
|
6944
7101
|
);
|
|
6945
7102
|
const exact = (key) => resolver.byPath.get(key) ?? resolver.byPathFolded.get(key.toLowerCase()) ?? null;
|
|
6946
7103
|
const direct = exact(joined);
|
|
@@ -7033,11 +7190,11 @@ function verifyInMemory(files, parts, maxPartBytes) {
|
|
|
7033
7190
|
return errors;
|
|
7034
7191
|
}
|
|
7035
7192
|
function resolveSafeOutputDirs(config) {
|
|
7036
|
-
const cwd =
|
|
7037
|
-
const outDir =
|
|
7038
|
-
const tmpDir =
|
|
7039
|
-
const root =
|
|
7040
|
-
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${
|
|
7193
|
+
const cwd = path13.resolve(config.cwd);
|
|
7194
|
+
const outDir = path13.resolve(cwd, config.outDir);
|
|
7195
|
+
const tmpDir = path13.resolve(cwd, config.tmpDir);
|
|
7196
|
+
const root = path13.parse(cwd).root;
|
|
7197
|
+
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path13.sep}`);
|
|
7041
7198
|
const reject = (reason) => {
|
|
7042
7199
|
throw new Error(
|
|
7043
7200
|
`Refusing to generate: ${reason}. outDir=${outDir} tmpDir=${tmpDir} cwd=${cwd}`
|
|
@@ -7093,14 +7250,14 @@ function listEntries(dir) {
|
|
|
7093
7250
|
const walk = (absolute, prefix) => {
|
|
7094
7251
|
let children;
|
|
7095
7252
|
try {
|
|
7096
|
-
children =
|
|
7253
|
+
children = fs12.readdirSync(absolute, { withFileTypes: true });
|
|
7097
7254
|
} catch {
|
|
7098
7255
|
return;
|
|
7099
7256
|
}
|
|
7100
7257
|
for (const child of children) {
|
|
7101
7258
|
const relative7 = prefix === "" ? child.name : `${prefix}/${child.name}`;
|
|
7102
7259
|
entries.push(relative7);
|
|
7103
|
-
if (child.isDirectory()) walk(
|
|
7260
|
+
if (child.isDirectory()) walk(path13.join(absolute, child.name), relative7);
|
|
7104
7261
|
}
|
|
7105
7262
|
};
|
|
7106
7263
|
walk(dir, "");
|
|
@@ -7117,28 +7274,28 @@ function markerPayload(dir, state, id, createdAt) {
|
|
|
7117
7274
|
pid: process.pid,
|
|
7118
7275
|
entries: listEntries(dir)
|
|
7119
7276
|
};
|
|
7120
|
-
const manifestPath =
|
|
7121
|
-
if (
|
|
7122
|
-
marker2.manifestSha256 = sha256Hex2(
|
|
7277
|
+
const manifestPath = path13.join(dir, "manifest.json");
|
|
7278
|
+
if (fs12.existsSync(manifestPath)) {
|
|
7279
|
+
marker2.manifestSha256 = sha256Hex2(fs12.readFileSync(manifestPath));
|
|
7123
7280
|
}
|
|
7124
7281
|
return marker2;
|
|
7125
7282
|
}
|
|
7126
7283
|
function writeOwnershipMarker(dir, marker2) {
|
|
7127
|
-
|
|
7128
|
-
|
|
7284
|
+
fs12.writeFileSync(
|
|
7285
|
+
path13.join(dir, OWNERSHIP_MARKER),
|
|
7129
7286
|
`${JSON.stringify(marker2, null, 2)}
|
|
7130
7287
|
`,
|
|
7131
7288
|
"utf8"
|
|
7132
7289
|
);
|
|
7133
7290
|
}
|
|
7134
7291
|
function readOwnershipMarker(dir) {
|
|
7135
|
-
const markerPath =
|
|
7136
|
-
if (!
|
|
7292
|
+
const markerPath = path13.join(dir, OWNERSHIP_MARKER);
|
|
7293
|
+
if (!fs12.existsSync(markerPath)) {
|
|
7137
7294
|
return { marker: null, problem: "it holds no .codebase-snapshot marker" };
|
|
7138
7295
|
}
|
|
7139
7296
|
let raw;
|
|
7140
7297
|
try {
|
|
7141
|
-
raw =
|
|
7298
|
+
raw = fs12.readFileSync(markerPath, "utf8");
|
|
7142
7299
|
} catch {
|
|
7143
7300
|
return { marker: null, problem: "its .codebase-snapshot marker could not be read" };
|
|
7144
7301
|
}
|
|
@@ -7206,11 +7363,11 @@ function assessSnapshotDirectory(dir) {
|
|
|
7206
7363
|
marker: marker2
|
|
7207
7364
|
};
|
|
7208
7365
|
}
|
|
7209
|
-
const manifestPath =
|
|
7210
|
-
if (
|
|
7366
|
+
const manifestPath = path13.join(dir, "manifest.json");
|
|
7367
|
+
if (fs12.existsSync(manifestPath)) {
|
|
7211
7368
|
let raw;
|
|
7212
7369
|
try {
|
|
7213
|
-
raw =
|
|
7370
|
+
raw = fs12.readFileSync(manifestPath, "utf8");
|
|
7214
7371
|
} catch {
|
|
7215
7372
|
return {
|
|
7216
7373
|
owned: false,
|
|
@@ -7292,13 +7449,13 @@ function containsNoFiles(dir) {
|
|
|
7292
7449
|
const current = pending.pop();
|
|
7293
7450
|
let entries;
|
|
7294
7451
|
try {
|
|
7295
|
-
entries =
|
|
7452
|
+
entries = fs12.readdirSync(current, { withFileTypes: true });
|
|
7296
7453
|
} catch {
|
|
7297
7454
|
return false;
|
|
7298
7455
|
}
|
|
7299
7456
|
for (const entry of entries) {
|
|
7300
7457
|
if (entry.isDirectory()) {
|
|
7301
|
-
pending.push(
|
|
7458
|
+
pending.push(path13.join(current, entry.name));
|
|
7302
7459
|
} else if (!IGNORABLE_ENTRIES.has(entry.name)) {
|
|
7303
7460
|
return false;
|
|
7304
7461
|
}
|
|
@@ -7307,13 +7464,13 @@ function containsNoFiles(dir) {
|
|
|
7307
7464
|
return true;
|
|
7308
7465
|
}
|
|
7309
7466
|
function assertReplaceable(target, label, secretRules) {
|
|
7310
|
-
if (!
|
|
7311
|
-
if (!
|
|
7467
|
+
if (!fs12.existsSync(target)) return;
|
|
7468
|
+
if (!fs12.statSync(target).isDirectory()) {
|
|
7312
7469
|
throw new Error(
|
|
7313
7470
|
`Refusing to write into ${label} ${target}: it exists but is not a directory.`
|
|
7314
7471
|
);
|
|
7315
7472
|
}
|
|
7316
|
-
const entries =
|
|
7473
|
+
const entries = fs12.readdirSync(target);
|
|
7317
7474
|
if (entries.length === 0) return;
|
|
7318
7475
|
if (entries.every((name) => IGNORABLE_ENTRIES.has(name))) return;
|
|
7319
7476
|
if (containsNoFiles(target)) return;
|
|
@@ -7333,18 +7490,18 @@ function assertReplaceable(target, label, secretRules) {
|
|
|
7333
7490
|
);
|
|
7334
7491
|
}
|
|
7335
7492
|
function assertStagingRootUsable(tmpDir, secretRules) {
|
|
7336
|
-
if (!
|
|
7337
|
-
if (!
|
|
7493
|
+
if (!fs12.existsSync(tmpDir)) return;
|
|
7494
|
+
if (!fs12.statSync(tmpDir).isDirectory()) {
|
|
7338
7495
|
throw new Error(`Refusing to write into tmpDir ${tmpDir}: it exists but is not a directory.`);
|
|
7339
7496
|
}
|
|
7340
|
-
const entries =
|
|
7497
|
+
const entries = fs12.readdirSync(tmpDir);
|
|
7341
7498
|
if (entries.length === 0) return;
|
|
7342
7499
|
const foreign = entries.filter((name) => {
|
|
7343
|
-
const full =
|
|
7500
|
+
const full = path13.join(tmpDir, name);
|
|
7344
7501
|
if (!name.startsWith(RUN_DIR_PREFIX)) return true;
|
|
7345
7502
|
let stats;
|
|
7346
7503
|
try {
|
|
7347
|
-
stats =
|
|
7504
|
+
stats = fs12.statSync(full);
|
|
7348
7505
|
} catch {
|
|
7349
7506
|
return true;
|
|
7350
7507
|
}
|
|
@@ -7352,7 +7509,7 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7352
7509
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7353
7510
|
if (marker2) return false;
|
|
7354
7511
|
try {
|
|
7355
|
-
return
|
|
7512
|
+
return fs12.readdirSync(full).length > 0;
|
|
7356
7513
|
} catch {
|
|
7357
7514
|
return true;
|
|
7358
7515
|
}
|
|
@@ -7367,13 +7524,13 @@ function assertStagingRootUsable(tmpDir, secretRules) {
|
|
|
7367
7524
|
function cleanStaleRunDirs(tmpDir) {
|
|
7368
7525
|
let entries;
|
|
7369
7526
|
try {
|
|
7370
|
-
entries =
|
|
7527
|
+
entries = fs12.readdirSync(tmpDir);
|
|
7371
7528
|
} catch {
|
|
7372
7529
|
return;
|
|
7373
7530
|
}
|
|
7374
7531
|
for (const name of entries) {
|
|
7375
7532
|
if (!name.startsWith(RUN_DIR_PREFIX)) continue;
|
|
7376
|
-
const full =
|
|
7533
|
+
const full = path13.join(tmpDir, name);
|
|
7377
7534
|
const { marker: marker2 } = readOwnershipMarker(full);
|
|
7378
7535
|
if (marker2) {
|
|
7379
7536
|
const created = Date.parse(marker2.createdAt);
|
|
@@ -7381,33 +7538,33 @@ function cleanStaleRunDirs(tmpDir) {
|
|
|
7381
7538
|
const abandoned = typeof marker2.pid === "number" && !isProcessAlive(marker2.pid);
|
|
7382
7539
|
if (aged || abandoned) {
|
|
7383
7540
|
try {
|
|
7384
|
-
|
|
7541
|
+
fs12.rmSync(full, { recursive: true, force: true });
|
|
7385
7542
|
} catch {
|
|
7386
7543
|
}
|
|
7387
7544
|
}
|
|
7388
7545
|
continue;
|
|
7389
7546
|
}
|
|
7390
7547
|
try {
|
|
7391
|
-
if (
|
|
7548
|
+
if (fs12.readdirSync(full).length === 0) fs12.rmSync(full, { recursive: true, force: true });
|
|
7392
7549
|
} catch {
|
|
7393
7550
|
}
|
|
7394
7551
|
}
|
|
7395
7552
|
}
|
|
7396
7553
|
function removeIfEmpty(dir) {
|
|
7397
7554
|
try {
|
|
7398
|
-
if (
|
|
7555
|
+
if (fs12.readdirSync(dir).length === 0) fs12.rmSync(dir, { recursive: true, force: true });
|
|
7399
7556
|
} catch {
|
|
7400
7557
|
}
|
|
7401
7558
|
}
|
|
7402
7559
|
function ensureParentDirectory(target, label) {
|
|
7403
|
-
const parent =
|
|
7404
|
-
if (
|
|
7560
|
+
const parent = path13.dirname(target);
|
|
7561
|
+
if (fs12.existsSync(parent) && !fs12.statSync(parent).isDirectory()) {
|
|
7405
7562
|
throw new Error(
|
|
7406
7563
|
`Refusing to create ${label} ${target}: ${parent} exists but is not a directory.`
|
|
7407
7564
|
);
|
|
7408
7565
|
}
|
|
7409
7566
|
try {
|
|
7410
|
-
|
|
7567
|
+
fs12.mkdirSync(parent, { recursive: true });
|
|
7411
7568
|
} catch (err) {
|
|
7412
7569
|
throw new Error(
|
|
7413
7570
|
`Refusing to create ${label} ${target}: its parent ${parent} could not be created (${err.message}).`
|
|
@@ -7416,7 +7573,7 @@ function ensureParentDirectory(target, label) {
|
|
|
7416
7573
|
}
|
|
7417
7574
|
function acquireRunLock(stagingRoot) {
|
|
7418
7575
|
const key = lockKeyFor(stagingRoot);
|
|
7419
|
-
const lockPath =
|
|
7576
|
+
const lockPath = path13.join(os.tmpdir(), `codebase-snapshot-${key}.lock`);
|
|
7420
7577
|
const payload = `${JSON.stringify({
|
|
7421
7578
|
pid: process.pid,
|
|
7422
7579
|
stagingRoot,
|
|
@@ -7425,22 +7582,22 @@ function acquireRunLock(stagingRoot) {
|
|
|
7425
7582
|
`;
|
|
7426
7583
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
7427
7584
|
try {
|
|
7428
|
-
const handle =
|
|
7585
|
+
const handle = fs12.openSync(lockPath, "wx");
|
|
7429
7586
|
try {
|
|
7430
|
-
|
|
7587
|
+
fs12.writeSync(handle, payload);
|
|
7431
7588
|
} finally {
|
|
7432
|
-
|
|
7589
|
+
fs12.closeSync(handle);
|
|
7433
7590
|
}
|
|
7434
7591
|
return () => {
|
|
7435
7592
|
try {
|
|
7436
|
-
|
|
7593
|
+
fs12.rmSync(lockPath, { force: true });
|
|
7437
7594
|
} catch {
|
|
7438
7595
|
}
|
|
7439
7596
|
};
|
|
7440
7597
|
} catch (err) {
|
|
7441
7598
|
if (err.code !== "EEXIST") throw err;
|
|
7442
7599
|
if (attempt === 0 && lockOwnerIsGone(lockPath)) {
|
|
7443
|
-
|
|
7600
|
+
fs12.rmSync(lockPath, { force: true });
|
|
7444
7601
|
continue;
|
|
7445
7602
|
}
|
|
7446
7603
|
throw new Error(
|
|
@@ -7453,7 +7610,7 @@ function acquireRunLock(stagingRoot) {
|
|
|
7453
7610
|
function lockKeyFor(stagingRoot) {
|
|
7454
7611
|
let key = stagingRoot;
|
|
7455
7612
|
try {
|
|
7456
|
-
key =
|
|
7613
|
+
key = fs12.realpathSync(stagingRoot);
|
|
7457
7614
|
} catch {
|
|
7458
7615
|
}
|
|
7459
7616
|
if (process.platform === "win32" || process.platform === "darwin") key = key.toLowerCase();
|
|
@@ -7462,7 +7619,7 @@ function lockKeyFor(stagingRoot) {
|
|
|
7462
7619
|
function lockOwnerIsGone(lockPath) {
|
|
7463
7620
|
let raw;
|
|
7464
7621
|
try {
|
|
7465
|
-
raw =
|
|
7622
|
+
raw = fs12.readFileSync(lockPath, "utf8");
|
|
7466
7623
|
} catch {
|
|
7467
7624
|
return false;
|
|
7468
7625
|
}
|
|
@@ -7482,12 +7639,12 @@ function lockOwnerIsGone(lockPath) {
|
|
|
7482
7639
|
}
|
|
7483
7640
|
function writeManifestAtomically(manifestPath, manifest) {
|
|
7484
7641
|
const tempPath = `${manifestPath}.${process.pid}.tmp`;
|
|
7485
|
-
|
|
7642
|
+
fs12.writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
7486
7643
|
try {
|
|
7487
|
-
|
|
7644
|
+
fs12.renameSync(tempPath, manifestPath);
|
|
7488
7645
|
} catch (err) {
|
|
7489
7646
|
try {
|
|
7490
|
-
|
|
7647
|
+
fs12.rmSync(tempPath, { force: true });
|
|
7491
7648
|
} catch {
|
|
7492
7649
|
}
|
|
7493
7650
|
throw err;
|
|
@@ -7510,31 +7667,31 @@ function swapIntoPlace(stagingDir, outDir) {
|
|
|
7510
7667
|
}
|
|
7511
7668
|
function swapOnce(stagingDir, outDir) {
|
|
7512
7669
|
const backupDir = `${outDir}.backup-${process.pid}-${Date.now()}`;
|
|
7513
|
-
const hadPrevious =
|
|
7514
|
-
if (hadPrevious)
|
|
7670
|
+
const hadPrevious = fs12.existsSync(outDir);
|
|
7671
|
+
if (hadPrevious) fs12.renameSync(outDir, backupDir);
|
|
7515
7672
|
try {
|
|
7516
7673
|
try {
|
|
7517
|
-
|
|
7674
|
+
fs12.renameSync(stagingDir, outDir);
|
|
7518
7675
|
} catch (err) {
|
|
7519
7676
|
if (err.code !== "EXDEV") throw err;
|
|
7520
7677
|
const partialDir = `${outDir}.partial-${process.pid}-${Date.now()}`;
|
|
7521
7678
|
try {
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7679
|
+
fs12.cpSync(stagingDir, partialDir, { recursive: true });
|
|
7680
|
+
fs12.renameSync(partialDir, outDir);
|
|
7681
|
+
fs12.rmSync(stagingDir, { recursive: true, force: true });
|
|
7525
7682
|
} catch (copyErr) {
|
|
7526
7683
|
try {
|
|
7527
|
-
|
|
7684
|
+
fs12.rmSync(partialDir, { recursive: true, force: true });
|
|
7528
7685
|
} catch {
|
|
7529
7686
|
}
|
|
7530
7687
|
throw copyErr;
|
|
7531
7688
|
}
|
|
7532
7689
|
}
|
|
7533
|
-
if (hadPrevious)
|
|
7690
|
+
if (hadPrevious) fs12.rmSync(backupDir, { recursive: true, force: true });
|
|
7534
7691
|
} catch (err) {
|
|
7535
|
-
if (hadPrevious &&
|
|
7536
|
-
if (
|
|
7537
|
-
|
|
7692
|
+
if (hadPrevious && fs12.existsSync(backupDir)) {
|
|
7693
|
+
if (fs12.existsSync(outDir)) fs12.rmSync(outDir, { recursive: true, force: true });
|
|
7694
|
+
fs12.renameSync(backupDir, outDir);
|
|
7538
7695
|
}
|
|
7539
7696
|
throw err;
|
|
7540
7697
|
}
|
|
@@ -7629,7 +7786,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7629
7786
|
// first run cannot have marked them yet, so the name alone keeps a run from recording its own
|
|
7630
7787
|
// output — but only at these exact paths, not at every directory that shares the name.
|
|
7631
7788
|
toolOwnedPaths: [config.outDir, config.tmpDir].map(
|
|
7632
|
-
(directory) =>
|
|
7789
|
+
(directory) => path13.relative(config.cwd, path13.resolve(config.cwd, directory)).replace(/\\/g, "/")
|
|
7633
7790
|
).filter((relative7) => relative7.length > 0 && !relative7.startsWith(".."))
|
|
7634
7791
|
});
|
|
7635
7792
|
const files = [];
|
|
@@ -7650,12 +7807,12 @@ function generateSnapshot(configInput, options) {
|
|
|
7650
7807
|
let totalSizeBytes = 0;
|
|
7651
7808
|
let largeFileCount = 0;
|
|
7652
7809
|
for (const relativePath of collection.files) {
|
|
7653
|
-
const absolutePath =
|
|
7810
|
+
const absolutePath = path13.join(config.cwd, relativePath);
|
|
7654
7811
|
let stats;
|
|
7655
7812
|
try {
|
|
7656
|
-
stats =
|
|
7813
|
+
stats = fs12.statSync(absolutePath);
|
|
7657
7814
|
if (!stats.isFile()) {
|
|
7658
|
-
const nestedRepository = stats.isDirectory() &&
|
|
7815
|
+
const nestedRepository = stats.isDirectory() && fs12.existsSync(path13.join(absolutePath, ".git"));
|
|
7659
7816
|
skipped.push(
|
|
7660
7817
|
nestedRepository ? {
|
|
7661
7818
|
path: relativePath,
|
|
@@ -7675,7 +7832,7 @@ function generateSnapshot(configInput, options) {
|
|
|
7675
7832
|
}
|
|
7676
7833
|
let buffer;
|
|
7677
7834
|
try {
|
|
7678
|
-
buffer =
|
|
7835
|
+
buffer = fs12.readFileSync(absolutePath);
|
|
7679
7836
|
} catch {
|
|
7680
7837
|
skipped.push({ path: relativePath, reason: "read-error" });
|
|
7681
7838
|
continue;
|
|
@@ -8005,12 +8162,12 @@ function generateSnapshot(configInput, options) {
|
|
|
8005
8162
|
let stagingDir = null;
|
|
8006
8163
|
try {
|
|
8007
8164
|
ensureParentDirectory(outDir, "outDir");
|
|
8008
|
-
|
|
8165
|
+
fs12.mkdirSync(tmpDir, { recursive: true });
|
|
8009
8166
|
cleanStaleRunDirs(tmpDir);
|
|
8010
8167
|
const snapshotId = crypto.randomUUID();
|
|
8011
8168
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8012
|
-
stagingDir =
|
|
8013
|
-
|
|
8169
|
+
stagingDir = path13.join(tmpDir, `${RUN_DIR_PREFIX}${process.pid}-${snapshotId.slice(0, 8)}`);
|
|
8170
|
+
fs12.mkdirSync(stagingDir);
|
|
8014
8171
|
writeOwnershipMarker(stagingDir, {
|
|
8015
8172
|
generator: GENERATOR_NAME,
|
|
8016
8173
|
version: GENERATOR_VERSION,
|
|
@@ -8020,41 +8177,41 @@ function generateSnapshot(configInput, options) {
|
|
|
8020
8177
|
id: snapshotId,
|
|
8021
8178
|
pid: process.pid
|
|
8022
8179
|
});
|
|
8023
|
-
const partsDir =
|
|
8024
|
-
const reportsDir =
|
|
8025
|
-
if (artifacts.parts)
|
|
8180
|
+
const partsDir = path13.join(stagingDir, "parts");
|
|
8181
|
+
const reportsDir = path13.join(stagingDir, "reports");
|
|
8182
|
+
if (artifacts.parts) fs12.mkdirSync(partsDir, { recursive: true });
|
|
8026
8183
|
if (artifacts.navigation || artifacts.projectTree || artifacts.audit) {
|
|
8027
|
-
|
|
8184
|
+
fs12.mkdirSync(reportsDir, { recursive: true });
|
|
8028
8185
|
}
|
|
8029
8186
|
if (artifacts.parts) {
|
|
8030
8187
|
for (const part of parts) {
|
|
8031
|
-
|
|
8188
|
+
fs12.writeFileSync(path13.join(partsDir, part.filename), part.markdown, "utf8");
|
|
8032
8189
|
}
|
|
8033
8190
|
}
|
|
8034
8191
|
if (projectTree !== null) {
|
|
8035
|
-
|
|
8192
|
+
fs12.writeFileSync(path13.join(reportsDir, "project-tree.md"), projectTree, "utf8");
|
|
8036
8193
|
}
|
|
8037
8194
|
if (artifacts.navigation) {
|
|
8038
|
-
|
|
8195
|
+
fs12.writeFileSync(path13.join(reportsDir, "navigation.md"), generateNavigation(manifest), "utf8");
|
|
8039
8196
|
}
|
|
8040
8197
|
if (artifacts.audit) {
|
|
8041
|
-
|
|
8042
|
-
|
|
8198
|
+
fs12.writeFileSync(
|
|
8199
|
+
path13.join(reportsDir, "audit.md"),
|
|
8043
8200
|
generateAuditReport(manifest, secretFindings, config.secretRules),
|
|
8044
8201
|
"utf8"
|
|
8045
8202
|
);
|
|
8046
8203
|
}
|
|
8047
8204
|
if (artifacts.readme) {
|
|
8048
|
-
|
|
8205
|
+
fs12.writeFileSync(path13.join(stagingDir, "README.md"), generateReadme(manifest, artifacts), "utf8");
|
|
8049
8206
|
}
|
|
8050
8207
|
if (artifacts.manifest) {
|
|
8051
|
-
|
|
8208
|
+
fs12.writeFileSync(path13.join(stagingDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf8");
|
|
8052
8209
|
}
|
|
8053
8210
|
if (monolithJson !== null) {
|
|
8054
|
-
|
|
8211
|
+
fs12.writeFileSync(path13.join(stagingDir, "full-codebase.json"), monolithJson, "utf8");
|
|
8055
8212
|
}
|
|
8056
8213
|
if (monolithMarkdown !== null) {
|
|
8057
|
-
|
|
8214
|
+
fs12.writeFileSync(path13.join(stagingDir, "full-codebase.md"), monolithMarkdown, "utf8");
|
|
8058
8215
|
}
|
|
8059
8216
|
writeOwnershipMarker(stagingDir, markerPayload(stagingDir, "complete", snapshotId, createdAt));
|
|
8060
8217
|
swapIntoPlace(stagingDir, outDir);
|
|
@@ -8063,7 +8220,7 @@ function generateSnapshot(configInput, options) {
|
|
|
8063
8220
|
const pendingHook = runAfterGenerate(config, manifest);
|
|
8064
8221
|
const shipHookState = () => {
|
|
8065
8222
|
if (artifacts.manifest && manifest.warnings.length !== warningsBeforeHook) {
|
|
8066
|
-
writeManifestAtomically(
|
|
8223
|
+
writeManifestAtomically(path13.join(outDir, "manifest.json"), manifest);
|
|
8067
8224
|
}
|
|
8068
8225
|
writeOwnershipMarker(outDir, markerPayload(outDir, "complete", snapshotId, createdAt));
|
|
8069
8226
|
};
|
|
@@ -8086,7 +8243,7 @@ function generateSnapshot(configInput, options) {
|
|
|
8086
8243
|
} catch (err) {
|
|
8087
8244
|
if (stagingDir !== null) {
|
|
8088
8245
|
try {
|
|
8089
|
-
|
|
8246
|
+
fs12.rmSync(stagingDir, { recursive: true, force: true });
|
|
8090
8247
|
} catch {
|
|
8091
8248
|
}
|
|
8092
8249
|
}
|
|
@@ -8100,6 +8257,6 @@ async function generateSnapshotAsync(configInput, options) {
|
|
|
8100
8257
|
return generateSnapshot(configInput, options);
|
|
8101
8258
|
}
|
|
8102
8259
|
|
|
8103
|
-
export { ARTIFACT_NAMES, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PRESETS, PromptCancelled, SCHEMA_VERSION, anchorForPath, appendGitignoreEntries, assertReplaceable, assertUsableConfigInput, collectFiles, compareManifests, countInvalidUtf8Bytes, countLines, decodeText, defaultIO, defineConfig, describeManifestShapeProblem, detectLanguage, detectPreset, escapeControls, explainPath, fenceForContent, fenceForText, findConfigFile, firstRunMessage, formatNumber, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, gitignorePath, globToRegExp, hasPriorSnapshot, isBinaryBuffer, isBinaryExtension, isBinaryFile, isDiscoveryMode, isEffectivelyEmpty, isInteractive, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, planFirstRun, profileForPath, renderConfig, renderDiffText, renderExplainText, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, unknownPresetMessage, validateSnapshot };
|
|
8104
|
-
//# sourceMappingURL=chunk-
|
|
8105
|
-
//# sourceMappingURL=chunk-
|
|
8260
|
+
export { ARTIFACT_NAMES, CHECK_INTERVAL_MS, DEFAULT_ANSWERS, DEFAULT_SECRET_PATTERNS, FAILURE_INTERVAL_MS, GENERATOR_NAME, GENERATOR_VERSION, LANGUAGE_PROFILES, MIN_MAX_PART_BYTES, PACKAGE_LATEST_URL, PRESETS, PromptCancelled, REQUEST_TIMEOUT_MS, SCHEMA_VERSION, anchorForPath, appendGitignoreEntries, assertReplaceable, assertUsableConfigInput, cacheDirectory, cacheFilePath, checkForUpdate, collectFiles, compareManifests, countInvalidUtf8Bytes, countLines, decodeText, defaultIO, defineConfig, describeManifestShapeProblem, detectLanguage, detectPreset, escapeControls, explainPath, fenceForContent, fenceForText, fetchLatestVersion, findConfigFile, firstRunMessage, formatNumber, formatUpdateNotice, generateProjectTree, generateSnapshot, generateSnapshotAsync, getPreset, gitignorePath, globToRegExp, hasPriorSnapshot, isBinaryBuffer, isBinaryExtension, isBinaryFile, isDiscoveryMode, isEffectivelyEmpty, isInteractive, isNewer, isResolvedConfig, isSensitivePath, listPresetNames, loadConfigFile, loadConfigFileDetailed, loadManifest, markResolvedConfig, matchRule, matchesExclude, normalizeResolvedConfig, parseByteSize, partitionFiles, planFirstRun, profileForPath, renderConfig, renderDiffText, renderExplainText, renumberParts, resolveConfig, resolveSafeOutputDirs, runInit, scanAndRedactSecrets, shouldCheck, stripJsonComments, summarizeJson, summarizeMarkdown, summarizeTypeScriptSource, summarizeWithProfile, supportsTypeScriptImports, truncatePreview, truncateToBytes, unknownPresetMessage, validateSnapshot };
|
|
8261
|
+
//# sourceMappingURL=chunk-3KUL3QRH.js.map
|
|
8262
|
+
//# sourceMappingURL=chunk-3KUL3QRH.js.map
|