dep-brain 0.5.0 → 0.5.1

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 CHANGED
@@ -65,7 +65,7 @@ async function main() {
65
65
  }
66
66
  if (command === "config") {
67
67
  if (!(await hasPackageJson(targetPath))) {
68
- console.error(`No package.json found at ${targetPath}`);
68
+ console.error(`No package.json found at ${sanitizeForLog(targetPath)}`);
69
69
  process.exitCode = 1;
70
70
  return;
71
71
  }
@@ -85,13 +85,13 @@ async function main() {
85
85
  return;
86
86
  }
87
87
  }
88
- console.error(`Unknown command: ${command}`);
88
+ console.error(`Unknown command: ${sanitizeForLog(command)}`);
89
89
  printHelp();
90
90
  process.exitCode = 1;
91
91
  return;
92
92
  }
93
93
  if (!(await hasPackageJson(targetPath))) {
94
- console.error(`No package.json found at ${targetPath}`);
94
+ console.error(`No package.json found at ${sanitizeForLog(targetPath)}`);
95
95
  process.exitCode = 1;
96
96
  return;
97
97
  }
@@ -210,3 +210,6 @@ async function writeOutput(output, outPath) {
210
210
  }
211
211
  process.stdout.write(`${output}\n`);
212
212
  }
213
+ function sanitizeForLog(value) {
214
+ return value.replace(/[\r\n]+/g, " ").trim();
215
+ }
@@ -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 graph = await buildDependencyGraph(rootDir);
7
- const projectFiles = await collectProjectFiles(rootDir, SOURCE_FILE_PATTERN, config.scan.excludePaths);
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(rootDir, "tsconfig.json");
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
- await readTextFile(path.join(rootDir, fileName));
27
+ const resolved = resolveWithinRoot(rootDir, fileName);
28
+ await readTextFile(resolved);
26
29
  return true;
27
30
  }
28
31
  catch {
@@ -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 = path.resolve(rootDir, configPath ?? "depbrain.config.json");
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,2 @@
1
+ export declare function resolveWithinRoot(rootDir: string, targetPath: string): string;
2
+ export declare function isWithinRoot(rootDir: string, targetPath: string): boolean;
@@ -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 خارج 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
+ }
@@ -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
- files.push(fullPath);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dep-brain",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "CLI and library for dependency health analysis",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",