@launchsecure/launch-kit 0.0.17 → 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.
- package/dist/chart-client/assets/index--120d9P9.css +1 -0
- package/dist/chart-client/assets/index-C8ANseEa.js +441 -0
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/index-Bf8zdL3x.css +32 -0
- package/dist/client/assets/index-Ds9UP_cj.js +291 -0
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/index-CofZh7pS.css +1 -0
- package/dist/council-client/assets/index-Dc41S-R2.js +198 -0
- package/dist/council-client/index.html +21 -0
- package/dist/deck-client/assets/{_baseUniq-BbqvoK-V.js → _baseUniq-DsfOm3t_.js} +1 -1
- package/dist/deck-client/assets/{arc-CMtYsIZt.js → arc-NJuvkBv1.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-BEN5hESa.js → architectureDiagram-Q4EWVU46-BgrcgZs0.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BV4CZ6k8.js → blockDiagram-DXYQGD6D-C3XoLi15.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-fLcBXqdD.js → c4Diagram-AHTNJAMY-FX2PjLfb.js} +1 -1
- package/dist/deck-client/assets/channel-ChQjD1T1.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-BO_19zwB.js → chunk-4BX2VUAB-D0aqsJV0.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-iYegd5fu.js → chunk-4TB4RGXK-7qRCCAgK.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-DM3QwYFL.js → chunk-55IACEB6-DfHG-iqb.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-DGznOul1.js → chunk-EDXVE4YY-DrR52j3B.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-DsANJqYW.js → chunk-FMBD7UC4-D5KSGATB.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-6PGH1F7d.js → chunk-OYMX7WX6-M7hsLRNU.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-Dihf0Uq7.js → chunk-QZHKN3VN-1ynAWO2m.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-Cali2wW5.js → chunk-YZCP3GAM-S2-nGw3D.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-B_9iqK1S.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-B_9iqK1S.js +1 -0
- package/dist/deck-client/assets/clone-BYt1AMfz.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-DsRY4vbI.js → cose-bilkent-S5V4N54A-BcMwozS2.js} +1 -1
- package/dist/deck-client/assets/cytoscape.esm-BQk4lpUV.js +331 -0
- package/dist/deck-client/assets/{dagre-KV5264BT-DJIKE_pI.js → dagre-KV5264BT-DtKMhl_1.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-Ckgli1SP.js → diagram-5BDNPKRD-1plH69us.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-CozcDzae.js → diagram-G4DWMVQ6-D_o-BHO3.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-xVSwW3f_.js → diagram-MMDJMWI5-ClZ1LIx6.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-CJeZVY-P.js → diagram-TYMM5635-B8dKHfRh.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-j4wjAERH.js → erDiagram-SMLLAGMA-CY2aCH7-.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-CVLZ1efi.js → flowDiagram-DWJPFMVM-DZZWHti8.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-CcIJ7pkP.js → ganttDiagram-T4ZO3ILL-OwGGa6Lu.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-BZRhQX-a.js → gitGraphDiagram-UUTBAWPF-GKyWD4Qt.js} +1 -1
- package/dist/deck-client/assets/{graph-D0l25xfo.js → graph-CORzYQdB.js} +1 -1
- package/dist/deck-client/assets/index-765AIQ9z.css +1 -0
- package/dist/deck-client/assets/{index-BXcoHWVM.js → index-hiIpM7EP.js} +93 -93
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BLwgxnYT.js → infoDiagram-42DDH7IO-DmgqJCcF.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-BfOLoWv3.js → ishikawaDiagram-UXIWVN3A-D-1v7knu.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-CPuL6C9h.js → journeyDiagram-VCZTEJTY-CYrGQE7b.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-D3uf7_tx.js → kanban-definition-6JOO6SKY-BJFDWiH-.js} +1 -1
- package/dist/deck-client/assets/{layout-CzToiXdK.js → layout-BTFFcaxF.js} +1 -1
- package/dist/deck-client/assets/{linear-BU36t460.js → linear-DAbl6COS.js} +1 -1
- package/dist/deck-client/assets/{min-DX_q-lqP.js → min-oWHBrFBm.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-Ccty4O16.js → mindmap-definition-QFDTVHPH-BTCB0VLO.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DVjsvH19.js → pieDiagram-DEJITSTG-CUZChWNA.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DtOXFVW9.js → quadrantDiagram-34T5L4WZ-4M1Um_e4.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-BbO_kKg6.js → requirementDiagram-MS252O5E-DLzQZ0B3.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-qbbj-CmC.js → sankeyDiagram-XADWPNL6-DcNgzV3E.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-JNKZAgfQ.js → sequenceDiagram-FGHM5R23-CAcI2vC9.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-dtFalcNx.js → stateDiagram-FHFEXIEX-CntjTTm5.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-YiaphOU_.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-Dpp5nqSJ.js → timeline-definition-GMOUNBTQ-D8zrit4U.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D8qEutX7.js → vennDiagram-DHZGUBPP-C4SuFPgo.js} +1 -1
- package/dist/deck-client/assets/{wardley-RL74JXVD-BwMqiNcL.js → wardley-RL74JXVD-B3F-Olcq.js} +58 -58
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Bxl9X3CK.js → wardleyDiagram-NUSXRM2D-kj73r6f-.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-DYcvxLhi.js → xychartDiagram-5P7HB3ND-CC_d_Ey3.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/chart-serve.js +452 -244
- package/dist/server/cli.js +558 -750
- package/dist/server/council-entry.js +1418 -0
- package/dist/server/council-serve.js +1039 -0
- package/dist/server/graph-mcp-entry.js +486 -695
- package/package.json +10 -9
- package/dist/chart-client/assets/index-BUhuLBaw.js +0 -441
- package/dist/chart-client/assets/index-CWRZxjqR.css +0 -1
- package/dist/client/assets/index-CAAipH3V.js +0 -291
- package/dist/client/assets/index-DtbN793z.css +0 -32
- package/dist/deck-client/assets/channel-Nf-B3Qor.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-3i3-miMR.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-3i3-miMR.js +0 -1
- package/dist/deck-client/assets/clone-DXBuQlG8.js +0 -1
- package/dist/deck-client/assets/cytoscape.esm-BiciSPf8.js +0 -331
- package/dist/deck-client/assets/index-Cdh-f3-c.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CviYYulW.js +0 -1
|
@@ -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,
|
|
94
|
-
const scm = (0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
571
|
-
|
|
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,
|
|
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,
|
|
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,15 +601,15 @@ __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
|
|
604
|
+
var import_node_fs18 = __toESM(require("node:fs"));
|
|
605
605
|
var import_node_path19 = __toESM(require("node:path"));
|
|
606
606
|
|
|
607
607
|
// src/server/graph/index.ts
|
|
608
|
-
var
|
|
608
|
+
var import_node_fs15 = require("node:fs");
|
|
609
609
|
var import_node_path16 = require("node:path");
|
|
610
610
|
|
|
611
611
|
// src/server/graph/core/graph-builder.ts
|
|
612
|
-
var
|
|
612
|
+
var import_node_fs12 = require("node:fs");
|
|
613
613
|
var import_node_path12 = require("node:path");
|
|
614
614
|
init_config();
|
|
615
615
|
|
|
@@ -617,36 +617,243 @@ init_config();
|
|
|
617
617
|
var import_node_path11 = require("node:path");
|
|
618
618
|
|
|
619
619
|
// src/server/graph/parsers/ts/typescript-project.ts
|
|
620
|
-
var
|
|
621
|
-
var
|
|
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
|
|
625
|
+
var import_node_fs3 = require("node:fs");
|
|
626
|
+
var import_node_path3 = require("node:path");
|
|
627
|
+
|
|
628
|
+
// src/server/graph/core/walk.ts
|
|
625
629
|
var import_node_fs2 = require("node:fs");
|
|
626
630
|
var import_node_path2 = require("node:path");
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
631
|
+
var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
632
|
+
"node_modules",
|
|
633
|
+
".git",
|
|
634
|
+
".next",
|
|
635
|
+
".launchsecure",
|
|
636
|
+
".claude",
|
|
637
|
+
"dist",
|
|
638
|
+
"build",
|
|
639
|
+
"out",
|
|
640
|
+
".turbo",
|
|
641
|
+
".vercel",
|
|
642
|
+
"coverage"
|
|
643
|
+
]);
|
|
644
|
+
function walk(dir, exts) {
|
|
645
|
+
const results = [];
|
|
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);
|
|
649
|
+
if (entry.isDirectory()) {
|
|
650
|
+
results.push(...walk(full, exts));
|
|
651
|
+
} else if (exts.includes((0, import_node_path2.extname)(entry.name))) {
|
|
652
|
+
results.push(full);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return results;
|
|
632
656
|
}
|
|
633
|
-
function
|
|
634
|
-
const
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
657
|
+
function walkWithIgnore(dir, exts, opts = {}) {
|
|
658
|
+
const results = [];
|
|
659
|
+
if (!(0, import_node_fs2.existsSync)(dir)) return results;
|
|
660
|
+
const skip = opts.extraIgnore ? /* @__PURE__ */ new Set([...DEFAULT_IGNORE_DIRS, ...opts.extraIgnore]) : DEFAULT_IGNORE_DIRS;
|
|
661
|
+
for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
|
|
662
|
+
if (entry.isDirectory()) {
|
|
663
|
+
if (skip.has(entry.name)) continue;
|
|
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));
|
|
667
|
+
}
|
|
639
668
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
669
|
+
return results;
|
|
670
|
+
}
|
|
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));
|
|
643
716
|
}
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
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;
|
|
647
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;
|
|
648
729
|
return null;
|
|
649
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
|
+
}
|
|
650
857
|
|
|
651
858
|
// src/server/graph/parsers/ts/typescript-project.ts
|
|
652
859
|
init_ts_extractor();
|
|
@@ -664,48 +871,26 @@ var CLASSIFICATION_TO_LAYER = {
|
|
|
664
871
|
"mcp-tool": "ui",
|
|
665
872
|
external: "ui"
|
|
666
873
|
};
|
|
667
|
-
function
|
|
668
|
-
const
|
|
669
|
-
if (
|
|
670
|
-
|
|
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
|
-
}
|
|
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, "/");
|
|
677
878
|
}
|
|
678
|
-
return
|
|
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
|
-
function toNodeId(srcDir, absPath) {
|
|
694
|
-
return (0, import_node_path4.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
879
|
+
return relFromSrc;
|
|
695
880
|
}
|
|
696
881
|
function resolveImport(srcDir, specifier) {
|
|
697
882
|
if (!specifier.startsWith("@/")) return null;
|
|
698
883
|
const rel = specifier.slice(2);
|
|
699
|
-
const base = (0,
|
|
700
|
-
for (const c of [base, base + ".ts", base + ".tsx", (0,
|
|
701
|
-
if ((0,
|
|
884
|
+
const base = (0, import_node_path5.join)(srcDir, rel);
|
|
885
|
+
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")]) {
|
|
886
|
+
if ((0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile()) return c;
|
|
702
887
|
}
|
|
703
888
|
return null;
|
|
704
889
|
}
|
|
705
890
|
function resolveRelativeImport(fromFile, specifier) {
|
|
706
|
-
const base = (0,
|
|
707
|
-
for (const c of [base, base + ".ts", base + ".tsx", (0,
|
|
708
|
-
if ((0,
|
|
891
|
+
const base = (0, import_node_path5.join)((0, import_node_path5.dirname)(fromFile), specifier);
|
|
892
|
+
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")]) {
|
|
893
|
+
if ((0, import_node_fs5.existsSync)(c) && (0, import_node_fs5.statSync)(c).isFile()) return c;
|
|
709
894
|
}
|
|
710
895
|
return null;
|
|
711
896
|
}
|
|
@@ -726,7 +911,7 @@ function resolveBarrelMap(barrelAbsPath, parsedByPath, memo, visiting) {
|
|
|
726
911
|
const resolved = resolveRelativeImport(barrelAbsPath, re.from);
|
|
727
912
|
if (!resolved) continue;
|
|
728
913
|
if (re.isWildcard) {
|
|
729
|
-
const targetBn = (0,
|
|
914
|
+
const targetBn = (0, import_node_path5.basename)(resolved);
|
|
730
915
|
const targetIsBarrel = targetBn === "index.ts" || targetBn === "index.tsx";
|
|
731
916
|
if (targetIsBarrel) {
|
|
732
917
|
const nested = resolveBarrelMap(resolved, parsedByPath, memo, visiting);
|
|
@@ -753,12 +938,12 @@ function buildAllBarrelMaps(srcDir, parsedByPath) {
|
|
|
753
938
|
const barrels = /* @__PURE__ */ new Map();
|
|
754
939
|
const memo = /* @__PURE__ */ new Map();
|
|
755
940
|
for (const [absPath, parsed] of parsedByPath) {
|
|
756
|
-
const bn = (0,
|
|
941
|
+
const bn = (0, import_node_path5.basename)(absPath);
|
|
757
942
|
if (bn !== "index.ts" && bn !== "index.tsx") continue;
|
|
758
943
|
if (parsed.reExports.length === 0) continue;
|
|
759
944
|
const map = resolveBarrelMap(absPath, parsedByPath, memo, /* @__PURE__ */ new Set());
|
|
760
945
|
if (map.size > 0) {
|
|
761
|
-
const barrelId = (0,
|
|
946
|
+
const barrelId = (0, import_node_path5.relative)(srcDir, (0, import_node_path5.dirname)(absPath)).replace(/\\/g, "/");
|
|
762
947
|
barrels.set(barrelId, map);
|
|
763
948
|
}
|
|
764
949
|
}
|
|
@@ -779,14 +964,15 @@ function extractRoute(id) {
|
|
|
779
964
|
return route || "/";
|
|
780
965
|
}
|
|
781
966
|
function nameFromFilename(absPath) {
|
|
782
|
-
return (0,
|
|
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());
|
|
783
968
|
}
|
|
784
|
-
function
|
|
785
|
-
let route = "/" + (0,
|
|
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");
|
|
786
973
|
route = route.replace(/\[([^\]]+)\]/g, ":$1");
|
|
787
974
|
route = route.replace(/\/+/g, "/");
|
|
788
|
-
|
|
789
|
-
return "/api" + route;
|
|
975
|
+
return route === "" ? "/" : route;
|
|
790
976
|
}
|
|
791
977
|
function camelToPascal(s) {
|
|
792
978
|
if (!s) return s;
|
|
@@ -871,7 +1057,7 @@ function matchRouteToPage(route, routeToNodeId) {
|
|
|
871
1057
|
if (routeToNodeId.has(normalized)) return routeToNodeId.get(normalized);
|
|
872
1058
|
return null;
|
|
873
1059
|
}
|
|
874
|
-
function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
1060
|
+
function extractEdges(srcDir, rootDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
875
1061
|
const edges = [];
|
|
876
1062
|
const flagged = [];
|
|
877
1063
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -899,7 +1085,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
899
1085
|
for (const name of names) {
|
|
900
1086
|
const targetAbs = barrelMap.get(name);
|
|
901
1087
|
if (targetAbs) {
|
|
902
|
-
const targetId = toNodeId(srcDir, targetAbs);
|
|
1088
|
+
const targetId = toNodeId(srcDir, rootDir, targetAbs);
|
|
903
1089
|
if (nodeIdSet.has(targetId)) {
|
|
904
1090
|
if (!byTarget.has(targetId)) byTarget.set(targetId, []);
|
|
905
1091
|
byTarget.get(targetId).push(name);
|
|
@@ -913,7 +1099,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
913
1099
|
} else {
|
|
914
1100
|
const resolved = resolveImport(srcDir, specifier);
|
|
915
1101
|
if (resolved) {
|
|
916
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1102
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
917
1103
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
918
1104
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
919
1105
|
}
|
|
@@ -922,7 +1108,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
922
1108
|
} else if (specifier.startsWith(".")) {
|
|
923
1109
|
const resolved = resolveRelativeImport(absPath, specifier);
|
|
924
1110
|
if (resolved) {
|
|
925
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1111
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
926
1112
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
927
1113
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
928
1114
|
}
|
|
@@ -966,24 +1152,30 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
966
1152
|
}
|
|
967
1153
|
return { edges, flagged };
|
|
968
1154
|
}
|
|
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
1155
|
function detect(rootDir) {
|
|
973
1156
|
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
974
|
-
return paths !== null
|
|
1157
|
+
return paths !== null;
|
|
975
1158
|
}
|
|
976
1159
|
function generate(rootDir) {
|
|
977
1160
|
const config = loadConfig(rootDir);
|
|
978
1161
|
const paths = resolveProjectPaths(rootDir, config);
|
|
979
1162
|
const srcDir = paths.srcDir;
|
|
980
|
-
const
|
|
981
|
-
const
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
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
|
+
}
|
|
987
1179
|
const parsedByPath = /* @__PURE__ */ new Map();
|
|
988
1180
|
for (const absPath of allDiscovered) {
|
|
989
1181
|
parsedByPath.set(absPath, parseFileTS(absPath));
|
|
@@ -993,9 +1185,9 @@ function generate(rootDir) {
|
|
|
993
1185
|
const apiNodes = [];
|
|
994
1186
|
const nodeIdSet = /* @__PURE__ */ new Set();
|
|
995
1187
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
996
|
-
const fileSet = allDiscovered.filter((f) => !(0,
|
|
1188
|
+
const fileSet = allDiscovered.filter((f) => !(0, import_node_path5.basename)(f).startsWith("index."));
|
|
997
1189
|
for (const absPath of fileSet) {
|
|
998
|
-
const id = toNodeId(srcDir, absPath);
|
|
1190
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
999
1191
|
const type = classifyType(absPath, id);
|
|
1000
1192
|
if (type === "test" || type === "story") continue;
|
|
1001
1193
|
const parsed = parsedByPath.get(absPath);
|
|
@@ -1010,7 +1202,7 @@ function generate(rootDir) {
|
|
|
1010
1202
|
const dbCalls = extractDbCallsTS(absPath);
|
|
1011
1203
|
const authWrappers = extractAuthWrappersTS(absPath);
|
|
1012
1204
|
const deep = extractDeep(absPath);
|
|
1013
|
-
const routePath = (
|
|
1205
|
+
const routePath = filePathToAppRoute(paths.appDir, absPath);
|
|
1014
1206
|
const mutations = dbCalls.filter((c) => c.isMutation);
|
|
1015
1207
|
const mutates = mutations.length > 0;
|
|
1016
1208
|
const authStrategy = [...authWrappers];
|
|
@@ -1054,11 +1246,12 @@ function generate(rootDir) {
|
|
|
1054
1246
|
const uiEdges = [];
|
|
1055
1247
|
const uiFlagged = [];
|
|
1056
1248
|
for (const absPath of fileSet) {
|
|
1057
|
-
const id = toNodeId(srcDir, absPath);
|
|
1249
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
1058
1250
|
if (!nodeIdSet.has(id)) continue;
|
|
1059
1251
|
const parsed = parsedByPath.get(absPath);
|
|
1060
1252
|
const { edges, flagged } = extractEdges(
|
|
1061
1253
|
srcDir,
|
|
1254
|
+
rootDir,
|
|
1062
1255
|
absPath,
|
|
1063
1256
|
id,
|
|
1064
1257
|
parsed,
|
|
@@ -1071,7 +1264,7 @@ function generate(rootDir) {
|
|
|
1071
1264
|
}
|
|
1072
1265
|
const fetchCallEntries = [];
|
|
1073
1266
|
for (const absPath of fileSet) {
|
|
1074
|
-
const sourceId = toNodeId(srcDir, absPath);
|
|
1267
|
+
const sourceId = toNodeId(srcDir, rootDir, absPath);
|
|
1075
1268
|
if (!nodeIdSet.has(sourceId)) continue;
|
|
1076
1269
|
const parsed = parsedByPath.get(absPath);
|
|
1077
1270
|
if (parsed.fetchCalls.length === 0) continue;
|
|
@@ -1087,20 +1280,7 @@ function generate(rootDir) {
|
|
|
1087
1280
|
});
|
|
1088
1281
|
}
|
|
1089
1282
|
const externalScanned = new Set(allDiscovered.map((f) => f.replace(/\\/g, "/")));
|
|
1090
|
-
const
|
|
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);
|
|
1283
|
+
const externalCandidates = walkWithIgnore(rootDir, [".ts", ".tsx"], { extraIgnore: /* @__PURE__ */ new Set(["src"]) });
|
|
1104
1284
|
for (const absPath of externalCandidates) {
|
|
1105
1285
|
const normalized = absPath.replace(/\\/g, "/");
|
|
1106
1286
|
if (externalScanned.has(normalized)) continue;
|
|
@@ -1110,7 +1290,7 @@ function generate(rootDir) {
|
|
|
1110
1290
|
} catch {
|
|
1111
1291
|
continue;
|
|
1112
1292
|
}
|
|
1113
|
-
const externalId = (0,
|
|
1293
|
+
const externalId = (0, import_node_path5.relative)(rootDir, absPath).replace(/\\/g, "/");
|
|
1114
1294
|
const edgesFromThis = [];
|
|
1115
1295
|
const seen = /* @__PURE__ */ new Set();
|
|
1116
1296
|
for (const imp of parsed.imports) {
|
|
@@ -1123,7 +1303,7 @@ function generate(rootDir) {
|
|
|
1123
1303
|
for (const name of names) {
|
|
1124
1304
|
const targetAbs = barrelMap.get(name);
|
|
1125
1305
|
if (!targetAbs) continue;
|
|
1126
|
-
const targetId2 = toNodeId(srcDir, targetAbs);
|
|
1306
|
+
const targetId2 = toNodeId(srcDir, rootDir, targetAbs);
|
|
1127
1307
|
if (!nodeIdSet.has(targetId2)) continue;
|
|
1128
1308
|
const key2 = `${externalId}\u2192${targetId2}`;
|
|
1129
1309
|
if (seen.has(key2)) continue;
|
|
@@ -1137,7 +1317,7 @@ function generate(rootDir) {
|
|
|
1137
1317
|
resolved = resolveRelativeImport(absPath, specifier);
|
|
1138
1318
|
}
|
|
1139
1319
|
if (!resolved) continue;
|
|
1140
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1320
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
1141
1321
|
if (!nodeIdSet.has(targetId)) continue;
|
|
1142
1322
|
if (targetId.endsWith("/index.ts") || targetId.endsWith("/index.tsx")) continue;
|
|
1143
1323
|
const key = `${externalId}\u2192${targetId}`;
|
|
@@ -1314,8 +1494,8 @@ var typescriptProjectParser = {
|
|
|
1314
1494
|
};
|
|
1315
1495
|
|
|
1316
1496
|
// src/server/graph/parsers/db/prisma-schema.ts
|
|
1317
|
-
var
|
|
1318
|
-
|
|
1497
|
+
var import_node_fs6 = require("node:fs");
|
|
1498
|
+
init_config();
|
|
1319
1499
|
function parseModels(content) {
|
|
1320
1500
|
const nodes = [];
|
|
1321
1501
|
const relations = [];
|
|
@@ -1406,11 +1586,25 @@ function parseEnums(content) {
|
|
|
1406
1586
|
return nodes;
|
|
1407
1587
|
}
|
|
1408
1588
|
function detect2(rootDir) {
|
|
1409
|
-
|
|
1589
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
1590
|
+
return paths?.dbConfig.kind === "prisma" && (0, import_node_fs6.existsSync)(paths.dbConfig.schemaPath);
|
|
1410
1591
|
}
|
|
1411
1592
|
function generate2(rootDir) {
|
|
1412
|
-
const
|
|
1413
|
-
|
|
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;
|
|
1607
|
+
const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
|
|
1414
1608
|
const { nodes: modelNodes, relations } = parseModels(content);
|
|
1415
1609
|
const enumNodes = parseEnums(content);
|
|
1416
1610
|
const allNodes = [...modelNodes, ...enumNodes];
|
|
@@ -1430,7 +1624,7 @@ function generate2(rootDir) {
|
|
|
1430
1624
|
metadata: {
|
|
1431
1625
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1432
1626
|
scope: "prisma-schema",
|
|
1433
|
-
source:
|
|
1627
|
+
source: schemaPath,
|
|
1434
1628
|
provider: "postgresql",
|
|
1435
1629
|
layer: "db",
|
|
1436
1630
|
total_models: modelNodes.length,
|
|
@@ -1467,8 +1661,9 @@ var prismaSchemaParser = {
|
|
|
1467
1661
|
};
|
|
1468
1662
|
|
|
1469
1663
|
// src/server/graph/parsers/db/sql-migrations.ts
|
|
1470
|
-
var
|
|
1664
|
+
var import_node_fs7 = require("node:fs");
|
|
1471
1665
|
var import_node_path6 = require("node:path");
|
|
1666
|
+
init_config();
|
|
1472
1667
|
var PG_TO_PRISMA = {
|
|
1473
1668
|
"TEXT": "String",
|
|
1474
1669
|
"VARCHAR": "String",
|
|
@@ -1617,20 +1812,30 @@ function parseUniqueIndex(sql, state) {
|
|
|
1617
1812
|
state.uniqueIndexes.get(m[1]).add(m[2]);
|
|
1618
1813
|
}
|
|
1619
1814
|
}
|
|
1620
|
-
function
|
|
1621
|
-
|
|
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) {
|
|
1622
1830
|
const state = {
|
|
1623
1831
|
tables: /* @__PURE__ */ new Map(),
|
|
1624
1832
|
enums: /* @__PURE__ */ new Map(),
|
|
1625
1833
|
fks: [],
|
|
1626
1834
|
uniqueIndexes: /* @__PURE__ */ new Map()
|
|
1627
1835
|
};
|
|
1628
|
-
if (!
|
|
1629
|
-
const
|
|
1630
|
-
|
|
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");
|
|
1836
|
+
if (!migrationsDir) return state;
|
|
1837
|
+
for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
|
|
1838
|
+
const sql = (0, import_node_fs7.readFileSync)(sqlPath, "utf-8");
|
|
1634
1839
|
parseCreateEnum(sql, state);
|
|
1635
1840
|
parseCreateTable(sql, state);
|
|
1636
1841
|
parseAlterTable(sql, state);
|
|
@@ -1640,10 +1845,9 @@ function parseMigrations(rootDir) {
|
|
|
1640
1845
|
}
|
|
1641
1846
|
return state;
|
|
1642
1847
|
}
|
|
1643
|
-
function loadPrismaState(
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
|
|
1848
|
+
function loadPrismaState(schemaPath) {
|
|
1849
|
+
if (!schemaPath || !(0, import_node_fs7.existsSync)(schemaPath)) return null;
|
|
1850
|
+
const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
|
|
1647
1851
|
const tables = /* @__PURE__ */ new Map();
|
|
1648
1852
|
const enums = /* @__PURE__ */ new Map();
|
|
1649
1853
|
const relations = [];
|
|
@@ -1807,14 +2011,28 @@ function verify(sqlState, prisma) {
|
|
|
1807
2011
|
}
|
|
1808
2012
|
return { contradictions, flaggedEdges };
|
|
1809
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
|
+
}
|
|
1810
2027
|
function detect3(rootDir) {
|
|
1811
|
-
const
|
|
1812
|
-
if (!
|
|
1813
|
-
return (
|
|
2028
|
+
const dir = migrationsDirFor(rootDir);
|
|
2029
|
+
if (!dir) return false;
|
|
2030
|
+
return discoverMigrationFiles(dir).length > 0;
|
|
1814
2031
|
}
|
|
1815
2032
|
function generate3(rootDir) {
|
|
1816
|
-
const
|
|
1817
|
-
const
|
|
2033
|
+
const migrationsDir = migrationsDirFor(rootDir);
|
|
2034
|
+
const sqlState = parseMigrations(migrationsDir);
|
|
2035
|
+
const prisma = loadPrismaState(schemaPathFor(rootDir));
|
|
1818
2036
|
const prismaTableIds = prisma ? new Set(prisma.tables.keys()) : /* @__PURE__ */ new Set();
|
|
1819
2037
|
const prismaEnumIds = prisma ? new Set(prisma.enums.keys()) : /* @__PURE__ */ new Set();
|
|
1820
2038
|
const nodes = [];
|
|
@@ -1860,7 +2078,7 @@ function generate3(rootDir) {
|
|
|
1860
2078
|
metadata: {
|
|
1861
2079
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1862
2080
|
scope: "sql-migrations",
|
|
1863
|
-
source: "
|
|
2081
|
+
source: migrationsDir ?? "none",
|
|
1864
2082
|
layer: "db",
|
|
1865
2083
|
sql_tables: sqlState.tables.size,
|
|
1866
2084
|
sql_enums: sqlState.enums.size,
|
|
@@ -2098,13 +2316,13 @@ var fetchResolverParser = {
|
|
|
2098
2316
|
};
|
|
2099
2317
|
|
|
2100
2318
|
// src/server/graph/parsers/crosslayer/api-annotations.ts
|
|
2101
|
-
var
|
|
2319
|
+
var import_node_fs8 = require("node:fs");
|
|
2102
2320
|
var import_node_path7 = require("node:path");
|
|
2103
2321
|
var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
|
|
2104
2322
|
function walk2(dir, exts) {
|
|
2105
|
-
if (!(0,
|
|
2323
|
+
if (!(0, import_node_fs8.existsSync)(dir)) return [];
|
|
2106
2324
|
const results = [];
|
|
2107
|
-
for (const entry of (0,
|
|
2325
|
+
for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
|
|
2108
2326
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
2109
2327
|
const full = (0, import_node_path7.join)(dir, entry.name);
|
|
2110
2328
|
if (entry.isDirectory()) {
|
|
@@ -2123,7 +2341,7 @@ var apiAnnotationsParser = {
|
|
|
2123
2341
|
layer: "crosslayer",
|
|
2124
2342
|
concern: "api-binding",
|
|
2125
2343
|
detect(rootDir) {
|
|
2126
|
-
return (0,
|
|
2344
|
+
return (0, import_node_fs8.existsSync)((0, import_node_path7.join)(rootDir, "src"));
|
|
2127
2345
|
},
|
|
2128
2346
|
generate(rootDir, layerOutputs) {
|
|
2129
2347
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -2140,7 +2358,7 @@ var apiAnnotationsParser = {
|
|
|
2140
2358
|
const flaggedEdges = [];
|
|
2141
2359
|
const seen = /* @__PURE__ */ new Set();
|
|
2142
2360
|
for (const absPath of files) {
|
|
2143
|
-
const content = (0,
|
|
2361
|
+
const content = (0, import_node_fs8.readFileSync)(absPath, "utf-8");
|
|
2144
2362
|
const sourceId = toNodeId2(srcDir, absPath);
|
|
2145
2363
|
if (!uiNodeIds.has(sourceId)) continue;
|
|
2146
2364
|
let match;
|
|
@@ -2184,14 +2402,14 @@ var apiAnnotationsParser = {
|
|
|
2184
2402
|
};
|
|
2185
2403
|
|
|
2186
2404
|
// src/server/graph/parsers/crosslayer/url-literal-scanner.ts
|
|
2187
|
-
var
|
|
2405
|
+
var import_node_fs9 = require("node:fs");
|
|
2188
2406
|
var import_node_path8 = require("node:path");
|
|
2189
2407
|
init_config();
|
|
2190
2408
|
var URL_LITERAL_RE = /['"`](\/api\/[^'"`\s]+?)['"`]/g;
|
|
2191
2409
|
function walk3(dir, exts) {
|
|
2192
|
-
if (!(0,
|
|
2410
|
+
if (!(0, import_node_fs9.existsSync)(dir)) return [];
|
|
2193
2411
|
const results = [];
|
|
2194
|
-
for (const entry of (0,
|
|
2412
|
+
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
2195
2413
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
2196
2414
|
const full = (0, import_node_path8.join)(dir, entry.name);
|
|
2197
2415
|
if (entry.isDirectory()) {
|
|
@@ -2234,7 +2452,7 @@ var urlLiteralScannerParser = {
|
|
|
2234
2452
|
for (const absPath of files) {
|
|
2235
2453
|
const sourceId = toNodeId3(srcDir, absPath);
|
|
2236
2454
|
if (!uiNodeIds.has(sourceId)) continue;
|
|
2237
|
-
const content = (0,
|
|
2455
|
+
const content = (0, import_node_fs9.readFileSync)(absPath, "utf-8");
|
|
2238
2456
|
let match;
|
|
2239
2457
|
URL_LITERAL_RE.lastIndex = 0;
|
|
2240
2458
|
while ((match = URL_LITERAL_RE.exec(content)) !== null) {
|
|
@@ -2265,7 +2483,7 @@ var urlLiteralScannerParser = {
|
|
|
2265
2483
|
};
|
|
2266
2484
|
|
|
2267
2485
|
// src/server/graph/parsers/static/static-values.ts
|
|
2268
|
-
var
|
|
2486
|
+
var import_node_fs10 = require("node:fs");
|
|
2269
2487
|
var import_node_path9 = require("node:path");
|
|
2270
2488
|
var parseCode = null;
|
|
2271
2489
|
function tryLoadTreeSitter() {
|
|
@@ -2304,14 +2522,14 @@ function extractEnumValues(rootDir) {
|
|
|
2304
2522
|
];
|
|
2305
2523
|
let content = "";
|
|
2306
2524
|
for (const p of schemaPaths) {
|
|
2307
|
-
if ((0,
|
|
2525
|
+
if ((0, import_node_fs10.existsSync)(p)) {
|
|
2308
2526
|
try {
|
|
2309
|
-
const stat = (0,
|
|
2527
|
+
const stat = (0, import_node_fs10.statSync)(p);
|
|
2310
2528
|
if (stat.isFile()) {
|
|
2311
|
-
content = (0,
|
|
2529
|
+
content = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
2312
2530
|
} else if (stat.isDirectory()) {
|
|
2313
|
-
const files = (0,
|
|
2314
|
-
content = files.map((f) => (0,
|
|
2531
|
+
const files = (0, import_node_fs10.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
|
|
2532
|
+
content = files.map((f) => (0, import_node_fs10.readFileSync)((0, import_node_path9.join)(p, f), "utf-8")).join("\n");
|
|
2315
2533
|
}
|
|
2316
2534
|
} catch {
|
|
2317
2535
|
continue;
|
|
@@ -2385,7 +2603,7 @@ function extractStringArrayFromNode(node) {
|
|
|
2385
2603
|
return values;
|
|
2386
2604
|
}
|
|
2387
2605
|
function findArrayDecl(root, varName) {
|
|
2388
|
-
function
|
|
2606
|
+
function walk4(node) {
|
|
2389
2607
|
if (node.type === "variable_declarator") {
|
|
2390
2608
|
const nameNode = node.childForFieldName("name");
|
|
2391
2609
|
const valueNode = node.childForFieldName("value");
|
|
@@ -2398,12 +2616,12 @@ function findArrayDecl(root, varName) {
|
|
|
2398
2616
|
}
|
|
2399
2617
|
}
|
|
2400
2618
|
for (const child of node.namedChildren) {
|
|
2401
|
-
const found =
|
|
2619
|
+
const found = walk4(child);
|
|
2402
2620
|
if (found) return found;
|
|
2403
2621
|
}
|
|
2404
2622
|
return null;
|
|
2405
2623
|
}
|
|
2406
|
-
return
|
|
2624
|
+
return walk4(root);
|
|
2407
2625
|
}
|
|
2408
2626
|
function extractObjectPropsRegex(objStr) {
|
|
2409
2627
|
const props = {};
|
|
@@ -2470,10 +2688,10 @@ function extractSeedData(rootDir) {
|
|
|
2470
2688
|
(0, import_node_path9.join)(rootDir, "prisma", "seed.ts"),
|
|
2471
2689
|
(0, import_node_path9.join)(rootDir, "prisma", "seed.js"),
|
|
2472
2690
|
(0, import_node_path9.join)(rootDir, "src", "server", "lib", "system-tags.ts")
|
|
2473
|
-
].filter(
|
|
2691
|
+
].filter(import_node_fs10.existsSync);
|
|
2474
2692
|
const useTreeSitter = tryLoadTreeSitter();
|
|
2475
2693
|
for (const filePath of seedFiles) {
|
|
2476
|
-
const content = (0,
|
|
2694
|
+
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
2477
2695
|
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
2478
2696
|
const seeded = detectSeededArrays(content, relPath);
|
|
2479
2697
|
let astRoot = null;
|
|
@@ -2568,9 +2786,9 @@ function extractSeedData(rootDir) {
|
|
|
2568
2786
|
return { nodes, edges };
|
|
2569
2787
|
}
|
|
2570
2788
|
function walkDir(dir, exts) {
|
|
2571
|
-
if (!(0,
|
|
2789
|
+
if (!(0, import_node_fs10.existsSync)(dir)) return [];
|
|
2572
2790
|
const results = [];
|
|
2573
|
-
for (const entry of (0,
|
|
2791
|
+
for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
|
|
2574
2792
|
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
|
|
2575
2793
|
const full = (0, import_node_path9.join)(dir, entry.name);
|
|
2576
2794
|
if (entry.isDirectory()) results.push(...walkDir(full, exts));
|
|
@@ -2581,9 +2799,9 @@ function walkDir(dir, exts) {
|
|
|
2581
2799
|
function extractConstants(rootDir) {
|
|
2582
2800
|
const nodes = [];
|
|
2583
2801
|
const srcDir = (0, import_node_path9.join)(rootDir, "src");
|
|
2584
|
-
if (!(0,
|
|
2802
|
+
if (!(0, import_node_fs10.existsSync)(srcDir)) return { nodes };
|
|
2585
2803
|
for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
|
|
2586
|
-
const content = (0,
|
|
2804
|
+
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
2587
2805
|
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
2588
2806
|
const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
|
|
2589
2807
|
let cm;
|
|
@@ -2617,7 +2835,7 @@ function extractConstants(rootDir) {
|
|
|
2617
2835
|
return { nodes };
|
|
2618
2836
|
}
|
|
2619
2837
|
function detect4(rootDir) {
|
|
2620
|
-
return (0,
|
|
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"));
|
|
2621
2839
|
}
|
|
2622
2840
|
function generate4(rootDir) {
|
|
2623
2841
|
const enumResult = extractEnumValues(rootDir);
|
|
@@ -2692,26 +2910,9 @@ var staticValuesParser = {
|
|
|
2692
2910
|
};
|
|
2693
2911
|
|
|
2694
2912
|
// src/server/graph/parsers/crosslayer/static-ref-scanner.ts
|
|
2695
|
-
var
|
|
2913
|
+
var import_node_fs11 = require("node:fs");
|
|
2696
2914
|
var import_node_path10 = require("node:path");
|
|
2697
2915
|
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
2916
|
var MIN_VALUE_LENGTH = 4;
|
|
2716
2917
|
var SKIP_VALUES = /* @__PURE__ */ new Set([
|
|
2717
2918
|
"true",
|
|
@@ -2854,11 +3055,11 @@ var staticRefScannerParser = {
|
|
|
2854
3055
|
if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
|
|
2855
3056
|
const srcDir = paths.srcDir;
|
|
2856
3057
|
const files = [
|
|
2857
|
-
...
|
|
2858
|
-
...
|
|
2859
|
-
...
|
|
2860
|
-
...
|
|
2861
|
-
...
|
|
3058
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "client"), [".ts", ".tsx"]),
|
|
3059
|
+
...walkWithIgnore(paths.appDir, [".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"])
|
|
2862
3063
|
];
|
|
2863
3064
|
const uiOutput = layerOutputs.get("ui");
|
|
2864
3065
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -2879,7 +3080,7 @@ var staticRefScannerParser = {
|
|
|
2879
3080
|
const sourceId = (0, import_node_path10.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
2880
3081
|
const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
|
|
2881
3082
|
if (!sourceLayer) continue;
|
|
2882
|
-
const content = (0,
|
|
3083
|
+
const content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
|
|
2883
3084
|
filesScanned++;
|
|
2884
3085
|
let fileRefs;
|
|
2885
3086
|
if (parseCode2) {
|
|
@@ -3126,9 +3327,9 @@ function applyCrossLayerResults(uiOutput, results) {
|
|
|
3126
3327
|
// src/server/graph/core/graph-builder.ts
|
|
3127
3328
|
function readGraphFromDisk(rootDir, layer) {
|
|
3128
3329
|
const filePath = (0, import_node_path12.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
3129
|
-
if (!(0,
|
|
3330
|
+
if (!(0, import_node_fs12.existsSync)(filePath)) return null;
|
|
3130
3331
|
try {
|
|
3131
|
-
return JSON.parse((0,
|
|
3332
|
+
return JSON.parse((0, import_node_fs12.readFileSync)(filePath, "utf-8"));
|
|
3132
3333
|
} catch {
|
|
3133
3334
|
return null;
|
|
3134
3335
|
}
|
|
@@ -3232,7 +3433,7 @@ init_config();
|
|
|
3232
3433
|
var import_node_path14 = require("node:path");
|
|
3233
3434
|
|
|
3234
3435
|
// src/server/graph/taggers/module-tagger.ts
|
|
3235
|
-
var
|
|
3436
|
+
var import_node_fs13 = require("node:fs");
|
|
3236
3437
|
var import_node_path13 = require("node:path");
|
|
3237
3438
|
function matchGlob(pattern, id) {
|
|
3238
3439
|
const patParts = pattern.split("/");
|
|
@@ -3273,11 +3474,11 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
|
|
|
3273
3474
|
for (const base of searchDirs) {
|
|
3274
3475
|
for (const convention of conventionDirs) {
|
|
3275
3476
|
const dir = (0, import_node_path13.join)(base, convention);
|
|
3276
|
-
if (!(0,
|
|
3477
|
+
if (!(0, import_node_fs13.existsSync)(dir)) continue;
|
|
3277
3478
|
try {
|
|
3278
|
-
const stat = (0,
|
|
3479
|
+
const stat = (0, import_node_fs13.statSync)(dir);
|
|
3279
3480
|
if (!stat.isDirectory()) continue;
|
|
3280
|
-
const entries = (0,
|
|
3481
|
+
const entries = (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
|
|
3281
3482
|
if (entries.length > 0) {
|
|
3282
3483
|
const relPath = dir.replace(rootDir + "/", "").replace(rootDir + "\\", "");
|
|
3283
3484
|
result.set(relPath, entries);
|
|
@@ -3594,7 +3795,7 @@ function createTaggerRegistry(config, rootDir) {
|
|
|
3594
3795
|
}
|
|
3595
3796
|
|
|
3596
3797
|
// src/server/graph/core/tag-store.ts
|
|
3597
|
-
var
|
|
3798
|
+
var import_node_fs14 = require("node:fs");
|
|
3598
3799
|
var import_node_path15 = require("node:path");
|
|
3599
3800
|
var TAGS_FILENAME = "tags.json";
|
|
3600
3801
|
var GRAPHS_DIR = ".launchsecure/graphs";
|
|
@@ -3604,14 +3805,14 @@ function tagsFilePath(rootDir) {
|
|
|
3604
3805
|
}
|
|
3605
3806
|
function readTagStore(rootDir) {
|
|
3606
3807
|
const filePath = tagsFilePath(rootDir);
|
|
3607
|
-
if (!(0,
|
|
3608
|
-
const stat = (0,
|
|
3808
|
+
if (!(0, import_node_fs14.existsSync)(filePath)) return {};
|
|
3809
|
+
const stat = (0, import_node_fs14.statSync)(filePath);
|
|
3609
3810
|
const cached = tagCache.get(filePath);
|
|
3610
3811
|
if (cached && cached.mtimeMs === stat.mtimeMs) {
|
|
3611
3812
|
return cached.store;
|
|
3612
3813
|
}
|
|
3613
3814
|
try {
|
|
3614
|
-
const content = (0,
|
|
3815
|
+
const content = (0, import_node_fs14.readFileSync)(filePath, "utf-8");
|
|
3615
3816
|
const store = JSON.parse(content);
|
|
3616
3817
|
tagCache.set(filePath, { mtimeMs: stat.mtimeMs, store });
|
|
3617
3818
|
return store;
|
|
@@ -3622,14 +3823,14 @@ function readTagStore(rootDir) {
|
|
|
3622
3823
|
function writeTagStore(rootDir, store) {
|
|
3623
3824
|
const filePath = tagsFilePath(rootDir);
|
|
3624
3825
|
const dir = (0, import_node_path15.dirname)(filePath);
|
|
3625
|
-
(0,
|
|
3826
|
+
(0, import_node_fs14.mkdirSync)(dir, { recursive: true });
|
|
3626
3827
|
const cleaned = {};
|
|
3627
3828
|
for (const [nodeId, tags] of Object.entries(store)) {
|
|
3628
3829
|
if (Object.keys(tags).length > 0) {
|
|
3629
3830
|
cleaned[nodeId] = tags;
|
|
3630
3831
|
}
|
|
3631
3832
|
}
|
|
3632
|
-
(0,
|
|
3833
|
+
(0, import_node_fs14.writeFileSync)(filePath, JSON.stringify(cleaned, null, 2) + "\n", "utf-8");
|
|
3633
3834
|
tagCache.delete(filePath);
|
|
3634
3835
|
}
|
|
3635
3836
|
function setTag(rootDir, nodeId, key, value) {
|
|
@@ -3653,8 +3854,8 @@ init_ts_extractor();
|
|
|
3653
3854
|
var GRAPHS_DIR2 = ".launchsecure/graphs";
|
|
3654
3855
|
function getAvailableLayers(rootDir) {
|
|
3655
3856
|
const dir = (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
|
|
3656
|
-
if (!(0,
|
|
3657
|
-
return (0,
|
|
3857
|
+
if (!(0, import_node_fs15.existsSync)(dir)) return [];
|
|
3858
|
+
return (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
|
|
3658
3859
|
}
|
|
3659
3860
|
var graphCache = /* @__PURE__ */ new Map();
|
|
3660
3861
|
var taggedCache = /* @__PURE__ */ new Map();
|
|
@@ -3668,8 +3869,8 @@ function tagsFilePath2(rootDir) {
|
|
|
3668
3869
|
return (0, import_node_path16.join)(graphsDir(rootDir), "tags.json");
|
|
3669
3870
|
}
|
|
3670
3871
|
function getMtimeMs(filePath) {
|
|
3671
|
-
if (!(0,
|
|
3672
|
-
return (0,
|
|
3872
|
+
if (!(0, import_node_fs15.existsSync)(filePath)) return 0;
|
|
3873
|
+
return (0, import_node_fs15.statSync)(filePath).mtimeMs;
|
|
3673
3874
|
}
|
|
3674
3875
|
function invalidateCache(filePath) {
|
|
3675
3876
|
graphCache.delete(filePath);
|
|
@@ -3708,20 +3909,20 @@ function applyTags(graph, layer, rootDir) {
|
|
|
3708
3909
|
}
|
|
3709
3910
|
function readGraphRaw(rootDir, layer) {
|
|
3710
3911
|
const filePath = graphFilePath(rootDir, layer);
|
|
3711
|
-
if (!(0,
|
|
3712
|
-
const stat = (0,
|
|
3912
|
+
if (!(0, import_node_fs15.existsSync)(filePath)) return null;
|
|
3913
|
+
const stat = (0, import_node_fs15.statSync)(filePath);
|
|
3713
3914
|
const cached = graphCache.get(filePath);
|
|
3714
3915
|
if (cached && cached.mtimeMs === stat.mtimeMs) {
|
|
3715
3916
|
return cached.graph;
|
|
3716
3917
|
}
|
|
3717
|
-
const content = (0,
|
|
3918
|
+
const content = (0, import_node_fs15.readFileSync)(filePath, "utf-8");
|
|
3718
3919
|
const graph = JSON.parse(content);
|
|
3719
3920
|
graphCache.set(filePath, { mtimeMs: stat.mtimeMs, graph });
|
|
3720
3921
|
return graph;
|
|
3721
3922
|
}
|
|
3722
3923
|
function readGraph(rootDir, layer) {
|
|
3723
3924
|
const rawFilePath = graphFilePath(rootDir, layer);
|
|
3724
|
-
if (!(0,
|
|
3925
|
+
if (!(0, import_node_fs15.existsSync)(rawFilePath)) return null;
|
|
3725
3926
|
const rawMtime = getMtimeMs(rawFilePath);
|
|
3726
3927
|
const tagsMtime = getMtimeMs(tagsFilePath2(rootDir));
|
|
3727
3928
|
const cacheKey = `${rootDir}:${layer}`;
|
|
@@ -3751,11 +3952,11 @@ async function generateGraph(rootDir, layer) {
|
|
|
3751
3952
|
mutationMethods: config.parsers?.patterns?.mutationMethods
|
|
3752
3953
|
});
|
|
3753
3954
|
const dir = graphsDir(rootDir);
|
|
3754
|
-
(0,
|
|
3955
|
+
(0, import_node_fs15.mkdirSync)(dir, { recursive: true });
|
|
3755
3956
|
const results = layer ? [generateLayer(rootDir, layer)].filter((r) => r !== null) : generateAll(rootDir);
|
|
3756
3957
|
for (const result of results) {
|
|
3757
3958
|
const filePath = graphFilePath(rootDir, result.layer);
|
|
3758
|
-
(0,
|
|
3959
|
+
(0, import_node_fs15.writeFileSync)(filePath, JSON.stringify(result.output, null, 2) + "\n", "utf-8");
|
|
3759
3960
|
invalidateCache(filePath);
|
|
3760
3961
|
invalidateTaggedCache(rootDir, result.layer);
|
|
3761
3962
|
}
|
|
@@ -3764,7 +3965,7 @@ async function generateGraph(rootDir, layer) {
|
|
|
3764
3965
|
|
|
3765
3966
|
// src/server/lockfile.ts
|
|
3766
3967
|
var import_node_child_process = require("node:child_process");
|
|
3767
|
-
var
|
|
3968
|
+
var import_node_fs16 = require("node:fs");
|
|
3768
3969
|
var import_node_os = require("node:os");
|
|
3769
3970
|
var import_node_path17 = require("node:path");
|
|
3770
3971
|
function lockDir(projectRoot) {
|
|
@@ -3780,12 +3981,12 @@ var _activeProjectRoot;
|
|
|
3780
3981
|
function readLock(projectRoot) {
|
|
3781
3982
|
const root = projectRoot ?? _activeProjectRoot;
|
|
3782
3983
|
const p = lockPath(root);
|
|
3783
|
-
if (!(0,
|
|
3984
|
+
if (!(0, import_node_fs16.existsSync)(p)) {
|
|
3784
3985
|
if (root) {
|
|
3785
3986
|
const globalP = lockPath();
|
|
3786
|
-
if ((0,
|
|
3987
|
+
if ((0, import_node_fs16.existsSync)(globalP)) {
|
|
3787
3988
|
try {
|
|
3788
|
-
const data = JSON.parse((0,
|
|
3989
|
+
const data = JSON.parse((0, import_node_fs16.readFileSync)(globalP, "utf-8"));
|
|
3789
3990
|
if (typeof data.pid === "number" && typeof data.port === "number" && data.cwd === root) {
|
|
3790
3991
|
return data;
|
|
3791
3992
|
}
|
|
@@ -3796,7 +3997,7 @@ function readLock(projectRoot) {
|
|
|
3796
3997
|
return null;
|
|
3797
3998
|
}
|
|
3798
3999
|
try {
|
|
3799
|
-
const data = JSON.parse((0,
|
|
4000
|
+
const data = JSON.parse((0, import_node_fs16.readFileSync)(p, "utf-8"));
|
|
3800
4001
|
if (typeof data.pid !== "number" || typeof data.port !== "number") return null;
|
|
3801
4002
|
return data;
|
|
3802
4003
|
} catch {
|
|
@@ -3833,7 +4034,7 @@ function getLiveLock(projectRoot) {
|
|
|
3833
4034
|
const live = listenerPid !== null ? listenerPid === lock.pid : isPidAlive(lock.pid);
|
|
3834
4035
|
if (!live) {
|
|
3835
4036
|
try {
|
|
3836
|
-
(0,
|
|
4037
|
+
(0, import_node_fs16.unlinkSync)(lockPath(root));
|
|
3837
4038
|
} catch {
|
|
3838
4039
|
}
|
|
3839
4040
|
return null;
|
|
@@ -3842,14 +4043,14 @@ function getLiveLock(projectRoot) {
|
|
|
3842
4043
|
}
|
|
3843
4044
|
function writeLock(data, projectRoot) {
|
|
3844
4045
|
const root = projectRoot ?? _activeProjectRoot;
|
|
3845
|
-
(0,
|
|
3846
|
-
(0,
|
|
4046
|
+
(0, import_node_fs16.mkdirSync)(lockDir(root), { recursive: true });
|
|
4047
|
+
(0, import_node_fs16.writeFileSync)(lockPath(root), JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
3847
4048
|
if (root) _activeProjectRoot = root;
|
|
3848
4049
|
}
|
|
3849
4050
|
function clearLock(projectRoot) {
|
|
3850
4051
|
const root = projectRoot ?? _activeProjectRoot;
|
|
3851
4052
|
try {
|
|
3852
|
-
(0,
|
|
4053
|
+
(0, import_node_fs16.unlinkSync)(lockPath(root));
|
|
3853
4054
|
} catch {
|
|
3854
4055
|
}
|
|
3855
4056
|
}
|
|
@@ -3858,13 +4059,13 @@ function clearLock(projectRoot) {
|
|
|
3858
4059
|
init_config();
|
|
3859
4060
|
|
|
3860
4061
|
// src/server/graph/core/audit-core.ts
|
|
3861
|
-
var
|
|
4062
|
+
var import_node_fs17 = require("node:fs");
|
|
3862
4063
|
var import_node_path18 = require("node:path");
|
|
3863
4064
|
function readGraphFile(rootDir, layer) {
|
|
3864
4065
|
const filePath = (0, import_node_path18.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
3865
|
-
if (!(0,
|
|
4066
|
+
if (!(0, import_node_fs17.existsSync)(filePath)) return null;
|
|
3866
4067
|
try {
|
|
3867
|
-
return JSON.parse((0,
|
|
4068
|
+
return JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
|
|
3868
4069
|
} catch {
|
|
3869
4070
|
return null;
|
|
3870
4071
|
}
|
|
@@ -3910,8 +4111,8 @@ function checkUnprotectedRoutes(rootDir) {
|
|
|
3910
4111
|
if (!api) return buildReport("api", "unprotected_routes", findings);
|
|
3911
4112
|
const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
3912
4113
|
let routePermsContent = "";
|
|
3913
|
-
if ((0,
|
|
3914
|
-
routePermsContent = (0,
|
|
4114
|
+
if ((0, import_node_fs17.existsSync)(routePermsPath)) {
|
|
4115
|
+
routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
|
|
3915
4116
|
}
|
|
3916
4117
|
const registeredRoutes = /* @__PURE__ */ new Set();
|
|
3917
4118
|
const routeEntryRe = /path:\s*'([^']+)'/g;
|
|
@@ -3990,8 +4191,8 @@ function checkUnenforcedPermissions(rootDir) {
|
|
|
3990
4191
|
const permissions = staticGraph.nodes.filter((n) => n.type === "seed_permission").map((n) => ({ id: n.id, key: n.value, name: n.name }));
|
|
3991
4192
|
const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
3992
4193
|
let routePermsContent = "";
|
|
3993
|
-
if ((0,
|
|
3994
|
-
routePermsContent = (0,
|
|
4194
|
+
if ((0, import_node_fs17.existsSync)(routePermsPath)) {
|
|
4195
|
+
routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
|
|
3995
4196
|
}
|
|
3996
4197
|
for (const perm of permissions) {
|
|
3997
4198
|
const regex = new RegExp(`permission:\\s*['"]${perm.key}['"]`);
|
|
@@ -4022,8 +4223,8 @@ function checkHardcodedValues(rootDir) {
|
|
|
4022
4223
|
for (const node of api.nodes) {
|
|
4023
4224
|
if (node.type !== "endpoint") continue;
|
|
4024
4225
|
const filePath = (0, import_node_path18.join)(rootDir, "src", node.id);
|
|
4025
|
-
if (!(0,
|
|
4026
|
-
const content = (0,
|
|
4226
|
+
if (!(0, import_node_fs17.existsSync)(filePath)) continue;
|
|
4227
|
+
const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
|
|
4027
4228
|
let m;
|
|
4028
4229
|
allCapsRe.lastIndex = 0;
|
|
4029
4230
|
while ((m = allCapsRe.exec(content)) !== null) {
|
|
@@ -4154,14 +4355,14 @@ function findProjectRoot(startDir) {
|
|
|
4154
4355
|
let dir = startDir;
|
|
4155
4356
|
for (let i = 0; i < 8; i++) {
|
|
4156
4357
|
const graphsDir2 = import_node_path19.default.join(dir, ".launchsecure", "graphs");
|
|
4157
|
-
if (
|
|
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;
|
|
4158
4359
|
const parent = import_node_path19.default.dirname(dir);
|
|
4159
4360
|
if (parent === dir) break;
|
|
4160
4361
|
dir = parent;
|
|
4161
4362
|
}
|
|
4162
4363
|
dir = startDir;
|
|
4163
4364
|
for (let i = 0; i < 8; i++) {
|
|
4164
|
-
if (
|
|
4365
|
+
if (import_node_fs18.default.existsSync(import_node_path19.default.join(dir, ".git"))) return dir;
|
|
4165
4366
|
const parent = import_node_path19.default.dirname(dir);
|
|
4166
4367
|
if (parent === dir) break;
|
|
4167
4368
|
dir = parent;
|
|
@@ -4222,16 +4423,16 @@ async function buildMergedGraph(root) {
|
|
|
4222
4423
|
};
|
|
4223
4424
|
}
|
|
4224
4425
|
function serveStatic(res, filePath) {
|
|
4225
|
-
if (!
|
|
4426
|
+
if (!import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) return false;
|
|
4226
4427
|
const ext = import_node_path19.default.extname(filePath).toLowerCase();
|
|
4227
4428
|
const mime = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
4228
4429
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
|
|
4229
|
-
|
|
4430
|
+
import_node_fs18.default.createReadStream(filePath).pipe(res);
|
|
4230
4431
|
return true;
|
|
4231
4432
|
}
|
|
4232
4433
|
function serveIndex(res, clientDir) {
|
|
4233
4434
|
const indexPath = import_node_path19.default.join(clientDir, "index.html");
|
|
4234
|
-
if (!
|
|
4435
|
+
if (!import_node_fs18.default.existsSync(indexPath)) {
|
|
4235
4436
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
4236
4437
|
res.end(`LaunchChart client bundle not found at ${clientDir}. Run 'npm run build:chart-client'.`);
|
|
4237
4438
|
return;
|
|
@@ -4239,14 +4440,14 @@ function serveIndex(res, clientDir) {
|
|
|
4239
4440
|
serveStatic(res, indexPath);
|
|
4240
4441
|
}
|
|
4241
4442
|
function tryListen(server, port) {
|
|
4242
|
-
return new Promise((
|
|
4443
|
+
return new Promise((resolve4, reject) => {
|
|
4243
4444
|
const onError = (err) => {
|
|
4244
4445
|
server.off("listening", onListening);
|
|
4245
4446
|
reject(err);
|
|
4246
4447
|
};
|
|
4247
4448
|
const onListening = () => {
|
|
4248
4449
|
server.off("error", onError);
|
|
4249
|
-
|
|
4450
|
+
resolve4(port);
|
|
4250
4451
|
};
|
|
4251
4452
|
server.once("error", onError);
|
|
4252
4453
|
server.once("listening", onListening);
|
|
@@ -4300,10 +4501,10 @@ async function startChartServer(opts = {}) {
|
|
|
4300
4501
|
if (req.method === "GET" && url2.pathname === "/api/projects") {
|
|
4301
4502
|
const projectList = projects.length > 0 ? projects.map((p) => {
|
|
4302
4503
|
const absRoot = import_node_path19.default.resolve(projectRoot, p.root);
|
|
4303
|
-
const hasGraphs =
|
|
4304
|
-
const
|
|
4305
|
-
return { name: p.name, root: p.root, hasGraphs, hasNextConfig
|
|
4306
|
-
}) : [{ name: import_node_path19.default.basename(projectRoot), root: ".", hasGraphs:
|
|
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"));
|
|
4506
|
+
return { name: p.name, root: p.root, hasGraphs, hasNextConfig };
|
|
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 }];
|
|
4307
4508
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4308
4509
|
res.end(JSON.stringify({ projects: projectList, monorepoRoot: projectRoot }));
|
|
4309
4510
|
return;
|
|
@@ -4355,14 +4556,14 @@ async function startChartServer(opts = {}) {
|
|
|
4355
4556
|
return;
|
|
4356
4557
|
}
|
|
4357
4558
|
const filePath = import_node_path19.default.join(reqRoot, relPath);
|
|
4358
|
-
if (!filePath.startsWith(reqRoot) || !
|
|
4559
|
+
if (!filePath.startsWith(reqRoot) || !import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) {
|
|
4359
4560
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
4360
4561
|
res.end(JSON.stringify({ error: "File not found" }));
|
|
4361
4562
|
return;
|
|
4362
4563
|
}
|
|
4363
4564
|
const ext = import_node_path19.default.extname(filePath).toLowerCase();
|
|
4364
4565
|
const langMap = { ".ts": "typescript", ".tsx": "tsx", ".js": "javascript", ".jsx": "jsx", ".prisma": "prisma", ".json": "json", ".css": "css" };
|
|
4365
|
-
const content =
|
|
4566
|
+
const content = import_node_fs18.default.readFileSync(filePath, "utf-8");
|
|
4366
4567
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4367
4568
|
res.end(JSON.stringify({ content, language: langMap[ext] ?? "text", path: relPath }));
|
|
4368
4569
|
return;
|
|
@@ -4405,7 +4606,7 @@ async function startChartServer(opts = {}) {
|
|
|
4405
4606
|
try {
|
|
4406
4607
|
const newConfig = JSON.parse(body);
|
|
4407
4608
|
const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
|
|
4408
|
-
|
|
4609
|
+
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(newConfig, null, 2) + "\n", "utf-8");
|
|
4409
4610
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4410
4611
|
res.end(JSON.stringify({ ok: true }));
|
|
4411
4612
|
} catch (err) {
|
|
@@ -4439,7 +4640,7 @@ async function startChartServer(opts = {}) {
|
|
|
4439
4640
|
const config2 = loadConfig(reqRoot);
|
|
4440
4641
|
config2.taggers = taggerConfig;
|
|
4441
4642
|
const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
|
|
4442
|
-
|
|
4643
|
+
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
4443
4644
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4444
4645
|
res.end(JSON.stringify({ ok: true }));
|
|
4445
4646
|
} catch (err) {
|
|
@@ -4506,16 +4707,23 @@ async function startChartServer(opts = {}) {
|
|
|
4506
4707
|
const paths = resolveProjectPaths(reqRoot, config2);
|
|
4507
4708
|
const overrides = {
|
|
4508
4709
|
appDir: !!config2.paths?.appDir,
|
|
4509
|
-
dbDir: !!config2.paths?.dbDir
|
|
4710
|
+
dbDir: !!config2.paths?.dbDir,
|
|
4711
|
+
srcRoots: !!(config2.paths?.srcRoots && config2.paths.srcRoots.length > 0)
|
|
4510
4712
|
};
|
|
4713
|
+
const relFromRoot = (abs) => import_node_path19.default.relative(reqRoot, abs) || ".";
|
|
4511
4714
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4512
4715
|
res.end(JSON.stringify({
|
|
4513
4716
|
projectRoot: reqRoot,
|
|
4514
4717
|
detected: paths ? {
|
|
4515
|
-
srcDir:
|
|
4516
|
-
appDir:
|
|
4517
|
-
apiDir:
|
|
4518
|
-
dbDir: paths.dbDir ?
|
|
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)
|
|
4519
4727
|
} : null,
|
|
4520
4728
|
overrides,
|
|
4521
4729
|
isOverride: overrides.appDir
|
|
@@ -4532,7 +4740,7 @@ async function startChartServer(opts = {}) {
|
|
|
4532
4740
|
return;
|
|
4533
4741
|
}
|
|
4534
4742
|
try {
|
|
4535
|
-
const entries =
|
|
4743
|
+
const entries = import_node_fs18.default.readdirSync(abs, { withFileTypes: true });
|
|
4536
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();
|
|
4537
4745
|
const parent = abs !== twoUp ? import_node_path19.default.dirname(abs) : null;
|
|
4538
4746
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -4563,7 +4771,7 @@ async function startChartServer(opts = {}) {
|
|
|
4563
4771
|
const config2 = loadConfig(projectRoot);
|
|
4564
4772
|
config2.projects = newProjects.length > 0 ? newProjects : void 0;
|
|
4565
4773
|
const configPath = import_node_path19.default.join(projectRoot, ".launchchart.json");
|
|
4566
|
-
|
|
4774
|
+
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
4567
4775
|
projects.length = 0;
|
|
4568
4776
|
if (config2.projects) projects.push(...config2.projects);
|
|
4569
4777
|
res.writeHead(200, { "Content-Type": "application/json" });
|