devlensio 1.0.0 → 1.0.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.
@@ -11,6 +11,83 @@ export function defaultParseResult(stdout) {
11
11
  }
12
12
  // Subprocess Extractor Registry
13
13
  // These extractors are spawned as child processes.
14
+ // ── extractor artifact resolution ────────────────────────────────────────────
15
+ // The subprocess extractors (python venv, java jar, go/rust static binaries)
16
+ // are DATA files inside the devlensio package. In a normal install they sit at
17
+ // `<pkg>/extractors/…` and resolve relative to this module. But when devlensio
18
+ // is BUNDLED into a standalone binary (`bun build --compile`, which is how the
19
+ // `@devlensio/cli` and MCP server ship), `import.meta.url` points at the binary
20
+ // itself, so the URL-relative path resolves to `/extractors/…` (nonexistent).
21
+ // The fallbacks below find the real extractor root for that case.
22
+ function resolveExtractorsRoot() {
23
+ // 1. Env override (CI / unusual layouts): DEVLENS_EXTRACTORS_DIR = the
24
+ // `extractors/` directory itself.
25
+ const env = process.env.DEVLENS_EXTRACTORS_DIR;
26
+ if (env) {
27
+ const candidate = path.resolve(env);
28
+ if (fs.existsSync(path.join(candidate, "python")) && fs.existsSync(path.join(candidate, "java"))) {
29
+ return candidate;
30
+ }
31
+ }
32
+ // 2. Normal install: `<pkg>/dist/extractors/../../extractors` = `<pkg>/extractors`.
33
+ const viaModule = fileURLToPath(new URL("../../extractors", import.meta.url));
34
+ if (fs.existsSync(viaModule))
35
+ return viaModule;
36
+ // 3. Bundled binary: walk up from this bundle's own directory AND from the
37
+ // cwd to find `<…>/node_modules/devlensio/extractors`. Covers running the
38
+ // compiled CLI inside a project that depends on devlensio, and global
39
+ // installs where devlensio sits hoisted beside the CLI package.
40
+ const scanRoots = [
41
+ fileURLToPath(new URL(".", import.meta.url)),
42
+ process.cwd(),
43
+ ];
44
+ for (const start of scanRoots) {
45
+ let dir = path.resolve(start);
46
+ for (;;) {
47
+ const candidate = path.join(dir, "node_modules", "devlensio", "extractors");
48
+ if (fs.existsSync(candidate))
49
+ return candidate;
50
+ const parent = path.dirname(dir);
51
+ if (parent === dir)
52
+ break;
53
+ dir = parent;
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+ const extractorsRoot = resolveExtractorsRoot();
59
+ /** Absolute path to an extractor artifact under the resolved root (or null). */
60
+ function extractorArtifact(rel) {
61
+ return extractorsRoot ? path.join(extractorsRoot, rel) : null;
62
+ }
63
+ function resolvePythonCommand() {
64
+ const venvBin = process.platform === "win32" ? "Scripts/python.exe" : "bin/python";
65
+ const venvPython = extractorArtifact(`python/.venv/${venvBin}`) ??
66
+ // Last resort: URL-relative (pre-fix behavior for direct-from-dist runs).
67
+ fileURLToPath(new URL(`../../extractors/python/.venv/${venvBin}`, import.meta.url));
68
+ return fs.existsSync(venvPython) ? venvPython : "python3";
69
+ }
70
+ function platformDir() {
71
+ return process.platform === "win32"
72
+ ? "windows-amd64"
73
+ : process.platform === "darwin"
74
+ ? `darwin-${process.arch === "arm64" ? "arm64" : "amd64"}`
75
+ : `linux-${process.arch === "arm64" ? "arm64" : "amd64"}`;
76
+ }
77
+ function resolveJavaJarPath() {
78
+ const rel = "java/devlens_java_extractor.jar";
79
+ return extractorArtifact(rel) ?? fileURLToPath(new URL(`../../extractors/${rel}`, import.meta.url));
80
+ }
81
+ function resolveGoBinaryPath() {
82
+ const exe = process.platform === "win32" ? ".exe" : "";
83
+ const rel = `go/bin/${platformDir()}/devlens_go_extractor${exe}`;
84
+ return extractorArtifact(rel) ?? fileURLToPath(new URL(`../../extractors/${rel}`, import.meta.url));
85
+ }
86
+ function resolveRustBinaryPath() {
87
+ const exe = process.platform === "win32" ? ".exe" : "";
88
+ const rel = `rust/bin/${platformDir()}/devlens_rust_extractor${exe}`;
89
+ return extractorArtifact(rel) ?? fileURLToPath(new URL(`../../extractors/${rel}`, import.meta.url));
90
+ }
14
91
  const SUBPROCESS_EXTRACTORS = {
15
92
  python: {
16
93
  language: "python",
@@ -26,7 +103,7 @@ const SUBPROCESS_EXTRACTORS = {
26
103
  // Absolute path — the runner spawns with cwd=repoPath, so a bare jar
27
104
  // name would be looked up inside the analyzed repo. fileURLToPath
28
105
  // also decodes percent-escapes (spaces in the path).
29
- args: ["-jar", fileURLToPath(new URL("../../extractors/java/devlens_java_extractor.jar", import.meta.url))],
106
+ args: ["-jar", resolveJavaJarPath()],
30
107
  parseResult: defaultParseResult,
31
108
  },
32
109
  go: {
@@ -52,44 +129,6 @@ const SUBPROCESS_EXTRACTORS = {
52
129
  export function getExtractor(language) {
53
130
  return SUBPROCESS_EXTRACTORS[language];
54
131
  }
55
- // The python extractor is a pip package installed into a venv that the
56
- // postinstall script creates (extractors/python/setup.mjs). Resolve that
57
- // venv's interpreter absolutely — same pattern as the java jar path —
58
- // because the runner spawns with cwd=repoPath. Platform-aware: Windows
59
- // venvs put the interpreter at Scripts\python.exe, Unix at bin/python.
60
- function resolvePythonCommand() {
61
- const venvBin = process.platform === "win32" ? "Scripts/python.exe" : "bin/python";
62
- const venvPython = fileURLToPath(new URL(`../../extractors/python/.venv/${venvBin}`, import.meta.url));
63
- return fs.existsSync(venvPython) ? venvPython : "python3";
64
- }
65
- // The Go extractor ships as a static binary per platform, cross-compiled at
66
- // publish time (prepack → extractors/go/build.mjs). Resolve the CURRENT
67
- // platform's binary absolutely — same reason as the java jar path (the runner
68
- // spawns with cwd=repoPath). fileURLToPath also decodes percent-escapes
69
- // (spaces in the path).
70
- function resolveGoBinaryPath() {
71
- const platformDir = process.platform === "win32"
72
- ? "windows-amd64"
73
- : process.platform === "darwin"
74
- ? `darwin-${process.arch === "arm64" ? "arm64" : "amd64"}`
75
- : `linux-${process.arch === "arm64" ? "arm64" : "amd64"}`;
76
- const exe = process.platform === "win32" ? ".exe" : "";
77
- return fileURLToPath(new URL(`../../extractors/go/bin/${platformDir}/devlens_go_extractor${exe}`, import.meta.url));
78
- }
79
- // The Rust extractor ships as a static binary per platform, cross-compiled at
80
- // publish time (prepack → extractors/rust/build.mjs). Resolve the CURRENT
81
- // platform's binary absolutely — same reason as the go binary path (the runner
82
- // spawns with cwd=repoPath). fileURLToPath also decodes percent-escapes
83
- // (spaces in the path).
84
- function resolveRustBinaryPath() {
85
- const platformDir = process.platform === "win32"
86
- ? "windows-amd64"
87
- : process.platform === "darwin"
88
- ? `darwin-${process.arch === "arm64" ? "arm64" : "amd64"}`
89
- : `linux-${process.arch === "arm64" ? "arm64" : "amd64"}`;
90
- const exe = process.platform === "win32" ? ".exe" : "";
91
- return fileURLToPath(new URL(`../../extractors/rust/bin/${platformDir}/devlens_rust_extractor${exe}`, import.meta.url));
92
- }
93
132
  // langauges handled inline meaning JS/TS
94
133
  export const INLINE_LANGUAGES = new Set(["javascript", "typescript"]);
95
134
  // Does `command` resolve? Absolute path → existsSync; bare name → PATH scan
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devlensio",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Codebase intelligence engine for TypeScript/JavaScript/React/Next.js, Python, Java, Go, and Rust repositories.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",