@launchsecure/launch-kit 0.0.18 → 0.0.19

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 (69) hide show
  1. package/dist/chart-client/assets/index-C8ANseEa.js +441 -0
  2. package/dist/chart-client/index.html +1 -1
  3. package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-DsfOm3t_.js} +1 -1
  4. package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-NJuvkBv1.js} +1 -1
  5. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-BgrcgZs0.js} +1 -1
  6. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-C3XoLi15.js} +1 -1
  7. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-FX2PjLfb.js} +1 -1
  8. package/dist/deck-client/assets/channel-ChQjD1T1.js +1 -0
  9. package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-D0aqsJV0.js} +1 -1
  10. package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-7qRCCAgK.js} +1 -1
  11. package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-DfHG-iqb.js} +1 -1
  12. package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-DrR52j3B.js} +1 -1
  13. package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-D5KSGATB.js} +1 -1
  14. package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-M7hsLRNU.js} +1 -1
  15. package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-1ynAWO2m.js} +1 -1
  16. package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.js → chunk-YZCP3GAM-S2-nGw3D.js} +1 -1
  17. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-B_9iqK1S.js +1 -0
  18. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-B_9iqK1S.js +1 -0
  19. package/dist/deck-client/assets/clone-BYt1AMfz.js +1 -0
  20. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-Bqp3p68D.js → cose-bilkent-S5V4N54A-BcMwozS2.js} +1 -1
  21. package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-DtKMhl_1.js} +1 -1
  22. package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-1plH69us.js} +1 -1
  23. package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-D_o-BHO3.js} +1 -1
  24. package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-ClZ1LIx6.js} +1 -1
  25. package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-B8dKHfRh.js} +1 -1
  26. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-CY2aCH7-.js} +1 -1
  27. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-DZZWHti8.js} +1 -1
  28. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-OwGGa6Lu.js} +1 -1
  29. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-GKyWD4Qt.js} +1 -1
  30. package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-CORzYQdB.js} +1 -1
  31. package/dist/deck-client/assets/{index-BfIfJXmS.js → index-hiIpM7EP.js} +3 -3
  32. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-DmgqJCcF.js} +1 -1
  33. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-D-1v7knu.js} +1 -1
  34. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-CYrGQE7b.js} +1 -1
  35. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-BJFDWiH-.js} +1 -1
  36. package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-BTFFcaxF.js} +1 -1
  37. package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-DAbl6COS.js} +1 -1
  38. package/dist/deck-client/assets/{min-CbUksbuI.js → min-oWHBrFBm.js} +1 -1
  39. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-BTCB0VLO.js} +1 -1
  40. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-CUZChWNA.js} +1 -1
  41. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-4M1Um_e4.js} +1 -1
  42. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-DLzQZ0B3.js} +1 -1
  43. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-DcNgzV3E.js} +1 -1
  44. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-CAcI2vC9.js} +1 -1
  45. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.js → stateDiagram-FHFEXIEX-CntjTTm5.js} +1 -1
  46. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-YiaphOU_.js +1 -0
  47. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-oUeZhRns.js → timeline-definition-GMOUNBTQ-D8zrit4U.js} +1 -1
  48. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-C4SuFPgo.js} +1 -1
  49. package/dist/deck-client/assets/wardley-RL74JXVD-B3F-Olcq.js +162 -0
  50. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-kj73r6f-.js} +1 -1
  51. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-CC_d_Ey3.js} +1 -1
  52. package/dist/deck-client/index.html +1 -1
  53. package/dist/server/chart-serve.js +392 -169
  54. package/dist/server/cli.js +384 -168
  55. package/dist/server/council-entry.js +0 -0
  56. package/dist/server/deck-server/deck-mcp-entry.js +0 -0
  57. package/dist/server/fb-wizard.js +0 -0
  58. package/dist/server/graph-mcp-entry.js +430 -206
  59. package/dist/server/server/cli.js +0 -0
  60. package/dist/server/server/fb-wizard.js +0 -0
  61. package/dist/server/server/graph-mcp-entry.js +0 -0
  62. package/package.json +18 -17
  63. package/dist/chart-client/assets/index-D7x8nz-H.js +0 -441
  64. package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
  65. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
  66. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
  67. package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
  68. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
  69. package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
@@ -602,19 +602,19 @@ __export(chart_serve_exports, {
602
602
  module.exports = __toCommonJS(chart_serve_exports);
603
603
  var import_node_http = __toESM(require("node:http"));
604
604
  var import_node_fs18 = __toESM(require("node:fs"));
605
- var import_node_path20 = __toESM(require("node:path"));
605
+ var import_node_path19 = __toESM(require("node:path"));
606
606
 
607
607
  // src/server/graph/index.ts
608
608
  var import_node_fs15 = require("node:fs");
609
- var import_node_path17 = require("node:path");
609
+ var import_node_path16 = require("node:path");
610
610
 
611
611
  // src/server/graph/core/graph-builder.ts
612
612
  var import_node_fs12 = require("node:fs");
613
- var import_node_path13 = require("node:path");
613
+ var import_node_path12 = require("node:path");
614
614
  init_config();
615
615
 
616
616
  // src/server/graph/core/parser-registry.ts
617
- var import_node_path12 = require("node:path");
617
+ var import_node_path11 = require("node:path");
618
618
 
619
619
  // src/server/graph/parsers/ts/typescript-project.ts
620
620
  var import_node_fs5 = require("node:fs");
@@ -622,35 +622,12 @@ var import_node_path5 = require("node:path");
622
622
  init_config();
623
623
 
624
624
  // src/server/graph/core/resolve-paths.ts
625
- var import_node_fs2 = require("node:fs");
626
- var import_node_path2 = require("node:path");
627
- function detectDbDir(rootDir, config) {
628
- if (config.paths?.dbDir) return (0, import_node_path2.join)(rootDir, config.paths.dbDir);
629
- const prismaDir = (0, import_node_path2.join)(rootDir, "prisma");
630
- if ((0, import_node_fs2.existsSync)(prismaDir)) return prismaDir;
631
- return null;
632
- }
633
- function resolveProjectPaths(rootDir, config) {
634
- const dbDir = detectDbDir(rootDir, config);
635
- if (config.paths?.appDir) {
636
- const appDir = (0, import_node_path2.join)(rootDir, config.paths.appDir);
637
- const srcDir = config.paths.srcDir ? (0, import_node_path2.join)(rootDir, config.paths.srcDir) : (0, import_node_path2.dirname)(appDir);
638
- return { srcDir, appDir, apiDir: (0, import_node_path2.join)(appDir, "api"), dbDir };
639
- }
640
- const srcApp = (0, import_node_path2.join)(rootDir, "src", "app");
641
- if ((0, import_node_fs2.existsSync)(srcApp)) {
642
- return { srcDir: (0, import_node_path2.join)(rootDir, "src"), appDir: srcApp, apiDir: (0, import_node_path2.join)(srcApp, "api"), dbDir };
643
- }
644
- const rootApp = (0, import_node_path2.join)(rootDir, "app");
645
- if ((0, import_node_fs2.existsSync)(rootApp)) {
646
- return { srcDir: rootDir, appDir: rootApp, apiDir: (0, import_node_path2.join)(rootApp, "api"), dbDir };
647
- }
648
- return null;
649
- }
650
-
651
- // src/server/graph/core/walk.ts
652
625
  var import_node_fs3 = require("node:fs");
653
626
  var import_node_path3 = require("node:path");
627
+
628
+ // src/server/graph/core/walk.ts
629
+ var import_node_fs2 = require("node:fs");
630
+ var import_node_path2 = require("node:path");
654
631
  var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
655
632
  "node_modules",
656
633
  ".git",
@@ -666,12 +643,12 @@ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
666
643
  ]);
667
644
  function walk(dir, exts) {
668
645
  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);
646
+ if (!(0, import_node_fs2.existsSync)(dir)) return results;
647
+ for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
648
+ const full = (0, import_node_path2.join)(dir, entry.name);
672
649
  if (entry.isDirectory()) {
673
650
  results.push(...walk(full, exts));
674
- } else if (exts.includes((0, import_node_path3.extname)(entry.name))) {
651
+ } else if (exts.includes((0, import_node_path2.extname)(entry.name))) {
675
652
  results.push(full);
676
653
  }
677
654
  }
@@ -679,19 +656,205 @@ function walk(dir, exts) {
679
656
  }
680
657
  function walkWithIgnore(dir, exts, opts = {}) {
681
658
  const results = [];
682
- if (!(0, import_node_fs3.existsSync)(dir)) return results;
659
+ if (!(0, import_node_fs2.existsSync)(dir)) return results;
683
660
  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 })) {
661
+ for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
685
662
  if (entry.isDirectory()) {
686
663
  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));
664
+ results.push(...walkWithIgnore((0, import_node_path2.join)(dir, entry.name), exts, opts));
665
+ } else if (exts.includes((0, import_node_path2.extname)(entry.name))) {
666
+ results.push((0, import_node_path2.join)(dir, entry.name));
690
667
  }
691
668
  }
692
669
  return results;
693
670
  }
694
671
 
672
+ // src/server/graph/core/resolve-paths.ts
673
+ function hasSqlFiles(dir) {
674
+ if (!(0, import_node_fs3.existsSync)(dir)) return false;
675
+ try {
676
+ return (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true }).some(
677
+ (e) => e.isFile() && e.name.endsWith(".sql")
678
+ );
679
+ } catch {
680
+ return false;
681
+ }
682
+ }
683
+ function hasNestedMigrationSql(dir) {
684
+ if (!(0, import_node_fs3.existsSync)(dir)) return false;
685
+ try {
686
+ return (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true }).some(
687
+ (e) => e.isDirectory() && (0, import_node_fs3.existsSync)((0, import_node_path3.join)(dir, e.name, "migration.sql"))
688
+ );
689
+ } catch {
690
+ return false;
691
+ }
692
+ }
693
+ function resolveDbFromDir(dir) {
694
+ if (!(0, import_node_fs3.existsSync)(dir)) return { kind: "none", schemaPath: null, migrationsDir: null };
695
+ const schemaPath = (0, import_node_path3.join)(dir, "schema.prisma");
696
+ if ((0, import_node_fs3.existsSync)(schemaPath)) {
697
+ const migrationsDir2 = (0, import_node_path3.join)(dir, "migrations");
698
+ return {
699
+ kind: "prisma",
700
+ schemaPath,
701
+ migrationsDir: (0, import_node_fs3.existsSync)(migrationsDir2) ? migrationsDir2 : null
702
+ };
703
+ }
704
+ const migrationsDir = (0, import_node_path3.join)(dir, "migrations");
705
+ if (hasSqlFiles(migrationsDir) || hasNestedMigrationSql(migrationsDir)) {
706
+ return { kind: "sql-migrations", migrationsDir, schemaPath: null };
707
+ }
708
+ if (hasSqlFiles(dir) || hasNestedMigrationSql(dir)) {
709
+ return { kind: "sql-migrations", migrationsDir: dir, schemaPath: null };
710
+ }
711
+ return { kind: "none", schemaPath: null, migrationsDir: null };
712
+ }
713
+ function detectDbConfig(rootDir, config) {
714
+ if (config.paths?.dbDir) {
715
+ return resolveDbFromDir((0, import_node_path3.join)(rootDir, config.paths.dbDir));
716
+ }
717
+ const candidates = ["prisma", "supabase", "drizzle", (0, import_node_path3.join)("db", "migrations"), "migrations"];
718
+ for (const c of candidates) {
719
+ const dir = (0, import_node_path3.join)(rootDir, c);
720
+ const resolved = resolveDbFromDir(dir);
721
+ if (resolved.kind !== "none") return resolved;
722
+ }
723
+ return { kind: "none", schemaPath: null, migrationsDir: null };
724
+ }
725
+ function detectDbDir(rootDir, config, dbConfig) {
726
+ if (config.paths?.dbDir) return (0, import_node_path3.join)(rootDir, config.paths.dbDir);
727
+ if (dbConfig.kind === "prisma") return (0, import_node_path3.dirname)(dbConfig.schemaPath);
728
+ if (dbConfig.kind === "sql-migrations") return dbConfig.migrationsDir;
729
+ return null;
730
+ }
731
+ var NON_SOURCE_DIRS = /* @__PURE__ */ new Set([
732
+ ...DEFAULT_IGNORE_DIRS,
733
+ // DB conventions (handled by db parsers)
734
+ "prisma",
735
+ "supabase",
736
+ "drizzle",
737
+ "migrations",
738
+ // Web assets
739
+ "public",
740
+ "static",
741
+ "assets",
742
+ // Docs
743
+ "docs",
744
+ "documentation",
745
+ // Test dirs (project tests aren't part of the structural graph)
746
+ "tests",
747
+ "__tests__",
748
+ "e2e",
749
+ "playwright",
750
+ "cypress",
751
+ // Monorepo workspace roots — separate graph projects per .launchchart.json
752
+ "packages",
753
+ "apps",
754
+ "services",
755
+ "libs"
756
+ ]);
757
+ function dirHasTSFiles(dir) {
758
+ if (!(0, import_node_fs3.existsSync)(dir)) return false;
759
+ try {
760
+ const stack = [dir];
761
+ while (stack.length > 0) {
762
+ const cur = stack.pop();
763
+ const entries = (0, import_node_fs3.readdirSync)(cur, { withFileTypes: true });
764
+ for (const e of entries) {
765
+ if (e.isFile() && (e.name.endsWith(".ts") || e.name.endsWith(".tsx"))) return true;
766
+ if (e.isDirectory() && !e.name.startsWith(".") && !DEFAULT_IGNORE_DIRS.has(e.name)) {
767
+ stack.push((0, import_node_path3.join)(cur, e.name));
768
+ }
769
+ }
770
+ }
771
+ } catch {
772
+ }
773
+ return false;
774
+ }
775
+ function collectCodeBearingChildren(dir, extraSkip) {
776
+ if (!(0, import_node_fs3.existsSync)(dir)) return [];
777
+ const out = [];
778
+ try {
779
+ for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
780
+ if (!entry.isDirectory()) continue;
781
+ if (entry.name.startsWith(".")) continue;
782
+ if (NON_SOURCE_DIRS.has(entry.name)) continue;
783
+ if (extraSkip?.has(entry.name)) continue;
784
+ const full = (0, import_node_path3.join)(dir, entry.name);
785
+ if (dirHasTSFiles(full)) out.push(full);
786
+ }
787
+ } catch {
788
+ }
789
+ return out;
790
+ }
791
+ function detectSrcRoots(rootDir, srcDir, appDir, config) {
792
+ if (config.paths?.srcRoots && config.paths.srcRoots.length > 0) {
793
+ const roots2 = /* @__PURE__ */ new Set();
794
+ roots2.add(appDir);
795
+ for (const r of config.paths.srcRoots) {
796
+ const abs = (0, import_node_path3.isAbsolute)(r) ? r : (0, import_node_path3.resolve)(rootDir, r);
797
+ roots2.add(abs);
798
+ }
799
+ return [...roots2];
800
+ }
801
+ const roots = /* @__PURE__ */ new Set();
802
+ roots.add(appDir);
803
+ for (const c of collectCodeBearingChildren(srcDir)) roots.add(c);
804
+ if (srcDir !== rootDir) {
805
+ const skipSrcWrapper = /* @__PURE__ */ new Set([(0, import_node_path3.basename)(srcDir)]);
806
+ for (const c of collectCodeBearingChildren(rootDir, skipSrcWrapper)) roots.add(c);
807
+ }
808
+ return [...roots];
809
+ }
810
+ var CONVENTION_NAMES = ["middleware.ts", "middleware.tsx", "instrumentation.ts", "instrumentation.tsx"];
811
+ function detectConventionFiles(rootDir, srcDir) {
812
+ const out = [];
813
+ const seen = /* @__PURE__ */ new Set();
814
+ const dirs = srcDir === rootDir ? [rootDir] : [srcDir, rootDir];
815
+ for (const dir of dirs) {
816
+ for (const name of CONVENTION_NAMES) {
817
+ const full = (0, import_node_path3.join)(dir, name);
818
+ if (!seen.has(full) && (0, import_node_fs3.existsSync)(full)) {
819
+ try {
820
+ if ((0, import_node_fs3.statSync)(full).isFile()) {
821
+ seen.add(full);
822
+ out.push(full);
823
+ }
824
+ } catch {
825
+ }
826
+ }
827
+ }
828
+ }
829
+ return out;
830
+ }
831
+ function resolveProjectPaths(rootDir, config) {
832
+ let srcDir;
833
+ let appDir;
834
+ if (config.paths?.appDir) {
835
+ appDir = (0, import_node_path3.join)(rootDir, config.paths.appDir);
836
+ srcDir = config.paths.srcDir ? (0, import_node_path3.join)(rootDir, config.paths.srcDir) : (0, import_node_path3.dirname)(appDir);
837
+ } else {
838
+ const srcApp = (0, import_node_path3.join)(rootDir, "src", "app");
839
+ const rootApp = (0, import_node_path3.join)(rootDir, "app");
840
+ if ((0, import_node_fs3.existsSync)(srcApp)) {
841
+ srcDir = (0, import_node_path3.join)(rootDir, "src");
842
+ appDir = srcApp;
843
+ } else if ((0, import_node_fs3.existsSync)(rootApp)) {
844
+ srcDir = rootDir;
845
+ appDir = rootApp;
846
+ } else {
847
+ return null;
848
+ }
849
+ }
850
+ const apiDir = (0, import_node_path3.join)(appDir, "api");
851
+ const dbConfig = detectDbConfig(rootDir, config);
852
+ const dbDir = detectDbDir(rootDir, config, dbConfig);
853
+ const srcRoots = detectSrcRoots(rootDir, srcDir, appDir, config);
854
+ const conventionFiles = detectConventionFiles(rootDir, srcDir);
855
+ return { srcDir, appDir, apiDir, dbDir, srcRoots, conventionFiles, dbConfig };
856
+ }
857
+
695
858
  // src/server/graph/parsers/ts/typescript-project.ts
696
859
  init_ts_extractor();
697
860
  var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]);
@@ -708,8 +871,12 @@ var CLASSIFICATION_TO_LAYER = {
708
871
  "mcp-tool": "ui",
709
872
  external: "ui"
710
873
  };
711
- function toNodeId(srcDir, absPath) {
712
- return (0, import_node_path5.relative)(srcDir, absPath).replace(/\\/g, "/");
874
+ function toNodeId(srcDir, rootDir, absPath) {
875
+ const relFromSrc = (0, import_node_path5.relative)(srcDir, absPath).replace(/\\/g, "/");
876
+ if (relFromSrc.startsWith("..")) {
877
+ return (0, import_node_path5.relative)(rootDir, absPath).replace(/\\/g, "/");
878
+ }
879
+ return relFromSrc;
713
880
  }
714
881
  function resolveImport(srcDir, specifier) {
715
882
  if (!specifier.startsWith("@/")) return null;
@@ -799,12 +966,13 @@ function extractRoute(id) {
799
966
  function nameFromFilename(absPath) {
800
967
  return (0, import_node_path5.basename)(absPath, (0, import_node_path5.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
801
968
  }
802
- function filePathToApiRoute(apiDir, absPath) {
803
- let route = "/" + (0, import_node_path5.relative)(apiDir, absPath).replace(/\\/g, "/").replace(/\/route\.tsx?$/, "");
969
+ function filePathToAppRoute(appDir, absPath) {
970
+ let route = ("/" + (0, import_node_path5.relative)(appDir, absPath).replace(/\\/g, "/")).replace(/\/route\.tsx?$/, "");
971
+ route = route.replace(/\/\([^)]+\)/g, "");
972
+ route = route.replace(/\[\.\.\.([^\]]+)\]/g, "*$1");
804
973
  route = route.replace(/\[([^\]]+)\]/g, ":$1");
805
974
  route = route.replace(/\/+/g, "/");
806
- if (route === "/") return "/api";
807
- return "/api" + route;
975
+ return route === "" ? "/" : route;
808
976
  }
809
977
  function camelToPascal(s) {
810
978
  if (!s) return s;
@@ -889,7 +1057,7 @@ function matchRouteToPage(route, routeToNodeId) {
889
1057
  if (routeToNodeId.has(normalized)) return routeToNodeId.get(normalized);
890
1058
  return null;
891
1059
  }
892
- function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
1060
+ function extractEdges(srcDir, rootDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
893
1061
  const edges = [];
894
1062
  const flagged = [];
895
1063
  const seen = /* @__PURE__ */ new Set();
@@ -917,7 +1085,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
917
1085
  for (const name of names) {
918
1086
  const targetAbs = barrelMap.get(name);
919
1087
  if (targetAbs) {
920
- const targetId = toNodeId(srcDir, targetAbs);
1088
+ const targetId = toNodeId(srcDir, rootDir, targetAbs);
921
1089
  if (nodeIdSet.has(targetId)) {
922
1090
  if (!byTarget.has(targetId)) byTarget.set(targetId, []);
923
1091
  byTarget.get(targetId).push(name);
@@ -931,7 +1099,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
931
1099
  } else {
932
1100
  const resolved = resolveImport(srcDir, specifier);
933
1101
  if (resolved) {
934
- const targetId = toNodeId(srcDir, resolved);
1102
+ const targetId = toNodeId(srcDir, rootDir, resolved);
935
1103
  if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
936
1104
  addEdge(targetId, edgeTypeFor(isTypeOnly, names));
937
1105
  }
@@ -940,7 +1108,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
940
1108
  } else if (specifier.startsWith(".")) {
941
1109
  const resolved = resolveRelativeImport(absPath, specifier);
942
1110
  if (resolved) {
943
- const targetId = toNodeId(srcDir, resolved);
1111
+ const targetId = toNodeId(srcDir, rootDir, resolved);
944
1112
  if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
945
1113
  addEdge(targetId, edgeTypeFor(isTypeOnly, names));
946
1114
  }
@@ -992,13 +1160,22 @@ function generate(rootDir) {
992
1160
  const config = loadConfig(rootDir);
993
1161
  const paths = resolveProjectPaths(rootDir, config);
994
1162
  const srcDir = paths.srcDir;
995
- const apiDir = paths.apiDir;
996
- const appFiles = walk(paths.appDir, [".tsx", ".ts"]);
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"]);
1001
- const allDiscovered = [...appFiles, ...clientFiles, ...serverFiles, ...libFiles, ...configFiles];
1163
+ const allDiscovered = [];
1164
+ const discoveredSet = /* @__PURE__ */ new Set();
1165
+ for (const root of paths.srcRoots) {
1166
+ for (const f of walk(root, [".tsx", ".ts"])) {
1167
+ if (!discoveredSet.has(f)) {
1168
+ discoveredSet.add(f);
1169
+ allDiscovered.push(f);
1170
+ }
1171
+ }
1172
+ }
1173
+ for (const conv of paths.conventionFiles) {
1174
+ if (!discoveredSet.has(conv)) {
1175
+ discoveredSet.add(conv);
1176
+ allDiscovered.push(conv);
1177
+ }
1178
+ }
1002
1179
  const parsedByPath = /* @__PURE__ */ new Map();
1003
1180
  for (const absPath of allDiscovered) {
1004
1181
  parsedByPath.set(absPath, parseFileTS(absPath));
@@ -1010,7 +1187,7 @@ function generate(rootDir) {
1010
1187
  const routeToNodeId = /* @__PURE__ */ new Map();
1011
1188
  const fileSet = allDiscovered.filter((f) => !(0, import_node_path5.basename)(f).startsWith("index."));
1012
1189
  for (const absPath of fileSet) {
1013
- const id = toNodeId(srcDir, absPath);
1190
+ const id = toNodeId(srcDir, rootDir, absPath);
1014
1191
  const type = classifyType(absPath, id);
1015
1192
  if (type === "test" || type === "story") continue;
1016
1193
  const parsed = parsedByPath.get(absPath);
@@ -1025,7 +1202,7 @@ function generate(rootDir) {
1025
1202
  const dbCalls = extractDbCallsTS(absPath);
1026
1203
  const authWrappers = extractAuthWrappersTS(absPath);
1027
1204
  const deep = extractDeep(absPath);
1028
- const routePath = (0, import_node_fs5.existsSync)(apiDir) ? filePathToApiRoute(apiDir, absPath) : `/api/${id.replace(/\/route\.tsx?$/, "")}`;
1205
+ const routePath = filePathToAppRoute(paths.appDir, absPath);
1029
1206
  const mutations = dbCalls.filter((c) => c.isMutation);
1030
1207
  const mutates = mutations.length > 0;
1031
1208
  const authStrategy = [...authWrappers];
@@ -1069,11 +1246,12 @@ function generate(rootDir) {
1069
1246
  const uiEdges = [];
1070
1247
  const uiFlagged = [];
1071
1248
  for (const absPath of fileSet) {
1072
- const id = toNodeId(srcDir, absPath);
1249
+ const id = toNodeId(srcDir, rootDir, absPath);
1073
1250
  if (!nodeIdSet.has(id)) continue;
1074
1251
  const parsed = parsedByPath.get(absPath);
1075
1252
  const { edges, flagged } = extractEdges(
1076
1253
  srcDir,
1254
+ rootDir,
1077
1255
  absPath,
1078
1256
  id,
1079
1257
  parsed,
@@ -1086,7 +1264,7 @@ function generate(rootDir) {
1086
1264
  }
1087
1265
  const fetchCallEntries = [];
1088
1266
  for (const absPath of fileSet) {
1089
- const sourceId = toNodeId(srcDir, absPath);
1267
+ const sourceId = toNodeId(srcDir, rootDir, absPath);
1090
1268
  if (!nodeIdSet.has(sourceId)) continue;
1091
1269
  const parsed = parsedByPath.get(absPath);
1092
1270
  if (parsed.fetchCalls.length === 0) continue;
@@ -1125,7 +1303,7 @@ function generate(rootDir) {
1125
1303
  for (const name of names) {
1126
1304
  const targetAbs = barrelMap.get(name);
1127
1305
  if (!targetAbs) continue;
1128
- const targetId2 = toNodeId(srcDir, targetAbs);
1306
+ const targetId2 = toNodeId(srcDir, rootDir, targetAbs);
1129
1307
  if (!nodeIdSet.has(targetId2)) continue;
1130
1308
  const key2 = `${externalId}\u2192${targetId2}`;
1131
1309
  if (seen.has(key2)) continue;
@@ -1139,7 +1317,7 @@ function generate(rootDir) {
1139
1317
  resolved = resolveRelativeImport(absPath, specifier);
1140
1318
  }
1141
1319
  if (!resolved) continue;
1142
- const targetId = toNodeId(srcDir, resolved);
1320
+ const targetId = toNodeId(srcDir, rootDir, resolved);
1143
1321
  if (!nodeIdSet.has(targetId)) continue;
1144
1322
  if (targetId.endsWith("/index.ts") || targetId.endsWith("/index.tsx")) continue;
1145
1323
  const key = `${externalId}\u2192${targetId}`;
@@ -1317,7 +1495,7 @@ var typescriptProjectParser = {
1317
1495
 
1318
1496
  // src/server/graph/parsers/db/prisma-schema.ts
1319
1497
  var import_node_fs6 = require("node:fs");
1320
- var import_node_path6 = require("node:path");
1498
+ init_config();
1321
1499
  function parseModels(content) {
1322
1500
  const nodes = [];
1323
1501
  const relations = [];
@@ -1408,10 +1586,24 @@ function parseEnums(content) {
1408
1586
  return nodes;
1409
1587
  }
1410
1588
  function detect2(rootDir) {
1411
- return (0, import_node_fs6.existsSync)((0, import_node_path6.join)(rootDir, "prisma", "schema.prisma"));
1589
+ const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
1590
+ return paths?.dbConfig.kind === "prisma" && (0, import_node_fs6.existsSync)(paths.dbConfig.schemaPath);
1412
1591
  }
1413
1592
  function generate2(rootDir) {
1414
- const schemaPath = (0, import_node_path6.join)(rootDir, "prisma", "schema.prisma");
1593
+ const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
1594
+ if (paths.dbConfig.kind !== "prisma") {
1595
+ return {
1596
+ metadata: { generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), layer: "db", source: "none" },
1597
+ nodes: [],
1598
+ edges: [],
1599
+ cross_refs: [],
1600
+ contradictions: [],
1601
+ warnings: [],
1602
+ flagged_edges: [],
1603
+ patterns: { total_tables: 0, total_enums: 0, total_relations: 0 }
1604
+ };
1605
+ }
1606
+ const schemaPath = paths.dbConfig.schemaPath;
1415
1607
  const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
1416
1608
  const { nodes: modelNodes, relations } = parseModels(content);
1417
1609
  const enumNodes = parseEnums(content);
@@ -1432,7 +1624,7 @@ function generate2(rootDir) {
1432
1624
  metadata: {
1433
1625
  generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1434
1626
  scope: "prisma-schema",
1435
- source: "prisma/schema.prisma",
1627
+ source: schemaPath,
1436
1628
  provider: "postgresql",
1437
1629
  layer: "db",
1438
1630
  total_models: modelNodes.length,
@@ -1470,7 +1662,8 @@ var prismaSchemaParser = {
1470
1662
 
1471
1663
  // src/server/graph/parsers/db/sql-migrations.ts
1472
1664
  var import_node_fs7 = require("node:fs");
1473
- var import_node_path7 = require("node:path");
1665
+ var import_node_path6 = require("node:path");
1666
+ init_config();
1474
1667
  var PG_TO_PRISMA = {
1475
1668
  "TEXT": "String",
1476
1669
  "VARCHAR": "String",
@@ -1619,19 +1812,29 @@ function parseUniqueIndex(sql, state) {
1619
1812
  state.uniqueIndexes.get(m[1]).add(m[2]);
1620
1813
  }
1621
1814
  }
1622
- function parseMigrations(rootDir) {
1623
- const migrationsDir = (0, import_node_path7.join)(rootDir, "prisma", "migrations");
1815
+ function discoverMigrationFiles(migrationsDir) {
1816
+ if (!(0, import_node_fs7.existsSync)(migrationsDir)) return [];
1817
+ const out = [];
1818
+ const entries = (0, import_node_fs7.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
1819
+ for (const entry of entries) {
1820
+ if (entry.isDirectory()) {
1821
+ const sqlPath = (0, import_node_path6.join)(migrationsDir, entry.name, "migration.sql");
1822
+ if ((0, import_node_fs7.existsSync)(sqlPath)) out.push(sqlPath);
1823
+ } else if (entry.isFile() && entry.name.endsWith(".sql")) {
1824
+ out.push((0, import_node_path6.join)(migrationsDir, entry.name));
1825
+ }
1826
+ }
1827
+ return out;
1828
+ }
1829
+ function parseMigrations(migrationsDir) {
1624
1830
  const state = {
1625
1831
  tables: /* @__PURE__ */ new Map(),
1626
1832
  enums: /* @__PURE__ */ new Map(),
1627
1833
  fks: [],
1628
1834
  uniqueIndexes: /* @__PURE__ */ new Map()
1629
1835
  };
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();
1632
- for (const dir of dirs) {
1633
- const sqlPath = (0, import_node_path7.join)(migrationsDir, dir, "migration.sql");
1634
- if (!(0, import_node_fs7.existsSync)(sqlPath)) continue;
1836
+ if (!migrationsDir) return state;
1837
+ for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
1635
1838
  const sql = (0, import_node_fs7.readFileSync)(sqlPath, "utf-8");
1636
1839
  parseCreateEnum(sql, state);
1637
1840
  parseCreateTable(sql, state);
@@ -1642,9 +1845,8 @@ function parseMigrations(rootDir) {
1642
1845
  }
1643
1846
  return state;
1644
1847
  }
1645
- function loadPrismaState(rootDir) {
1646
- const schemaPath = (0, import_node_path7.join)(rootDir, "prisma", "schema.prisma");
1647
- if (!(0, import_node_fs7.existsSync)(schemaPath)) return null;
1848
+ function loadPrismaState(schemaPath) {
1849
+ if (!schemaPath || !(0, import_node_fs7.existsSync)(schemaPath)) return null;
1648
1850
  const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
1649
1851
  const tables = /* @__PURE__ */ new Map();
1650
1852
  const enums = /* @__PURE__ */ new Map();
@@ -1809,14 +2011,28 @@ function verify(sqlState, prisma) {
1809
2011
  }
1810
2012
  return { contradictions, flaggedEdges };
1811
2013
  }
2014
+ function migrationsDirFor(rootDir) {
2015
+ const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2016
+ if (!paths) return null;
2017
+ if (paths.dbConfig.kind === "prisma" || paths.dbConfig.kind === "sql-migrations") {
2018
+ return paths.dbConfig.migrationsDir;
2019
+ }
2020
+ return null;
2021
+ }
2022
+ function schemaPathFor(rootDir) {
2023
+ const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2024
+ if (!paths) return null;
2025
+ return paths.dbConfig.kind === "prisma" ? paths.dbConfig.schemaPath : null;
2026
+ }
1812
2027
  function detect3(rootDir) {
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")));
2028
+ const dir = migrationsDirFor(rootDir);
2029
+ if (!dir) return false;
2030
+ return discoverMigrationFiles(dir).length > 0;
1816
2031
  }
1817
2032
  function generate3(rootDir) {
1818
- const sqlState = parseMigrations(rootDir);
1819
- const prisma = loadPrismaState(rootDir);
2033
+ const migrationsDir = migrationsDirFor(rootDir);
2034
+ const sqlState = parseMigrations(migrationsDir);
2035
+ const prisma = loadPrismaState(schemaPathFor(rootDir));
1820
2036
  const prismaTableIds = prisma ? new Set(prisma.tables.keys()) : /* @__PURE__ */ new Set();
1821
2037
  const prismaEnumIds = prisma ? new Set(prisma.enums.keys()) : /* @__PURE__ */ new Set();
1822
2038
  const nodes = [];
@@ -1862,7 +2078,7 @@ function generate3(rootDir) {
1862
2078
  metadata: {
1863
2079
  generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1864
2080
  scope: "sql-migrations",
1865
- source: "prisma/migrations/",
2081
+ source: migrationsDir ?? "none",
1866
2082
  layer: "db",
1867
2083
  sql_tables: sqlState.tables.size,
1868
2084
  sql_enums: sqlState.enums.size,
@@ -2101,31 +2317,31 @@ var fetchResolverParser = {
2101
2317
 
2102
2318
  // src/server/graph/parsers/crosslayer/api-annotations.ts
2103
2319
  var import_node_fs8 = require("node:fs");
2104
- var import_node_path8 = require("node:path");
2320
+ var import_node_path7 = require("node:path");
2105
2321
  var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
2106
2322
  function walk2(dir, exts) {
2107
2323
  if (!(0, import_node_fs8.existsSync)(dir)) return [];
2108
2324
  const results = [];
2109
2325
  for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
2110
2326
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2111
- const full = (0, import_node_path8.join)(dir, entry.name);
2327
+ const full = (0, import_node_path7.join)(dir, entry.name);
2112
2328
  if (entry.isDirectory()) {
2113
2329
  results.push(...walk2(full, exts));
2114
- } else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
2330
+ } else if (exts.includes((0, import_node_path7.extname)(entry.name))) {
2115
2331
  results.push(full);
2116
2332
  }
2117
2333
  }
2118
2334
  return results;
2119
2335
  }
2120
2336
  function toNodeId2(srcDir, absPath) {
2121
- return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
2337
+ return (0, import_node_path7.relative)(srcDir, absPath).replace(/\\/g, "/");
2122
2338
  }
2123
2339
  var apiAnnotationsParser = {
2124
2340
  id: "api-annotations",
2125
2341
  layer: "crosslayer",
2126
2342
  concern: "api-binding",
2127
2343
  detect(rootDir) {
2128
- return (0, import_node_fs8.existsSync)((0, import_node_path8.join)(rootDir, "src"));
2344
+ return (0, import_node_fs8.existsSync)((0, import_node_path7.join)(rootDir, "src"));
2129
2345
  },
2130
2346
  generate(rootDir, layerOutputs) {
2131
2347
  const apiOutput = layerOutputs.get("api");
@@ -2136,7 +2352,7 @@ var apiAnnotationsParser = {
2136
2352
  const uiNodeIds = new Set(uiOutput?.nodes.map((n) => n.id) ?? []);
2137
2353
  const apiRoutes = loadApiRoutesFromOutput(apiOutput);
2138
2354
  const apiPathMap = buildApiPathMap(apiRoutes);
2139
- const srcDir = (0, import_node_path8.join)(rootDir, "src");
2355
+ const srcDir = (0, import_node_path7.join)(rootDir, "src");
2140
2356
  const files = walk2(srcDir, [".ts", ".tsx"]);
2141
2357
  const crossRefs = [];
2142
2358
  const flaggedEdges = [];
@@ -2187,7 +2403,7 @@ var apiAnnotationsParser = {
2187
2403
 
2188
2404
  // src/server/graph/parsers/crosslayer/url-literal-scanner.ts
2189
2405
  var import_node_fs9 = require("node:fs");
2190
- var import_node_path9 = require("node:path");
2406
+ var import_node_path8 = require("node:path");
2191
2407
  init_config();
2192
2408
  var URL_LITERAL_RE = /['"`](\/api\/[^'"`\s]+?)['"`]/g;
2193
2409
  function walk3(dir, exts) {
@@ -2195,17 +2411,17 @@ function walk3(dir, exts) {
2195
2411
  const results = [];
2196
2412
  for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
2197
2413
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
2198
- const full = (0, import_node_path9.join)(dir, entry.name);
2414
+ const full = (0, import_node_path8.join)(dir, entry.name);
2199
2415
  if (entry.isDirectory()) {
2200
2416
  results.push(...walk3(full, exts));
2201
- } else if (exts.includes((0, import_node_path9.extname)(entry.name))) {
2417
+ } else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
2202
2418
  results.push(full);
2203
2419
  }
2204
2420
  }
2205
2421
  return results;
2206
2422
  }
2207
2423
  function toNodeId3(srcDir, absPath) {
2208
- return (0, import_node_path9.relative)(srcDir, absPath).replace(/\\/g, "/");
2424
+ return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
2209
2425
  }
2210
2426
  var urlLiteralScannerParser = {
2211
2427
  id: "url-literal-scanner",
@@ -2226,7 +2442,7 @@ var urlLiteralScannerParser = {
2226
2442
  const apiPathMap = buildApiPathMap(apiRoutes);
2227
2443
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2228
2444
  const srcDir = paths.srcDir;
2229
- const clientDir = (0, import_node_path9.join)(srcDir, "client");
2445
+ const clientDir = (0, import_node_path8.join)(srcDir, "client");
2230
2446
  const files = [
2231
2447
  ...walk3(clientDir, [".ts", ".tsx"]),
2232
2448
  ...walk3(paths.appDir, [".ts", ".tsx"])
@@ -2268,7 +2484,7 @@ var urlLiteralScannerParser = {
2268
2484
 
2269
2485
  // src/server/graph/parsers/static/static-values.ts
2270
2486
  var import_node_fs10 = require("node:fs");
2271
- var import_node_path10 = require("node:path");
2487
+ var import_node_path9 = require("node:path");
2272
2488
  var parseCode = null;
2273
2489
  function tryLoadTreeSitter() {
2274
2490
  if (parseCode) return true;
@@ -2301,8 +2517,8 @@ function extractEnumValues(rootDir) {
2301
2517
  const nodes = [];
2302
2518
  const edges = [];
2303
2519
  const schemaPaths = [
2304
- (0, import_node_path10.join)(rootDir, "prisma", "schema.prisma"),
2305
- (0, import_node_path10.join)(rootDir, "prisma", "schema")
2520
+ (0, import_node_path9.join)(rootDir, "prisma", "schema.prisma"),
2521
+ (0, import_node_path9.join)(rootDir, "prisma", "schema")
2306
2522
  ];
2307
2523
  let content = "";
2308
2524
  for (const p of schemaPaths) {
@@ -2313,7 +2529,7 @@ function extractEnumValues(rootDir) {
2313
2529
  content = (0, import_node_fs10.readFileSync)(p, "utf-8");
2314
2530
  } else if (stat.isDirectory()) {
2315
2531
  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");
2532
+ content = files.map((f) => (0, import_node_fs10.readFileSync)((0, import_node_path9.join)(p, f), "utf-8")).join("\n");
2317
2533
  }
2318
2534
  } catch {
2319
2535
  continue;
@@ -2469,14 +2685,14 @@ function extractSeedData(rootDir) {
2469
2685
  const nodes = [];
2470
2686
  const edges = [];
2471
2687
  const seedFiles = [
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")
2688
+ (0, import_node_path9.join)(rootDir, "prisma", "seed.ts"),
2689
+ (0, import_node_path9.join)(rootDir, "prisma", "seed.js"),
2690
+ (0, import_node_path9.join)(rootDir, "src", "server", "lib", "system-tags.ts")
2475
2691
  ].filter(import_node_fs10.existsSync);
2476
2692
  const useTreeSitter = tryLoadTreeSitter();
2477
2693
  for (const filePath of seedFiles) {
2478
2694
  const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
2479
- const relPath = (0, import_node_path10.relative)(rootDir, filePath);
2695
+ const relPath = (0, import_node_path9.relative)(rootDir, filePath);
2480
2696
  const seeded = detectSeededArrays(content, relPath);
2481
2697
  let astRoot = null;
2482
2698
  if (useTreeSitter && parseCode) {
@@ -2574,7 +2790,7 @@ function walkDir(dir, exts) {
2574
2790
  const results = [];
2575
2791
  for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
2576
2792
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
2577
- const full = (0, import_node_path10.join)(dir, entry.name);
2793
+ const full = (0, import_node_path9.join)(dir, entry.name);
2578
2794
  if (entry.isDirectory()) results.push(...walkDir(full, exts));
2579
2795
  else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
2580
2796
  }
@@ -2582,11 +2798,11 @@ function walkDir(dir, exts) {
2582
2798
  }
2583
2799
  function extractConstants(rootDir) {
2584
2800
  const nodes = [];
2585
- const srcDir = (0, import_node_path10.join)(rootDir, "src");
2801
+ const srcDir = (0, import_node_path9.join)(rootDir, "src");
2586
2802
  if (!(0, import_node_fs10.existsSync)(srcDir)) return { nodes };
2587
2803
  for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
2588
2804
  const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
2589
- const relPath = (0, import_node_path10.relative)(rootDir, filePath);
2805
+ const relPath = (0, import_node_path9.relative)(rootDir, filePath);
2590
2806
  const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
2591
2807
  let cm;
2592
2808
  while ((cm = constArrayRe.exec(content)) !== null) {
@@ -2619,7 +2835,7 @@ function extractConstants(rootDir) {
2619
2835
  return { nodes };
2620
2836
  }
2621
2837
  function detect4(rootDir) {
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"));
2838
+ return (0, import_node_fs10.existsSync)((0, import_node_path9.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs10.existsSync)((0, import_node_path9.join)(rootDir, "prisma", "seed.ts"));
2623
2839
  }
2624
2840
  function generate4(rootDir) {
2625
2841
  const enumResult = extractEnumValues(rootDir);
@@ -2695,7 +2911,7 @@ var staticValuesParser = {
2695
2911
 
2696
2912
  // src/server/graph/parsers/crosslayer/static-ref-scanner.ts
2697
2913
  var import_node_fs11 = require("node:fs");
2698
- var import_node_path11 = require("node:path");
2914
+ var import_node_path10 = require("node:path");
2699
2915
  init_config();
2700
2916
  var MIN_VALUE_LENGTH = 4;
2701
2917
  var SKIP_VALUES = /* @__PURE__ */ new Set([
@@ -2839,11 +3055,11 @@ var staticRefScannerParser = {
2839
3055
  if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
2840
3056
  const srcDir = paths.srcDir;
2841
3057
  const files = [
2842
- ...walkWithIgnore((0, import_node_path11.join)(srcDir, "client"), [".ts", ".tsx"]),
3058
+ ...walkWithIgnore((0, import_node_path10.join)(srcDir, "client"), [".ts", ".tsx"]),
2843
3059
  ...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"])
3060
+ ...walkWithIgnore((0, import_node_path10.join)(srcDir, "server"), [".ts", ".tsx"]),
3061
+ ...walkWithIgnore((0, import_node_path10.join)(srcDir, "lib"), [".ts", ".tsx"]),
3062
+ ...walkWithIgnore((0, import_node_path10.join)(srcDir, "config"), [".ts", ".tsx"])
2847
3063
  ];
2848
3064
  const uiOutput = layerOutputs.get("ui");
2849
3065
  const apiOutput = layerOutputs.get("api");
@@ -2861,7 +3077,7 @@ var staticRefScannerParser = {
2861
3077
  const seen = /* @__PURE__ */ new Set();
2862
3078
  let filesScanned = 0;
2863
3079
  for (const absPath of files) {
2864
- const sourceId = (0, import_node_path11.relative)(srcDir, absPath).replace(/\\/g, "/");
3080
+ const sourceId = (0, import_node_path10.relative)(srcDir, absPath).replace(/\\/g, "/");
2865
3081
  const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
2866
3082
  if (!sourceLayer) continue;
2867
3083
  const content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
@@ -2980,7 +3196,7 @@ function registerBuiltins(registry, disabled) {
2980
3196
  function loadCustomParsers(registry, config, rootDir, disabled) {
2981
3197
  for (const entry of config.parsers?.custom ?? []) {
2982
3198
  try {
2983
- const absPath = (0, import_node_path12.resolve)(rootDir, entry.path);
3199
+ const absPath = (0, import_node_path11.resolve)(rootDir, entry.path);
2984
3200
  const mod = require(absPath);
2985
3201
  const parser = "default" in mod ? mod.default : mod;
2986
3202
  if (disabled.has(parser.id)) continue;
@@ -3110,7 +3326,7 @@ function applyCrossLayerResults(uiOutput, results) {
3110
3326
 
3111
3327
  // src/server/graph/core/graph-builder.ts
3112
3328
  function readGraphFromDisk(rootDir, layer) {
3113
- const filePath = (0, import_node_path13.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3329
+ const filePath = (0, import_node_path12.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3114
3330
  if (!(0, import_node_fs12.existsSync)(filePath)) return null;
3115
3331
  try {
3116
3332
  return JSON.parse((0, import_node_fs12.readFileSync)(filePath, "utf-8"));
@@ -3214,11 +3430,11 @@ function generateAll(rootDir) {
3214
3430
  init_config();
3215
3431
 
3216
3432
  // src/server/graph/core/tagger-registry.ts
3217
- var import_node_path15 = require("node:path");
3433
+ var import_node_path14 = require("node:path");
3218
3434
 
3219
3435
  // src/server/graph/taggers/module-tagger.ts
3220
3436
  var import_node_fs13 = require("node:fs");
3221
- var import_node_path14 = require("node:path");
3437
+ var import_node_path13 = require("node:path");
3222
3438
  function matchGlob(pattern, id) {
3223
3439
  const patParts = pattern.split("/");
3224
3440
  const idParts = id.split("/");
@@ -3251,13 +3467,13 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
3251
3467
  const conventionDirs = [...CONVENTION_DIRS_BUILTIN, ...extraConventionDirs];
3252
3468
  const searchDirs = [
3253
3469
  rootDir,
3254
- (0, import_node_path14.join)(rootDir, "src"),
3255
- (0, import_node_path14.join)(rootDir, "app"),
3256
- (0, import_node_path14.join)(rootDir, "lib")
3470
+ (0, import_node_path13.join)(rootDir, "src"),
3471
+ (0, import_node_path13.join)(rootDir, "app"),
3472
+ (0, import_node_path13.join)(rootDir, "lib")
3257
3473
  ];
3258
3474
  for (const base of searchDirs) {
3259
3475
  for (const convention of conventionDirs) {
3260
- const dir = (0, import_node_path14.join)(base, convention);
3476
+ const dir = (0, import_node_path13.join)(base, convention);
3261
3477
  if (!(0, import_node_fs13.existsSync)(dir)) continue;
3262
3478
  try {
3263
3479
  const stat = (0, import_node_fs13.statSync)(dir);
@@ -3556,7 +3772,7 @@ function loadCustomTaggers(registry, config, rootDir, disabled) {
3556
3772
  for (const entry of config.taggers?.custom ?? []) {
3557
3773
  if (disabled.has(entry.id)) continue;
3558
3774
  try {
3559
- const absPath = (0, import_node_path15.resolve)(rootDir, entry.path);
3775
+ const absPath = (0, import_node_path14.resolve)(rootDir, entry.path);
3560
3776
  const mod = require(absPath);
3561
3777
  const tagger = "default" in mod ? mod.default : mod;
3562
3778
  const override = config.taggers?.trackUntagged?.[tagger.id];
@@ -3580,12 +3796,12 @@ function createTaggerRegistry(config, rootDir) {
3580
3796
 
3581
3797
  // src/server/graph/core/tag-store.ts
3582
3798
  var import_node_fs14 = require("node:fs");
3583
- var import_node_path16 = require("node:path");
3799
+ var import_node_path15 = require("node:path");
3584
3800
  var TAGS_FILENAME = "tags.json";
3585
3801
  var GRAPHS_DIR = ".launchsecure/graphs";
3586
3802
  var tagCache = /* @__PURE__ */ new Map();
3587
3803
  function tagsFilePath(rootDir) {
3588
- return (0, import_node_path16.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
3804
+ return (0, import_node_path15.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
3589
3805
  }
3590
3806
  function readTagStore(rootDir) {
3591
3807
  const filePath = tagsFilePath(rootDir);
@@ -3606,7 +3822,7 @@ function readTagStore(rootDir) {
3606
3822
  }
3607
3823
  function writeTagStore(rootDir, store) {
3608
3824
  const filePath = tagsFilePath(rootDir);
3609
- const dir = (0, import_node_path16.dirname)(filePath);
3825
+ const dir = (0, import_node_path15.dirname)(filePath);
3610
3826
  (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
3611
3827
  const cleaned = {};
3612
3828
  for (const [nodeId, tags] of Object.entries(store)) {
@@ -3637,20 +3853,20 @@ function removeTag(rootDir, nodeId, key) {
3637
3853
  init_ts_extractor();
3638
3854
  var GRAPHS_DIR2 = ".launchsecure/graphs";
3639
3855
  function getAvailableLayers(rootDir) {
3640
- const dir = (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
3856
+ const dir = (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
3641
3857
  if (!(0, import_node_fs15.existsSync)(dir)) return [];
3642
3858
  return (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
3643
3859
  }
3644
3860
  var graphCache = /* @__PURE__ */ new Map();
3645
3861
  var taggedCache = /* @__PURE__ */ new Map();
3646
3862
  function graphsDir(rootDir) {
3647
- return (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
3863
+ return (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
3648
3864
  }
3649
3865
  function graphFilePath(rootDir, layer) {
3650
- return (0, import_node_path17.join)(graphsDir(rootDir), `${layer}.json`);
3866
+ return (0, import_node_path16.join)(graphsDir(rootDir), `${layer}.json`);
3651
3867
  }
3652
3868
  function tagsFilePath2(rootDir) {
3653
- return (0, import_node_path17.join)(graphsDir(rootDir), "tags.json");
3869
+ return (0, import_node_path16.join)(graphsDir(rootDir), "tags.json");
3654
3870
  }
3655
3871
  function getMtimeMs(filePath) {
3656
3872
  if (!(0, import_node_fs15.existsSync)(filePath)) return 0;
@@ -3751,15 +3967,15 @@ async function generateGraph(rootDir, layer) {
3751
3967
  var import_node_child_process = require("node:child_process");
3752
3968
  var import_node_fs16 = require("node:fs");
3753
3969
  var import_node_os = require("node:os");
3754
- var import_node_path18 = require("node:path");
3970
+ var import_node_path17 = require("node:path");
3755
3971
  function lockDir(projectRoot) {
3756
3972
  if (projectRoot) {
3757
- return (0, import_node_path18.join)(projectRoot, ".launchsecure");
3973
+ return (0, import_node_path17.join)(projectRoot, ".launchsecure");
3758
3974
  }
3759
- return (0, import_node_path18.join)((0, import_node_os.homedir)(), ".launchsecure");
3975
+ return (0, import_node_path17.join)((0, import_node_os.homedir)(), ".launchsecure");
3760
3976
  }
3761
3977
  function lockPath(projectRoot) {
3762
- return (0, import_node_path18.join)(lockDir(projectRoot), "launch-chart.lock");
3978
+ return (0, import_node_path17.join)(lockDir(projectRoot), "launch-chart.lock");
3763
3979
  }
3764
3980
  var _activeProjectRoot;
3765
3981
  function readLock(projectRoot) {
@@ -3844,9 +4060,9 @@ init_config();
3844
4060
 
3845
4061
  // src/server/graph/core/audit-core.ts
3846
4062
  var import_node_fs17 = require("node:fs");
3847
- var import_node_path19 = require("node:path");
4063
+ var import_node_path18 = require("node:path");
3848
4064
  function readGraphFile(rootDir, layer) {
3849
- const filePath = (0, import_node_path19.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
4065
+ const filePath = (0, import_node_path18.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
3850
4066
  if (!(0, import_node_fs17.existsSync)(filePath)) return null;
3851
4067
  try {
3852
4068
  return JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
@@ -3893,7 +4109,7 @@ function checkUnprotectedRoutes(rootDir) {
3893
4109
  const api = readGraphFile(rootDir, "api");
3894
4110
  const staticGraph = readGraphFile(rootDir, "static");
3895
4111
  if (!api) return buildReport("api", "unprotected_routes", findings);
3896
- const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
4112
+ const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
3897
4113
  let routePermsContent = "";
3898
4114
  if ((0, import_node_fs17.existsSync)(routePermsPath)) {
3899
4115
  routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
@@ -3973,7 +4189,7 @@ function checkUnenforcedPermissions(rootDir) {
3973
4189
  const staticGraph = readGraphFile(rootDir, "static");
3974
4190
  if (!staticGraph) return buildReport("static", "unenforced_permissions", findings);
3975
4191
  const permissions = staticGraph.nodes.filter((n) => n.type === "seed_permission").map((n) => ({ id: n.id, key: n.value, name: n.name }));
3976
- const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
4192
+ const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
3977
4193
  let routePermsContent = "";
3978
4194
  if ((0, import_node_fs17.existsSync)(routePermsPath)) {
3979
4195
  routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
@@ -4006,7 +4222,7 @@ function checkHardcodedValues(rootDir) {
4006
4222
  const seen = /* @__PURE__ */ new Set();
4007
4223
  for (const node of api.nodes) {
4008
4224
  if (node.type !== "endpoint") continue;
4009
- const filePath = (0, import_node_path19.join)(rootDir, "src", node.id);
4225
+ const filePath = (0, import_node_path18.join)(rootDir, "src", node.id);
4010
4226
  if (!(0, import_node_fs17.existsSync)(filePath)) continue;
4011
4227
  const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
4012
4228
  let m;
@@ -4138,16 +4354,16 @@ var MIME_TYPES = {
4138
4354
  function findProjectRoot(startDir) {
4139
4355
  let dir = startDir;
4140
4356
  for (let i = 0; i < 8; i++) {
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);
4357
+ const graphsDir2 = import_node_path19.default.join(dir, ".launchsecure", "graphs");
4358
+ if (import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "ui.json")) || import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "api.json")) || import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "db.json"))) return dir;
4359
+ const parent = import_node_path19.default.dirname(dir);
4144
4360
  if (parent === dir) break;
4145
4361
  dir = parent;
4146
4362
  }
4147
4363
  dir = startDir;
4148
4364
  for (let i = 0; i < 8; i++) {
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);
4365
+ if (import_node_fs18.default.existsSync(import_node_path19.default.join(dir, ".git"))) return dir;
4366
+ const parent = import_node_path19.default.dirname(dir);
4151
4367
  if (parent === dir) break;
4152
4368
  dir = parent;
4153
4369
  }
@@ -4156,7 +4372,7 @@ function findProjectRoot(startDir) {
4156
4372
  function resolveRequestRoot(url, monorepoRoot, projects) {
4157
4373
  const projectParam = url.searchParams.get("project");
4158
4374
  if (!projectParam || projects.length === 0) return monorepoRoot;
4159
- const resolved = import_node_path20.default.resolve(monorepoRoot, projectParam);
4375
+ const resolved = import_node_path19.default.resolve(monorepoRoot, projectParam);
4160
4376
  if (!resolved.startsWith(monorepoRoot)) {
4161
4377
  throw new Error("Project path outside monorepo root");
4162
4378
  }
@@ -4208,14 +4424,14 @@ async function buildMergedGraph(root) {
4208
4424
  }
4209
4425
  function serveStatic(res, filePath) {
4210
4426
  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();
4427
+ const ext = import_node_path19.default.extname(filePath).toLowerCase();
4212
4428
  const mime = MIME_TYPES[ext] ?? "application/octet-stream";
4213
4429
  res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
4214
4430
  import_node_fs18.default.createReadStream(filePath).pipe(res);
4215
4431
  return true;
4216
4432
  }
4217
4433
  function serveIndex(res, clientDir) {
4218
- const indexPath = import_node_path20.default.join(clientDir, "index.html");
4434
+ const indexPath = import_node_path19.default.join(clientDir, "index.html");
4219
4435
  if (!import_node_fs18.default.existsSync(indexPath)) {
4220
4436
  res.writeHead(500, { "Content-Type": "text/plain" });
4221
4437
  res.end(`LaunchChart client bundle not found at ${clientDir}. Run 'npm run build:chart-client'.`);
@@ -4224,14 +4440,14 @@ function serveIndex(res, clientDir) {
4224
4440
  serveStatic(res, indexPath);
4225
4441
  }
4226
4442
  function tryListen(server, port) {
4227
- return new Promise((resolve3, reject) => {
4443
+ return new Promise((resolve4, reject) => {
4228
4444
  const onError = (err) => {
4229
4445
  server.off("listening", onListening);
4230
4446
  reject(err);
4231
4447
  };
4232
4448
  const onListening = () => {
4233
4449
  server.off("error", onError);
4234
- resolve3(port);
4450
+ resolve4(port);
4235
4451
  };
4236
4452
  server.once("error", onError);
4237
4453
  server.once("listening", onListening);
@@ -4268,7 +4484,7 @@ async function startChartServer(opts = {}) {
4268
4484
  }
4269
4485
  return { port: existing.port, url: existing.url };
4270
4486
  }
4271
- const clientDir = opts.clientDir ?? import_node_path20.default.join(__dirname, "..", "chart-client");
4487
+ const clientDir = opts.clientDir ?? import_node_path19.default.join(__dirname, "..", "chart-client");
4272
4488
  const rootConfig = loadConfig(projectRoot);
4273
4489
  const projects = rootConfig.projects ?? [];
4274
4490
  const server = import_node_http.default.createServer((req, res) => {
@@ -4284,11 +4500,11 @@ async function startChartServer(opts = {}) {
4284
4500
  }
4285
4501
  if (req.method === "GET" && url2.pathname === "/api/projects") {
4286
4502
  const projectList = projects.length > 0 ? projects.map((p) => {
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"));
4503
+ const absRoot = import_node_path19.default.resolve(projectRoot, p.root);
4504
+ const hasGraphs = import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, ".launchsecure", "graphs"));
4505
+ const hasNextConfig = import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.ts")) || import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.js")) || import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.mjs"));
4290
4506
  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 }];
4507
+ }) : [{ name: import_node_path19.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs18.default.existsSync(import_node_path19.default.join(projectRoot, ".launchsecure", "graphs")), hasNextConfig: true }];
4292
4508
  res.writeHead(200, { "Content-Type": "application/json" });
4293
4509
  res.end(JSON.stringify({ projects: projectList, monorepoRoot: projectRoot }));
4294
4510
  return;
@@ -4334,18 +4550,18 @@ async function startChartServer(opts = {}) {
4334
4550
  }
4335
4551
  if (req.method === "GET" && url2.pathname === "/api/file-content") {
4336
4552
  const relPath = url2.searchParams.get("path");
4337
- if (!relPath || relPath.includes("..") || import_node_path20.default.isAbsolute(relPath)) {
4553
+ if (!relPath || relPath.includes("..") || import_node_path19.default.isAbsolute(relPath)) {
4338
4554
  res.writeHead(400, { "Content-Type": "application/json" });
4339
4555
  res.end(JSON.stringify({ error: "Invalid path" }));
4340
4556
  return;
4341
4557
  }
4342
- const filePath = import_node_path20.default.join(reqRoot, relPath);
4558
+ const filePath = import_node_path19.default.join(reqRoot, relPath);
4343
4559
  if (!filePath.startsWith(reqRoot) || !import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) {
4344
4560
  res.writeHead(404, { "Content-Type": "application/json" });
4345
4561
  res.end(JSON.stringify({ error: "File not found" }));
4346
4562
  return;
4347
4563
  }
4348
- const ext = import_node_path20.default.extname(filePath).toLowerCase();
4564
+ const ext = import_node_path19.default.extname(filePath).toLowerCase();
4349
4565
  const langMap = { ".ts": "typescript", ".tsx": "tsx", ".js": "javascript", ".jsx": "jsx", ".prisma": "prisma", ".json": "json", ".css": "css" };
4350
4566
  const content = import_node_fs18.default.readFileSync(filePath, "utf-8");
4351
4567
  res.writeHead(200, { "Content-Type": "application/json" });
@@ -4389,7 +4605,7 @@ async function startChartServer(opts = {}) {
4389
4605
  req.on("end", () => {
4390
4606
  try {
4391
4607
  const newConfig = JSON.parse(body);
4392
- const configPath = import_node_path20.default.join(reqRoot, ".launchchart.json");
4608
+ const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
4393
4609
  import_node_fs18.default.writeFileSync(configPath, JSON.stringify(newConfig, null, 2) + "\n", "utf-8");
4394
4610
  res.writeHead(200, { "Content-Type": "application/json" });
4395
4611
  res.end(JSON.stringify({ ok: true }));
@@ -4423,7 +4639,7 @@ async function startChartServer(opts = {}) {
4423
4639
  const taggerConfig = JSON.parse(body);
4424
4640
  const config2 = loadConfig(reqRoot);
4425
4641
  config2.taggers = taggerConfig;
4426
- const configPath = import_node_path20.default.join(reqRoot, ".launchchart.json");
4642
+ const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
4427
4643
  import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4428
4644
  res.writeHead(200, { "Content-Type": "application/json" });
4429
4645
  res.end(JSON.stringify({ ok: true }));
@@ -4491,16 +4707,23 @@ async function startChartServer(opts = {}) {
4491
4707
  const paths = resolveProjectPaths(reqRoot, config2);
4492
4708
  const overrides = {
4493
4709
  appDir: !!config2.paths?.appDir,
4494
- dbDir: !!config2.paths?.dbDir
4710
+ dbDir: !!config2.paths?.dbDir,
4711
+ srcRoots: !!(config2.paths?.srcRoots && config2.paths.srcRoots.length > 0)
4495
4712
  };
4713
+ const relFromRoot = (abs) => import_node_path19.default.relative(reqRoot, abs) || ".";
4496
4714
  res.writeHead(200, { "Content-Type": "application/json" });
4497
4715
  res.end(JSON.stringify({
4498
4716
  projectRoot: reqRoot,
4499
4717
  detected: paths ? {
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
4718
+ srcDir: relFromRoot(paths.srcDir),
4719
+ appDir: relFromRoot(paths.appDir),
4720
+ apiDir: relFromRoot(paths.apiDir),
4721
+ dbDir: paths.dbDir ? relFromRoot(paths.dbDir) : null,
4722
+ dbKind: paths.dbConfig.kind,
4723
+ dbSchemaPath: paths.dbConfig.schemaPath ? relFromRoot(paths.dbConfig.schemaPath) : null,
4724
+ dbMigrationsDir: paths.dbConfig.migrationsDir ? relFromRoot(paths.dbConfig.migrationsDir) : null,
4725
+ srcRoots: paths.srcRoots.map(relFromRoot),
4726
+ conventionFiles: paths.conventionFiles.map(relFromRoot)
4504
4727
  } : null,
4505
4728
  overrides,
4506
4729
  isOverride: overrides.appDir
@@ -4509,8 +4732,8 @@ async function startChartServer(opts = {}) {
4509
4732
  }
4510
4733
  if (req.method === "GET" && url2.pathname === "/api/browse-dir") {
4511
4734
  const browsePath = url2.searchParams.get("path") || projectRoot;
4512
- const abs = import_node_path20.default.resolve(browsePath);
4513
- const twoUp = import_node_path20.default.resolve(projectRoot, "..", "..");
4735
+ const abs = import_node_path19.default.resolve(browsePath);
4736
+ const twoUp = import_node_path19.default.resolve(projectRoot, "..", "..");
4514
4737
  if (!abs.startsWith(twoUp)) {
4515
4738
  res.writeHead(403, { "Content-Type": "application/json" });
4516
4739
  res.end(JSON.stringify({ ok: false, error: "Path outside allowed range" }));
@@ -4519,9 +4742,9 @@ async function startChartServer(opts = {}) {
4519
4742
  try {
4520
4743
  const entries = import_node_fs18.default.readdirSync(abs, { withFileTypes: true });
4521
4744
  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();
4522
- const parent = abs !== twoUp ? import_node_path20.default.dirname(abs) : null;
4745
+ const parent = abs !== twoUp ? import_node_path19.default.dirname(abs) : null;
4523
4746
  res.writeHead(200, { "Content-Type": "application/json" });
4524
- res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path20.default.relative(projectRoot, abs) || "." }));
4747
+ res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path19.default.relative(projectRoot, abs) || "." }));
4525
4748
  } catch (err) {
4526
4749
  res.writeHead(400, { "Content-Type": "application/json" });
4527
4750
  res.end(JSON.stringify({ ok: false, error: String(err) }));
@@ -4547,7 +4770,7 @@ async function startChartServer(opts = {}) {
4547
4770
  const { projects: newProjects } = JSON.parse(body);
4548
4771
  const config2 = loadConfig(projectRoot);
4549
4772
  config2.projects = newProjects.length > 0 ? newProjects : void 0;
4550
- const configPath = import_node_path20.default.join(projectRoot, ".launchchart.json");
4773
+ const configPath = import_node_path19.default.join(projectRoot, ".launchchart.json");
4551
4774
  import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
4552
4775
  projects.length = 0;
4553
4776
  if (config2.projects) projects.push(...config2.projects);
@@ -4561,7 +4784,7 @@ async function startChartServer(opts = {}) {
4561
4784
  return;
4562
4785
  }
4563
4786
  if (url2.pathname !== "/") {
4564
- const staticPath = import_node_path20.default.join(clientDir, url2.pathname);
4787
+ const staticPath = import_node_path19.default.join(clientDir, url2.pathname);
4565
4788
  if (serveStatic(res, staticPath)) return;
4566
4789
  }
4567
4790
  serveIndex(res, clientDir);