@neat.is/core 0.6.2-dev.20260724 → 0.6.2

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/neatd.js CHANGED
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  reconcileDaemonRecordSync,
4
4
  startDaemon
5
- } from "./chunk-64JJOXES.js";
5
+ } from "./chunk-MSZ4NALT.js";
6
6
  import {
7
7
  listProjects,
8
8
  registryPath
9
- } from "./chunk-ZZ3VUCWL.js";
9
+ } from "./chunk-AOWANF2K.js";
10
10
  import {
11
11
  BindAuthorityError,
12
12
  __require
package/dist/server.cjs CHANGED
@@ -6193,7 +6193,7 @@ function keywordArrayStrings(argsNode, key) {
6193
6193
  }
6194
6194
  return [];
6195
6195
  }
6196
- function collectApiRouterPrefixes(root) {
6196
+ function collectPythonRouterPrefixes(root) {
6197
6197
  const prefixes = /* @__PURE__ */ new Map();
6198
6198
  walk(root, (node) => {
6199
6199
  if (node.type !== "assignment") return;
@@ -6202,7 +6202,8 @@ function collectApiRouterPrefixes(root) {
6202
6202
  const fn = right.childForFieldName("function");
6203
6203
  if (!fn) return;
6204
6204
  const ctor = fn.type === "attribute" ? fn.childForFieldName("attribute")?.text : fn.text;
6205
- if (ctor !== "APIRouter") return;
6205
+ const prefixKey = ctor === "APIRouter" ? "prefix" : ctor === "Blueprint" ? "url_prefix" : null;
6206
+ if (!prefixKey) return;
6206
6207
  const left = node.childForFieldName("left");
6207
6208
  if (!left || left.type !== "identifier") return;
6208
6209
  const args = right.childForFieldName("arguments");
@@ -6210,7 +6211,7 @@ function collectApiRouterPrefixes(root) {
6210
6211
  for (let i = 0; i < args.namedChildCount; i++) {
6211
6212
  const arg = args.namedChild(i);
6212
6213
  if (arg?.type !== "keyword_argument") continue;
6213
- if (arg.childForFieldName("name")?.text !== "prefix") continue;
6214
+ if (arg.childForFieldName("name")?.text !== prefixKey) continue;
6214
6215
  const val = arg.childForFieldName("value");
6215
6216
  const p = val ? pyStaticStringText(val) : null;
6216
6217
  if (p !== null) prefixes.set(left.text, p);
@@ -6218,9 +6219,9 @@ function collectApiRouterPrefixes(root) {
6218
6219
  });
6219
6220
  return prefixes;
6220
6221
  }
6221
- function fastapiRoutesFromSource(source, parser) {
6222
+ function pythonRoutesFromSource(source, parser, framework) {
6222
6223
  const tree = parseSource2(parser, source);
6223
- const prefixes = collectApiRouterPrefixes(tree.rootNode);
6224
+ const prefixes = collectPythonRouterPrefixes(tree.rootNode);
6224
6225
  const out = [];
6225
6226
  walk(tree.rootNode, (node) => {
6226
6227
  if (node.type !== "decorator") return;
@@ -6231,7 +6232,9 @@ function fastapiRoutesFromSource(source, parser) {
6231
6232
  const method = fn.childForFieldName("attribute")?.text?.toLowerCase();
6232
6233
  if (!method) return;
6233
6234
  const isVerb = FASTAPI_METHODS.has(method);
6234
- if (!isVerb && method !== "api_route") return;
6235
+ const isFlaskRoute = method === "route";
6236
+ const isApiRoute = method === "api_route";
6237
+ if (!isVerb && !isFlaskRoute && !isApiRoute) return;
6235
6238
  const args = call.childForFieldName("arguments");
6236
6239
  const first = args?.namedChild(0);
6237
6240
  if (!first || first.type !== "string") return;
@@ -6242,17 +6245,41 @@ function fastapiRoutesFromSource(source, parser) {
6242
6245
  const pathTemplate = canonicalizeTemplate(prefix + rawPath);
6243
6246
  const line = node.startPosition.row + 1;
6244
6247
  if (isVerb) {
6245
- out.push({ method: method.toUpperCase(), pathTemplate, line, framework: "fastapi" });
6248
+ out.push({ method: method.toUpperCase(), pathTemplate, line, framework });
6246
6249
  return;
6247
6250
  }
6248
6251
  const methods = keywordArrayStrings(args, "methods");
6249
- const list = methods.length > 0 ? methods : ["ALL"];
6252
+ const list = methods.length > 0 ? methods : isFlaskRoute ? ["GET"] : ["ALL"];
6250
6253
  for (const m of list) {
6254
+ out.push({ method: m === "ALL" ? "ALL" : m.toUpperCase(), pathTemplate, line, framework });
6255
+ }
6256
+ });
6257
+ return out;
6258
+ }
6259
+ function djangoRoutesFromSource(source, parser) {
6260
+ const tree = parseSource2(parser, source);
6261
+ const out = [];
6262
+ walk(tree.rootNode, (node) => {
6263
+ if (node.type !== "assignment") return;
6264
+ if (node.childForFieldName("left")?.text !== "urlpatterns") return;
6265
+ const list = node.childForFieldName("right");
6266
+ if (!list || list.type !== "list") return;
6267
+ for (let i = 0; i < list.namedChildCount; i++) {
6268
+ const el = list.namedChild(i);
6269
+ if (el?.type !== "call") continue;
6270
+ if (el.childForFieldName("function")?.text !== "path") continue;
6271
+ const args = el.childForFieldName("arguments");
6272
+ const first = args?.namedChild(0);
6273
+ if (first?.type !== "string") continue;
6274
+ const raw = pyStaticStringText(first);
6275
+ if (raw === null) continue;
6276
+ const second = args?.namedChild(1);
6277
+ if (second?.type === "call" && second.childForFieldName("function")?.text === "include") continue;
6251
6278
  out.push({
6252
- method: m === "ALL" ? "ALL" : m.toUpperCase(),
6253
- pathTemplate,
6254
- line,
6255
- framework: "fastapi"
6279
+ method: "ALL",
6280
+ pathTemplate: canonicalizeTemplate(raw),
6281
+ line: el.startPosition.row + 1,
6282
+ framework: "django"
6256
6283
  });
6257
6284
  }
6258
6285
  });
@@ -6273,7 +6300,10 @@ async function addRoutes(graph, services) {
6273
6300
  const hasHono = deps["hono"] !== void 0;
6274
6301
  const hasNext = deps["next"] !== void 0;
6275
6302
  const hasFastapi = deps["fastapi"] !== void 0;
6276
- if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasFastapi) continue;
6303
+ const hasFlask = deps["flask"] !== void 0;
6304
+ const hasDjango = deps["django"] !== void 0;
6305
+ if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasFastapi && !hasFlask && !hasDjango)
6306
+ continue;
6277
6307
  const files = await loadSourceFiles(service.dir);
6278
6308
  for (const file of files) {
6279
6309
  if (isTestPath(file.path)) continue;
@@ -6284,7 +6314,8 @@ async function addRoutes(graph, services) {
6284
6314
  let routes;
6285
6315
  try {
6286
6316
  if (isPy) {
6287
- routes = hasFastapi ? fastapiRoutesFromSource(file.content, pyParser) : [];
6317
+ routes = hasFastapi || hasFlask ? pythonRoutesFromSource(file.content, pyParser, hasFastapi ? "fastapi" : "flask") : [];
6318
+ if (hasDjango) routes = routes.concat(djangoRoutesFromSource(file.content, pyParser));
6288
6319
  } else if (hasNext && (isNextAppRouteFile(relFile) || isNextPagesApiFile(relFile))) {
6289
6320
  routes = nextRoutesFromFile(file.content, relFile, jsParser);
6290
6321
  } else if (hasExpress || hasFastify || hasHono) {