@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.
- package/dist/commands/app/index.d.ts +10 -0
- package/dist/commands/app/index.js +245 -0
- package/dist/commands/app/index.js.map +1 -0
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +41 -0
- package/dist/commands/auth/index.js.map +1 -0
- package/dist/commands/auth/login.d.ts +8 -0
- package/dist/commands/auth/login.js +65 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.d.ts +5 -0
- package/dist/commands/auth/logout.js +14 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/auth/sessions.d.ts +4 -0
- package/dist/commands/auth/sessions.js +30 -0
- package/dist/commands/auth/sessions.js.map +1 -0
- package/dist/commands/auth/status.d.ts +4 -0
- package/dist/commands/auth/status.js +53 -0
- package/dist/commands/auth/status.js.map +1 -0
- package/dist/commands/credits/index.d.ts +2 -0
- package/dist/commands/credits/index.js +51 -0
- package/dist/commands/credits/index.js.map +1 -0
- package/dist/commands/mcp/index.d.ts +2 -0
- package/dist/commands/mcp/index.js +70 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/open/index.d.ts +10 -0
- package/dist/commands/open/index.js +57 -0
- package/dist/commands/open/index.js.map +1 -0
- package/dist/commands/scan/index.d.ts +2 -0
- package/dist/commands/scan/index.js +140 -0
- package/dist/commands/scan/index.js.map +1 -0
- package/dist/commands/target/index.d.ts +2 -0
- package/dist/commands/target/index.js +146 -0
- package/dist/commands/target/index.js.map +1 -0
- package/dist/commands/tm/index.d.ts +2 -0
- package/dist/commands/tm/index.js +266 -0
- package/dist/commands/tm/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/extractor/adapters/go/index.d.ts +7 -0
- package/dist/internal/extractor/adapters/go/index.js +71 -0
- package/dist/internal/extractor/adapters/go/index.js.map +1 -0
- package/dist/internal/extractor/adapters/go/manifest.d.ts +37 -0
- package/dist/internal/extractor/adapters/go/manifest.js +199 -0
- package/dist/internal/extractor/adapters/go/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/go/parser.d.ts +6 -0
- package/dist/internal/extractor/adapters/go/parser.js +23 -0
- package/dist/internal/extractor/adapters/go/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/go/scanner.d.ts +39 -0
- package/dist/internal/extractor/adapters/go/scanner.js +216 -0
- package/dist/internal/extractor/adapters/go/scanner.js.map +1 -0
- package/dist/internal/extractor/adapters/python/index.d.ts +5 -0
- package/dist/internal/extractor/adapters/python/index.js +68 -0
- package/dist/internal/extractor/adapters/python/index.js.map +1 -0
- package/dist/internal/extractor/adapters/python/manifest.d.ts +25 -0
- package/dist/internal/extractor/adapters/python/manifest.js +236 -0
- package/dist/internal/extractor/adapters/python/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/python/parser.d.ts +5 -0
- package/dist/internal/extractor/adapters/python/parser.js +22 -0
- package/dist/internal/extractor/adapters/python/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/python/scanner.d.ts +37 -0
- package/dist/internal/extractor/adapters/python/scanner.js +284 -0
- package/dist/internal/extractor/adapters/python/scanner.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/index.d.ts +9 -0
- package/dist/internal/extractor/adapters/typescript/index.js +84 -0
- package/dist/internal/extractor/adapters/typescript/index.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/manifest.d.ts +41 -0
- package/dist/internal/extractor/adapters/typescript/manifest.js +156 -0
- package/dist/internal/extractor/adapters/typescript/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/parser.d.ts +14 -0
- package/dist/internal/extractor/adapters/typescript/parser.js +33 -0
- package/dist/internal/extractor/adapters/typescript/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/scanner.d.ts +43 -0
- package/dist/internal/extractor/adapters/typescript/scanner.js +188 -0
- package/dist/internal/extractor/adapters/typescript/scanner.js.map +1 -0
- package/dist/internal/extractor/index.d.ts +22 -0
- package/dist/internal/extractor/index.js +107 -0
- package/dist/internal/extractor/index.js.map +1 -0
- package/dist/internal/extractor/types.d.ts +124 -0
- package/dist/internal/extractor/types.js +28 -0
- package/dist/internal/extractor/types.js.map +1 -0
- package/dist/internal/extractor/walker.d.ts +32 -0
- package/dist/internal/extractor/walker.js +110 -0
- package/dist/internal/extractor/walker.js.map +1 -0
- package/dist/internal/ide-setup.d.ts +7 -0
- package/dist/internal/ide-setup.js +131 -0
- package/dist/internal/ide-setup.js.map +1 -0
- package/dist/internal/orgs.d.ts +8 -0
- package/dist/internal/orgs.js +31 -0
- package/dist/internal/orgs.js.map +1 -0
- package/dist/internal/project-binding.d.ts +11 -0
- package/dist/internal/project-binding.js +96 -0
- package/dist/internal/project-binding.js.map +1 -0
- package/dist/internal/target-auth/api-config.d.ts +37 -0
- package/dist/internal/target-auth/api-config.js +40 -0
- package/dist/internal/target-auth/api-config.js.map +1 -0
- package/dist/internal/target-auth/config.d.ts +20 -0
- package/dist/internal/target-auth/config.js +58 -0
- package/dist/internal/target-auth/config.js.map +1 -0
- package/dist/internal/target-auth/index.d.ts +30 -0
- package/dist/internal/target-auth/index.js +101 -0
- package/dist/internal/target-auth/index.js.map +1 -0
- package/dist/internal/target-auth/keychain.d.ts +23 -0
- package/dist/internal/target-auth/keychain.js +150 -0
- package/dist/internal/target-auth/keychain.js.map +1 -0
- package/dist/internal/target-auth/types.d.ts +51 -0
- package/dist/internal/target-auth/types.js +11 -0
- package/dist/internal/target-auth/types.js.map +1 -0
- package/dist/internal/target-auth/workos.d.ts +20 -0
- package/dist/internal/target-auth/workos.js +196 -0
- package/dist/internal/target-auth/workos.js.map +1 -0
- 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,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;
|