@launchsecure/launch-kit 0.0.12 → 0.0.13
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/server/chart-serve.js +26 -22
- package/dist/server/cli.js +26 -22
- package/dist/server/graph/queries/classify.scm +41 -0
- package/dist/server/graph-mcp-entry.js +27 -23
- package/package.json +1 -1
|
@@ -408,6 +408,24 @@ function extractDbCallsTS(absPath) {
|
|
|
408
408
|
}
|
|
409
409
|
return calls;
|
|
410
410
|
}
|
|
411
|
+
function classifyFile(absPath) {
|
|
412
|
+
const fileName = require("path").basename(absPath);
|
|
413
|
+
if (fileName.includes(".test.") || fileName.includes(".spec.") || fileName.includes("__test")) return "test";
|
|
414
|
+
if (fileName.includes(".stories.")) return "story";
|
|
415
|
+
const tree = parseSource(absPath);
|
|
416
|
+
const root = tree.rootNode;
|
|
417
|
+
const classifyQuery = getQuery("classify");
|
|
418
|
+
const captures = classifyQuery.captures(root);
|
|
419
|
+
const capNames = new Set(captures.map((c) => c.name));
|
|
420
|
+
if (capNames.has("http_export") || capNames.has("http_export_fn")) return "endpoint";
|
|
421
|
+
if (fileName === "page.tsx" && capNames.has("has_jsx")) return "page";
|
|
422
|
+
if (fileName === "layout.tsx" && capNames.has("has_jsx")) return "layout";
|
|
423
|
+
if (capNames.has("has_create_context") || capNames.has("has_create_context_bare")) return "context";
|
|
424
|
+
if (capNames.has("has_jsx")) return "component";
|
|
425
|
+
if (capNames.has("hook_decl") || capNames.has("hook_const")) return "hook";
|
|
426
|
+
if (fileName.includes("config") || fileName.includes(".config.")) return "config";
|
|
427
|
+
return "lib";
|
|
428
|
+
}
|
|
411
429
|
function extractAuthWrappersTS(absPath) {
|
|
412
430
|
const tree = parseSource(absPath);
|
|
413
431
|
const root = tree.rootNode;
|
|
@@ -580,7 +598,6 @@ function extractDeep(absPath) {
|
|
|
580
598
|
}
|
|
581
599
|
|
|
582
600
|
// src/server/graph/parsers/ui/react-nextjs.ts
|
|
583
|
-
var RENDER_TYPES = /* @__PURE__ */ new Set(["component", "ui", "layout", "context"]);
|
|
584
601
|
function walk(dir, exts) {
|
|
585
602
|
const results = [];
|
|
586
603
|
if (!(0, import_node_fs3.existsSync)(dir)) return results;
|
|
@@ -681,20 +698,10 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
|
|
|
681
698
|
}
|
|
682
699
|
return barrels;
|
|
683
700
|
}
|
|
684
|
-
function classifyType(id) {
|
|
685
|
-
|
|
686
|
-
if (id.
|
|
687
|
-
|
|
688
|
-
if (id.startsWith("client/components/")) return "component";
|
|
689
|
-
if (id.startsWith("client/hooks/")) return "hook";
|
|
690
|
-
if (/client\/lib\/.*-context\./.test(id)) return "context";
|
|
691
|
-
if (id.startsWith("client/lib/")) return id.includes("config") ? "config" : "util";
|
|
692
|
-
if (id.startsWith("client/api/")) return "util";
|
|
693
|
-
if (id.startsWith("server/mcp/")) return "mcp-tool";
|
|
694
|
-
if (id.startsWith("server/lib/")) return "lib";
|
|
695
|
-
if (id.startsWith("server/")) return "lib";
|
|
696
|
-
if (id.startsWith("lib/") || id.startsWith("config/")) return "lib";
|
|
697
|
-
return "component";
|
|
701
|
+
function classifyType(absPath, id) {
|
|
702
|
+
const contentType = classifyFile(absPath);
|
|
703
|
+
if (contentType === "lib" && id.startsWith("server/mcp/")) return "mcp-tool";
|
|
704
|
+
return contentType;
|
|
698
705
|
}
|
|
699
706
|
function extractRoute(id) {
|
|
700
707
|
if (!id.endsWith("/page.tsx")) return null;
|
|
@@ -799,13 +806,10 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, nodeTypeMap,
|
|
|
799
806
|
if (label) edge.label = label;
|
|
800
807
|
edges.push(edge);
|
|
801
808
|
}
|
|
802
|
-
function edgeTypeFor(
|
|
809
|
+
function edgeTypeFor(_targetId, isTypeOnlyImport, importedNames) {
|
|
803
810
|
if (isTypeOnlyImport) return "imports";
|
|
804
|
-
const
|
|
805
|
-
if (
|
|
806
|
-
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
807
|
-
if (anyRendered) return "renders";
|
|
808
|
-
}
|
|
811
|
+
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
812
|
+
if (anyRendered) return "renders";
|
|
809
813
|
return "imports";
|
|
810
814
|
}
|
|
811
815
|
for (const imp of parsed.imports) {
|
|
@@ -912,7 +916,7 @@ function generate(rootDir) {
|
|
|
912
916
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
913
917
|
for (const absPath of fileSet) {
|
|
914
918
|
const id = toNodeId(srcDir, absPath);
|
|
915
|
-
const type = classifyType(id);
|
|
919
|
+
const type = classifyType(absPath, id);
|
|
916
920
|
const parsed = parsedByPath.get(absPath);
|
|
917
921
|
const name = parsed.name || nameFromFilename(absPath);
|
|
918
922
|
const route = extractRoute(id);
|
package/dist/server/cli.js
CHANGED
|
@@ -6690,6 +6690,24 @@ function extractDbCallsTS(absPath) {
|
|
|
6690
6690
|
}
|
|
6691
6691
|
return calls;
|
|
6692
6692
|
}
|
|
6693
|
+
function classifyFile(absPath) {
|
|
6694
|
+
const fileName = require("path").basename(absPath);
|
|
6695
|
+
if (fileName.includes(".test.") || fileName.includes(".spec.") || fileName.includes("__test")) return "test";
|
|
6696
|
+
if (fileName.includes(".stories.")) return "story";
|
|
6697
|
+
const tree = parseSource(absPath);
|
|
6698
|
+
const root = tree.rootNode;
|
|
6699
|
+
const classifyQuery = getQuery("classify");
|
|
6700
|
+
const captures = classifyQuery.captures(root);
|
|
6701
|
+
const capNames = new Set(captures.map((c) => c.name));
|
|
6702
|
+
if (capNames.has("http_export") || capNames.has("http_export_fn")) return "endpoint";
|
|
6703
|
+
if (fileName === "page.tsx" && capNames.has("has_jsx")) return "page";
|
|
6704
|
+
if (fileName === "layout.tsx" && capNames.has("has_jsx")) return "layout";
|
|
6705
|
+
if (capNames.has("has_create_context") || capNames.has("has_create_context_bare")) return "context";
|
|
6706
|
+
if (capNames.has("has_jsx")) return "component";
|
|
6707
|
+
if (capNames.has("hook_decl") || capNames.has("hook_const")) return "hook";
|
|
6708
|
+
if (fileName.includes("config") || fileName.includes(".config.")) return "config";
|
|
6709
|
+
return "lib";
|
|
6710
|
+
}
|
|
6693
6711
|
function extractAuthWrappersTS(absPath) {
|
|
6694
6712
|
const tree = parseSource(absPath);
|
|
6695
6713
|
const root = tree.rootNode;
|
|
@@ -6862,7 +6880,6 @@ function extractDeep(absPath) {
|
|
|
6862
6880
|
}
|
|
6863
6881
|
|
|
6864
6882
|
// src/server/graph/parsers/ui/react-nextjs.ts
|
|
6865
|
-
var RENDER_TYPES = /* @__PURE__ */ new Set(["component", "ui", "layout", "context"]);
|
|
6866
6883
|
function walk(dir, exts) {
|
|
6867
6884
|
const results = [];
|
|
6868
6885
|
if (!(0, import_node_fs3.existsSync)(dir)) return results;
|
|
@@ -6963,20 +6980,10 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
|
|
|
6963
6980
|
}
|
|
6964
6981
|
return barrels;
|
|
6965
6982
|
}
|
|
6966
|
-
function classifyType(id) {
|
|
6967
|
-
|
|
6968
|
-
if (id.
|
|
6969
|
-
|
|
6970
|
-
if (id.startsWith("client/components/")) return "component";
|
|
6971
|
-
if (id.startsWith("client/hooks/")) return "hook";
|
|
6972
|
-
if (/client\/lib\/.*-context\./.test(id)) return "context";
|
|
6973
|
-
if (id.startsWith("client/lib/")) return id.includes("config") ? "config" : "util";
|
|
6974
|
-
if (id.startsWith("client/api/")) return "util";
|
|
6975
|
-
if (id.startsWith("server/mcp/")) return "mcp-tool";
|
|
6976
|
-
if (id.startsWith("server/lib/")) return "lib";
|
|
6977
|
-
if (id.startsWith("server/")) return "lib";
|
|
6978
|
-
if (id.startsWith("lib/") || id.startsWith("config/")) return "lib";
|
|
6979
|
-
return "component";
|
|
6983
|
+
function classifyType(absPath, id) {
|
|
6984
|
+
const contentType = classifyFile(absPath);
|
|
6985
|
+
if (contentType === "lib" && id.startsWith("server/mcp/")) return "mcp-tool";
|
|
6986
|
+
return contentType;
|
|
6980
6987
|
}
|
|
6981
6988
|
function extractRoute(id) {
|
|
6982
6989
|
if (!id.endsWith("/page.tsx")) return null;
|
|
@@ -7081,13 +7088,10 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, nodeTypeMap,
|
|
|
7081
7088
|
if (label) edge.label = label;
|
|
7082
7089
|
edges.push(edge);
|
|
7083
7090
|
}
|
|
7084
|
-
function edgeTypeFor(
|
|
7091
|
+
function edgeTypeFor(_targetId, isTypeOnlyImport, importedNames) {
|
|
7085
7092
|
if (isTypeOnlyImport) return "imports";
|
|
7086
|
-
const
|
|
7087
|
-
if (
|
|
7088
|
-
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
7089
|
-
if (anyRendered) return "renders";
|
|
7090
|
-
}
|
|
7093
|
+
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
7094
|
+
if (anyRendered) return "renders";
|
|
7091
7095
|
return "imports";
|
|
7092
7096
|
}
|
|
7093
7097
|
for (const imp of parsed.imports) {
|
|
@@ -7194,7 +7198,7 @@ function generate(rootDir) {
|
|
|
7194
7198
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
7195
7199
|
for (const absPath of fileSet) {
|
|
7196
7200
|
const id = toNodeId(srcDir, absPath);
|
|
7197
|
-
const type = classifyType(id);
|
|
7201
|
+
const type = classifyType(absPath, id);
|
|
7198
7202
|
const parsed = parsedByPath.get(absPath);
|
|
7199
7203
|
const name = parsed.name || nameFromFilename(absPath);
|
|
7200
7204
|
const route = extractRoute(id);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
; Detect JSX usage (component/page/layout)
|
|
2
|
+
[(jsx_element) (jsx_self_closing_element)] @has_jsx
|
|
3
|
+
|
|
4
|
+
; Detect React hooks (function name starts with use)
|
|
5
|
+
(function_declaration
|
|
6
|
+
name: (identifier) @hook_decl
|
|
7
|
+
(#match? @hook_decl "^use[A-Z]"))
|
|
8
|
+
|
|
9
|
+
(lexical_declaration
|
|
10
|
+
(variable_declarator
|
|
11
|
+
name: (identifier) @hook_const
|
|
12
|
+
(#match? @hook_const "^use[A-Z]")))
|
|
13
|
+
|
|
14
|
+
; Detect useState/useEffect usage (consumer of hooks)
|
|
15
|
+
(call_expression
|
|
16
|
+
function: (identifier) @hook_call
|
|
17
|
+
(#match? @hook_call "^use[A-Z]"))
|
|
18
|
+
|
|
19
|
+
; Detect React.createContext
|
|
20
|
+
(call_expression
|
|
21
|
+
function: (member_expression
|
|
22
|
+
object: (identifier) @_react
|
|
23
|
+
property: (property_identifier) @_createCtx)
|
|
24
|
+
(#eq? @_react "React")
|
|
25
|
+
(#eq? @_createCtx "createContext")) @has_create_context
|
|
26
|
+
|
|
27
|
+
(call_expression
|
|
28
|
+
function: (identifier) @_createCtx2
|
|
29
|
+
(#eq? @_createCtx2 "createContext")) @has_create_context_bare
|
|
30
|
+
|
|
31
|
+
; Detect HTTP method exports (API endpoint)
|
|
32
|
+
(export_statement
|
|
33
|
+
declaration: (lexical_declaration
|
|
34
|
+
(variable_declarator
|
|
35
|
+
name: (identifier) @http_export
|
|
36
|
+
(#match? @http_export "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$"))))
|
|
37
|
+
|
|
38
|
+
(export_statement
|
|
39
|
+
declaration: (function_declaration
|
|
40
|
+
name: (identifier) @http_export_fn
|
|
41
|
+
(#match? @http_export_fn "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$")))
|
|
@@ -456,6 +456,24 @@ function extractDbCallsTS(absPath) {
|
|
|
456
456
|
}
|
|
457
457
|
return calls;
|
|
458
458
|
}
|
|
459
|
+
function classifyFile(absPath) {
|
|
460
|
+
const fileName = require("path").basename(absPath);
|
|
461
|
+
if (fileName.includes(".test.") || fileName.includes(".spec.") || fileName.includes("__test")) return "test";
|
|
462
|
+
if (fileName.includes(".stories.")) return "story";
|
|
463
|
+
const tree = parseSource(absPath);
|
|
464
|
+
const root = tree.rootNode;
|
|
465
|
+
const classifyQuery = getQuery("classify");
|
|
466
|
+
const captures = classifyQuery.captures(root);
|
|
467
|
+
const capNames = new Set(captures.map((c) => c.name));
|
|
468
|
+
if (capNames.has("http_export") || capNames.has("http_export_fn")) return "endpoint";
|
|
469
|
+
if (fileName === "page.tsx" && capNames.has("has_jsx")) return "page";
|
|
470
|
+
if (fileName === "layout.tsx" && capNames.has("has_jsx")) return "layout";
|
|
471
|
+
if (capNames.has("has_create_context") || capNames.has("has_create_context_bare")) return "context";
|
|
472
|
+
if (capNames.has("has_jsx")) return "component";
|
|
473
|
+
if (capNames.has("hook_decl") || capNames.has("hook_const")) return "hook";
|
|
474
|
+
if (fileName.includes("config") || fileName.includes(".config.")) return "config";
|
|
475
|
+
return "lib";
|
|
476
|
+
}
|
|
459
477
|
function extractAuthWrappersTS(absPath) {
|
|
460
478
|
const tree = parseSource(absPath);
|
|
461
479
|
const root = tree.rootNode;
|
|
@@ -757,20 +775,10 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
|
|
|
757
775
|
}
|
|
758
776
|
return barrels;
|
|
759
777
|
}
|
|
760
|
-
function classifyType(id) {
|
|
761
|
-
|
|
762
|
-
if (id.
|
|
763
|
-
|
|
764
|
-
if (id.startsWith("client/components/")) return "component";
|
|
765
|
-
if (id.startsWith("client/hooks/")) return "hook";
|
|
766
|
-
if (/client\/lib\/.*-context\./.test(id)) return "context";
|
|
767
|
-
if (id.startsWith("client/lib/")) return id.includes("config") ? "config" : "util";
|
|
768
|
-
if (id.startsWith("client/api/")) return "util";
|
|
769
|
-
if (id.startsWith("server/mcp/")) return "mcp-tool";
|
|
770
|
-
if (id.startsWith("server/lib/")) return "lib";
|
|
771
|
-
if (id.startsWith("server/")) return "lib";
|
|
772
|
-
if (id.startsWith("lib/") || id.startsWith("config/")) return "lib";
|
|
773
|
-
return "component";
|
|
778
|
+
function classifyType(absPath, id) {
|
|
779
|
+
const contentType = classifyFile(absPath);
|
|
780
|
+
if (contentType === "lib" && id.startsWith("server/mcp/")) return "mcp-tool";
|
|
781
|
+
return contentType;
|
|
774
782
|
}
|
|
775
783
|
function extractRoute(id) {
|
|
776
784
|
if (!id.endsWith("/page.tsx")) return null;
|
|
@@ -875,13 +883,10 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, nodeTypeMap,
|
|
|
875
883
|
if (label) edge.label = label;
|
|
876
884
|
edges.push(edge);
|
|
877
885
|
}
|
|
878
|
-
function edgeTypeFor(
|
|
886
|
+
function edgeTypeFor(_targetId, isTypeOnlyImport, importedNames) {
|
|
879
887
|
if (isTypeOnlyImport) return "imports";
|
|
880
|
-
const
|
|
881
|
-
if (
|
|
882
|
-
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
883
|
-
if (anyRendered) return "renders";
|
|
884
|
-
}
|
|
888
|
+
const anyRendered = importedNames.some((n) => parsed.jsxElements.has(n));
|
|
889
|
+
if (anyRendered) return "renders";
|
|
885
890
|
return "imports";
|
|
886
891
|
}
|
|
887
892
|
for (const imp of parsed.imports) {
|
|
@@ -988,7 +993,7 @@ function generate(rootDir) {
|
|
|
988
993
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
989
994
|
for (const absPath of fileSet) {
|
|
990
995
|
const id = toNodeId(srcDir, absPath);
|
|
991
|
-
const type = classifyType(id);
|
|
996
|
+
const type = classifyType(absPath, id);
|
|
992
997
|
const parsed = parsedByPath.get(absPath);
|
|
993
998
|
const name = parsed.name || nameFromFilename(absPath);
|
|
994
999
|
const route = extractRoute(id);
|
|
@@ -1176,14 +1181,13 @@ function generate(rootDir) {
|
|
|
1176
1181
|
}
|
|
1177
1182
|
};
|
|
1178
1183
|
}
|
|
1179
|
-
var import_node_fs4, import_node_path4,
|
|
1184
|
+
var import_node_fs4, import_node_path4, reactNextjsParser;
|
|
1180
1185
|
var init_react_nextjs = __esm({
|
|
1181
1186
|
"src/server/graph/parsers/ui/react-nextjs.ts"() {
|
|
1182
1187
|
"use strict";
|
|
1183
1188
|
import_node_fs4 = require("node:fs");
|
|
1184
1189
|
import_node_path4 = require("node:path");
|
|
1185
1190
|
init_ts_extractor();
|
|
1186
|
-
RENDER_TYPES = /* @__PURE__ */ new Set(["component", "ui", "layout", "context"]);
|
|
1187
1191
|
reactNextjsParser = {
|
|
1188
1192
|
id: "react-nextjs",
|
|
1189
1193
|
layer: "ui",
|
package/package.json
CHANGED