@launchsecure/launch-kit 0.0.16 → 0.0.18

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.
Files changed (84) hide show
  1. package/dist/chart-client/assets/index--120d9P9.css +1 -0
  2. package/dist/chart-client/assets/index-D7x8nz-H.js +441 -0
  3. package/dist/chart-client/index.html +2 -2
  4. package/dist/client/assets/index-Bf8zdL3x.css +32 -0
  5. package/dist/client/assets/index-Ds9UP_cj.js +291 -0
  6. package/dist/client/index.html +2 -2
  7. package/dist/council-client/assets/index-CofZh7pS.css +1 -0
  8. package/dist/council-client/assets/index-Dc41S-R2.js +198 -0
  9. package/dist/council-client/index.html +21 -0
  10. package/dist/deck-client/assets/_baseUniq-2gclQXo7.js +1 -0
  11. package/dist/deck-client/assets/arc-DcMY5Wm0.js +1 -0
  12. package/dist/deck-client/assets/architectureDiagram-Q4EWVU46-B8iirmmJ.js +36 -0
  13. package/dist/deck-client/assets/blockDiagram-DXYQGD6D-B4JBLjmJ.js +132 -0
  14. package/dist/deck-client/assets/c4Diagram-AHTNJAMY-CojrJAk8.js +10 -0
  15. package/dist/deck-client/assets/channel-ERh5jKXV.js +1 -0
  16. package/dist/deck-client/assets/chunk-4BX2VUAB-Bmb_BMDo.js +1 -0
  17. package/dist/deck-client/assets/chunk-4TB4RGXK-CumBy8qe.js +206 -0
  18. package/dist/deck-client/assets/chunk-55IACEB6-Ka8Hb1wD.js +1 -0
  19. package/dist/deck-client/assets/chunk-EDXVE4YY-B3sIPiQo.js +1 -0
  20. package/dist/deck-client/assets/chunk-FMBD7UC4-C1tYkaqu.js +15 -0
  21. package/dist/deck-client/assets/chunk-OYMX7WX6-D7Wacbky.js +231 -0
  22. package/dist/deck-client/assets/chunk-QZHKN3VN-ChXI0vO3.js +1 -0
  23. package/dist/deck-client/assets/chunk-YZCP3GAM-BXhiqf8u.js +1 -0
  24. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +1 -0
  25. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +1 -0
  26. package/dist/deck-client/assets/clone-DfWhlD4X.js +1 -0
  27. package/dist/deck-client/assets/cose-bilkent-S5V4N54A-Bqp3p68D.js +1 -0
  28. package/dist/deck-client/assets/cytoscape.esm-BQk4lpUV.js +331 -0
  29. package/dist/deck-client/assets/dagre-KV5264BT-BS-rtyhZ.js +4 -0
  30. package/dist/deck-client/assets/defaultLocale-DX6XiGOO.js +1 -0
  31. package/dist/deck-client/assets/diagram-5BDNPKRD-BIrj9YGI.js +10 -0
  32. package/dist/deck-client/assets/diagram-G4DWMVQ6-noHWPIg4.js +24 -0
  33. package/dist/deck-client/assets/diagram-MMDJMWI5-C2qHxvqV.js +43 -0
  34. package/dist/deck-client/assets/diagram-TYMM5635-BytnGQr-.js +24 -0
  35. package/dist/deck-client/assets/erDiagram-SMLLAGMA-BfK5m2YQ.js +85 -0
  36. package/dist/deck-client/assets/flowDiagram-DWJPFMVM-Cq925G1Z.js +162 -0
  37. package/dist/deck-client/assets/ganttDiagram-T4ZO3ILL-DhhHPAmj.js +292 -0
  38. package/dist/deck-client/assets/gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js +106 -0
  39. package/dist/deck-client/assets/graph-RTawgVWm.js +1 -0
  40. package/dist/deck-client/assets/index-765AIQ9z.css +1 -0
  41. package/dist/deck-client/assets/index-BfIfJXmS.js +476 -0
  42. package/dist/deck-client/assets/infoDiagram-42DDH7IO-BlR584kX.js +2 -0
  43. package/dist/deck-client/assets/init-Gi6I4Gst.js +1 -0
  44. package/dist/deck-client/assets/ishikawaDiagram-UXIWVN3A-DygKoNGY.js +70 -0
  45. package/dist/deck-client/assets/journeyDiagram-VCZTEJTY-BnaiYp9N.js +139 -0
  46. package/dist/deck-client/assets/kanban-definition-6JOO6SKY-BQBUBzJC.js +89 -0
  47. package/dist/deck-client/assets/katex-DkKDou_j.js +257 -0
  48. package/dist/deck-client/assets/layout-DeZ8HI1T.js +1 -0
  49. package/dist/deck-client/assets/linear-C6roLi_9.js +1 -0
  50. package/dist/deck-client/assets/min-CbUksbuI.js +1 -0
  51. package/dist/deck-client/assets/mindmap-definition-QFDTVHPH-iNxV62yN.js +96 -0
  52. package/dist/deck-client/assets/ordinal-Cboi1Yqb.js +1 -0
  53. package/dist/deck-client/assets/pieDiagram-DEJITSTG-DHVA0jaG.js +30 -0
  54. package/dist/deck-client/assets/quadrantDiagram-34T5L4WZ-DBeKKLUQ.js +7 -0
  55. package/dist/deck-client/assets/requirementDiagram-MS252O5E-CBwITx7p.js +84 -0
  56. package/dist/deck-client/assets/sankeyDiagram-XADWPNL6-BtE-1YTU.js +10 -0
  57. package/dist/deck-client/assets/sequenceDiagram-FGHM5R23-DN96yPP2.js +157 -0
  58. package/dist/deck-client/assets/stateDiagram-FHFEXIEX-VUkKC2uJ.js +1 -0
  59. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +1 -0
  60. package/dist/deck-client/assets/timeline-definition-GMOUNBTQ-oUeZhRns.js +120 -0
  61. package/dist/deck-client/assets/vennDiagram-DHZGUBPP-D87fK90n.js +34 -0
  62. package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +162 -0
  63. package/dist/deck-client/assets/wardleyDiagram-NUSXRM2D-Ca_i0QRA.js +20 -0
  64. package/dist/deck-client/assets/xychartDiagram-5P7HB3ND-CUOJVIvq.js +7 -0
  65. package/dist/deck-client/index.html +21 -0
  66. package/dist/server/chart-serve.js +258 -273
  67. package/dist/server/cli.js +305 -713
  68. package/dist/server/council-entry.js +1418 -0
  69. package/dist/server/council-serve.js +1039 -0
  70. package/dist/server/deck-mcp-entry.js +1789 -0
  71. package/dist/server/deck-serve.js +1275 -0
  72. package/dist/server/deck-server/deck-mcp-entry.js +1789 -0
  73. package/dist/server/deck-server/deck-serve.js +1275 -0
  74. package/dist/server/fb-wizard.js +0 -0
  75. package/dist/server/graph-mcp-entry.js +268 -701
  76. package/dist/server/server/chart-serve.js +4643 -0
  77. package/dist/server/server/cli.js +13360 -0
  78. package/dist/server/server/fb-wizard.js +136 -0
  79. package/dist/server/server/graph-mcp-entry.js +6776 -0
  80. package/package.json +25 -18
  81. package/dist/chart-client/assets/index-BpQPtTuo.js +0 -441
  82. package/dist/chart-client/assets/index-CbZ13AXL.css +0 -1
  83. package/dist/client/assets/index-3ENenBk-.js +0 -291
  84. package/dist/client/assets/index-BCYw64M7.css +0 -32
@@ -90,15 +90,15 @@ function getQuery(name) {
90
90
  ensureInit();
91
91
  const cached = queryCache.get(name);
92
92
  if (cached) return cached;
93
- const scmPath = (0, import_node_path3.join)(queriesDir, `${name}.scm`);
94
- const scm = (0, import_node_fs3.readFileSync)(scmPath, "utf-8");
93
+ const scmPath = (0, import_node_path4.join)(queriesDir, `${name}.scm`);
94
+ const scm = (0, import_node_fs4.readFileSync)(scmPath, "utf-8");
95
95
  const query = tsxLanguage.query(scm);
96
96
  queryCache.set(name, query);
97
97
  return query;
98
98
  }
99
99
  function parseSource(absPath) {
100
100
  ensureInit();
101
- const content = (0, import_node_fs3.readFileSync)(absPath, "utf-8");
101
+ const content = (0, import_node_fs4.readFileSync)(absPath, "utf-8");
102
102
  return parserInstance.parse(content);
103
103
  }
104
104
  function parseCodeTS(code) {
@@ -563,17 +563,17 @@ function extractDeep(absPath) {
563
563
  }
564
564
  return { elements, stateVars, conditions, variables, responses, params };
565
565
  }
566
- var import_node_fs3, import_node_path3, tsxLanguage, parserInstance, initPromise, initialized, queriesDir, queryCache, PRISMA_MUTATION_METHODS_BUILTIN, DB_IDENTIFIERS_FALLBACK, extraDbIdentifiers, extraMutationMethods;
566
+ var import_node_fs4, import_node_path4, tsxLanguage, parserInstance, initPromise, initialized, queriesDir, queryCache, PRISMA_MUTATION_METHODS_BUILTIN, DB_IDENTIFIERS_FALLBACK, extraDbIdentifiers, extraMutationMethods;
567
567
  var init_ts_extractor = __esm({
568
568
  "src/server/graph/core/ts-extractor.ts"() {
569
569
  "use strict";
570
- import_node_fs3 = require("node:fs");
571
- import_node_path3 = require("node:path");
570
+ import_node_fs4 = require("node:fs");
571
+ import_node_path4 = require("node:path");
572
572
  initialized = false;
573
573
  queriesDir = (() => {
574
- const srcPath = (0, import_node_path3.join)((0, import_node_path3.dirname)(__filename), "..", "queries");
574
+ const srcPath = (0, import_node_path4.join)((0, import_node_path4.dirname)(__filename), "..", "queries");
575
575
  if (require("fs").existsSync(srcPath)) return srcPath;
576
- return (0, import_node_path3.join)((0, import_node_path3.dirname)(__filename), "graph", "queries");
576
+ return (0, import_node_path4.join)((0, import_node_path4.dirname)(__filename), "graph", "queries");
577
577
  })();
578
578
  queryCache = /* @__PURE__ */ new Map();
579
579
  PRISMA_MUTATION_METHODS_BUILTIN = [
@@ -601,24 +601,24 @@ __export(chart_serve_exports, {
601
601
  });
602
602
  module.exports = __toCommonJS(chart_serve_exports);
603
603
  var import_node_http = __toESM(require("node:http"));
604
- var import_node_fs17 = __toESM(require("node:fs"));
605
- var import_node_path19 = __toESM(require("node:path"));
604
+ var import_node_fs18 = __toESM(require("node:fs"));
605
+ var import_node_path20 = __toESM(require("node:path"));
606
606
 
607
607
  // src/server/graph/index.ts
608
- var import_node_fs14 = require("node:fs");
609
- var import_node_path16 = require("node:path");
608
+ var import_node_fs15 = require("node:fs");
609
+ var import_node_path17 = require("node:path");
610
610
 
611
611
  // src/server/graph/core/graph-builder.ts
612
- var import_node_fs11 = require("node:fs");
613
- var import_node_path12 = require("node:path");
612
+ var import_node_fs12 = require("node:fs");
613
+ var import_node_path13 = require("node:path");
614
614
  init_config();
615
615
 
616
616
  // src/server/graph/core/parser-registry.ts
617
- var import_node_path11 = require("node:path");
617
+ var import_node_path12 = require("node:path");
618
618
 
619
619
  // src/server/graph/parsers/ts/typescript-project.ts
620
- var import_node_fs4 = require("node:fs");
621
- var import_node_path4 = require("node:path");
620
+ var import_node_fs5 = require("node:fs");
621
+ var import_node_path5 = require("node:path");
622
622
  init_config();
623
623
 
624
624
  // src/server/graph/core/resolve-paths.ts
@@ -648,6 +648,50 @@ function resolveProjectPaths(rootDir, config) {
648
648
  return null;
649
649
  }
650
650
 
651
+ // src/server/graph/core/walk.ts
652
+ var import_node_fs3 = require("node:fs");
653
+ var import_node_path3 = require("node:path");
654
+ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
655
+ "node_modules",
656
+ ".git",
657
+ ".next",
658
+ ".launchsecure",
659
+ ".claude",
660
+ "dist",
661
+ "build",
662
+ "out",
663
+ ".turbo",
664
+ ".vercel",
665
+ "coverage"
666
+ ]);
667
+ function walk(dir, exts) {
668
+ const results = [];
669
+ if (!(0, import_node_fs3.existsSync)(dir)) return results;
670
+ for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
671
+ const full = (0, import_node_path3.join)(dir, entry.name);
672
+ if (entry.isDirectory()) {
673
+ results.push(...walk(full, exts));
674
+ } else if (exts.includes((0, import_node_path3.extname)(entry.name))) {
675
+ results.push(full);
676
+ }
677
+ }
678
+ return results;
679
+ }
680
+ function walkWithIgnore(dir, exts, opts = {}) {
681
+ const results = [];
682
+ if (!(0, import_node_fs3.existsSync)(dir)) return results;
683
+ const skip = opts.extraIgnore ? /* @__PURE__ */ new Set([...DEFAULT_IGNORE_DIRS, ...opts.extraIgnore]) : DEFAULT_IGNORE_DIRS;
684
+ for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
685
+ if (entry.isDirectory()) {
686
+ if (skip.has(entry.name)) continue;
687
+ results.push(...walkWithIgnore((0, import_node_path3.join)(dir, entry.name), exts, opts));
688
+ } else if (exts.includes((0, import_node_path3.extname)(entry.name))) {
689
+ results.push((0, import_node_path3.join)(dir, entry.name));
690
+ }
691
+ }
692
+ return results;
693
+ }
694
+
651
695
  // src/server/graph/parsers/ts/typescript-project.ts
652
696
  init_ts_extractor();
653
697
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]);
@@ -664,48 +708,22 @@ var CLASSIFICATION_TO_LAYER = {
664
708
  "mcp-tool": "ui",
665
709
  external: "ui"
666
710
  };
667
- function walk(dir, exts) {
668
- const results = [];
669
- if (!(0, import_node_fs4.existsSync)(dir)) return results;
670
- for (const entry of (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true })) {
671
- const full = (0, import_node_path4.join)(dir, entry.name);
672
- if (entry.isDirectory()) {
673
- results.push(...walk(full, exts));
674
- } else if (exts.includes((0, import_node_path4.extname)(entry.name))) {
675
- results.push(full);
676
- }
677
- }
678
- return results;
679
- }
680
- function walkWithIgnore(dir, exts, ignoreDirs) {
681
- const results = [];
682
- if (!(0, import_node_fs4.existsSync)(dir)) return results;
683
- for (const entry of (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true })) {
684
- if (entry.isDirectory()) {
685
- if (ignoreDirs.has(entry.name)) continue;
686
- results.push(...walkWithIgnore((0, import_node_path4.join)(dir, entry.name), exts, ignoreDirs));
687
- } else if (exts.includes((0, import_node_path4.extname)(entry.name))) {
688
- results.push((0, import_node_path4.join)(dir, entry.name));
689
- }
690
- }
691
- return results;
692
- }
693
711
  function toNodeId(srcDir, absPath) {
694
- return (0, import_node_path4.relative)(srcDir, absPath).replace(/\\/g, "/");
712
+ return (0, import_node_path5.relative)(srcDir, absPath).replace(/\\/g, "/");
695
713
  }
696
714
  function resolveImport(srcDir, specifier) {
697
715
  if (!specifier.startsWith("@/")) return null;
698
716
  const rel = specifier.slice(2);
699
- const base = (0, import_node_path4.join)(srcDir, rel);
700
- for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path4.join)(base, "index.ts"), (0, import_node_path4.join)(base, "index.tsx")]) {
701
- if ((0, import_node_fs4.existsSync)(c) && (0, import_node_fs4.statSync)(c).isFile()) return c;
717
+ const base = (0, import_node_path5.join)(srcDir, rel);
718
+ for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path5.join)(base, "index.ts"), (0, import_node_path5.join)(base, "index.tsx")]) {
719
+ if ((0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile()) return c;
702
720
  }
703
721
  return null;
704
722
  }
705
723
  function resolveRelativeImport(fromFile, specifier) {
706
- const base = (0, import_node_path4.join)((0, import_node_path4.dirname)(fromFile), specifier);
707
- for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path4.join)(base, "index.ts"), (0, import_node_path4.join)(base, "index.tsx")]) {
708
- if ((0, import_node_fs4.existsSync)(c) && (0, import_node_fs4.statSync)(c).isFile()) return c;
724
+ const base = (0, import_node_path5.join)((0, import_node_path5.dirname)(fromFile), specifier);
725
+ for (const c of [base, base + ".ts", base + ".tsx", (0, import_node_path5.join)(base, "index.ts"), (0, import_node_path5.join)(base, "index.tsx")]) {
726
+ if ((0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile()) return c;
709
727
  }
710
728
  return null;
711
729
  }
@@ -726,7 +744,7 @@ function resolveBarrelMap(barrelAbsPath, parsedByPath, memo, visiting) {
726
744
  const resolved = resolveRelativeImport(barrelAbsPath, re.from);
727
745
  if (!resolved) continue;
728
746
  if (re.isWildcard) {
729
- const targetBn = (0, import_node_path4.basename)(resolved);
747
+ const targetBn = (0, import_node_path5.basename)(resolved);
730
748
  const targetIsBarrel = targetBn === "index.ts" || targetBn === "index.tsx";
731
749
  if (targetIsBarrel) {
732
750
  const nested = resolveBarrelMap(resolved, parsedByPath, memo, visiting);
@@ -753,12 +771,12 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
753
771
  const barrels = /* @__PURE__ */ new Map();
754
772
  const memo = /* @__PURE__ */ new Map();
755
773
  for (const [absPath, parsed] of parsedByPath) {
756
- const bn = (0, import_node_path4.basename)(absPath);
774
+ const bn = (0, import_node_path5.basename)(absPath);
757
775
  if (bn !== "index.ts" && bn !== "index.tsx") continue;
758
776
  if (parsed.reExports.length === 0) continue;
759
777
  const map = resolveBarrelMap(absPath, parsedByPath, memo, /* @__PURE__ */ new Set());
760
778
  if (map.size > 0) {
761
- const barrelId = (0, import_node_path4.relative)(srcDir, (0, import_node_path4.dirname)(absPath)).replace(/\\/g, "/");
779
+ const barrelId = (0, import_node_path5.relative)(srcDir, (0, import_node_path5.dirname)(absPath)).replace(/\\/g, "/");
762
780
  barrels.set(barrelId, map);
763
781
  }
764
782
  }
@@ -779,10 +797,10 @@ function extractRoute(id) {
779
797
  return route || "/";
780
798
  }
781
799
  function nameFromFilename(absPath) {
782
- return (0, import_node_path4.basename)(absPath, (0, import_node_path4.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
800
+ return (0, import_node_path5.basename)(absPath, (0, import_node_path5.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
783
801
  }
784
802
  function filePathToApiRoute(apiDir, absPath) {
785
- let route = "/" + (0, import_node_path4.relative)(apiDir, absPath).replace(/\\/g, "/").replace(/\/route\.tsx?$/, "");
803
+ let route = "/" + (0, import_node_path5.relative)(apiDir, absPath).replace(/\\/g, "/").replace(/\/route\.tsx?$/, "");
786
804
  route = route.replace(/\[([^\]]+)\]/g, ":$1");
787
805
  route = route.replace(/\/+/g, "/");
788
806
  if (route === "/") return "/api";
@@ -966,12 +984,9 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
966
984
  }
967
985
  return { edges, flagged };
968
986
  }
969
- function hasNextConfig(rootDir) {
970
- return (0, import_node_fs4.existsSync)((0, import_node_path4.join)(rootDir, "next.config.ts")) || (0, import_node_fs4.existsSync)((0, import_node_path4.join)(rootDir, "next.config.js")) || (0, import_node_fs4.existsSync)((0, import_node_path4.join)(rootDir, "next.config.mjs"));
971
- }
972
987
  function detect(rootDir) {
973
988
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
974
- return paths !== null && hasNextConfig(rootDir);
989
+ return paths !== null;
975
990
  }
976
991
  function generate(rootDir) {
977
992
  const config = loadConfig(rootDir);
@@ -979,10 +994,10 @@ function generate(rootDir) {
979
994
  const srcDir = paths.srcDir;
980
995
  const apiDir = paths.apiDir;
981
996
  const appFiles = walk(paths.appDir, [".tsx", ".ts"]);
982
- const clientFiles = walk((0, import_node_path4.join)(srcDir, "client"), [".tsx", ".ts"]);
983
- const serverFiles = walk((0, import_node_path4.join)(srcDir, "server"), [".ts", ".tsx"]);
984
- const libFiles = walk((0, import_node_path4.join)(srcDir, "lib"), [".ts", ".tsx"]);
985
- const configFiles = walk((0, import_node_path4.join)(srcDir, "config"), [".ts", ".tsx"]);
997
+ const clientFiles = walk((0, import_node_path5.join)(srcDir, "client"), [".tsx", ".ts"]);
998
+ const serverFiles = walk((0, import_node_path5.join)(srcDir, "server"), [".ts", ".tsx"]);
999
+ const libFiles = walk((0, import_node_path5.join)(srcDir, "lib"), [".ts", ".tsx"]);
1000
+ const configFiles = walk((0, import_node_path5.join)(srcDir, "config"), [".ts", ".tsx"]);
986
1001
  const allDiscovered = [...appFiles, ...clientFiles, ...serverFiles, ...libFiles, ...configFiles];
987
1002
  const parsedByPath = /* @__PURE__ */ new Map();
988
1003
  for (const absPath of allDiscovered) {
@@ -993,7 +1008,7 @@ function generate(rootDir) {
993
1008
  const apiNodes = [];
994
1009
  const nodeIdSet = /* @__PURE__ */ new Set();
995
1010
  const routeToNodeId = /* @__PURE__ */ new Map();
996
- const fileSet = allDiscovered.filter((f) => !(0, import_node_path4.basename)(f).startsWith("index."));
1011
+ const fileSet = allDiscovered.filter((f) => !(0, import_node_path5.basename)(f).startsWith("index."));
997
1012
  for (const absPath of fileSet) {
998
1013
  const id = toNodeId(srcDir, absPath);
999
1014
  const type = classifyType(absPath, id);
@@ -1010,7 +1025,7 @@ function generate(rootDir) {
1010
1025
  const dbCalls = extractDbCallsTS(absPath);
1011
1026
  const authWrappers = extractAuthWrappersTS(absPath);
1012
1027
  const deep = extractDeep(absPath);
1013
- const routePath = (0, import_node_fs4.existsSync)(apiDir) ? filePathToApiRoute(apiDir, absPath) : `/api/${id.replace(/\/route\.tsx?$/, "")}`;
1028
+ const routePath = (0, import_node_fs5.existsSync)(apiDir) ? filePathToApiRoute(apiDir, absPath) : `/api/${id.replace(/\/route\.tsx?$/, "")}`;
1014
1029
  const mutations = dbCalls.filter((c) => c.isMutation);
1015
1030
  const mutates = mutations.length > 0;
1016
1031
  const authStrategy = [...authWrappers];
@@ -1087,20 +1102,7 @@ function generate(rootDir) {
1087
1102
  });
1088
1103
  }
1089
1104
  const externalScanned = new Set(allDiscovered.map((f) => f.replace(/\\/g, "/")));
1090
- const IGNORE_DIRS = /* @__PURE__ */ new Set([
1091
- "node_modules",
1092
- ".next",
1093
- "dist",
1094
- ".launchsecure",
1095
- ".git",
1096
- "src",
1097
- "coverage",
1098
- ".turbo",
1099
- "build",
1100
- "out",
1101
- ".vercel"
1102
- ]);
1103
- const externalCandidates = walkWithIgnore(rootDir, [".ts", ".tsx"], IGNORE_DIRS);
1105
+ const externalCandidates = walkWithIgnore(rootDir, [".ts", ".tsx"], { extraIgnore: /* @__PURE__ */ new Set(["src"]) });
1104
1106
  for (const absPath of externalCandidates) {
1105
1107
  const normalized = absPath.replace(/\\/g, "/");
1106
1108
  if (externalScanned.has(normalized)) continue;
@@ -1110,7 +1112,7 @@ function generate(rootDir) {
1110
1112
  } catch {
1111
1113
  continue;
1112
1114
  }
1113
- const externalId = (0, import_node_path4.relative)(rootDir, absPath).replace(/\\/g, "/");
1115
+ const externalId = (0, import_node_path5.relative)(rootDir, absPath).replace(/\\/g, "/");
1114
1116
  const edgesFromThis = [];
1115
1117
  const seen = /* @__PURE__ */ new Set();
1116
1118
  for (const imp of parsed.imports) {
@@ -1314,8 +1316,8 @@ var typescriptProjectParser = {
1314
1316
  };
1315
1317
 
1316
1318
  // src/server/graph/parsers/db/prisma-schema.ts
1317
- var import_node_fs5 = require("node:fs");
1318
- var import_node_path5 = require("node:path");
1319
+ var import_node_fs6 = require("node:fs");
1320
+ var import_node_path6 = require("node:path");
1319
1321
  function parseModels(content) {
1320
1322
  const nodes = [];
1321
1323
  const relations = [];
@@ -1406,11 +1408,11 @@ function parseEnums(content) {
1406
1408
  return nodes;
1407
1409
  }
1408
1410
  function detect2(rootDir) {
1409
- return (0, import_node_fs5.existsSync)((0, import_node_path5.join)(rootDir, "prisma", "schema.prisma"));
1411
+ return (0, import_node_fs6.existsSync)((0, import_node_path6.join)(rootDir, "prisma", "schema.prisma"));
1410
1412
  }
1411
1413
  function generate2(rootDir) {
1412
- const schemaPath = (0, import_node_path5.join)(rootDir, "prisma", "schema.prisma");
1413
- const content = (0, import_node_fs5.readFileSync)(schemaPath, "utf-8");
1414
+ const schemaPath = (0, import_node_path6.join)(rootDir, "prisma", "schema.prisma");
1415
+ const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
1414
1416
  const { nodes: modelNodes, relations } = parseModels(content);
1415
1417
  const enumNodes = parseEnums(content);
1416
1418
  const allNodes = [...modelNodes, ...enumNodes];
@@ -1467,8 +1469,8 @@ var prismaSchemaParser = {
1467
1469
  };
1468
1470
 
1469
1471
  // src/server/graph/parsers/db/sql-migrations.ts
1470
- var import_node_fs6 = require("node:fs");
1471
- var import_node_path6 = require("node:path");
1472
+ var import_node_fs7 = require("node:fs");
1473
+ var import_node_path7 = require("node:path");
1472
1474
  var PG_TO_PRISMA = {
1473
1475
  "TEXT": "String",
1474
1476
  "VARCHAR": "String",
@@ -1618,19 +1620,19 @@ function parseUniqueIndex(sql, state) {
1618
1620
  }
1619
1621
  }
1620
1622
  function parseMigrations(rootDir) {
1621
- const migrationsDir = (0, import_node_path6.join)(rootDir, "prisma", "migrations");
1623
+ const migrationsDir = (0, import_node_path7.join)(rootDir, "prisma", "migrations");
1622
1624
  const state = {
1623
1625
  tables: /* @__PURE__ */ new Map(),
1624
1626
  enums: /* @__PURE__ */ new Map(),
1625
1627
  fks: [],
1626
1628
  uniqueIndexes: /* @__PURE__ */ new Map()
1627
1629
  };
1628
- if (!(0, import_node_fs6.existsSync)(migrationsDir)) return state;
1629
- const dirs = (0, import_node_fs6.readdirSync)(migrationsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
1630
+ if (!(0, import_node_fs7.existsSync)(migrationsDir)) return state;
1631
+ const dirs = (0, import_node_fs7.readdirSync)(migrationsDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
1630
1632
  for (const dir of dirs) {
1631
- const sqlPath = (0, import_node_path6.join)(migrationsDir, dir, "migration.sql");
1632
- if (!(0, import_node_fs6.existsSync)(sqlPath)) continue;
1633
- const sql = (0, import_node_fs6.readFileSync)(sqlPath, "utf-8");
1633
+ const sqlPath = (0, import_node_path7.join)(migrationsDir, dir, "migration.sql");
1634
+ if (!(0, import_node_fs7.existsSync)(sqlPath)) continue;
1635
+ const sql = (0, import_node_fs7.readFileSync)(sqlPath, "utf-8");
1634
1636
  parseCreateEnum(sql, state);
1635
1637
  parseCreateTable(sql, state);
1636
1638
  parseAlterTable(sql, state);
@@ -1641,9 +1643,9 @@ function parseMigrations(rootDir) {
1641
1643
  return state;
1642
1644
  }
1643
1645
  function loadPrismaState(rootDir) {
1644
- const schemaPath = (0, import_node_path6.join)(rootDir, "prisma", "schema.prisma");
1645
- if (!(0, import_node_fs6.existsSync)(schemaPath)) return null;
1646
- const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
1646
+ const schemaPath = (0, import_node_path7.join)(rootDir, "prisma", "schema.prisma");
1647
+ if (!(0, import_node_fs7.existsSync)(schemaPath)) return null;
1648
+ const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
1647
1649
  const tables = /* @__PURE__ */ new Map();
1648
1650
  const enums = /* @__PURE__ */ new Map();
1649
1651
  const relations = [];
@@ -1808,9 +1810,9 @@ function verify(sqlState, prisma) {
1808
1810
  return { contradictions, flaggedEdges };
1809
1811
  }
1810
1812
  function detect3(rootDir) {
1811
- const migrationsDir = (0, import_node_path6.join)(rootDir, "prisma", "migrations");
1812
- if (!(0, import_node_fs6.existsSync)(migrationsDir)) return false;
1813
- return (0, import_node_fs6.readdirSync)(migrationsDir, { withFileTypes: true }).some((d) => d.isDirectory() && (0, import_node_fs6.existsSync)((0, import_node_path6.join)(migrationsDir, d.name, "migration.sql")));
1813
+ const migrationsDir = (0, import_node_path7.join)(rootDir, "prisma", "migrations");
1814
+ if (!(0, import_node_fs7.existsSync)(migrationsDir)) return false;
1815
+ return (0, import_node_fs7.readdirSync)(migrationsDir, { withFileTypes: true }).some((d) => d.isDirectory() && (0, import_node_fs7.existsSync)((0, import_node_path7.join)(migrationsDir, d.name, "migration.sql")));
1814
1816
  }
1815
1817
  function generate3(rootDir) {
1816
1818
  const sqlState = parseMigrations(rootDir);
@@ -2098,32 +2100,32 @@ var fetchResolverParser = {
2098
2100
  };
2099
2101
 
2100
2102
  // src/server/graph/parsers/crosslayer/api-annotations.ts
2101
- var import_node_fs7 = require("node:fs");
2102
- var import_node_path7 = require("node:path");
2103
+ var import_node_fs8 = require("node:fs");
2104
+ var import_node_path8 = require("node:path");
2103
2105
  var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
2104
2106
  function walk2(dir, exts) {
2105
- if (!(0, import_node_fs7.existsSync)(dir)) return [];
2107
+ if (!(0, import_node_fs8.existsSync)(dir)) return [];
2106
2108
  const results = [];
2107
- for (const entry of (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true })) {
2109
+ for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
2108
2110
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2109
- const full = (0, import_node_path7.join)(dir, entry.name);
2111
+ const full = (0, import_node_path8.join)(dir, entry.name);
2110
2112
  if (entry.isDirectory()) {
2111
2113
  results.push(...walk2(full, exts));
2112
- } else if (exts.includes((0, import_node_path7.extname)(entry.name))) {
2114
+ } else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
2113
2115
  results.push(full);
2114
2116
  }
2115
2117
  }
2116
2118
  return results;
2117
2119
  }
2118
2120
  function toNodeId2(srcDir, absPath) {
2119
- return (0, import_node_path7.relative)(srcDir, absPath).replace(/\\/g, "/");
2121
+ return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
2120
2122
  }
2121
2123
  var apiAnnotationsParser = {
2122
2124
  id: "api-annotations",
2123
2125
  layer: "crosslayer",
2124
2126
  concern: "api-binding",
2125
2127
  detect(rootDir) {
2126
- return (0, import_node_fs7.existsSync)((0, import_node_path7.join)(rootDir, "src"));
2128
+ return (0, import_node_fs8.existsSync)((0, import_node_path8.join)(rootDir, "src"));
2127
2129
  },
2128
2130
  generate(rootDir, layerOutputs) {
2129
2131
  const apiOutput = layerOutputs.get("api");
@@ -2134,13 +2136,13 @@ var apiAnnotationsParser = {
2134
2136
  const uiNodeIds = new Set(uiOutput?.nodes.map((n) => n.id) ?? []);
2135
2137
  const apiRoutes = loadApiRoutesFromOutput(apiOutput);
2136
2138
  const apiPathMap = buildApiPathMap(apiRoutes);
2137
- const srcDir = (0, import_node_path7.join)(rootDir, "src");
2139
+ const srcDir = (0, import_node_path8.join)(rootDir, "src");
2138
2140
  const files = walk2(srcDir, [".ts", ".tsx"]);
2139
2141
  const crossRefs = [];
2140
2142
  const flaggedEdges = [];
2141
2143
  const seen = /* @__PURE__ */ new Set();
2142
2144
  for (const absPath of files) {
2143
- const content = (0, import_node_fs7.readFileSync)(absPath, "utf-8");
2145
+ const content = (0, import_node_fs8.readFileSync)(absPath, "utf-8");
2144
2146
  const sourceId = toNodeId2(srcDir, absPath);
2145
2147
  if (!uiNodeIds.has(sourceId)) continue;
2146
2148
  let match;
@@ -2184,26 +2186,26 @@ var apiAnnotationsParser = {
2184
2186
  };
2185
2187
 
2186
2188
  // src/server/graph/parsers/crosslayer/url-literal-scanner.ts
2187
- var import_node_fs8 = require("node:fs");
2188
- var import_node_path8 = require("node:path");
2189
+ var import_node_fs9 = require("node:fs");
2190
+ var import_node_path9 = require("node:path");
2189
2191
  init_config();
2190
2192
  var URL_LITERAL_RE = /['"`](\/api\/[^'"`\s]+?)['"`]/g;
2191
2193
  function walk3(dir, exts) {
2192
- if (!(0, import_node_fs8.existsSync)(dir)) return [];
2194
+ if (!(0, import_node_fs9.existsSync)(dir)) return [];
2193
2195
  const results = [];
2194
- for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
2196
+ for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
2195
2197
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2196
- const full = (0, import_node_path8.join)(dir, entry.name);
2198
+ const full = (0, import_node_path9.join)(dir, entry.name);
2197
2199
  if (entry.isDirectory()) {
2198
2200
  results.push(...walk3(full, exts));
2199
- } else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
2201
+ } else if (exts.includes((0, import_node_path9.extname)(entry.name))) {
2200
2202
  results.push(full);
2201
2203
  }
2202
2204
  }
2203
2205
  return results;
2204
2206
  }
2205
2207
  function toNodeId3(srcDir, absPath) {
2206
- return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
2208
+ return (0, import_node_path9.relative)(srcDir, absPath).replace(/\\/g, "/");
2207
2209
  }
2208
2210
  var urlLiteralScannerParser = {
2209
2211
  id: "url-literal-scanner",
@@ -2224,7 +2226,7 @@ var urlLiteralScannerParser = {
2224
2226
  const apiPathMap = buildApiPathMap(apiRoutes);
2225
2227
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2226
2228
  const srcDir = paths.srcDir;
2227
- const clientDir = (0, import_node_path8.join)(srcDir, "client");
2229
+ const clientDir = (0, import_node_path9.join)(srcDir, "client");
2228
2230
  const files = [
2229
2231
  ...walk3(clientDir, [".ts", ".tsx"]),
2230
2232
  ...walk3(paths.appDir, [".ts", ".tsx"])
@@ -2234,7 +2236,7 @@ var urlLiteralScannerParser = {
2234
2236
  for (const absPath of files) {
2235
2237
  const sourceId = toNodeId3(srcDir, absPath);
2236
2238
  if (!uiNodeIds.has(sourceId)) continue;
2237
- const content = (0, import_node_fs8.readFileSync)(absPath, "utf-8");
2239
+ const content = (0, import_node_fs9.readFileSync)(absPath, "utf-8");
2238
2240
  let match;
2239
2241
  URL_LITERAL_RE.lastIndex = 0;
2240
2242
  while ((match = URL_LITERAL_RE.exec(content)) !== null) {
@@ -2265,8 +2267,8 @@ var urlLiteralScannerParser = {
2265
2267
  };
2266
2268
 
2267
2269
  // src/server/graph/parsers/static/static-values.ts
2268
- var import_node_fs9 = require("node:fs");
2269
- var import_node_path9 = require("node:path");
2270
+ var import_node_fs10 = require("node:fs");
2271
+ var import_node_path10 = require("node:path");
2270
2272
  var parseCode = null;
2271
2273
  function tryLoadTreeSitter() {
2272
2274
  if (parseCode) return true;
@@ -2299,19 +2301,19 @@ function extractEnumValues(rootDir) {
2299
2301
  const nodes = [];
2300
2302
  const edges = [];
2301
2303
  const schemaPaths = [
2302
- (0, import_node_path9.join)(rootDir, "prisma", "schema.prisma"),
2303
- (0, import_node_path9.join)(rootDir, "prisma", "schema")
2304
+ (0, import_node_path10.join)(rootDir, "prisma", "schema.prisma"),
2305
+ (0, import_node_path10.join)(rootDir, "prisma", "schema")
2304
2306
  ];
2305
2307
  let content = "";
2306
2308
  for (const p of schemaPaths) {
2307
- if ((0, import_node_fs9.existsSync)(p)) {
2309
+ if ((0, import_node_fs10.existsSync)(p)) {
2308
2310
  try {
2309
- const stat = (0, import_node_fs9.statSync)(p);
2311
+ const stat = (0, import_node_fs10.statSync)(p);
2310
2312
  if (stat.isFile()) {
2311
- content = (0, import_node_fs9.readFileSync)(p, "utf-8");
2313
+ content = (0, import_node_fs10.readFileSync)(p, "utf-8");
2312
2314
  } else if (stat.isDirectory()) {
2313
- const files = (0, import_node_fs9.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
2314
- content = files.map((f) => (0, import_node_fs9.readFileSync)((0, import_node_path9.join)(p, f), "utf-8")).join("\n");
2315
+ const files = (0, import_node_fs10.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
2316
+ content = files.map((f) => (0, import_node_fs10.readFileSync)((0, import_node_path10.join)(p, f), "utf-8")).join("\n");
2315
2317
  }
2316
2318
  } catch {
2317
2319
  continue;
@@ -2385,7 +2387,7 @@ function extractStringArrayFromNode(node) {
2385
2387
  return values;
2386
2388
  }
2387
2389
  function findArrayDecl(root, varName) {
2388
- function walk5(node) {
2390
+ function walk4(node) {
2389
2391
  if (node.type === "variable_declarator") {
2390
2392
  const nameNode = node.childForFieldName("name");
2391
2393
  const valueNode = node.childForFieldName("value");
@@ -2398,12 +2400,12 @@ function findArrayDecl(root, varName) {
2398
2400
  }
2399
2401
  }
2400
2402
  for (const child of node.namedChildren) {
2401
- const found = walk5(child);
2403
+ const found = walk4(child);
2402
2404
  if (found) return found;
2403
2405
  }
2404
2406
  return null;
2405
2407
  }
2406
- return walk5(root);
2408
+ return walk4(root);
2407
2409
  }
2408
2410
  function extractObjectPropsRegex(objStr) {
2409
2411
  const props = {};
@@ -2467,14 +2469,14 @@ function extractSeedData(rootDir) {
2467
2469
  const nodes = [];
2468
2470
  const edges = [];
2469
2471
  const seedFiles = [
2470
- (0, import_node_path9.join)(rootDir, "prisma", "seed.ts"),
2471
- (0, import_node_path9.join)(rootDir, "prisma", "seed.js"),
2472
- (0, import_node_path9.join)(rootDir, "src", "server", "lib", "system-tags.ts")
2473
- ].filter(import_node_fs9.existsSync);
2472
+ (0, import_node_path10.join)(rootDir, "prisma", "seed.ts"),
2473
+ (0, import_node_path10.join)(rootDir, "prisma", "seed.js"),
2474
+ (0, import_node_path10.join)(rootDir, "src", "server", "lib", "system-tags.ts")
2475
+ ].filter(import_node_fs10.existsSync);
2474
2476
  const useTreeSitter = tryLoadTreeSitter();
2475
2477
  for (const filePath of seedFiles) {
2476
- const content = (0, import_node_fs9.readFileSync)(filePath, "utf-8");
2477
- const relPath = (0, import_node_path9.relative)(rootDir, filePath);
2478
+ const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
2479
+ const relPath = (0, import_node_path10.relative)(rootDir, filePath);
2478
2480
  const seeded = detectSeededArrays(content, relPath);
2479
2481
  let astRoot = null;
2480
2482
  if (useTreeSitter && parseCode) {
@@ -2568,11 +2570,11 @@ function extractSeedData(rootDir) {
2568
2570
  return { nodes, edges };
2569
2571
  }
2570
2572
  function walkDir(dir, exts) {
2571
- if (!(0, import_node_fs9.existsSync)(dir)) return [];
2573
+ if (!(0, import_node_fs10.existsSync)(dir)) return [];
2572
2574
  const results = [];
2573
- for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
2575
+ for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
2574
2576
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
2575
- const full = (0, import_node_path9.join)(dir, entry.name);
2577
+ const full = (0, import_node_path10.join)(dir, entry.name);
2576
2578
  if (entry.isDirectory()) results.push(...walkDir(full, exts));
2577
2579
  else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
2578
2580
  }
@@ -2580,11 +2582,11 @@ function walkDir(dir, exts) {
2580
2582
  }
2581
2583
  function extractConstants(rootDir) {
2582
2584
  const nodes = [];
2583
- const srcDir = (0, import_node_path9.join)(rootDir, "src");
2584
- if (!(0, import_node_fs9.existsSync)(srcDir)) return { nodes };
2585
+ const srcDir = (0, import_node_path10.join)(rootDir, "src");
2586
+ if (!(0, import_node_fs10.existsSync)(srcDir)) return { nodes };
2585
2587
  for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
2586
- const content = (0, import_node_fs9.readFileSync)(filePath, "utf-8");
2587
- const relPath = (0, import_node_path9.relative)(rootDir, filePath);
2588
+ const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
2589
+ const relPath = (0, import_node_path10.relative)(rootDir, filePath);
2588
2590
  const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
2589
2591
  let cm;
2590
2592
  while ((cm = constArrayRe.exec(content)) !== null) {
@@ -2617,7 +2619,7 @@ function extractConstants(rootDir) {
2617
2619
  return { nodes };
2618
2620
  }
2619
2621
  function detect4(rootDir) {
2620
- return (0, import_node_fs9.existsSync)((0, import_node_path9.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs9.existsSync)((0, import_node_path9.join)(rootDir, "prisma", "seed.ts"));
2622
+ return (0, import_node_fs10.existsSync)((0, import_node_path10.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs10.existsSync)((0, import_node_path10.join)(rootDir, "prisma", "seed.ts"));
2621
2623
  }
2622
2624
  function generate4(rootDir) {
2623
2625
  const enumResult = extractEnumValues(rootDir);
@@ -2692,26 +2694,9 @@ var staticValuesParser = {
2692
2694
  };
2693
2695
 
2694
2696
  // src/server/graph/parsers/crosslayer/static-ref-scanner.ts
2695
- var import_node_fs10 = require("node:fs");
2696
- var import_node_path10 = require("node:path");
2697
+ var import_node_fs11 = require("node:fs");
2698
+ var import_node_path11 = require("node:path");
2697
2699
  init_config();
2698
- function walk4(dir, exts) {
2699
- if (!(0, import_node_fs10.existsSync)(dir)) return [];
2700
- const results = [];
2701
- function recurse(d) {
2702
- for (const entry of (0, import_node_fs10.readdirSync)(d, { withFileTypes: true })) {
2703
- const full = (0, import_node_path10.join)(d, entry.name);
2704
- if (entry.isDirectory()) {
2705
- if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
2706
- recurse(full);
2707
- } else if (exts.some((ext) => entry.name.endsWith(ext))) {
2708
- results.push(full);
2709
- }
2710
- }
2711
- }
2712
- recurse(dir);
2713
- return results;
2714
- }
2715
2700
  var MIN_VALUE_LENGTH = 4;
2716
2701
  var SKIP_VALUES = /* @__PURE__ */ new Set([
2717
2702
  "true",
@@ -2854,11 +2839,11 @@ var staticRefScannerParser = {
2854
2839
  if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
2855
2840
  const srcDir = paths.srcDir;
2856
2841
  const files = [
2857
- ...walk4((0, import_node_path10.join)(srcDir, "client"), [".ts", ".tsx"]),
2858
- ...walk4(paths.appDir, [".ts", ".tsx"]),
2859
- ...walk4((0, import_node_path10.join)(srcDir, "server"), [".ts", ".tsx"]),
2860
- ...walk4((0, import_node_path10.join)(srcDir, "lib"), [".ts", ".tsx"]),
2861
- ...walk4((0, import_node_path10.join)(srcDir, "config"), [".ts", ".tsx"])
2842
+ ...walkWithIgnore((0, import_node_path11.join)(srcDir, "client"), [".ts", ".tsx"]),
2843
+ ...walkWithIgnore(paths.appDir, [".ts", ".tsx"]),
2844
+ ...walkWithIgnore((0, import_node_path11.join)(srcDir, "server"), [".ts", ".tsx"]),
2845
+ ...walkWithIgnore((0, import_node_path11.join)(srcDir, "lib"), [".ts", ".tsx"]),
2846
+ ...walkWithIgnore((0, import_node_path11.join)(srcDir, "config"), [".ts", ".tsx"])
2862
2847
  ];
2863
2848
  const uiOutput = layerOutputs.get("ui");
2864
2849
  const apiOutput = layerOutputs.get("api");
@@ -2876,10 +2861,10 @@ var staticRefScannerParser = {
2876
2861
  const seen = /* @__PURE__ */ new Set();
2877
2862
  let filesScanned = 0;
2878
2863
  for (const absPath of files) {
2879
- const sourceId = (0, import_node_path10.relative)(srcDir, absPath).replace(/\\/g, "/");
2864
+ const sourceId = (0, import_node_path11.relative)(srcDir, absPath).replace(/\\/g, "/");
2880
2865
  const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
2881
2866
  if (!sourceLayer) continue;
2882
- const content = (0, import_node_fs10.readFileSync)(absPath, "utf-8");
2867
+ const content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
2883
2868
  filesScanned++;
2884
2869
  let fileRefs;
2885
2870
  if (parseCode2) {
@@ -2995,7 +2980,7 @@ function registerBuiltins(registry, disabled) {
2995
2980
  function loadCustomParsers(registry, config, rootDir, disabled) {
2996
2981
  for (const entry of config.parsers?.custom ?? []) {
2997
2982
  try {
2998
- const absPath = (0, import_node_path11.resolve)(rootDir, entry.path);
2983
+ const absPath = (0, import_node_path12.resolve)(rootDir, entry.path);
2999
2984
  const mod = require(absPath);
3000
2985
  const parser = "default" in mod ? mod.default : mod;
3001
2986
  if (disabled.has(parser.id)) continue;
@@ -3125,10 +3110,10 @@ function applyCrossLayerResults(uiOutput, results) {
3125
3110
 
3126
3111
  // src/server/graph/core/graph-builder.ts
3127
3112
  function readGraphFromDisk(rootDir, layer) {
3128
- const filePath = (0, import_node_path12.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3129
- if (!(0, import_node_fs11.existsSync)(filePath)) return null;
3113
+ const filePath = (0, import_node_path13.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3114
+ if (!(0, import_node_fs12.existsSync)(filePath)) return null;
3130
3115
  try {
3131
- return JSON.parse((0, import_node_fs11.readFileSync)(filePath, "utf-8"));
3116
+ return JSON.parse((0, import_node_fs12.readFileSync)(filePath, "utf-8"));
3132
3117
  } catch {
3133
3118
  return null;
3134
3119
  }
@@ -3229,11 +3214,11 @@ function generateAll(rootDir) {
3229
3214
  init_config();
3230
3215
 
3231
3216
  // src/server/graph/core/tagger-registry.ts
3232
- var import_node_path14 = require("node:path");
3217
+ var import_node_path15 = require("node:path");
3233
3218
 
3234
3219
  // src/server/graph/taggers/module-tagger.ts
3235
- var import_node_fs12 = require("node:fs");
3236
- var import_node_path13 = require("node:path");
3220
+ var import_node_fs13 = require("node:fs");
3221
+ var import_node_path14 = require("node:path");
3237
3222
  function matchGlob(pattern, id) {
3238
3223
  const patParts = pattern.split("/");
3239
3224
  const idParts = id.split("/");
@@ -3266,18 +3251,18 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
3266
3251
  const conventionDirs = [...CONVENTION_DIRS_BUILTIN, ...extraConventionDirs];
3267
3252
  const searchDirs = [
3268
3253
  rootDir,
3269
- (0, import_node_path13.join)(rootDir, "src"),
3270
- (0, import_node_path13.join)(rootDir, "app"),
3271
- (0, import_node_path13.join)(rootDir, "lib")
3254
+ (0, import_node_path14.join)(rootDir, "src"),
3255
+ (0, import_node_path14.join)(rootDir, "app"),
3256
+ (0, import_node_path14.join)(rootDir, "lib")
3272
3257
  ];
3273
3258
  for (const base of searchDirs) {
3274
3259
  for (const convention of conventionDirs) {
3275
- const dir = (0, import_node_path13.join)(base, convention);
3276
- if (!(0, import_node_fs12.existsSync)(dir)) continue;
3260
+ const dir = (0, import_node_path14.join)(base, convention);
3261
+ if (!(0, import_node_fs13.existsSync)(dir)) continue;
3277
3262
  try {
3278
- const stat = (0, import_node_fs12.statSync)(dir);
3263
+ const stat = (0, import_node_fs13.statSync)(dir);
3279
3264
  if (!stat.isDirectory()) continue;
3280
- const entries = (0, import_node_fs12.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
3265
+ const entries = (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
3281
3266
  if (entries.length > 0) {
3282
3267
  const relPath = dir.replace(rootDir + "/", "").replace(rootDir + "\\", "");
3283
3268
  result.set(relPath, entries);
@@ -3571,7 +3556,7 @@ function loadCustomTaggers(registry, config, rootDir, disabled) {
3571
3556
  for (const entry of config.taggers?.custom ?? []) {
3572
3557
  if (disabled.has(entry.id)) continue;
3573
3558
  try {
3574
- const absPath = (0, import_node_path14.resolve)(rootDir, entry.path);
3559
+ const absPath = (0, import_node_path15.resolve)(rootDir, entry.path);
3575
3560
  const mod = require(absPath);
3576
3561
  const tagger = "default" in mod ? mod.default : mod;
3577
3562
  const override = config.taggers?.trackUntagged?.[tagger.id];
@@ -3594,24 +3579,24 @@ function createTaggerRegistry(config, rootDir) {
3594
3579
  }
3595
3580
 
3596
3581
  // src/server/graph/core/tag-store.ts
3597
- var import_node_fs13 = require("node:fs");
3598
- var import_node_path15 = require("node:path");
3582
+ var import_node_fs14 = require("node:fs");
3583
+ var import_node_path16 = require("node:path");
3599
3584
  var TAGS_FILENAME = "tags.json";
3600
3585
  var GRAPHS_DIR = ".launchsecure/graphs";
3601
3586
  var tagCache = /* @__PURE__ */ new Map();
3602
3587
  function tagsFilePath(rootDir) {
3603
- return (0, import_node_path15.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
3588
+ return (0, import_node_path16.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
3604
3589
  }
3605
3590
  function readTagStore(rootDir) {
3606
3591
  const filePath = tagsFilePath(rootDir);
3607
- if (!(0, import_node_fs13.existsSync)(filePath)) return {};
3608
- const stat = (0, import_node_fs13.statSync)(filePath);
3592
+ if (!(0, import_node_fs14.existsSync)(filePath)) return {};
3593
+ const stat = (0, import_node_fs14.statSync)(filePath);
3609
3594
  const cached = tagCache.get(filePath);
3610
3595
  if (cached && cached.mtimeMs === stat.mtimeMs) {
3611
3596
  return cached.store;
3612
3597
  }
3613
3598
  try {
3614
- const content = (0, import_node_fs13.readFileSync)(filePath, "utf-8");
3599
+ const content = (0, import_node_fs14.readFileSync)(filePath, "utf-8");
3615
3600
  const store = JSON.parse(content);
3616
3601
  tagCache.set(filePath, { mtimeMs: stat.mtimeMs, store });
3617
3602
  return store;
@@ -3621,15 +3606,15 @@ function readTagStore(rootDir) {
3621
3606
  }
3622
3607
  function writeTagStore(rootDir, store) {
3623
3608
  const filePath = tagsFilePath(rootDir);
3624
- const dir = (0, import_node_path15.dirname)(filePath);
3625
- (0, import_node_fs13.mkdirSync)(dir, { recursive: true });
3609
+ const dir = (0, import_node_path16.dirname)(filePath);
3610
+ (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
3626
3611
  const cleaned = {};
3627
3612
  for (const [nodeId, tags] of Object.entries(store)) {
3628
3613
  if (Object.keys(tags).length > 0) {
3629
3614
  cleaned[nodeId] = tags;
3630
3615
  }
3631
3616
  }
3632
- (0, import_node_fs13.writeFileSync)(filePath, JSON.stringify(cleaned, null, 2) + "\n", "utf-8");
3617
+ (0, import_node_fs14.writeFileSync)(filePath, JSON.stringify(cleaned, null, 2) + "\n", "utf-8");
3633
3618
  tagCache.delete(filePath);
3634
3619
  }
3635
3620
  function setTag(rootDir, nodeId, key, value) {
@@ -3652,24 +3637,24 @@ function removeTag(rootDir, nodeId, key) {
3652
3637
  init_ts_extractor();
3653
3638
  var GRAPHS_DIR2 = ".launchsecure/graphs";
3654
3639
  function getAvailableLayers(rootDir) {
3655
- const dir = (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
3656
- if (!(0, import_node_fs14.existsSync)(dir)) return [];
3657
- return (0, import_node_fs14.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
3640
+ const dir = (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
3641
+ if (!(0, import_node_fs15.existsSync)(dir)) return [];
3642
+ return (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
3658
3643
  }
3659
3644
  var graphCache = /* @__PURE__ */ new Map();
3660
3645
  var taggedCache = /* @__PURE__ */ new Map();
3661
3646
  function graphsDir(rootDir) {
3662
- return (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
3647
+ return (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
3663
3648
  }
3664
3649
  function graphFilePath(rootDir, layer) {
3665
- return (0, import_node_path16.join)(graphsDir(rootDir), `${layer}.json`);
3650
+ return (0, import_node_path17.join)(graphsDir(rootDir), `${layer}.json`);
3666
3651
  }
3667
3652
  function tagsFilePath2(rootDir) {
3668
- return (0, import_node_path16.join)(graphsDir(rootDir), "tags.json");
3653
+ return (0, import_node_path17.join)(graphsDir(rootDir), "tags.json");
3669
3654
  }
3670
3655
  function getMtimeMs(filePath) {
3671
- if (!(0, import_node_fs14.existsSync)(filePath)) return 0;
3672
- return (0, import_node_fs14.statSync)(filePath).mtimeMs;
3656
+ if (!(0, import_node_fs15.existsSync)(filePath)) return 0;
3657
+ return (0, import_node_fs15.statSync)(filePath).mtimeMs;
3673
3658
  }
3674
3659
  function invalidateCache(filePath) {
3675
3660
  graphCache.delete(filePath);
@@ -3708,20 +3693,20 @@ function applyTags(graph, layer, rootDir) {
3708
3693
  }
3709
3694
  function readGraphRaw(rootDir, layer) {
3710
3695
  const filePath = graphFilePath(rootDir, layer);
3711
- if (!(0, import_node_fs14.existsSync)(filePath)) return null;
3712
- const stat = (0, import_node_fs14.statSync)(filePath);
3696
+ if (!(0, import_node_fs15.existsSync)(filePath)) return null;
3697
+ const stat = (0, import_node_fs15.statSync)(filePath);
3713
3698
  const cached = graphCache.get(filePath);
3714
3699
  if (cached && cached.mtimeMs === stat.mtimeMs) {
3715
3700
  return cached.graph;
3716
3701
  }
3717
- const content = (0, import_node_fs14.readFileSync)(filePath, "utf-8");
3702
+ const content = (0, import_node_fs15.readFileSync)(filePath, "utf-8");
3718
3703
  const graph = JSON.parse(content);
3719
3704
  graphCache.set(filePath, { mtimeMs: stat.mtimeMs, graph });
3720
3705
  return graph;
3721
3706
  }
3722
3707
  function readGraph(rootDir, layer) {
3723
3708
  const rawFilePath = graphFilePath(rootDir, layer);
3724
- if (!(0, import_node_fs14.existsSync)(rawFilePath)) return null;
3709
+ if (!(0, import_node_fs15.existsSync)(rawFilePath)) return null;
3725
3710
  const rawMtime = getMtimeMs(rawFilePath);
3726
3711
  const tagsMtime = getMtimeMs(tagsFilePath2(rootDir));
3727
3712
  const cacheKey = `${rootDir}:${layer}`;
@@ -3751,11 +3736,11 @@ async function generateGraph(rootDir, layer) {
3751
3736
  mutationMethods: config.parsers?.patterns?.mutationMethods
3752
3737
  });
3753
3738
  const dir = graphsDir(rootDir);
3754
- (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
3739
+ (0, import_node_fs15.mkdirSync)(dir, { recursive: true });
3755
3740
  const results = layer ? [generateLayer(rootDir, layer)].filter((r) => r !== null) : generateAll(rootDir);
3756
3741
  for (const result of results) {
3757
3742
  const filePath = graphFilePath(rootDir, result.layer);
3758
- (0, import_node_fs14.writeFileSync)(filePath, JSON.stringify(result.output, null, 2) + "\n", "utf-8");
3743
+ (0, import_node_fs15.writeFileSync)(filePath, JSON.stringify(result.output, null, 2) + "\n", "utf-8");
3759
3744
  invalidateCache(filePath);
3760
3745
  invalidateTaggedCache(rootDir, result.layer);
3761
3746
  }
@@ -3764,28 +3749,28 @@ async function generateGraph(rootDir, layer) {
3764
3749
 
3765
3750
  // src/server/lockfile.ts
3766
3751
  var import_node_child_process = require("node:child_process");
3767
- var import_node_fs15 = require("node:fs");
3752
+ var import_node_fs16 = require("node:fs");
3768
3753
  var import_node_os = require("node:os");
3769
- var import_node_path17 = require("node:path");
3754
+ var import_node_path18 = require("node:path");
3770
3755
  function lockDir(projectRoot) {
3771
3756
  if (projectRoot) {
3772
- return (0, import_node_path17.join)(projectRoot, ".launchsecure");
3757
+ return (0, import_node_path18.join)(projectRoot, ".launchsecure");
3773
3758
  }
3774
- return (0, import_node_path17.join)((0, import_node_os.homedir)(), ".launchsecure");
3759
+ return (0, import_node_path18.join)((0, import_node_os.homedir)(), ".launchsecure");
3775
3760
  }
3776
3761
  function lockPath(projectRoot) {
3777
- return (0, import_node_path17.join)(lockDir(projectRoot), "launch-chart.lock");
3762
+ return (0, import_node_path18.join)(lockDir(projectRoot), "launch-chart.lock");
3778
3763
  }
3779
3764
  var _activeProjectRoot;
3780
3765
  function readLock(projectRoot) {
3781
3766
  const root = projectRoot ?? _activeProjectRoot;
3782
3767
  const p = lockPath(root);
3783
- if (!(0, import_node_fs15.existsSync)(p)) {
3768
+ if (!(0, import_node_fs16.existsSync)(p)) {
3784
3769
  if (root) {
3785
3770
  const globalP = lockPath();
3786
- if ((0, import_node_fs15.existsSync)(globalP)) {
3771
+ if ((0, import_node_fs16.existsSync)(globalP)) {
3787
3772
  try {
3788
- const data = JSON.parse((0, import_node_fs15.readFileSync)(globalP, "utf-8"));
3773
+ const data = JSON.parse((0, import_node_fs16.readFileSync)(globalP, "utf-8"));
3789
3774
  if (typeof data.pid === "number" && typeof data.port === "number" && data.cwd === root) {
3790
3775
  return data;
3791
3776
  }
@@ -3796,7 +3781,7 @@ function readLock(projectRoot) {
3796
3781
  return null;
3797
3782
  }
3798
3783
  try {
3799
- const data = JSON.parse((0, import_node_fs15.readFileSync)(p, "utf-8"));
3784
+ const data = JSON.parse((0, import_node_fs16.readFileSync)(p, "utf-8"));
3800
3785
  if (typeof data.pid !== "number" || typeof data.port !== "number") return null;
3801
3786
  return data;
3802
3787
  } catch {
@@ -3833,7 +3818,7 @@ function getLiveLock(projectRoot) {
3833
3818
  const live = listenerPid !== null ? listenerPid === lock.pid : isPidAlive(lock.pid);
3834
3819
  if (!live) {
3835
3820
  try {
3836
- (0, import_node_fs15.unlinkSync)(lockPath(root));
3821
+ (0, import_node_fs16.unlinkSync)(lockPath(root));
3837
3822
  } catch {
3838
3823
  }
3839
3824
  return null;
@@ -3842,14 +3827,14 @@ function getLiveLock(projectRoot) {
3842
3827
  }
3843
3828
  function writeLock(data, projectRoot) {
3844
3829
  const root = projectRoot ?? _activeProjectRoot;
3845
- (0, import_node_fs15.mkdirSync)(lockDir(root), { recursive: true });
3846
- (0, import_node_fs15.writeFileSync)(lockPath(root), JSON.stringify(data, null, 2) + "\n", "utf-8");
3830
+ (0, import_node_fs16.mkdirSync)(lockDir(root), { recursive: true });
3831
+ (0, import_node_fs16.writeFileSync)(lockPath(root), JSON.stringify(data, null, 2) + "\n", "utf-8");
3847
3832
  if (root) _activeProjectRoot = root;
3848
3833
  }
3849
3834
  function clearLock(projectRoot) {
3850
3835
  const root = projectRoot ?? _activeProjectRoot;
3851
3836
  try {
3852
- (0, import_node_fs15.unlinkSync)(lockPath(root));
3837
+ (0, import_node_fs16.unlinkSync)(lockPath(root));
3853
3838
  } catch {
3854
3839
  }
3855
3840
  }
@@ -3858,13 +3843,13 @@ function clearLock(projectRoot) {
3858
3843
  init_config();
3859
3844
 
3860
3845
  // src/server/graph/core/audit-core.ts
3861
- var import_node_fs16 = require("node:fs");
3862
- var import_node_path18 = require("node:path");
3846
+ var import_node_fs17 = require("node:fs");
3847
+ var import_node_path19 = require("node:path");
3863
3848
  function readGraphFile(rootDir, layer) {
3864
- const filePath = (0, import_node_path18.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3865
- if (!(0, import_node_fs16.existsSync)(filePath)) return null;
3849
+ const filePath = (0, import_node_path19.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3850
+ if (!(0, import_node_fs17.existsSync)(filePath)) return null;
3866
3851
  try {
3867
- return JSON.parse((0, import_node_fs16.readFileSync)(filePath, "utf-8"));
3852
+ return JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
3868
3853
  } catch {
3869
3854
  return null;
3870
3855
  }
@@ -3908,10 +3893,10 @@ function checkUnprotectedRoutes(rootDir) {
3908
3893
  const api = readGraphFile(rootDir, "api");
3909
3894
  const staticGraph = readGraphFile(rootDir, "static");
3910
3895
  if (!api) return buildReport("api", "unprotected_routes", findings);
3911
- const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
3896
+ const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
3912
3897
  let routePermsContent = "";
3913
- if ((0, import_node_fs16.existsSync)(routePermsPath)) {
3914
- routePermsContent = (0, import_node_fs16.readFileSync)(routePermsPath, "utf-8");
3898
+ if ((0, import_node_fs17.existsSync)(routePermsPath)) {
3899
+ routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
3915
3900
  }
3916
3901
  const registeredRoutes = /* @__PURE__ */ new Set();
3917
3902
  const routeEntryRe = /path:\s*'([^']+)'/g;
@@ -3988,10 +3973,10 @@ function checkUnenforcedPermissions(rootDir) {
3988
3973
  const staticGraph = readGraphFile(rootDir, "static");
3989
3974
  if (!staticGraph) return buildReport("static", "unenforced_permissions", findings);
3990
3975
  const permissions = staticGraph.nodes.filter((n) => n.type === "seed_permission").map((n) => ({ id: n.id, key: n.value, name: n.name }));
3991
- const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
3976
+ const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
3992
3977
  let routePermsContent = "";
3993
- if ((0, import_node_fs16.existsSync)(routePermsPath)) {
3994
- routePermsContent = (0, import_node_fs16.readFileSync)(routePermsPath, "utf-8");
3978
+ if ((0, import_node_fs17.existsSync)(routePermsPath)) {
3979
+ routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
3995
3980
  }
3996
3981
  for (const perm of permissions) {
3997
3982
  const regex = new RegExp(`permission:\\s*['"]${perm.key}['"]`);
@@ -4021,9 +4006,9 @@ function checkHardcodedValues(rootDir) {
4021
4006
  const seen = /* @__PURE__ */ new Set();
4022
4007
  for (const node of api.nodes) {
4023
4008
  if (node.type !== "endpoint") continue;
4024
- const filePath = (0, import_node_path18.join)(rootDir, "src", node.id);
4025
- if (!(0, import_node_fs16.existsSync)(filePath)) continue;
4026
- const content = (0, import_node_fs16.readFileSync)(filePath, "utf-8");
4009
+ const filePath = (0, import_node_path19.join)(rootDir, "src", node.id);
4010
+ if (!(0, import_node_fs17.existsSync)(filePath)) continue;
4011
+ const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
4027
4012
  let m;
4028
4013
  allCapsRe.lastIndex = 0;
4029
4014
  while ((m = allCapsRe.exec(content)) !== null) {
@@ -4153,16 +4138,16 @@ var MIME_TYPES = {
4153
4138
  function findProjectRoot(startDir) {
4154
4139
  let dir = startDir;
4155
4140
  for (let i = 0; i < 8; i++) {
4156
- const graphsDir2 = import_node_path19.default.join(dir, ".launchsecure", "graphs");
4157
- if (import_node_fs17.default.existsSync(import_node_path19.default.join(graphsDir2, "ui.json")) || import_node_fs17.default.existsSync(import_node_path19.default.join(graphsDir2, "api.json")) || import_node_fs17.default.existsSync(import_node_path19.default.join(graphsDir2, "db.json"))) return dir;
4158
- const parent = import_node_path19.default.dirname(dir);
4141
+ const graphsDir2 = import_node_path20.default.join(dir, ".launchsecure", "graphs");
4142
+ if (import_node_fs18.default.existsSync(import_node_path20.default.join(graphsDir2, "ui.json")) || import_node_fs18.default.existsSync(import_node_path20.default.join(graphsDir2, "api.json")) || import_node_fs18.default.existsSync(import_node_path20.default.join(graphsDir2, "db.json"))) return dir;
4143
+ const parent = import_node_path20.default.dirname(dir);
4159
4144
  if (parent === dir) break;
4160
4145
  dir = parent;
4161
4146
  }
4162
4147
  dir = startDir;
4163
4148
  for (let i = 0; i < 8; i++) {
4164
- if (import_node_fs17.default.existsSync(import_node_path19.default.join(dir, ".git"))) return dir;
4165
- const parent = import_node_path19.default.dirname(dir);
4149
+ if (import_node_fs18.default.existsSync(import_node_path20.default.join(dir, ".git"))) return dir;
4150
+ const parent = import_node_path20.default.dirname(dir);
4166
4151
  if (parent === dir) break;
4167
4152
  dir = parent;
4168
4153
  }
@@ -4171,7 +4156,7 @@ function findProjectRoot(startDir) {
4171
4156
  function resolveRequestRoot(url, monorepoRoot, projects) {
4172
4157
  const projectParam = url.searchParams.get("project");
4173
4158
  if (!projectParam || projects.length === 0) return monorepoRoot;
4174
- const resolved = import_node_path19.default.resolve(monorepoRoot, projectParam);
4159
+ const resolved = import_node_path20.default.resolve(monorepoRoot, projectParam);
4175
4160
  if (!resolved.startsWith(monorepoRoot)) {
4176
4161
  throw new Error("Project path outside monorepo root");
4177
4162
  }
@@ -4222,16 +4207,16 @@ async function buildMergedGraph(root) {
4222
4207
  };
4223
4208
  }
4224
4209
  function serveStatic(res, filePath) {
4225
- if (!import_node_fs17.default.existsSync(filePath) || !import_node_fs17.default.statSync(filePath).isFile()) return false;
4226
- const ext = import_node_path19.default.extname(filePath).toLowerCase();
4210
+ if (!import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) return false;
4211
+ const ext = import_node_path20.default.extname(filePath).toLowerCase();
4227
4212
  const mime = MIME_TYPES[ext] ?? "application/octet-stream";
4228
4213
  res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
4229
- import_node_fs17.default.createReadStream(filePath).pipe(res);
4214
+ import_node_fs18.default.createReadStream(filePath).pipe(res);
4230
4215
  return true;
4231
4216
  }
4232
4217
  function serveIndex(res, clientDir) {
4233
- const indexPath = import_node_path19.default.join(clientDir, "index.html");
4234
- if (!import_node_fs17.default.existsSync(indexPath)) {
4218
+ const indexPath = import_node_path20.default.join(clientDir, "index.html");
4219
+ if (!import_node_fs18.default.existsSync(indexPath)) {
4235
4220
  res.writeHead(500, { "Content-Type": "text/plain" });
4236
4221
  res.end(`LaunchChart client bundle not found at ${clientDir}. Run 'npm run build:chart-client'.`);
4237
4222
  return;
@@ -4283,7 +4268,7 @@ async function startChartServer(opts = {}) {
4283
4268
  }
4284
4269
  return { port: existing.port, url: existing.url };
4285
4270
  }
4286
- const clientDir = opts.clientDir ?? import_node_path19.default.join(__dirname, "..", "chart-client");
4271
+ const clientDir = opts.clientDir ?? import_node_path20.default.join(__dirname, "..", "chart-client");
4287
4272
  const rootConfig = loadConfig(projectRoot);
4288
4273
  const projects = rootConfig.projects ?? [];
4289
4274
  const server = import_node_http.default.createServer((req, res) => {
@@ -4299,11 +4284,11 @@ async function startChartServer(opts = {}) {
4299
4284
  }
4300
4285
  if (req.method === "GET" && url2.pathname === "/api/projects") {
4301
4286
  const projectList = projects.length > 0 ? projects.map((p) => {
4302
- const absRoot = import_node_path19.default.resolve(projectRoot, p.root);
4303
- const hasGraphs = import_node_fs17.default.existsSync(import_node_path19.default.join(absRoot, ".launchsecure", "graphs"));
4304
- const hasNextConfig2 = import_node_fs17.default.existsSync(import_node_path19.default.join(absRoot, "next.config.ts")) || import_node_fs17.default.existsSync(import_node_path19.default.join(absRoot, "next.config.js")) || import_node_fs17.default.existsSync(import_node_path19.default.join(absRoot, "next.config.mjs"));
4305
- return { name: p.name, root: p.root, hasGraphs, hasNextConfig: hasNextConfig2 };
4306
- }) : [{ name: import_node_path19.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs17.default.existsSync(import_node_path19.default.join(projectRoot, ".launchsecure", "graphs")), hasNextConfig: true }];
4287
+ const absRoot = import_node_path20.default.resolve(projectRoot, p.root);
4288
+ const hasGraphs = import_node_fs18.default.existsSync(import_node_path20.default.join(absRoot, ".launchsecure", "graphs"));
4289
+ const hasNextConfig = import_node_fs18.default.existsSync(import_node_path20.default.join(absRoot, "next.config.ts")) || import_node_fs18.default.existsSync(import_node_path20.default.join(absRoot, "next.config.js")) || import_node_fs18.default.existsSync(import_node_path20.default.join(absRoot, "next.config.mjs"));
4290
+ return { name: p.name, root: p.root, hasGraphs, hasNextConfig };
4291
+ }) : [{ name: import_node_path20.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs18.default.existsSync(import_node_path20.default.join(projectRoot, ".launchsecure", "graphs")), hasNextConfig: true }];
4307
4292
  res.writeHead(200, { "Content-Type": "application/json" });
4308
4293
  res.end(JSON.stringify({ projects: projectList, monorepoRoot: projectRoot }));
4309
4294
  return;
@@ -4349,20 +4334,20 @@ async function startChartServer(opts = {}) {
4349
4334
  }
4350
4335
  if (req.method === "GET" && url2.pathname === "/api/file-content") {
4351
4336
  const relPath = url2.searchParams.get("path");
4352
- if (!relPath || relPath.includes("..") || import_node_path19.default.isAbsolute(relPath)) {
4337
+ if (!relPath || relPath.includes("..") || import_node_path20.default.isAbsolute(relPath)) {
4353
4338
  res.writeHead(400, { "Content-Type": "application/json" });
4354
4339
  res.end(JSON.stringify({ error: "Invalid path" }));
4355
4340
  return;
4356
4341
  }
4357
- const filePath = import_node_path19.default.join(reqRoot, relPath);
4358
- if (!filePath.startsWith(reqRoot) || !import_node_fs17.default.existsSync(filePath) || !import_node_fs17.default.statSync(filePath).isFile()) {
4342
+ const filePath = import_node_path20.default.join(reqRoot, relPath);
4343
+ if (!filePath.startsWith(reqRoot) || !import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) {
4359
4344
  res.writeHead(404, { "Content-Type": "application/json" });
4360
4345
  res.end(JSON.stringify({ error: "File not found" }));
4361
4346
  return;
4362
4347
  }
4363
- const ext = import_node_path19.default.extname(filePath).toLowerCase();
4348
+ const ext = import_node_path20.default.extname(filePath).toLowerCase();
4364
4349
  const langMap = { ".ts": "typescript", ".tsx": "tsx", ".js": "javascript", ".jsx": "jsx", ".prisma": "prisma", ".json": "json", ".css": "css" };
4365
- const content = import_node_fs17.default.readFileSync(filePath, "utf-8");
4350
+ const content = import_node_fs18.default.readFileSync(filePath, "utf-8");
4366
4351
  res.writeHead(200, { "Content-Type": "application/json" });
4367
4352
  res.end(JSON.stringify({ content, language: langMap[ext] ?? "text", path: relPath }));
4368
4353
  return;
@@ -4404,8 +4389,8 @@ async function startChartServer(opts = {}) {
4404
4389
  req.on("end", () => {
4405
4390
  try {
4406
4391
  const newConfig = JSON.parse(body);
4407
- const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
4408
- import_node_fs17.default.writeFileSync(configPath, JSON.stringify(newConfig, null, 2) + "\n", "utf-8");
4392
+ const configPath = import_node_path20.default.join(reqRoot, ".launchchart.json");
4393
+ import_node_fs18.default.writeFileSync(configPath, JSON.stringify(newConfig, null, 2) + "\n", "utf-8");
4409
4394
  res.writeHead(200, { "Content-Type": "application/json" });
4410
4395
  res.end(JSON.stringify({ ok: true }));
4411
4396
  } catch (err) {
@@ -4438,8 +4423,8 @@ async function startChartServer(opts = {}) {
4438
4423
  const taggerConfig = JSON.parse(body);
4439
4424
  const config2 = loadConfig(reqRoot);
4440
4425
  config2.taggers = taggerConfig;
4441
- const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
4442
- import_node_fs17.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4426
+ const configPath = import_node_path20.default.join(reqRoot, ".launchchart.json");
4427
+ import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4443
4428
  res.writeHead(200, { "Content-Type": "application/json" });
4444
4429
  res.end(JSON.stringify({ ok: true }));
4445
4430
  } catch (err) {
@@ -4512,10 +4497,10 @@ async function startChartServer(opts = {}) {
4512
4497
  res.end(JSON.stringify({
4513
4498
  projectRoot: reqRoot,
4514
4499
  detected: paths ? {
4515
- srcDir: import_node_path19.default.relative(reqRoot, paths.srcDir) || ".",
4516
- appDir: import_node_path19.default.relative(reqRoot, paths.appDir),
4517
- apiDir: import_node_path19.default.relative(reqRoot, paths.apiDir),
4518
- dbDir: paths.dbDir ? import_node_path19.default.relative(reqRoot, paths.dbDir) : null
4500
+ srcDir: import_node_path20.default.relative(reqRoot, paths.srcDir) || ".",
4501
+ appDir: import_node_path20.default.relative(reqRoot, paths.appDir),
4502
+ apiDir: import_node_path20.default.relative(reqRoot, paths.apiDir),
4503
+ dbDir: paths.dbDir ? import_node_path20.default.relative(reqRoot, paths.dbDir) : null
4519
4504
  } : null,
4520
4505
  overrides,
4521
4506
  isOverride: overrides.appDir
@@ -4524,19 +4509,19 @@ async function startChartServer(opts = {}) {
4524
4509
  }
4525
4510
  if (req.method === "GET" && url2.pathname === "/api/browse-dir") {
4526
4511
  const browsePath = url2.searchParams.get("path") || projectRoot;
4527
- const abs = import_node_path19.default.resolve(browsePath);
4528
- const twoUp = import_node_path19.default.resolve(projectRoot, "..", "..");
4512
+ const abs = import_node_path20.default.resolve(browsePath);
4513
+ const twoUp = import_node_path20.default.resolve(projectRoot, "..", "..");
4529
4514
  if (!abs.startsWith(twoUp)) {
4530
4515
  res.writeHead(403, { "Content-Type": "application/json" });
4531
4516
  res.end(JSON.stringify({ ok: false, error: "Path outside allowed range" }));
4532
4517
  return;
4533
4518
  }
4534
4519
  try {
4535
- const entries = import_node_fs17.default.readdirSync(abs, { withFileTypes: true });
4520
+ const entries = import_node_fs18.default.readdirSync(abs, { withFileTypes: true });
4536
4521
  const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist" && e.name !== ".next").map((e) => e.name).sort();
4537
- const parent = abs !== twoUp ? import_node_path19.default.dirname(abs) : null;
4522
+ const parent = abs !== twoUp ? import_node_path20.default.dirname(abs) : null;
4538
4523
  res.writeHead(200, { "Content-Type": "application/json" });
4539
- res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path19.default.relative(projectRoot, abs) || "." }));
4524
+ res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path20.default.relative(projectRoot, abs) || "." }));
4540
4525
  } catch (err) {
4541
4526
  res.writeHead(400, { "Content-Type": "application/json" });
4542
4527
  res.end(JSON.stringify({ ok: false, error: String(err) }));
@@ -4562,8 +4547,8 @@ async function startChartServer(opts = {}) {
4562
4547
  const { projects: newProjects } = JSON.parse(body);
4563
4548
  const config2 = loadConfig(projectRoot);
4564
4549
  config2.projects = newProjects.length > 0 ? newProjects : void 0;
4565
- const configPath = import_node_path19.default.join(projectRoot, ".launchchart.json");
4566
- import_node_fs17.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4550
+ const configPath = import_node_path20.default.join(projectRoot, ".launchchart.json");
4551
+ import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4567
4552
  projects.length = 0;
4568
4553
  if (config2.projects) projects.push(...config2.projects);
4569
4554
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -4576,7 +4561,7 @@ async function startChartServer(opts = {}) {
4576
4561
  return;
4577
4562
  }
4578
4563
  if (url2.pathname !== "/") {
4579
- const staticPath = import_node_path19.default.join(clientDir, url2.pathname);
4564
+ const staticPath = import_node_path20.default.join(clientDir, url2.pathname);
4580
4565
  if (serveStatic(res, staticPath)) return;
4581
4566
  }
4582
4567
  serveIndex(res, clientDir);