@neat.is/core 0.6.2-dev.20260723 → 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/{chunk-ZZ3VUCWL.js → chunk-AOWANF2K.js} +46 -15
- package/dist/chunk-AOWANF2K.js.map +1 -0
- package/dist/{chunk-64JJOXES.js → chunk-MSZ4NALT.js} +59 -26
- package/dist/chunk-MSZ4NALT.js.map +1 -0
- package/dist/cli.cjs +311 -26
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +17 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +104 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +104 -41
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +45 -14
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-64JJOXES.js.map +0 -1
- package/dist/chunk-ZZ3VUCWL.js.map +0 -1
|
@@ -4977,7 +4977,7 @@ function keywordArrayStrings(argsNode, key) {
|
|
|
4977
4977
|
}
|
|
4978
4978
|
return [];
|
|
4979
4979
|
}
|
|
4980
|
-
function
|
|
4980
|
+
function collectPythonRouterPrefixes(root) {
|
|
4981
4981
|
const prefixes = /* @__PURE__ */ new Map();
|
|
4982
4982
|
walk(root, (node) => {
|
|
4983
4983
|
if (node.type !== "assignment") return;
|
|
@@ -4986,7 +4986,8 @@ function collectApiRouterPrefixes(root) {
|
|
|
4986
4986
|
const fn = right.childForFieldName("function");
|
|
4987
4987
|
if (!fn) return;
|
|
4988
4988
|
const ctor = fn.type === "attribute" ? fn.childForFieldName("attribute")?.text : fn.text;
|
|
4989
|
-
|
|
4989
|
+
const prefixKey = ctor === "APIRouter" ? "prefix" : ctor === "Blueprint" ? "url_prefix" : null;
|
|
4990
|
+
if (!prefixKey) return;
|
|
4990
4991
|
const left = node.childForFieldName("left");
|
|
4991
4992
|
if (!left || left.type !== "identifier") return;
|
|
4992
4993
|
const args = right.childForFieldName("arguments");
|
|
@@ -4994,7 +4995,7 @@ function collectApiRouterPrefixes(root) {
|
|
|
4994
4995
|
for (let i = 0; i < args.namedChildCount; i++) {
|
|
4995
4996
|
const arg = args.namedChild(i);
|
|
4996
4997
|
if (arg?.type !== "keyword_argument") continue;
|
|
4997
|
-
if (arg.childForFieldName("name")?.text !==
|
|
4998
|
+
if (arg.childForFieldName("name")?.text !== prefixKey) continue;
|
|
4998
4999
|
const val = arg.childForFieldName("value");
|
|
4999
5000
|
const p = val ? pyStaticStringText(val) : null;
|
|
5000
5001
|
if (p !== null) prefixes.set(left.text, p);
|
|
@@ -5002,9 +5003,9 @@ function collectApiRouterPrefixes(root) {
|
|
|
5002
5003
|
});
|
|
5003
5004
|
return prefixes;
|
|
5004
5005
|
}
|
|
5005
|
-
function
|
|
5006
|
+
function pythonRoutesFromSource(source, parser, framework) {
|
|
5006
5007
|
const tree = parseSource2(parser, source);
|
|
5007
|
-
const prefixes =
|
|
5008
|
+
const prefixes = collectPythonRouterPrefixes(tree.rootNode);
|
|
5008
5009
|
const out = [];
|
|
5009
5010
|
walk(tree.rootNode, (node) => {
|
|
5010
5011
|
if (node.type !== "decorator") return;
|
|
@@ -5015,7 +5016,9 @@ function fastapiRoutesFromSource(source, parser) {
|
|
|
5015
5016
|
const method = fn.childForFieldName("attribute")?.text?.toLowerCase();
|
|
5016
5017
|
if (!method) return;
|
|
5017
5018
|
const isVerb = FASTAPI_METHODS.has(method);
|
|
5018
|
-
|
|
5019
|
+
const isFlaskRoute = method === "route";
|
|
5020
|
+
const isApiRoute = method === "api_route";
|
|
5021
|
+
if (!isVerb && !isFlaskRoute && !isApiRoute) return;
|
|
5019
5022
|
const args = call.childForFieldName("arguments");
|
|
5020
5023
|
const first = args?.namedChild(0);
|
|
5021
5024
|
if (!first || first.type !== "string") return;
|
|
@@ -5026,17 +5029,41 @@ function fastapiRoutesFromSource(source, parser) {
|
|
|
5026
5029
|
const pathTemplate = canonicalizeTemplate(prefix + rawPath);
|
|
5027
5030
|
const line = node.startPosition.row + 1;
|
|
5028
5031
|
if (isVerb) {
|
|
5029
|
-
out.push({ method: method.toUpperCase(), pathTemplate, line, framework
|
|
5032
|
+
out.push({ method: method.toUpperCase(), pathTemplate, line, framework });
|
|
5030
5033
|
return;
|
|
5031
5034
|
}
|
|
5032
5035
|
const methods = keywordArrayStrings(args, "methods");
|
|
5033
|
-
const list = methods.length > 0 ? methods : ["ALL"];
|
|
5036
|
+
const list = methods.length > 0 ? methods : isFlaskRoute ? ["GET"] : ["ALL"];
|
|
5034
5037
|
for (const m of list) {
|
|
5038
|
+
out.push({ method: m === "ALL" ? "ALL" : m.toUpperCase(), pathTemplate, line, framework });
|
|
5039
|
+
}
|
|
5040
|
+
});
|
|
5041
|
+
return out;
|
|
5042
|
+
}
|
|
5043
|
+
function djangoRoutesFromSource(source, parser) {
|
|
5044
|
+
const tree = parseSource2(parser, source);
|
|
5045
|
+
const out = [];
|
|
5046
|
+
walk(tree.rootNode, (node) => {
|
|
5047
|
+
if (node.type !== "assignment") return;
|
|
5048
|
+
if (node.childForFieldName("left")?.text !== "urlpatterns") return;
|
|
5049
|
+
const list = node.childForFieldName("right");
|
|
5050
|
+
if (!list || list.type !== "list") return;
|
|
5051
|
+
for (let i = 0; i < list.namedChildCount; i++) {
|
|
5052
|
+
const el = list.namedChild(i);
|
|
5053
|
+
if (el?.type !== "call") continue;
|
|
5054
|
+
if (el.childForFieldName("function")?.text !== "path") continue;
|
|
5055
|
+
const args = el.childForFieldName("arguments");
|
|
5056
|
+
const first = args?.namedChild(0);
|
|
5057
|
+
if (first?.type !== "string") continue;
|
|
5058
|
+
const raw = pyStaticStringText(first);
|
|
5059
|
+
if (raw === null) continue;
|
|
5060
|
+
const second = args?.namedChild(1);
|
|
5061
|
+
if (second?.type === "call" && second.childForFieldName("function")?.text === "include") continue;
|
|
5035
5062
|
out.push({
|
|
5036
|
-
method:
|
|
5037
|
-
pathTemplate,
|
|
5038
|
-
line,
|
|
5039
|
-
framework: "
|
|
5063
|
+
method: "ALL",
|
|
5064
|
+
pathTemplate: canonicalizeTemplate(raw),
|
|
5065
|
+
line: el.startPosition.row + 1,
|
|
5066
|
+
framework: "django"
|
|
5040
5067
|
});
|
|
5041
5068
|
}
|
|
5042
5069
|
});
|
|
@@ -5057,7 +5084,10 @@ async function addRoutes(graph, services) {
|
|
|
5057
5084
|
const hasHono = deps["hono"] !== void 0;
|
|
5058
5085
|
const hasNext = deps["next"] !== void 0;
|
|
5059
5086
|
const hasFastapi = deps["fastapi"] !== void 0;
|
|
5060
|
-
|
|
5087
|
+
const hasFlask = deps["flask"] !== void 0;
|
|
5088
|
+
const hasDjango = deps["django"] !== void 0;
|
|
5089
|
+
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasFastapi && !hasFlask && !hasDjango)
|
|
5090
|
+
continue;
|
|
5061
5091
|
const files = await loadSourceFiles(service.dir);
|
|
5062
5092
|
for (const file of files) {
|
|
5063
5093
|
if (isTestPath(file.path)) continue;
|
|
@@ -5068,7 +5098,8 @@ async function addRoutes(graph, services) {
|
|
|
5068
5098
|
let routes;
|
|
5069
5099
|
try {
|
|
5070
5100
|
if (isPy) {
|
|
5071
|
-
routes = hasFastapi ?
|
|
5101
|
+
routes = hasFastapi || hasFlask ? pythonRoutesFromSource(file.content, pyParser, hasFastapi ? "fastapi" : "flask") : [];
|
|
5102
|
+
if (hasDjango) routes = routes.concat(djangoRoutesFromSource(file.content, pyParser));
|
|
5072
5103
|
} else if (hasNext && (isNextAppRouteFile(relFile) || isNextPagesApiFile(relFile))) {
|
|
5073
5104
|
routes = nextRoutesFromFile(file.content, relFile, jsParser);
|
|
5074
5105
|
} else if (hasExpress || hasFastify || hasHono) {
|
|
@@ -9995,4 +10026,4 @@ export {
|
|
|
9995
10026
|
recordConnectorPoll,
|
|
9996
10027
|
buildApi
|
|
9997
10028
|
};
|
|
9998
|
-
//# sourceMappingURL=chunk-
|
|
10029
|
+
//# sourceMappingURL=chunk-AOWANF2K.js.map
|