@cr8rcho/alkahest 0.1.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/README.ko.md +208 -0
- package/README.md +208 -0
- package/dist/assets/dashboard.html +647 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +68 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/hook.d.ts +1 -0
- package/dist/commands/hook.js +64 -0
- package/dist/commands/hook.js.map +1 -0
- package/dist/commands/login.d.ts +11 -0
- package/dist/commands/login.js +27 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/mcp.d.ts +6 -0
- package/dist/commands/mcp.js +13 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/publish.d.ts +19 -0
- package/dist/commands/publish.js +27 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/scan.d.ts +11 -0
- package/dist/commands/scan.js +29 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/update.d.ts +15 -0
- package/dist/commands/update.js +41 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/view.d.ts +6 -0
- package/dist/commands/view.js +21 -0
- package/dist/commands/view.js.map +1 -0
- package/dist/core/adapters/angular.d.ts +2 -0
- package/dist/core/adapters/angular.js +305 -0
- package/dist/core/adapters/angular.js.map +1 -0
- package/dist/core/adapters/astro.d.ts +3 -0
- package/dist/core/adapters/astro.js +140 -0
- package/dist/core/adapters/astro.js.map +1 -0
- package/dist/core/adapters/compose.d.ts +2 -0
- package/dist/core/adapters/compose.js +195 -0
- package/dist/core/adapters/compose.js.map +1 -0
- package/dist/core/adapters/django.d.ts +2 -0
- package/dist/core/adapters/django.js +314 -0
- package/dist/core/adapters/django.js.map +1 -0
- package/dist/core/adapters/expo-router.d.ts +2 -0
- package/dist/core/adapters/expo-router.js +60 -0
- package/dist/core/adapters/expo-router.js.map +1 -0
- package/dist/core/adapters/flask.d.ts +2 -0
- package/dist/core/adapters/flask.js +249 -0
- package/dist/core/adapters/flask.js.map +1 -0
- package/dist/core/adapters/flutter.d.ts +2 -0
- package/dist/core/adapters/flutter.js +232 -0
- package/dist/core/adapters/flutter.js.map +1 -0
- package/dist/core/adapters/index.d.ts +19 -0
- package/dist/core/adapters/index.js +59 -0
- package/dist/core/adapters/index.js.map +1 -0
- package/dist/core/adapters/next-app.d.ts +2 -0
- package/dist/core/adapters/next-app.js +62 -0
- package/dist/core/adapters/next-app.js.map +1 -0
- package/dist/core/adapters/next-pages.d.ts +2 -0
- package/dist/core/adapters/next-pages.js +70 -0
- package/dist/core/adapters/next-pages.js.map +1 -0
- package/dist/core/adapters/nuxt.d.ts +2 -0
- package/dist/core/adapters/nuxt.js +59 -0
- package/dist/core/adapters/nuxt.js.map +1 -0
- package/dist/core/adapters/rails.d.ts +2 -0
- package/dist/core/adapters/rails.js +275 -0
- package/dist/core/adapters/rails.js.map +1 -0
- package/dist/core/adapters/react-jsx.d.ts +68 -0
- package/dist/core/adapters/react-jsx.js +355 -0
- package/dist/core/adapters/react-jsx.js.map +1 -0
- package/dist/core/adapters/react-navigation.d.ts +2 -0
- package/dist/core/adapters/react-navigation.js +153 -0
- package/dist/core/adapters/react-navigation.js.map +1 -0
- package/dist/core/adapters/react-router.d.ts +2 -0
- package/dist/core/adapters/react-router.js +249 -0
- package/dist/core/adapters/react-router.js.map +1 -0
- package/dist/core/adapters/remix.d.ts +2 -0
- package/dist/core/adapters/remix.js +109 -0
- package/dist/core/adapters/remix.js.map +1 -0
- package/dist/core/adapters/static-html.d.ts +2 -0
- package/dist/core/adapters/static-html.js +157 -0
- package/dist/core/adapters/static-html.js.map +1 -0
- package/dist/core/adapters/sveltekit.d.ts +2 -0
- package/dist/core/adapters/sveltekit.js +151 -0
- package/dist/core/adapters/sveltekit.js.map +1 -0
- package/dist/core/adapters/swiftui.d.ts +2 -0
- package/dist/core/adapters/swiftui.js +216 -0
- package/dist/core/adapters/swiftui.js.map +1 -0
- package/dist/core/adapters/types.d.ts +65 -0
- package/dist/core/adapters/types.js +2 -0
- package/dist/core/adapters/types.js.map +1 -0
- package/dist/core/adapters/uikit.d.ts +2 -0
- package/dist/core/adapters/uikit.js +178 -0
- package/dist/core/adapters/uikit.js.map +1 -0
- package/dist/core/adapters/vue-router.d.ts +2 -0
- package/dist/core/adapters/vue-router.js +224 -0
- package/dist/core/adapters/vue-router.js.map +1 -0
- package/dist/core/adapters/vue-sfc.d.ts +28 -0
- package/dist/core/adapters/vue-sfc.js +132 -0
- package/dist/core/adapters/vue-sfc.js.map +1 -0
- package/dist/core/credentials.d.ts +24 -0
- package/dist/core/credentials.js +30 -0
- package/dist/core/credentials.js.map +1 -0
- package/dist/core/dashboard.d.ts +9 -0
- package/dist/core/dashboard.js +20 -0
- package/dist/core/dashboard.js.map +1 -0
- package/dist/core/emit.d.ts +7 -0
- package/dist/core/emit.js +23 -0
- package/dist/core/emit.js.map +1 -0
- package/dist/core/hash.d.ts +2 -0
- package/dist/core/hash.js +6 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/pipeline.d.ts +25 -0
- package/dist/core/pipeline.js +122 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/publish.d.ts +31 -0
- package/dist/core/publish.js +87 -0
- package/dist/core/publish.js.map +1 -0
- package/dist/core/resolve.d.ts +42 -0
- package/dist/core/resolve.js +128 -0
- package/dist/core/resolve.js.map +1 -0
- package/dist/core/serve.d.ts +5 -0
- package/dist/core/serve.js +52 -0
- package/dist/core/serve.js.map +1 -0
- package/dist/core/types.d.ts +117 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/version.d.ts +23 -0
- package/dist/core/version.js +102 -0
- package/dist/core/version.js.map +1 -0
- package/dist/mcp/server.d.ts +7 -0
- package/dist/mcp/server.js +224 -0
- package/dist/mcp/server.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join, relative, sep } from "node:path";
|
|
3
|
+
// endpoint(view-fn name) → route, rebuilt each discover() and read by parse().
|
|
4
|
+
let endpointToRoute = new Map();
|
|
5
|
+
let routeToInfo = new Map();
|
|
6
|
+
export const flaskAdapter = {
|
|
7
|
+
id: "flask",
|
|
8
|
+
router: "flask-routes",
|
|
9
|
+
detect(projectRoot) {
|
|
10
|
+
let found = false;
|
|
11
|
+
walkPy(projectRoot, (file) => {
|
|
12
|
+
if (found)
|
|
13
|
+
return;
|
|
14
|
+
const src = safeRead(file);
|
|
15
|
+
if (/\bFlask\s*\(\s*__name__/.test(src) || /@(?:app|bp|\w+)\.route\s*\(/.test(src))
|
|
16
|
+
found = true;
|
|
17
|
+
});
|
|
18
|
+
return found;
|
|
19
|
+
},
|
|
20
|
+
discover(projectRoot) {
|
|
21
|
+
endpointToRoute = new Map();
|
|
22
|
+
routeToInfo = new Map();
|
|
23
|
+
const files = [];
|
|
24
|
+
const usedRelPaths = new Set();
|
|
25
|
+
walkPy(projectRoot, (file) => {
|
|
26
|
+
const src = safeRead(file);
|
|
27
|
+
const blueprints = blueprintInfo(src); // Blueprint var → {name, url_prefix}
|
|
28
|
+
for (const r of routesInFile(src, file, blueprints)) {
|
|
29
|
+
if (routeToInfo.has(r.route))
|
|
30
|
+
continue; // first declaration wins
|
|
31
|
+
// Resolve the template now so it's the screen's file (1:1 with the route) and its relPath key.
|
|
32
|
+
if (r.template)
|
|
33
|
+
r.templateFile = resolveTemplate(projectRoot, r.template);
|
|
34
|
+
routeToInfo.set(r.route, r);
|
|
35
|
+
endpointToRoute.set(r.endpoint, r.route);
|
|
36
|
+
const repr = r.templateFile ?? r.viewFile;
|
|
37
|
+
let relPath = relative(projectRoot, repr).split(sep).join("/");
|
|
38
|
+
if (usedRelPaths.has(relPath))
|
|
39
|
+
relPath = `${relPath}#${r.route}`;
|
|
40
|
+
usedRelPaths.add(relPath);
|
|
41
|
+
files.push({
|
|
42
|
+
absPath: repr,
|
|
43
|
+
relPath,
|
|
44
|
+
id: r.route,
|
|
45
|
+
route: r.route,
|
|
46
|
+
title: titleFromRoute(r.route, r.endpoint),
|
|
47
|
+
isEntry: r.route === "/",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
files.sort((a, b) => a.route.localeCompare(b.route));
|
|
52
|
+
return files;
|
|
53
|
+
},
|
|
54
|
+
parse(file) {
|
|
55
|
+
const info = routeToInfo.get(file.id);
|
|
56
|
+
const viewSrc = info ? viewBody(safeRead(info.viewFile), info.fn) : "";
|
|
57
|
+
const templateSrc = info?.templateFile ? safeRead(info.templateFile) : "";
|
|
58
|
+
return parseFlask(viewSrc, templateSrc);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
// ---------- route discovery ----------
|
|
62
|
+
const ROUTE_DECORATOR = /@(\w+)\.route\s*\(\s*["']([^"']+)["']/;
|
|
63
|
+
const DEF_LINE = /^def\s+(\w+)\s*\(/;
|
|
64
|
+
const RENDER = /render_template\s*\(\s*["']([^"']+)["']/;
|
|
65
|
+
// `bp = Blueprint("blog", __name__, url_prefix="/blog")` — name is the 1st arg, url_prefix optional.
|
|
66
|
+
const BLUEPRINT = /(\w+)\s*=\s*Blueprint\s*\(\s*["']([^"']+)["'][^)]*?(?:url_prefix\s*=\s*["']([^"']+)["'])?\s*\)/g;
|
|
67
|
+
/** Blueprint variable → {name, url_prefix}. A `@bp.route('/x')` becomes route `<prefix>/x`, endpoint `<name>.<fn>`. */
|
|
68
|
+
function blueprintInfo(src) {
|
|
69
|
+
const map = new Map();
|
|
70
|
+
for (const m of src.matchAll(BLUEPRINT))
|
|
71
|
+
map.set(m[1], { name: m[2], prefix: m[3] ?? "" });
|
|
72
|
+
return map;
|
|
73
|
+
}
|
|
74
|
+
/** Every `@x.route('/path')`-decorated view fn in a file → its route + endpoint + template. */
|
|
75
|
+
function routesInFile(src, file, blueprints) {
|
|
76
|
+
const lines = src.split(/\r?\n/);
|
|
77
|
+
const out = [];
|
|
78
|
+
for (let i = 0; i < lines.length; i++) {
|
|
79
|
+
const dec = lines[i].trim().match(ROUTE_DECORATOR);
|
|
80
|
+
if (!dec)
|
|
81
|
+
continue;
|
|
82
|
+
const decoratorVar = dec[1];
|
|
83
|
+
const path = dec[2];
|
|
84
|
+
// The decorated function is the next `def` line (skipping additional decorators).
|
|
85
|
+
let j = i + 1;
|
|
86
|
+
while (j < lines.length && /^\s*@/.test(lines[j]))
|
|
87
|
+
j++;
|
|
88
|
+
const defM = lines[j]?.trim().match(DEF_LINE);
|
|
89
|
+
if (!defM)
|
|
90
|
+
continue;
|
|
91
|
+
const fn = defM[1];
|
|
92
|
+
const bp = blueprints.get(decoratorVar);
|
|
93
|
+
// Blueprint routes carry the prefix on the path and a `<bpName>.<fn>` endpoint (how url_for refers to them).
|
|
94
|
+
const route = joinRoute(bp?.prefix ?? "", path);
|
|
95
|
+
const endpoint = bp ? `${bp.name}.${fn}` : fn;
|
|
96
|
+
const template = templateOfBody(lines, j);
|
|
97
|
+
out.push({ route, endpoint, fn, viewFile: file, template, templateFile: null });
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
/** First render_template('x.html') in the fn body (from its def line to the next top-level def). */
|
|
102
|
+
function templateOfBody(lines, defLine) {
|
|
103
|
+
for (let i = defLine; i < lines.length; i++) {
|
|
104
|
+
if (i > defLine && /^\S/.test(lines[i]) && /^(?:def|@)\b/.test(lines[i].trim()))
|
|
105
|
+
break;
|
|
106
|
+
const m = lines[i].match(RENDER);
|
|
107
|
+
if (m)
|
|
108
|
+
return m[1];
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
/** Resolve a Jinja template name to a file under any `templates/` dir. */
|
|
113
|
+
function resolveTemplate(projectRoot, name) {
|
|
114
|
+
let hit = null;
|
|
115
|
+
walkExt(projectRoot, [".html"], (file) => {
|
|
116
|
+
if (hit)
|
|
117
|
+
return;
|
|
118
|
+
const norm = file.split(sep).join("/");
|
|
119
|
+
if (norm.endsWith("/templates/" + name) || norm.endsWith("/" + name))
|
|
120
|
+
hit = file;
|
|
121
|
+
});
|
|
122
|
+
return hit;
|
|
123
|
+
}
|
|
124
|
+
/** Body of view fn `endpoint` — its def line to the next top-level def/decorator. */
|
|
125
|
+
function viewBody(src, endpoint) {
|
|
126
|
+
const lines = src.split("\n");
|
|
127
|
+
const start = lines.findIndex((l) => new RegExp(`^def\\s+${endpoint}\\s*\\(`).test(l));
|
|
128
|
+
if (start < 0)
|
|
129
|
+
return "";
|
|
130
|
+
const out = [lines[start]];
|
|
131
|
+
for (let i = start + 1; i < lines.length; i++) {
|
|
132
|
+
if (/^\S/.test(lines[i]) && /^(?:def|@)\b/.test(lines[i]))
|
|
133
|
+
break;
|
|
134
|
+
out.push(lines[i]);
|
|
135
|
+
}
|
|
136
|
+
return out.join("\n");
|
|
137
|
+
}
|
|
138
|
+
// ---------- signal extraction (view body + template) ----------
|
|
139
|
+
const URL_FOR = /\burl_for\s*\(\s*["']([^"']+)["']/;
|
|
140
|
+
const HREF = /<a\b[^>]*?\shref=["']([^"'#{]+)["']/i;
|
|
141
|
+
const REDIRECT_URLFOR = /\bredirect\s*\(\s*url_for\s*\(\s*["']([^"']+)["']/;
|
|
142
|
+
const REDIRECT_PATH = /\bredirect\s*\(\s*["'](\/[^"']*)["']/;
|
|
143
|
+
const HTTP_CALL = /\brequests\.(get|post|put|delete|patch)\s*\(\s*["']([^"']+)["']/;
|
|
144
|
+
const QUERY_CALL = /\b([A-Z]\w*)\.query\.(all|filter|filter_by|get|get_or_404|first|count)\b/;
|
|
145
|
+
const FORM_ACTION = /<form\b[^>]*?\saction=["']([^"']+)["']/i;
|
|
146
|
+
const FEATURE_RULES = [
|
|
147
|
+
{ re: /<button\b[^>]*>([^<]*)/i, kind: "button", label: (m) => m[1].trim() || "Button" },
|
|
148
|
+
{ re: /<(?:input|textarea|select)\b[^>]*\bplaceholder=["']([^"']*)["']/i, kind: "input", label: (m) => m[1] || "Input" },
|
|
149
|
+
{ re: /<(?:input|textarea|select)\b/i, kind: "input", label: () => "Input" },
|
|
150
|
+
{ re: /<form\b/i, kind: "form", label: () => "Form" },
|
|
151
|
+
];
|
|
152
|
+
function parseFlask(viewSrc, templateSrc) {
|
|
153
|
+
const navs = [];
|
|
154
|
+
const calls = [];
|
|
155
|
+
const features = [];
|
|
156
|
+
// --- view body: redirects + data calls ---
|
|
157
|
+
viewSrc.split(/\r?\n/).forEach((rawLine, i) => {
|
|
158
|
+
const line = rawLine.trim();
|
|
159
|
+
const redFor = line.match(REDIRECT_URLFOR);
|
|
160
|
+
const redPath = line.match(REDIRECT_PATH);
|
|
161
|
+
if (redFor)
|
|
162
|
+
navs.push({ target: endpointToRoute.get(redFor[1]) ?? null, raw: snippet(line), trigger: "redirect()", line: i + 1 });
|
|
163
|
+
else if (redPath)
|
|
164
|
+
navs.push({ target: normalize(redPath[1]), raw: snippet(line), trigger: "redirect()", line: i + 1 });
|
|
165
|
+
const httpM = line.match(HTTP_CALL);
|
|
166
|
+
if (httpM)
|
|
167
|
+
calls.push({ url: httpM[2], method: httpM[1].toUpperCase(), raw: snippet(line), trigger: "requests", line: i + 1 });
|
|
168
|
+
const q = line.match(QUERY_CALL);
|
|
169
|
+
if (q)
|
|
170
|
+
calls.push({ url: `${q[1]}.${q[2]}`, raw: snippet(line), trigger: "query", line: i + 1 });
|
|
171
|
+
});
|
|
172
|
+
// --- template: url_for() + <a href> nav, <form action> calls, features ---
|
|
173
|
+
templateSrc.split(/\r?\n/).forEach((rawLine, i) => {
|
|
174
|
+
const line = rawLine.trim();
|
|
175
|
+
const uf = line.match(URL_FOR);
|
|
176
|
+
if (uf && !/['"]static['"]/.test(uf[0])) {
|
|
177
|
+
navs.push({ target: endpointToRoute.get(uf[1]) ?? null, raw: snippet(line), trigger: "url_for()", line: i + 1 });
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
const href = line.match(HREF);
|
|
181
|
+
if (href)
|
|
182
|
+
navs.push({ target: normalize(href[1]), raw: snippet(line), trigger: "<a href>", line: i + 1 });
|
|
183
|
+
}
|
|
184
|
+
const action = line.match(FORM_ACTION);
|
|
185
|
+
if (action)
|
|
186
|
+
calls.push({ url: action[1], method: "POST", raw: snippet(line), trigger: "<form action>", line: i + 1 });
|
|
187
|
+
for (const rule of FEATURE_RULES) {
|
|
188
|
+
const m = line.match(rule.re);
|
|
189
|
+
if (m) {
|
|
190
|
+
features.push({ kind: rule.kind, label: rule.label(m), detail: m[0].trim().slice(0, 40), line: i + 1 });
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return { navs, calls, features, components: [], contains: [] };
|
|
196
|
+
}
|
|
197
|
+
// ---------- helpers ----------
|
|
198
|
+
function joinRoute(prefix, path) {
|
|
199
|
+
const combined = (prefix + path).replace(/\/{2,}/g, "/");
|
|
200
|
+
let r = combined.startsWith("/") ? combined : "/" + combined;
|
|
201
|
+
if (r.length > 1)
|
|
202
|
+
r = r.replace(/\/+$/, "");
|
|
203
|
+
return r === "" ? "/" : r;
|
|
204
|
+
}
|
|
205
|
+
function normalize(path) {
|
|
206
|
+
let r = path.startsWith("/") ? path : "/" + path;
|
|
207
|
+
r = r.replace(/\/{2,}/g, "/");
|
|
208
|
+
return r.length > 1 ? r.replace(/\/+$/, "") : "/";
|
|
209
|
+
}
|
|
210
|
+
function titleFromRoute(route, endpoint) {
|
|
211
|
+
if (route === "/")
|
|
212
|
+
return "Home";
|
|
213
|
+
const base = endpoint || route.split("/").filter((s) => s && !s.startsWith("<")).pop() || route;
|
|
214
|
+
return base.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
215
|
+
}
|
|
216
|
+
function walkPy(dir, onFile) {
|
|
217
|
+
walkExt(dir, [".py"], onFile);
|
|
218
|
+
}
|
|
219
|
+
function walkExt(dir, exts, onFile) {
|
|
220
|
+
let entries;
|
|
221
|
+
try {
|
|
222
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
for (const entry of entries) {
|
|
228
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "__pycache__")
|
|
229
|
+
continue;
|
|
230
|
+
const full = join(dir, entry.name);
|
|
231
|
+
if (entry.isDirectory())
|
|
232
|
+
walkExt(full, exts, onFile);
|
|
233
|
+
else if (exts.some((e) => entry.name.endsWith(e)))
|
|
234
|
+
onFile(full);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function safeRead(file) {
|
|
238
|
+
try {
|
|
239
|
+
return readFileSync(file, "utf8");
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return "";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function snippet(text) {
|
|
246
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
247
|
+
return flat.length > 80 ? flat.slice(0, 77) + "..." : flat;
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=flask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flask.js","sourceRoot":"","sources":["../../../src/core/adapters/flask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join, relative, sep, basename } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Flutter adapter (Dart). Pairs with swiftui/uikit/compose as the native set. Dart can't reuse
|
|
5
|
+
* any JS parser, so this is a zero-dependency line/regex scan (swiftui's style).
|
|
6
|
+
*
|
|
7
|
+
* Screen = a page-level Widget: `class X extends StatelessWidget|StatefulWidget`. id = class name.
|
|
8
|
+
* Navigation has three flavours, all resolved to a target screen:
|
|
9
|
+
* - imperative: Navigator.push(context, MaterialPageRoute(builder: (_) => DetailsScreen())) → DetailsScreen
|
|
10
|
+
* - named: Navigator.pushNamed(context, '/details') → via the `routes:` table (route → widget)
|
|
11
|
+
* - go_router: context.go('/details') / context.push('/details') / GoRoute(path:'/details', builder: … Widget)
|
|
12
|
+
* call = http/dio calls + Uri.parse('url'); feature = ElevatedButton/TextField/ListView/etc.
|
|
13
|
+
*
|
|
14
|
+
* The route→widget map (named routes + GoRoute) is built across all files during discover, so
|
|
15
|
+
* parse() can turn a string route into the widget-class screen id.
|
|
16
|
+
*/
|
|
17
|
+
const WIDGET_CLASS = /\bclass\s+([A-Za-z_]\w*)\s+extends\s+(StatelessWidget|StatefulWidget)\b/;
|
|
18
|
+
const APP_SHELL = /\breturn\s+(?:const\s+)?(?:MaterialApp|CupertinoApp|WidgetsApp)\b/;
|
|
19
|
+
const SKIP_DIRS = /^(build|\.dart_tool|\.idea|ios|android|web|macos|linux|windows)$/i;
|
|
20
|
+
// route string → widget class name, populated during discover (named routes + GoRoute paths).
|
|
21
|
+
let routeToWidget = new Map();
|
|
22
|
+
function libDirOf(projectRoot) {
|
|
23
|
+
const lib = join(projectRoot, "lib");
|
|
24
|
+
return existsSync(lib) ? lib : existsSync(join(projectRoot, "pubspec.yaml")) ? projectRoot : null;
|
|
25
|
+
}
|
|
26
|
+
export const flutterAdapter = {
|
|
27
|
+
id: "flutter",
|
|
28
|
+
router: "flutter-nav",
|
|
29
|
+
detect(projectRoot) {
|
|
30
|
+
const pubspec = join(projectRoot, "pubspec.yaml");
|
|
31
|
+
if (existsSync(pubspec)) {
|
|
32
|
+
const src = safeRead(pubspec);
|
|
33
|
+
if (/^\s*flutter\s*:/m.test(src) || /\bsdk:\s*flutter\b/.test(src))
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// Fallback: a .dart file with a Widget class.
|
|
37
|
+
let found = false;
|
|
38
|
+
walkDart(projectRoot, (file) => {
|
|
39
|
+
if (found)
|
|
40
|
+
return;
|
|
41
|
+
if (WIDGET_CLASS.test(safeRead(file)))
|
|
42
|
+
found = true;
|
|
43
|
+
});
|
|
44
|
+
return found;
|
|
45
|
+
},
|
|
46
|
+
discover(projectRoot) {
|
|
47
|
+
const root = libDirOf(projectRoot) ?? projectRoot;
|
|
48
|
+
const files = [];
|
|
49
|
+
routeToWidget = new Map();
|
|
50
|
+
walkDart(root, (file) => {
|
|
51
|
+
const src = safeRead(file);
|
|
52
|
+
// route→widget map (named-route table + go_router GoRoute) for resolving string targets later.
|
|
53
|
+
collectRoutes(src, routeToWidget);
|
|
54
|
+
const primary = primaryWidget(file, src);
|
|
55
|
+
if (!primary)
|
|
56
|
+
return;
|
|
57
|
+
files.push({
|
|
58
|
+
absPath: file,
|
|
59
|
+
relPath: relative(projectRoot, file).split(sep).join("/"),
|
|
60
|
+
id: primary,
|
|
61
|
+
route: primary,
|
|
62
|
+
title: primary.replace(/(Page|Screen|View|Widget)$/, "") || primary,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
// Entry: the screen the app shell opens first — the '/' named route, else MaterialApp(home: X()).
|
|
66
|
+
const entryId = routeToWidget.get("/") ?? homeWidget(root);
|
|
67
|
+
if (entryId) {
|
|
68
|
+
const e = files.find((f) => f.id === entryId);
|
|
69
|
+
if (e)
|
|
70
|
+
e.isEntry = true;
|
|
71
|
+
}
|
|
72
|
+
files.sort((a, b) => a.id.localeCompare(b.id));
|
|
73
|
+
return files;
|
|
74
|
+
},
|
|
75
|
+
parse(file) {
|
|
76
|
+
return parseDart(safeRead(file.absPath));
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
// ---------- discovery ----------
|
|
80
|
+
function walkDart(dir, onFile) {
|
|
81
|
+
let entries;
|
|
82
|
+
try {
|
|
83
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
90
|
+
continue;
|
|
91
|
+
const full = join(dir, entry.name);
|
|
92
|
+
if (entry.isDirectory()) {
|
|
93
|
+
if (SKIP_DIRS.test(entry.name))
|
|
94
|
+
continue;
|
|
95
|
+
walkDart(full, onFile);
|
|
96
|
+
}
|
|
97
|
+
else if (entry.name.endsWith(".dart")) {
|
|
98
|
+
onFile(full);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A file's primary page widget: prefer the one matching the filename, else the first widget class.
|
|
104
|
+
* An app-shell widget (build returns MaterialApp/CupertinoApp/WidgetsApp) is not a screen; skip a
|
|
105
|
+
* file that is only that shell.
|
|
106
|
+
*/
|
|
107
|
+
function primaryWidget(file, src) {
|
|
108
|
+
const names = [];
|
|
109
|
+
for (const line of src.split("\n")) {
|
|
110
|
+
const m = line.match(WIDGET_CLASS);
|
|
111
|
+
if (m)
|
|
112
|
+
names.push(m[1]);
|
|
113
|
+
}
|
|
114
|
+
if (!names.length)
|
|
115
|
+
return null;
|
|
116
|
+
if (APP_SHELL.test(src) && names.length === 1)
|
|
117
|
+
return null; // pure app shell, e.g. MyApp → MaterialApp
|
|
118
|
+
const stem = pascal(basename(file, ".dart"));
|
|
119
|
+
return names.find((n) => n.toLowerCase() === stem.toLowerCase()) ?? names[0];
|
|
120
|
+
}
|
|
121
|
+
/** `MaterialApp(home: SomeWidget())` → the first-shown screen (used when there's no '/' named route). */
|
|
122
|
+
function homeWidget(root) {
|
|
123
|
+
let home = null;
|
|
124
|
+
walkDart(root, (file) => {
|
|
125
|
+
if (home)
|
|
126
|
+
return;
|
|
127
|
+
const m = safeRead(file).match(/\bhome:\s*(?:const\s+)?([A-Z]\w*)\s*\(/);
|
|
128
|
+
if (m)
|
|
129
|
+
home = m[1];
|
|
130
|
+
});
|
|
131
|
+
return home;
|
|
132
|
+
}
|
|
133
|
+
/** route string → widget class, from a `routes: { '/x': (c) => XPage() }` table and `GoRoute(path:'/x', builder: … YPage())`. */
|
|
134
|
+
function collectRoutes(src, map) {
|
|
135
|
+
// named-route table entries: '/path': (ctx) => SomeWidget(
|
|
136
|
+
for (const m of src.matchAll(/["']([^"']+)["']\s*:\s*\([^)]*\)\s*=>\s*(?:const\s+)?([A-Z]\w*)\s*\(/g)) {
|
|
137
|
+
if (!map.has(m[1]))
|
|
138
|
+
map.set(m[1], m[2]);
|
|
139
|
+
}
|
|
140
|
+
// go_router: GoRoute(path: '/x', builder: (c, s) => SomeWidget(
|
|
141
|
+
for (const m of src.matchAll(/GoRoute\s*\(\s*path:\s*["']([^"']+)["'][\s\S]{0,120}?=>\s*(?:const\s+)?([A-Z]\w*)\s*\(/g)) {
|
|
142
|
+
if (!map.has(m[1]))
|
|
143
|
+
map.set(m[1], m[2]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ---------- parsing (line heuristics) ----------
|
|
147
|
+
const FEATURE_RULES = [
|
|
148
|
+
{ re: /\b(?:ElevatedButton|TextButton|OutlinedButton|IconButton|FloatingActionButton|FilledButton|CupertinoButton)\b/, kind: "button", label: () => "Button" },
|
|
149
|
+
{ re: /\b(?:TextField|TextFormField|CupertinoTextField)\b/, kind: "input", label: () => "Input" },
|
|
150
|
+
{ re: /\b(?:Switch|Checkbox|Radio|Slider|DropdownButton)\b/, kind: "input", label: () => "Input" },
|
|
151
|
+
{ re: /\b(?:ListView|GridView)\b/, kind: "list", label: () => "List" },
|
|
152
|
+
];
|
|
153
|
+
const WIDGET_INSTANCE = /\b([A-Z]\w*(?:Page|Screen|View))\s*\(/;
|
|
154
|
+
const PUSH_NAMED = /\b(?:pushNamed|pushReplacementNamed|popAndPushNamed)\s*\(\s*[^,]+,\s*["']([^"']+)["']/;
|
|
155
|
+
const GO_ROUTER = /\bcontext\.(?:go|push|replace)\s*\(\s*["']([^"']+)["']/;
|
|
156
|
+
const HTTP_CALL = /\b(?:http|dio)\.(get|post|put|delete|patch)\s*(?:<[^>]*>)?\s*\(\s*(?:Uri\.parse\(\s*)?["']([^"']+)["']/;
|
|
157
|
+
const URI_PARSE = /\bUri\.parse\s*\(\s*["']([^"']+)["']/;
|
|
158
|
+
function parseDart(src) {
|
|
159
|
+
const lines = src.split("\n");
|
|
160
|
+
const navs = [];
|
|
161
|
+
const calls = [];
|
|
162
|
+
const features = [];
|
|
163
|
+
const components = new Set();
|
|
164
|
+
for (let i = 0; i < lines.length; i++) {
|
|
165
|
+
const line = lines[i];
|
|
166
|
+
const lineNo = i + 1;
|
|
167
|
+
// --- transition (imperative): Navigator.push(... => SomeScreen()) ---
|
|
168
|
+
if (/\bNavigator\.(push|pushReplacement)\b/.test(line)) {
|
|
169
|
+
const target = findPushTarget(lines, i);
|
|
170
|
+
navs.push({ target, raw: snippet(line), trigger: "Navigator.push", line: lineNo });
|
|
171
|
+
if (target)
|
|
172
|
+
components.add(target);
|
|
173
|
+
}
|
|
174
|
+
// --- transition (named): pushNamed(context, '/route') → widget via the route table ---
|
|
175
|
+
const named = line.match(PUSH_NAMED);
|
|
176
|
+
if (named) {
|
|
177
|
+
const target = routeToWidget.get(named[1]) ?? null;
|
|
178
|
+
navs.push({ target, raw: snippet(line), trigger: "pushNamed", line: lineNo });
|
|
179
|
+
}
|
|
180
|
+
// --- transition (go_router): context.go('/route') → widget via the route table ---
|
|
181
|
+
const go = line.match(GO_ROUTER);
|
|
182
|
+
if (go) {
|
|
183
|
+
const target = routeToWidget.get(go[1]) ?? null;
|
|
184
|
+
navs.push({ target, raw: snippet(line), trigger: "context.go", line: lineNo });
|
|
185
|
+
}
|
|
186
|
+
// --- call: http/dio + Uri.parse ---
|
|
187
|
+
const httpM = line.match(HTTP_CALL);
|
|
188
|
+
if (httpM) {
|
|
189
|
+
calls.push({ url: httpM[2], method: httpM[1].toUpperCase(), raw: snippet(line), trigger: "http", line: lineNo });
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const uriM = line.match(URI_PARSE);
|
|
193
|
+
if (uriM)
|
|
194
|
+
calls.push({ url: uriM[1], raw: snippet(line), trigger: "Uri", line: lineNo });
|
|
195
|
+
}
|
|
196
|
+
// --- feature: Flutter controls (one per line) ---
|
|
197
|
+
for (const rule of FEATURE_RULES) {
|
|
198
|
+
const m = line.match(rule.re);
|
|
199
|
+
if (m) {
|
|
200
|
+
features.push({ kind: rule.kind, label: rule.label(m), detail: m[0].trim().slice(0, 40), line: lineNo });
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { navs, calls, features, components: [...components].sort(), contains: [] };
|
|
206
|
+
}
|
|
207
|
+
/** Target page widget for a Navigator.push: an XxxPage|Screen|View( on the same/next 3 lines. */
|
|
208
|
+
function findPushTarget(lines, i) {
|
|
209
|
+
for (let j = i; j < Math.min(i + 4, lines.length); j++) {
|
|
210
|
+
const inst = lines[j].match(WIDGET_INSTANCE);
|
|
211
|
+
if (inst)
|
|
212
|
+
return inst[1];
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
// ---------- helpers ----------
|
|
217
|
+
function pascal(name) {
|
|
218
|
+
return name.replace(/(?:^|_)([a-z])/g, (_, c) => c.toUpperCase());
|
|
219
|
+
}
|
|
220
|
+
function safeRead(file) {
|
|
221
|
+
try {
|
|
222
|
+
return readFileSync(file, "utf8");
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return "";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function snippet(text) {
|
|
229
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
230
|
+
return flat.length > 80 ? flat.slice(0, 77) + "..." : flat;
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=flutter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flutter.js","sourceRoot":"","sources":["../../../src/core/adapters/flutter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FrameworkAdapter } from "./types.js";
|
|
2
|
+
export type { FrameworkAdapter, ScreenFile, RawScreen, RawNav, RawCall, RawFeature } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registered adapters (in detection priority order). Add new platforms here.
|
|
5
|
+
* - Next.js (app/ or pages/ dir) before react-router (dep check) so a Next app — which also
|
|
6
|
+
* depends on React — isn't misread as a plain SPA. The Next adapters also bow out for
|
|
7
|
+
* react-native projects (Expo Router shares the `app/` dir convention).
|
|
8
|
+
* - expo-router (file-based, needs `expo-router` dep) before react-navigation (config-based),
|
|
9
|
+
* since an Expo app pulls in @react-navigation transitively.
|
|
10
|
+
* - remix before react-router: RR7 framework mode shares the `react-router` dependency, so the
|
|
11
|
+
* plain-SPA adapter would otherwise claim a Remix app.
|
|
12
|
+
* - swiftui before uikit: a SwiftUI app may import UIKit, so it's claimed by swiftui first;
|
|
13
|
+
* only pure-UIKit apps fall to the uikit adapter.
|
|
14
|
+
* - static-html is the LAST fallback: by the time it runs the project matched no framework, so
|
|
15
|
+
* "a folder of .html files" still yields a map.
|
|
16
|
+
*/
|
|
17
|
+
export declare const ADAPTERS: FrameworkAdapter[];
|
|
18
|
+
/** First adapter that matches the project. Null if none. */
|
|
19
|
+
export declare function selectAdapter(projectRoot: string): FrameworkAdapter | null;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { nextAppAdapter } from "./next-app.js";
|
|
2
|
+
import { nextPagesAdapter } from "./next-pages.js";
|
|
3
|
+
import { remixAdapter } from "./remix.js";
|
|
4
|
+
import { reactRouterAdapter } from "./react-router.js";
|
|
5
|
+
import { expoRouterAdapter } from "./expo-router.js";
|
|
6
|
+
import { reactNavigationAdapter } from "./react-navigation.js";
|
|
7
|
+
import { nuxtAdapter } from "./nuxt.js";
|
|
8
|
+
import { vueRouterAdapter } from "./vue-router.js";
|
|
9
|
+
import { svelteKitAdapter } from "./sveltekit.js";
|
|
10
|
+
import { astroAdapter } from "./astro.js";
|
|
11
|
+
import { angularAdapter } from "./angular.js";
|
|
12
|
+
import { swiftUiAdapter } from "./swiftui.js";
|
|
13
|
+
import { uikitAdapter } from "./uikit.js";
|
|
14
|
+
import { composeAdapter } from "./compose.js";
|
|
15
|
+
import { flutterAdapter } from "./flutter.js";
|
|
16
|
+
import { djangoAdapter } from "./django.js";
|
|
17
|
+
import { flaskAdapter } from "./flask.js";
|
|
18
|
+
import { railsAdapter } from "./rails.js";
|
|
19
|
+
import { staticHtmlAdapter } from "./static-html.js";
|
|
20
|
+
/**
|
|
21
|
+
* Registered adapters (in detection priority order). Add new platforms here.
|
|
22
|
+
* - Next.js (app/ or pages/ dir) before react-router (dep check) so a Next app — which also
|
|
23
|
+
* depends on React — isn't misread as a plain SPA. The Next adapters also bow out for
|
|
24
|
+
* react-native projects (Expo Router shares the `app/` dir convention).
|
|
25
|
+
* - expo-router (file-based, needs `expo-router` dep) before react-navigation (config-based),
|
|
26
|
+
* since an Expo app pulls in @react-navigation transitively.
|
|
27
|
+
* - remix before react-router: RR7 framework mode shares the `react-router` dependency, so the
|
|
28
|
+
* plain-SPA adapter would otherwise claim a Remix app.
|
|
29
|
+
* - swiftui before uikit: a SwiftUI app may import UIKit, so it's claimed by swiftui first;
|
|
30
|
+
* only pure-UIKit apps fall to the uikit adapter.
|
|
31
|
+
* - static-html is the LAST fallback: by the time it runs the project matched no framework, so
|
|
32
|
+
* "a folder of .html files" still yields a map.
|
|
33
|
+
*/
|
|
34
|
+
export const ADAPTERS = [
|
|
35
|
+
nextAppAdapter,
|
|
36
|
+
nextPagesAdapter,
|
|
37
|
+
remixAdapter,
|
|
38
|
+
reactRouterAdapter,
|
|
39
|
+
expoRouterAdapter,
|
|
40
|
+
reactNavigationAdapter,
|
|
41
|
+
nuxtAdapter,
|
|
42
|
+
vueRouterAdapter,
|
|
43
|
+
svelteKitAdapter,
|
|
44
|
+
astroAdapter,
|
|
45
|
+
angularAdapter,
|
|
46
|
+
swiftUiAdapter,
|
|
47
|
+
uikitAdapter,
|
|
48
|
+
composeAdapter,
|
|
49
|
+
flutterAdapter,
|
|
50
|
+
djangoAdapter,
|
|
51
|
+
flaskAdapter,
|
|
52
|
+
railsAdapter,
|
|
53
|
+
staticHtmlAdapter,
|
|
54
|
+
];
|
|
55
|
+
/** First adapter that matches the project. Null if none. */
|
|
56
|
+
export function selectAdapter(projectRoot) {
|
|
57
|
+
return ADAPTERS.find((a) => a.detect(projectRoot)) ?? null;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/adapters/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAuB;IAC1C,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,kBAAkB;IAClB,iBAAiB;IACjB,sBAAsB;IACtB,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,YAAY;IACZ,cAAc;IACd,cAAc;IACd,YAAY;IACZ,cAAc;IACd,cAAc;IACd,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,iBAAiB;CAClB,CAAC;AAEF,4DAA4D;AAC5D,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC;AAC7D,CAAC"}
|