@zivis/cli 0.1.0-alpha.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.
Files changed (112) hide show
  1. package/dist/commands/app/index.d.ts +10 -0
  2. package/dist/commands/app/index.js +245 -0
  3. package/dist/commands/app/index.js.map +1 -0
  4. package/dist/commands/auth/index.d.ts +2 -0
  5. package/dist/commands/auth/index.js +41 -0
  6. package/dist/commands/auth/index.js.map +1 -0
  7. package/dist/commands/auth/login.d.ts +8 -0
  8. package/dist/commands/auth/login.js +65 -0
  9. package/dist/commands/auth/login.js.map +1 -0
  10. package/dist/commands/auth/logout.d.ts +5 -0
  11. package/dist/commands/auth/logout.js +14 -0
  12. package/dist/commands/auth/logout.js.map +1 -0
  13. package/dist/commands/auth/sessions.d.ts +4 -0
  14. package/dist/commands/auth/sessions.js +30 -0
  15. package/dist/commands/auth/sessions.js.map +1 -0
  16. package/dist/commands/auth/status.d.ts +4 -0
  17. package/dist/commands/auth/status.js +53 -0
  18. package/dist/commands/auth/status.js.map +1 -0
  19. package/dist/commands/credits/index.d.ts +2 -0
  20. package/dist/commands/credits/index.js +51 -0
  21. package/dist/commands/credits/index.js.map +1 -0
  22. package/dist/commands/mcp/index.d.ts +2 -0
  23. package/dist/commands/mcp/index.js +70 -0
  24. package/dist/commands/mcp/index.js.map +1 -0
  25. package/dist/commands/open/index.d.ts +10 -0
  26. package/dist/commands/open/index.js +57 -0
  27. package/dist/commands/open/index.js.map +1 -0
  28. package/dist/commands/scan/index.d.ts +2 -0
  29. package/dist/commands/scan/index.js +140 -0
  30. package/dist/commands/scan/index.js.map +1 -0
  31. package/dist/commands/target/index.d.ts +2 -0
  32. package/dist/commands/target/index.js +146 -0
  33. package/dist/commands/target/index.js.map +1 -0
  34. package/dist/commands/tm/index.d.ts +2 -0
  35. package/dist/commands/tm/index.js +266 -0
  36. package/dist/commands/tm/index.js.map +1 -0
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.js +41 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/internal/extractor/adapters/go/index.d.ts +7 -0
  41. package/dist/internal/extractor/adapters/go/index.js +71 -0
  42. package/dist/internal/extractor/adapters/go/index.js.map +1 -0
  43. package/dist/internal/extractor/adapters/go/manifest.d.ts +37 -0
  44. package/dist/internal/extractor/adapters/go/manifest.js +199 -0
  45. package/dist/internal/extractor/adapters/go/manifest.js.map +1 -0
  46. package/dist/internal/extractor/adapters/go/parser.d.ts +6 -0
  47. package/dist/internal/extractor/adapters/go/parser.js +23 -0
  48. package/dist/internal/extractor/adapters/go/parser.js.map +1 -0
  49. package/dist/internal/extractor/adapters/go/scanner.d.ts +39 -0
  50. package/dist/internal/extractor/adapters/go/scanner.js +216 -0
  51. package/dist/internal/extractor/adapters/go/scanner.js.map +1 -0
  52. package/dist/internal/extractor/adapters/python/index.d.ts +5 -0
  53. package/dist/internal/extractor/adapters/python/index.js +68 -0
  54. package/dist/internal/extractor/adapters/python/index.js.map +1 -0
  55. package/dist/internal/extractor/adapters/python/manifest.d.ts +25 -0
  56. package/dist/internal/extractor/adapters/python/manifest.js +236 -0
  57. package/dist/internal/extractor/adapters/python/manifest.js.map +1 -0
  58. package/dist/internal/extractor/adapters/python/parser.d.ts +5 -0
  59. package/dist/internal/extractor/adapters/python/parser.js +22 -0
  60. package/dist/internal/extractor/adapters/python/parser.js.map +1 -0
  61. package/dist/internal/extractor/adapters/python/scanner.d.ts +37 -0
  62. package/dist/internal/extractor/adapters/python/scanner.js +284 -0
  63. package/dist/internal/extractor/adapters/python/scanner.js.map +1 -0
  64. package/dist/internal/extractor/adapters/typescript/index.d.ts +9 -0
  65. package/dist/internal/extractor/adapters/typescript/index.js +84 -0
  66. package/dist/internal/extractor/adapters/typescript/index.js.map +1 -0
  67. package/dist/internal/extractor/adapters/typescript/manifest.d.ts +41 -0
  68. package/dist/internal/extractor/adapters/typescript/manifest.js +156 -0
  69. package/dist/internal/extractor/adapters/typescript/manifest.js.map +1 -0
  70. package/dist/internal/extractor/adapters/typescript/parser.d.ts +14 -0
  71. package/dist/internal/extractor/adapters/typescript/parser.js +33 -0
  72. package/dist/internal/extractor/adapters/typescript/parser.js.map +1 -0
  73. package/dist/internal/extractor/adapters/typescript/scanner.d.ts +43 -0
  74. package/dist/internal/extractor/adapters/typescript/scanner.js +188 -0
  75. package/dist/internal/extractor/adapters/typescript/scanner.js.map +1 -0
  76. package/dist/internal/extractor/index.d.ts +22 -0
  77. package/dist/internal/extractor/index.js +107 -0
  78. package/dist/internal/extractor/index.js.map +1 -0
  79. package/dist/internal/extractor/types.d.ts +124 -0
  80. package/dist/internal/extractor/types.js +28 -0
  81. package/dist/internal/extractor/types.js.map +1 -0
  82. package/dist/internal/extractor/walker.d.ts +32 -0
  83. package/dist/internal/extractor/walker.js +110 -0
  84. package/dist/internal/extractor/walker.js.map +1 -0
  85. package/dist/internal/ide-setup.d.ts +7 -0
  86. package/dist/internal/ide-setup.js +131 -0
  87. package/dist/internal/ide-setup.js.map +1 -0
  88. package/dist/internal/orgs.d.ts +8 -0
  89. package/dist/internal/orgs.js +31 -0
  90. package/dist/internal/orgs.js.map +1 -0
  91. package/dist/internal/project-binding.d.ts +11 -0
  92. package/dist/internal/project-binding.js +96 -0
  93. package/dist/internal/project-binding.js.map +1 -0
  94. package/dist/internal/target-auth/api-config.d.ts +37 -0
  95. package/dist/internal/target-auth/api-config.js +40 -0
  96. package/dist/internal/target-auth/api-config.js.map +1 -0
  97. package/dist/internal/target-auth/config.d.ts +20 -0
  98. package/dist/internal/target-auth/config.js +58 -0
  99. package/dist/internal/target-auth/config.js.map +1 -0
  100. package/dist/internal/target-auth/index.d.ts +30 -0
  101. package/dist/internal/target-auth/index.js +101 -0
  102. package/dist/internal/target-auth/index.js.map +1 -0
  103. package/dist/internal/target-auth/keychain.d.ts +23 -0
  104. package/dist/internal/target-auth/keychain.js +150 -0
  105. package/dist/internal/target-auth/keychain.js.map +1 -0
  106. package/dist/internal/target-auth/types.d.ts +51 -0
  107. package/dist/internal/target-auth/types.js +11 -0
  108. package/dist/internal/target-auth/types.js.map +1 -0
  109. package/dist/internal/target-auth/workos.d.ts +20 -0
  110. package/dist/internal/target-auth/workos.js +196 -0
  111. package/dist/internal/target-auth/workos.js.map +1 -0
  112. package/package.json +41 -0
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Python manifest analysis.
3
+ *
4
+ * Reads pyproject.toml (PEP 621 + Poetry sections) and requirements.txt.
5
+ * Other formats (Pipfile, setup.py) deferred — they're either rare in
6
+ * modern projects (setup.py) or layer on top of these two.
7
+ */
8
+ import * as fs from "node:fs/promises";
9
+ import * as path from "node:path";
10
+ import TOML from "@iarna/toml";
11
+ export const WEB_FRAMEWORK_PACKAGES = {
12
+ fastapi: "fastapi",
13
+ flask: "flask",
14
+ starlette: "starlette",
15
+ django: "django",
16
+ aiohttp: "aiohttp",
17
+ bottle: "bottle",
18
+ tornado: "tornado",
19
+ sanic: "sanic",
20
+ quart: "quart",
21
+ };
22
+ export const DATA_STORE_PACKAGES = {
23
+ sqlalchemy: { kind: "postgres", client: "sqlalchemy" }, // dialect varies; default to pg
24
+ asyncpg: { kind: "postgres", client: "asyncpg" },
25
+ psycopg: { kind: "postgres", client: "psycopg" },
26
+ psycopg2: { kind: "postgres", client: "psycopg2" },
27
+ "psycopg2-binary": { kind: "postgres", client: "psycopg2" },
28
+ motor: { kind: "mongo", client: "motor" },
29
+ pymongo: { kind: "mongo", client: "pymongo" },
30
+ redis: { kind: "redis", client: "redis-py" },
31
+ "aioredis": { kind: "redis", client: "aioredis" },
32
+ pymysql: { kind: "mysql", client: "pymysql" },
33
+ aiosqlite: { kind: "sqlite", client: "aiosqlite" },
34
+ sqlmodel: { kind: "postgres", client: "sqlmodel" },
35
+ };
36
+ export const AI_SDK_PACKAGES = {
37
+ anthropic: "Anthropic",
38
+ openai: "OpenAI",
39
+ langchain: "LangChain",
40
+ "langchain-core": "LangChain",
41
+ "langchain-anthropic": "LangChain (Anthropic)",
42
+ "langchain-openai": "LangChain (OpenAI)",
43
+ llamaindex: "LlamaIndex",
44
+ "llama-index": "LlamaIndex",
45
+ vertexai: "Vertex AI",
46
+ "google-generativeai": "Google Generative AI",
47
+ cohere: "Cohere",
48
+ "boto3": "AWS (boto3)", // bedrock typically uses boto3
49
+ };
50
+ export async function readManifests(rootDir, manifestFiles) {
51
+ const out = [];
52
+ for (const file of manifestFiles) {
53
+ try {
54
+ const raw = await fs.readFile(file, "utf8");
55
+ const base = path.basename(file);
56
+ if (base === "pyproject.toml") {
57
+ out.push(parsePyproject(file, rootDir, raw));
58
+ }
59
+ else if (base === "requirements.txt") {
60
+ out.push(parseRequirementsTxt(file, rootDir, raw));
61
+ }
62
+ }
63
+ catch {
64
+ // skip unreadable / unparsable
65
+ }
66
+ }
67
+ return out;
68
+ }
69
+ function parsePyproject(filePath, rootDir, raw) {
70
+ const result = {
71
+ filePath: relPosix(rootDir, filePath),
72
+ format: "pyproject.toml",
73
+ deps: {},
74
+ };
75
+ let parsed;
76
+ try {
77
+ parsed = TOML.parse(raw);
78
+ }
79
+ catch {
80
+ return result;
81
+ }
82
+ // PEP 621: project.dependencies = ["fastapi >=0.100", ...]
83
+ const projectDeps = parsed?.project?.dependencies;
84
+ if (Array.isArray(projectDeps)) {
85
+ for (const spec of projectDeps) {
86
+ if (typeof spec !== "string")
87
+ continue;
88
+ const [name, version] = splitPep508(spec);
89
+ if (name)
90
+ result.deps[name] = version;
91
+ }
92
+ }
93
+ // PEP 621: optional-dependencies = { test = [...], dev = [...] }
94
+ const opt = parsed?.project?.["optional-dependencies"];
95
+ if (opt && typeof opt === "object") {
96
+ for (const groupSpec of Object.values(opt)) {
97
+ if (!Array.isArray(groupSpec))
98
+ continue;
99
+ for (const spec of groupSpec) {
100
+ if (typeof spec !== "string")
101
+ continue;
102
+ const [name, version] = splitPep508(spec);
103
+ if (name)
104
+ result.deps[name] = version;
105
+ }
106
+ }
107
+ }
108
+ // Poetry: tool.poetry.dependencies = { fastapi = "^0.100" } (also dev-dependencies)
109
+ const poetryDeps = parsed?.tool?.poetry?.dependencies;
110
+ if (poetryDeps && typeof poetryDeps === "object") {
111
+ for (const [name, value] of Object.entries(poetryDeps)) {
112
+ if (name === "python")
113
+ continue;
114
+ const ver = typeof value === "string" ? value : value?.version ?? "*";
115
+ result.deps[name] = String(ver);
116
+ }
117
+ }
118
+ const poetryDevDeps = parsed?.tool?.poetry?.["dev-dependencies"] ?? parsed?.tool?.poetry?.group?.dev?.dependencies;
119
+ if (poetryDevDeps && typeof poetryDevDeps === "object") {
120
+ for (const [name, value] of Object.entries(poetryDevDeps)) {
121
+ if (name === "python")
122
+ continue;
123
+ const ver = typeof value === "string" ? value : value?.version ?? "*";
124
+ result.deps[name] = String(ver);
125
+ }
126
+ }
127
+ return result;
128
+ }
129
+ function parseRequirementsTxt(filePath, rootDir, raw) {
130
+ const result = {
131
+ filePath: relPosix(rootDir, filePath),
132
+ format: "requirements.txt",
133
+ deps: {},
134
+ };
135
+ for (const rawLine of raw.split("\n")) {
136
+ let line = rawLine.trim();
137
+ if (!line || line.startsWith("#"))
138
+ continue;
139
+ if (line.startsWith("-"))
140
+ continue; // -e, -r, -c, --hash, etc.
141
+ // strip inline comments
142
+ const hashAt = line.indexOf(" #");
143
+ if (hashAt > 0)
144
+ line = line.slice(0, hashAt).trim();
145
+ const [name, version] = splitPep508(line);
146
+ if (name)
147
+ result.deps[name] = version;
148
+ }
149
+ return result;
150
+ }
151
+ /** "fastapi>=0.100,<0.110" → ["fastapi", ">=0.100,<0.110"] */
152
+ function splitPep508(spec) {
153
+ // strip extras like fastapi[all]
154
+ const cleaned = spec.replace(/\[[^\]]*\]/g, "").trim();
155
+ const m = cleaned.match(/^([A-Za-z0-9_.\-]+)\s*(.*)$/);
156
+ if (!m)
157
+ return ["", ""];
158
+ return [m[1].toLowerCase(), m[2].trim() || "*"];
159
+ }
160
+ export function summarizeManifests(parsed) {
161
+ return parsed.map((m) => ({
162
+ language: "python",
163
+ file: m.filePath,
164
+ dependencies: m.deps,
165
+ }));
166
+ }
167
+ export function findExternalServices(parsed) {
168
+ const seen = new Map();
169
+ for (const m of parsed) {
170
+ for (const [pkg, vendor] of Object.entries(AI_SDK_PACKAGES)) {
171
+ const ver = m.deps[pkg];
172
+ if (!ver)
173
+ continue;
174
+ const key = `ai_sdk::${pkg}`;
175
+ const existing = seen.get(key);
176
+ if (existing) {
177
+ existing.callSites.push({ file: m.filePath, line: 1 });
178
+ continue;
179
+ }
180
+ seen.set(key, {
181
+ name: vendor,
182
+ kind: "ai_sdk",
183
+ package: pkg,
184
+ version: ver,
185
+ callSites: [{ file: m.filePath, line: 1 }],
186
+ });
187
+ }
188
+ }
189
+ return [...seen.values()];
190
+ }
191
+ export function findDataStores(parsed) {
192
+ const seen = new Map();
193
+ for (const m of parsed) {
194
+ for (const [pkg, info] of Object.entries(DATA_STORE_PACKAGES)) {
195
+ const ver = m.deps[pkg];
196
+ if (!ver)
197
+ continue;
198
+ const key = `${info.kind}::${info.client}`;
199
+ const existing = seen.get(key);
200
+ if (existing) {
201
+ existing.evidence.push({ file: m.filePath, line: 1, kind: "config" });
202
+ continue;
203
+ }
204
+ seen.set(key, {
205
+ name: defaultDataStoreName(info.kind),
206
+ kind: info.kind,
207
+ client: info.client,
208
+ version: ver,
209
+ evidence: [{ file: m.filePath, line: 1, kind: "config" }],
210
+ });
211
+ }
212
+ }
213
+ return [...seen.values()];
214
+ }
215
+ export function detectFrameworkFromManifest(m) {
216
+ for (const [pkg, fw] of Object.entries(WEB_FRAMEWORK_PACKAGES)) {
217
+ if (m.deps[pkg])
218
+ return fw;
219
+ }
220
+ return undefined;
221
+ }
222
+ function defaultDataStoreName(kind) {
223
+ switch (kind) {
224
+ case "postgres": return "postgres";
225
+ case "mysql": return "mysql";
226
+ case "mongo": return "mongo";
227
+ case "redis": return "redis";
228
+ case "sqlite": return "sqlite";
229
+ default: return "data-store";
230
+ }
231
+ }
232
+ function relPosix(rootDir, abs) {
233
+ const rel = path.relative(rootDir, abs);
234
+ return rel.split(path.sep).join("/");
235
+ }
236
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/internal/extractor/adapters/python/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * tree-sitter-python loader.
3
+ */
4
+ import { Parser } from "web-tree-sitter";
5
+ export declare function getPythonParser(): Promise<Parser>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * tree-sitter-python loader.
3
+ */
4
+ import { createRequire } from "node:module";
5
+ import * as path from "node:path";
6
+ import { Parser, Language } from "web-tree-sitter";
7
+ const require = createRequire(import.meta.url);
8
+ let parserPromise = null;
9
+ export function getPythonParser() {
10
+ if (!parserPromise) {
11
+ parserPromise = (async () => {
12
+ await Parser.init();
13
+ const wasmDir = path.dirname(require.resolve("@vscode/tree-sitter-wasm/package.json"));
14
+ const lang = await Language.load(path.join(wasmDir, "wasm", "tree-sitter-python.wasm"));
15
+ const p = new Parser();
16
+ p.setLanguage(lang);
17
+ return p;
18
+ })();
19
+ }
20
+ return parserPromise;
21
+ }
22
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../../../src/internal/extractor/adapters/python/parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,IAAI,aAAa,GAA2B,IAAI,CAAC;AAEjD,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,aAAa,GAAG,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,CAAC;YACvF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;YACxF,MAAM,CAAC,GAAG,IAAI,MAAM,EAAE,CAAC;YACvB,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,EAAE,CAAC;IACP,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * AST scanner for Python source files.
3
+ *
4
+ * Patterns covered:
5
+ * 1. import_statement / import_from_statement → tracked-package imports
6
+ * (AI SDKs, web frameworks, DB clients).
7
+ * 2. Decorator-based routes (FastAPI, Flask):
8
+ * @app.get("/path") → method=GET
9
+ * @app.post("/path") → method=POST
10
+ * @app.route("/path", …) → method=ALL (Flask default; verbs in `methods=` kw not parsed yet)
11
+ * @router.get("/x", …) → method=GET (FastAPI APIRouter convention)
12
+ * 3. Django urls.py-style call: path("/route", view, …) / re_path(…) → method=ALL
13
+ * 4. aiohttp: app.router.add_get("/path", h) / add_post(…) / etc.
14
+ *
15
+ * Privacy invariant: identifier names + dotted attribute names + string
16
+ * literals on routes only. Function bodies and decorator args beyond the
17
+ * route path are never inspected.
18
+ */
19
+ import type { EvidenceLocation, Evidence, HttpRouteEvidence, ImportEvidence } from "../../types.js";
20
+ export interface FileScanResult {
21
+ file: string;
22
+ imports: ImportEvidence[];
23
+ routes: HttpRouteEvidence[];
24
+ }
25
+ export declare function scanFile(absPath: string, repoRel: string): Promise<FileScanResult>;
26
+ export interface ScannedAggregates {
27
+ components: Array<{
28
+ name: string;
29
+ sourceFile: string;
30
+ framework?: string;
31
+ routes: HttpRouteEvidence[];
32
+ imports: ImportEvidence[];
33
+ }>;
34
+ aiSdkCallSites: Map<string, EvidenceLocation[]>;
35
+ dataStoreEvidence: Map<string, Evidence[]>;
36
+ }
37
+ export declare function aggregate(scans: FileScanResult[]): ScannedAggregates;
@@ -0,0 +1,284 @@
1
+ /**
2
+ * AST scanner for Python source files.
3
+ *
4
+ * Patterns covered:
5
+ * 1. import_statement / import_from_statement → tracked-package imports
6
+ * (AI SDKs, web frameworks, DB clients).
7
+ * 2. Decorator-based routes (FastAPI, Flask):
8
+ * @app.get("/path") → method=GET
9
+ * @app.post("/path") → method=POST
10
+ * @app.route("/path", …) → method=ALL (Flask default; verbs in `methods=` kw not parsed yet)
11
+ * @router.get("/x", …) → method=GET (FastAPI APIRouter convention)
12
+ * 3. Django urls.py-style call: path("/route", view, …) / re_path(…) → method=ALL
13
+ * 4. aiohttp: app.router.add_get("/path", h) / add_post(…) / etc.
14
+ *
15
+ * Privacy invariant: identifier names + dotted attribute names + string
16
+ * literals on routes only. Function bodies and decorator args beyond the
17
+ * route path are never inspected.
18
+ */
19
+ import * as fs from "node:fs/promises";
20
+ import { getPythonParser } from "./parser.js";
21
+ import { AI_SDK_PACKAGES, DATA_STORE_PACKAGES, WEB_FRAMEWORK_PACKAGES, } from "./manifest.js";
22
+ const HTTP_METHODS = new Set(["get", "post", "put", "delete", "patch", "head", "options"]);
23
+ const ROUTER_IDENTIFIERS = new Set(["app", "router", "blueprint", "bp", "api"]);
24
+ const DJANGO_PATH_FNS = new Set(["path", "re_path", "url"]);
25
+ const AIOHTTP_ADD_FNS = /^add_(get|post|put|delete|patch|head|options)$/;
26
+ const TRACKED_PACKAGES = new Set([
27
+ ...Object.keys(AI_SDK_PACKAGES),
28
+ ...Object.keys(DATA_STORE_PACKAGES),
29
+ ...Object.keys(WEB_FRAMEWORK_PACKAGES),
30
+ ]);
31
+ export async function scanFile(absPath, repoRel) {
32
+ const parser = await getPythonParser();
33
+ const source = await fs.readFile(absPath, "utf8");
34
+ const tree = parser.parse(source);
35
+ if (!tree)
36
+ return { file: repoRel, imports: [], routes: [] };
37
+ const imports = [];
38
+ const routes = [];
39
+ walk(tree.rootNode, (node) => {
40
+ if (node.type === "import_statement" || node.type === "import_from_statement") {
41
+ const pkgs = extractImportPackages(node);
42
+ for (const pkg of pkgs) {
43
+ if (trackedPackageMatch(pkg)) {
44
+ imports.push({
45
+ kind: "import",
46
+ file: repoRel,
47
+ line: node.startPosition.row + 1,
48
+ package: pkg,
49
+ });
50
+ }
51
+ }
52
+ return;
53
+ }
54
+ if (node.type === "decorator") {
55
+ const route = extractDecoratorRoute(node);
56
+ if (route) {
57
+ routes.push({
58
+ kind: "http_route",
59
+ file: repoRel,
60
+ line: node.startPosition.row + 1,
61
+ method: route.method,
62
+ path: route.path,
63
+ });
64
+ }
65
+ return;
66
+ }
67
+ if (node.type === "call") {
68
+ const route = extractCallRoute(node);
69
+ if (route) {
70
+ routes.push({
71
+ kind: "http_route",
72
+ file: repoRel,
73
+ line: node.startPosition.row + 1,
74
+ method: route.method,
75
+ path: route.path,
76
+ });
77
+ }
78
+ }
79
+ });
80
+ return { file: repoRel, imports, routes };
81
+ }
82
+ function walk(node, visit) {
83
+ visit(node);
84
+ for (let i = 0; i < node.namedChildCount; i++) {
85
+ const child = node.namedChild(i);
86
+ if (child)
87
+ walk(child, visit);
88
+ }
89
+ }
90
+ /**
91
+ * Pull the top-level package(s) out of an import statement.
92
+ *
93
+ * - `import anthropic` → ["anthropic"]
94
+ * - `import langchain.chat_models` → ["langchain"] (we track the root)
95
+ * - `from fastapi import FastAPI` → ["fastapi"]
96
+ * - `from langchain.schema import HumanMessage` → ["langchain"]
97
+ *
98
+ * Sub-modules collapse to the root because the manifest table is keyed
99
+ * by distribution name, which is also the import root for the packages
100
+ * we care about.
101
+ */
102
+ function extractImportPackages(node) {
103
+ const out = [];
104
+ if (node.type === "import_from_statement") {
105
+ // import_from_statement → module_name as the "module" field
106
+ const moduleField = node.childForFieldName("module_name");
107
+ if (moduleField) {
108
+ const root = topLevelImportName(moduleField);
109
+ if (root)
110
+ out.push(root);
111
+ }
112
+ return out;
113
+ }
114
+ // import_statement: one or more dotted_name (or aliased_import wrapping it)
115
+ for (const child of node.namedChildren) {
116
+ if (!child)
117
+ continue;
118
+ if (child.type === "dotted_name") {
119
+ const root = topLevelImportName(child);
120
+ if (root)
121
+ out.push(root);
122
+ }
123
+ else if (child.type === "aliased_import") {
124
+ const inner = child.childForFieldName("name") ?? child.namedChildren[0];
125
+ if (inner) {
126
+ const root = topLevelImportName(inner);
127
+ if (root)
128
+ out.push(root);
129
+ }
130
+ }
131
+ }
132
+ return out;
133
+ }
134
+ function topLevelImportName(node) {
135
+ const text = node.text;
136
+ if (!text)
137
+ return null;
138
+ const root = text.split(".")[0].trim();
139
+ return root || null;
140
+ }
141
+ function trackedPackageMatch(pkg) {
142
+ return TRACKED_PACKAGES.has(pkg) ? pkg : null;
143
+ }
144
+ /**
145
+ * Match @app.get("/path"), @router.post(…), @app.route("/x", …).
146
+ * Returns the route + method, or null if it isn't a known shape.
147
+ */
148
+ function extractDecoratorRoute(node) {
149
+ // decorator → `@` + (call | attribute | identifier)
150
+ // We only care about call shapes: @app.get("/path", …)
151
+ const callNode = node.namedChildren.find((c) => c?.type === "call");
152
+ if (!callNode)
153
+ return null;
154
+ const fn = callNode.childForFieldName("function");
155
+ const args = callNode.childForFieldName("arguments");
156
+ if (!fn || !args)
157
+ return null;
158
+ if (fn.type !== "attribute")
159
+ return null;
160
+ const objectNode = fn.childForFieldName("object");
161
+ const attrNode = fn.childForFieldName("attribute");
162
+ if (!objectNode || !attrNode)
163
+ return null;
164
+ const objectName = objectNode.text.toLowerCase();
165
+ const attrName = attrNode.text.toLowerCase();
166
+ // Object must be a router-y identifier — keep the false-positive surface
167
+ // tight even though we'd lose decorators on uncommon names like `myapi`.
168
+ if (!ROUTER_IDENTIFIERS.has(objectName))
169
+ return null;
170
+ let method = null;
171
+ if (HTTP_METHODS.has(attrName))
172
+ method = attrName.toUpperCase();
173
+ else if (attrName === "route")
174
+ method = "ALL"; // Flask default; verbs in methods= kwarg not yet parsed
175
+ if (!method)
176
+ return null;
177
+ return readRoutePath(args, method);
178
+ }
179
+ /**
180
+ * Match Django path("/route", view, …) / re_path(…) and aiohttp
181
+ * app.router.add_get("/path", h) / add_post(…) etc.
182
+ */
183
+ function extractCallRoute(node) {
184
+ const fn = node.childForFieldName("function");
185
+ const args = node.childForFieldName("arguments");
186
+ if (!fn || !args)
187
+ return null;
188
+ // Django: bare identifier function, e.g. `path("/route", view)`.
189
+ if (fn.type === "identifier") {
190
+ const name = fn.text;
191
+ if (!DJANGO_PATH_FNS.has(name))
192
+ return null;
193
+ return readRoutePath(args, "ALL");
194
+ }
195
+ // aiohttp: app.router.add_get("/path", h) — attribute call where the
196
+ // method name is encoded into the attribute (add_get, add_post, …).
197
+ if (fn.type === "attribute") {
198
+ const attrNode = fn.childForFieldName("attribute");
199
+ if (!attrNode)
200
+ return null;
201
+ const m = attrNode.text.match(AIOHTTP_ADD_FNS);
202
+ if (!m)
203
+ return null;
204
+ return readRoutePath(args, m[1].toUpperCase());
205
+ }
206
+ return null;
207
+ }
208
+ /** Pull the first positional string-literal argument as the route path. */
209
+ function readRoutePath(argsNode, method) {
210
+ for (const arg of argsNode.namedChildren) {
211
+ if (!arg)
212
+ continue;
213
+ // Skip kwargs (we only want the first positional).
214
+ if (arg.type === "keyword_argument")
215
+ continue;
216
+ if (arg.type !== "string")
217
+ return null;
218
+ // string → string_start, string_content, string_end
219
+ const content = arg.namedChildren.find((c) => c?.type === "string_content");
220
+ if (!content) {
221
+ // fall back: strip leading/trailing quote chars from raw text
222
+ const text = arg.text;
223
+ if (text.length >= 2 && (text.startsWith('"') || text.startsWith("'"))) {
224
+ return { method, path: text.slice(1, -1) };
225
+ }
226
+ return null;
227
+ }
228
+ return { method, path: content.text };
229
+ }
230
+ return null;
231
+ }
232
+ export function aggregate(scans) {
233
+ const components = [];
234
+ const aiSdkCallSites = new Map();
235
+ const dataStoreEvidence = new Map();
236
+ for (const s of scans) {
237
+ if (s.routes.length === 0 && s.imports.length === 0)
238
+ continue;
239
+ for (const imp of s.imports) {
240
+ if (AI_SDK_PACKAGES[imp.package]) {
241
+ const arr = aiSdkCallSites.get(imp.package) ?? [];
242
+ arr.push({ file: imp.file, line: imp.line });
243
+ aiSdkCallSites.set(imp.package, arr);
244
+ }
245
+ if (DATA_STORE_PACKAGES[imp.package]) {
246
+ const key = DATA_STORE_PACKAGES[imp.package].client;
247
+ const arr = dataStoreEvidence.get(key) ?? [];
248
+ arr.push({ kind: "import", file: imp.file, line: imp.line, package: imp.package });
249
+ dataStoreEvidence.set(key, arr);
250
+ }
251
+ }
252
+ if (s.routes.length === 0)
253
+ continue;
254
+ const name = deriveComponentName(s.file);
255
+ const framework = detectFrameworkFromImports(s.imports);
256
+ components.push({
257
+ name,
258
+ sourceFile: s.file,
259
+ framework,
260
+ routes: s.routes,
261
+ imports: s.imports,
262
+ });
263
+ }
264
+ return { components, aiSdkCallSites, dataStoreEvidence };
265
+ }
266
+ function deriveComponentName(filePath) {
267
+ const segs = filePath.split("/");
268
+ // Skip common project-layout prefixes.
269
+ const skipPrefixes = new Set(["src", "app", "apps", "backend", "api"]);
270
+ const start = skipPrefixes.has(segs[0]) ? 1 : 0;
271
+ if (segs.length - start >= 2)
272
+ return segs[start];
273
+ const last = segs[segs.length - 1];
274
+ return last.replace(/\.py$/, "");
275
+ }
276
+ function detectFrameworkFromImports(imports) {
277
+ for (const imp of imports) {
278
+ const fw = WEB_FRAMEWORK_PACKAGES[imp.package];
279
+ if (fw)
280
+ return fw;
281
+ }
282
+ return undefined;
283
+ }
284
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../../../src/internal/extractor/adapters/python/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * TypeScript / JavaScript language adapter.
3
+ *
4
+ * Handles .ts/.tsx/.js/.jsx + package.json. Combines manifest analysis
5
+ * (cheap, runs against package.json) with AST scanning (per source file)
6
+ * to produce components, external services, and data stores.
7
+ */
8
+ import type { LanguageAdapter } from "../../types.js";
9
+ export declare const typescriptAdapter: LanguageAdapter;