dep-brain 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +13 -5
- package/dist/core/context.js +8 -5
- package/dist/utils/config.js +2 -2
- package/dist/utils/file-parser.js +4 -0
- package/dist/utils/path.d.ts +2 -0
- package/dist/utils/path.js +16 -0
- package/dist/utils/workspaces.js +11 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -48,7 +48,8 @@ async function main() {
|
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
try {
|
|
51
|
-
const
|
|
51
|
+
const resolvedFrom = resolveUserPath(fromPath);
|
|
52
|
+
const raw = await fs.readFile(resolvedFrom, "utf8");
|
|
52
53
|
const reportData = JSON.parse(raw);
|
|
53
54
|
const output = flags.has("--json")
|
|
54
55
|
? JSON.stringify(reportData, null, 2)
|
|
@@ -65,7 +66,7 @@ async function main() {
|
|
|
65
66
|
}
|
|
66
67
|
if (command === "config") {
|
|
67
68
|
if (!(await hasPackageJson(targetPath))) {
|
|
68
|
-
console.error(`No package.json found at ${targetPath}`);
|
|
69
|
+
console.error(`No package.json found at ${sanitizeForLog(targetPath)}`);
|
|
69
70
|
process.exitCode = 1;
|
|
70
71
|
return;
|
|
71
72
|
}
|
|
@@ -85,13 +86,13 @@ async function main() {
|
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
console.error(`Unknown command: ${command}`);
|
|
89
|
+
console.error(`Unknown command: ${sanitizeForLog(command)}`);
|
|
89
90
|
printHelp();
|
|
90
91
|
process.exitCode = 1;
|
|
91
92
|
return;
|
|
92
93
|
}
|
|
93
94
|
if (!(await hasPackageJson(targetPath))) {
|
|
94
|
-
console.error(`No package.json found at ${targetPath}`);
|
|
95
|
+
console.error(`No package.json found at ${sanitizeForLog(targetPath)}`);
|
|
95
96
|
process.exitCode = 1;
|
|
96
97
|
return;
|
|
97
98
|
}
|
|
@@ -205,8 +206,15 @@ async function loadPackageVersion() {
|
|
|
205
206
|
}
|
|
206
207
|
async function writeOutput(output, outPath) {
|
|
207
208
|
if (outPath) {
|
|
208
|
-
|
|
209
|
+
const resolved = resolveUserPath(outPath);
|
|
210
|
+
await fs.writeFile(resolved, `${output}\n`, "utf8");
|
|
209
211
|
return;
|
|
210
212
|
}
|
|
211
213
|
process.stdout.write(`${output}\n`);
|
|
212
214
|
}
|
|
215
|
+
function sanitizeForLog(value) {
|
|
216
|
+
return value.replace(/[\r\n]+/g, " ").trim();
|
|
217
|
+
}
|
|
218
|
+
function resolveUserPath(value) {
|
|
219
|
+
return path.resolve(process.cwd(), value);
|
|
220
|
+
}
|
package/dist/core/context.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { buildDependencyGraph } from "./graph-builder.js";
|
|
3
3
|
import { collectProjectFiles, readTextFile } from "../utils/file-parser.js";
|
|
4
|
+
import { resolveWithinRoot } from "../utils/path.js";
|
|
4
5
|
const SOURCE_FILE_PATTERN = /\.(c|m)?(t|j)sx?$/;
|
|
5
6
|
export async function buildAnalysisContext(rootDir, config) {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
7
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
8
|
+
const graph = await buildDependencyGraph(resolvedRoot);
|
|
9
|
+
const projectFiles = await collectProjectFiles(resolvedRoot, SOURCE_FILE_PATTERN, config.scan.excludePaths);
|
|
8
10
|
const fileEntries = await Promise.all(projectFiles.map(async (filePath) => ({
|
|
9
11
|
path: filePath,
|
|
10
12
|
content: await readTextFile(filePath)
|
|
11
13
|
})));
|
|
12
14
|
const sourceText = fileEntries.map((entry) => entry.content).join("\n");
|
|
13
|
-
const hasTypeScriptConfig = await hasFile(
|
|
15
|
+
const hasTypeScriptConfig = await hasFile(resolvedRoot, "tsconfig.json");
|
|
14
16
|
return {
|
|
15
|
-
rootDir,
|
|
17
|
+
rootDir: resolvedRoot,
|
|
16
18
|
graph,
|
|
17
19
|
sourceText,
|
|
18
20
|
projectFiles,
|
|
@@ -22,7 +24,8 @@ export async function buildAnalysisContext(rootDir, config) {
|
|
|
22
24
|
}
|
|
23
25
|
async function hasFile(rootDir, fileName) {
|
|
24
26
|
try {
|
|
25
|
-
|
|
27
|
+
const resolved = resolveWithinRoot(rootDir, fileName);
|
|
28
|
+
await readTextFile(resolved);
|
|
26
29
|
return true;
|
|
27
30
|
}
|
|
28
31
|
catch {
|
package/dist/utils/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { readJsonFile } from "./file-parser.js";
|
|
2
|
+
import { resolveWithinRoot } from "./path.js";
|
|
3
3
|
export const defaultConfig = {
|
|
4
4
|
ignore: {
|
|
5
5
|
dependencies: [],
|
|
@@ -32,7 +32,7 @@ export const defaultConfig = {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
export async function loadDepBrainConfig(rootDir, configPath) {
|
|
35
|
-
const resolvedPath =
|
|
35
|
+
const resolvedPath = resolveWithinRoot(rootDir, configPath ?? "depbrain.config.json");
|
|
36
36
|
try {
|
|
37
37
|
const loaded = await readJsonFile(resolvedPath);
|
|
38
38
|
return normalizeConfig(loaded);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { isWithinRoot } from "./path.js";
|
|
3
4
|
export async function readJsonFile(filePath) {
|
|
4
5
|
const content = await fs.readFile(filePath, "utf8");
|
|
5
6
|
return JSON.parse(content);
|
|
@@ -11,6 +12,9 @@ export async function collectProjectFiles(rootDir, pattern, excludePaths = []) {
|
|
|
11
12
|
return collectProjectFilesInternal(rootDir, rootDir, pattern, excludePaths);
|
|
12
13
|
}
|
|
13
14
|
async function collectProjectFilesInternal(currentDir, baseDir, pattern, excludePaths) {
|
|
15
|
+
if (!isWithinRoot(baseDir, currentDir)) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
14
18
|
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
15
19
|
const files = [];
|
|
16
20
|
for (const entry of entries) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function resolveWithinRoot(rootDir, targetPath) {
|
|
3
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
4
|
+
const resolvedTarget = path.resolve(resolvedRoot, targetPath);
|
|
5
|
+
if (!isWithinRoot(resolvedRoot, resolvedTarget)) {
|
|
6
|
+
throw new Error(`Path is outside root: ${resolvedTarget}`);
|
|
7
|
+
}
|
|
8
|
+
return resolvedTarget;
|
|
9
|
+
}
|
|
10
|
+
export function isWithinRoot(rootDir, targetPath) {
|
|
11
|
+
const relative = path.relative(rootDir, targetPath);
|
|
12
|
+
if (!relative || relative === ".") {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
16
|
+
}
|
package/dist/utils/workspaces.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { readJsonFile } from "./file-parser.js";
|
|
4
|
+
import { isWithinRoot, resolveWithinRoot } from "./path.js";
|
|
4
5
|
export async function findWorkspacePackages(rootDir) {
|
|
5
6
|
const rootPackageJsonPath = path.join(rootDir, "package.json");
|
|
6
7
|
const rootPackage = await readJsonFile(rootPackageJsonPath).catch(() => null);
|
|
@@ -37,12 +38,21 @@ async function collectPackageJsonFiles(rootDir) {
|
|
|
37
38
|
continue;
|
|
38
39
|
}
|
|
39
40
|
const fullPath = path.join(rootDir, entry.name);
|
|
41
|
+
if (!isWithinRoot(rootDir, fullPath)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
40
44
|
if (entry.isDirectory()) {
|
|
41
45
|
files.push(...(await collectPackageJsonFiles(fullPath)));
|
|
42
46
|
continue;
|
|
43
47
|
}
|
|
44
48
|
if (entry.isFile() && entry.name === "package.json") {
|
|
45
|
-
|
|
49
|
+
try {
|
|
50
|
+
const resolved = resolveWithinRoot(rootDir, fullPath);
|
|
51
|
+
files.push(resolved);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
46
56
|
}
|
|
47
57
|
}
|
|
48
58
|
return files;
|