@launchsecure/launch-kit 0.0.18 → 0.0.20
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-C8ANseEa.js +441 -0
- package/dist/chart-client/index.html +1 -1
- package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-DsfOm3t_.js} +1 -1
- package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-NJuvkBv1.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-BgrcgZs0.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-C3XoLi15.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-FX2PjLfb.js} +1 -1
- package/dist/deck-client/assets/channel-ChQjD1T1.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-D0aqsJV0.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-7qRCCAgK.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-DfHG-iqb.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-DrR52j3B.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-D5KSGATB.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-M7hsLRNU.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-1ynAWO2m.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.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-Bqp3p68D.js → cose-bilkent-S5V4N54A-BcMwozS2.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-DtKMhl_1.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-1plH69us.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-D_o-BHO3.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-ClZ1LIx6.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-B8dKHfRh.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-CY2aCH7-.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-DZZWHti8.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-OwGGa6Lu.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-GKyWD4Qt.js} +1 -1
- package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-CORzYQdB.js} +1 -1
- package/dist/deck-client/assets/{index-BfIfJXmS.js → index-hiIpM7EP.js} +3 -3
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-DmgqJCcF.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-D-1v7knu.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-CYrGQE7b.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-BJFDWiH-.js} +1 -1
- package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-BTFFcaxF.js} +1 -1
- package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-DAbl6COS.js} +1 -1
- package/dist/deck-client/assets/{min-CbUksbuI.js → min-oWHBrFBm.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-BTCB0VLO.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-CUZChWNA.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-4M1Um_e4.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-DLzQZ0B3.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-DcNgzV3E.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-CAcI2vC9.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.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-oUeZhRns.js → timeline-definition-GMOUNBTQ-D8zrit4U.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-C4SuFPgo.js} +1 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-B3F-Olcq.js +162 -0
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-kj73r6f-.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-CC_d_Ey3.js} +1 -1
- package/dist/deck-client/index.html +1 -1
- package/dist/server/chart-serve.js +549 -207
- package/dist/server/cli.js +541 -206
- package/dist/server/council-entry.js +0 -0
- package/dist/server/deck-server/deck-mcp-entry.js +0 -0
- package/dist/server/fb-wizard.js +0 -0
- package/dist/server/graph-mcp-entry.js +587 -244
- package/dist/server/server/cli.js +0 -0
- package/dist/server/server/fb-wizard.js +0 -0
- package/dist/server/server/graph-mcp-entry.js +0 -0
- package/package.json +18 -17
- package/dist/chart-client/assets/index-D7x8nz-H.js +0 -441
- package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
- package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
- package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
package/dist/server/cli.js
CHANGED
|
@@ -1731,7 +1731,7 @@ var require_usage_reader = __commonJS({
|
|
|
1731
1731
|
async readJsonlFile(filePath, cutoffTime) {
|
|
1732
1732
|
const entries = [];
|
|
1733
1733
|
const fileProcessedEntries = /* @__PURE__ */ new Set();
|
|
1734
|
-
return new Promise((
|
|
1734
|
+
return new Promise((resolve4) => {
|
|
1735
1735
|
const rl = readline.createInterface({
|
|
1736
1736
|
input: createReadStream(filePath),
|
|
1737
1737
|
crlfDelay: Infinity
|
|
@@ -1789,11 +1789,11 @@ var require_usage_reader = __commonJS({
|
|
|
1789
1789
|
}
|
|
1790
1790
|
});
|
|
1791
1791
|
rl.on("close", () => {
|
|
1792
|
-
|
|
1792
|
+
resolve4(entries);
|
|
1793
1793
|
});
|
|
1794
1794
|
rl.on("error", (error) => {
|
|
1795
1795
|
console.error("Error reading file:", filePath, error);
|
|
1796
|
-
|
|
1796
|
+
resolve4(entries);
|
|
1797
1797
|
});
|
|
1798
1798
|
});
|
|
1799
1799
|
}
|
|
@@ -3591,7 +3591,7 @@ var require_src = __commonJS({
|
|
|
3591
3591
|
if (session.active) throw new Error(`Agent already running in session ${sessionId}`);
|
|
3592
3592
|
const { command, args = [], env = {} } = options;
|
|
3593
3593
|
if (!command) throw new Error("startScriptInSession requires a command");
|
|
3594
|
-
return new Promise((
|
|
3594
|
+
return new Promise((resolve4, reject) => {
|
|
3595
3595
|
this.scriptBridge.startSession(sessionId, {
|
|
3596
3596
|
command,
|
|
3597
3597
|
args,
|
|
@@ -3613,7 +3613,7 @@ var require_src = __commonJS({
|
|
|
3613
3613
|
session.lastActivity = /* @__PURE__ */ new Date();
|
|
3614
3614
|
this.broadcastToSession(sessionId, { type: "script_stopped", sessionId });
|
|
3615
3615
|
if (exitCode === 0) {
|
|
3616
|
-
|
|
3616
|
+
resolve4({ code: exitCode, signal });
|
|
3617
3617
|
} else {
|
|
3618
3618
|
reject(new Error(`Script exited with code ${exitCode}`));
|
|
3619
3619
|
}
|
|
@@ -5908,7 +5908,7 @@ var PostImplLaunchExecutor = class {
|
|
|
5908
5908
|
return 3001;
|
|
5909
5909
|
}
|
|
5910
5910
|
startDevServer(port, databaseUrl) {
|
|
5911
|
-
return new Promise((
|
|
5911
|
+
return new Promise((resolve4) => {
|
|
5912
5912
|
const env = { ...process.env, PORT: String(port), ...databaseUrl ? { DATABASE_URL: databaseUrl } : {} };
|
|
5913
5913
|
this.devProcess = (0, import_child_process3.spawn)("npm", ["run", "dev"], {
|
|
5914
5914
|
cwd: this.workingDir,
|
|
@@ -5920,7 +5920,7 @@ var PostImplLaunchExecutor = class {
|
|
|
5920
5920
|
const timeout = setTimeout(() => {
|
|
5921
5921
|
if (!resolved) {
|
|
5922
5922
|
resolved = true;
|
|
5923
|
-
this.healthCheck(port).then(
|
|
5923
|
+
this.healthCheck(port).then(resolve4);
|
|
5924
5924
|
}
|
|
5925
5925
|
}, 15e3);
|
|
5926
5926
|
const onData = (data) => {
|
|
@@ -5929,7 +5929,7 @@ var PostImplLaunchExecutor = class {
|
|
|
5929
5929
|
if (!resolved) {
|
|
5930
5930
|
resolved = true;
|
|
5931
5931
|
clearTimeout(timeout);
|
|
5932
|
-
|
|
5932
|
+
resolve4(true);
|
|
5933
5933
|
}
|
|
5934
5934
|
}
|
|
5935
5935
|
};
|
|
@@ -5940,7 +5940,7 @@ var PostImplLaunchExecutor = class {
|
|
|
5940
5940
|
if (!resolved) {
|
|
5941
5941
|
resolved = true;
|
|
5942
5942
|
clearTimeout(timeout);
|
|
5943
|
-
|
|
5943
|
+
resolve4(false);
|
|
5944
5944
|
}
|
|
5945
5945
|
});
|
|
5946
5946
|
this.devProcess.unref();
|
|
@@ -6963,15 +6963,15 @@ ${links}
|
|
|
6963
6963
|
|
|
6964
6964
|
// src/server/graph/index.ts
|
|
6965
6965
|
var import_node_fs15 = require("node:fs");
|
|
6966
|
-
var
|
|
6966
|
+
var import_node_path16 = require("node:path");
|
|
6967
6967
|
|
|
6968
6968
|
// src/server/graph/core/graph-builder.ts
|
|
6969
6969
|
var import_node_fs12 = require("node:fs");
|
|
6970
|
-
var
|
|
6970
|
+
var import_node_path12 = require("node:path");
|
|
6971
6971
|
init_config();
|
|
6972
6972
|
|
|
6973
6973
|
// src/server/graph/core/parser-registry.ts
|
|
6974
|
-
var
|
|
6974
|
+
var import_node_path11 = require("node:path");
|
|
6975
6975
|
|
|
6976
6976
|
// src/server/graph/parsers/ts/typescript-project.ts
|
|
6977
6977
|
var import_node_fs5 = require("node:fs");
|
|
@@ -6979,35 +6979,12 @@ var import_node_path5 = require("node:path");
|
|
|
6979
6979
|
init_config();
|
|
6980
6980
|
|
|
6981
6981
|
// src/server/graph/core/resolve-paths.ts
|
|
6982
|
-
var import_node_fs2 = require("node:fs");
|
|
6983
|
-
var import_node_path2 = require("node:path");
|
|
6984
|
-
function detectDbDir(rootDir, config) {
|
|
6985
|
-
if (config.paths?.dbDir) return (0, import_node_path2.join)(rootDir, config.paths.dbDir);
|
|
6986
|
-
const prismaDir = (0, import_node_path2.join)(rootDir, "prisma");
|
|
6987
|
-
if ((0, import_node_fs2.existsSync)(prismaDir)) return prismaDir;
|
|
6988
|
-
return null;
|
|
6989
|
-
}
|
|
6990
|
-
function resolveProjectPaths(rootDir, config) {
|
|
6991
|
-
const dbDir = detectDbDir(rootDir, config);
|
|
6992
|
-
if (config.paths?.appDir) {
|
|
6993
|
-
const appDir = (0, import_node_path2.join)(rootDir, config.paths.appDir);
|
|
6994
|
-
const srcDir = config.paths.srcDir ? (0, import_node_path2.join)(rootDir, config.paths.srcDir) : (0, import_node_path2.dirname)(appDir);
|
|
6995
|
-
return { srcDir, appDir, apiDir: (0, import_node_path2.join)(appDir, "api"), dbDir };
|
|
6996
|
-
}
|
|
6997
|
-
const srcApp = (0, import_node_path2.join)(rootDir, "src", "app");
|
|
6998
|
-
if ((0, import_node_fs2.existsSync)(srcApp)) {
|
|
6999
|
-
return { srcDir: (0, import_node_path2.join)(rootDir, "src"), appDir: srcApp, apiDir: (0, import_node_path2.join)(srcApp, "api"), dbDir };
|
|
7000
|
-
}
|
|
7001
|
-
const rootApp = (0, import_node_path2.join)(rootDir, "app");
|
|
7002
|
-
if ((0, import_node_fs2.existsSync)(rootApp)) {
|
|
7003
|
-
return { srcDir: rootDir, appDir: rootApp, apiDir: (0, import_node_path2.join)(rootApp, "api"), dbDir };
|
|
7004
|
-
}
|
|
7005
|
-
return null;
|
|
7006
|
-
}
|
|
7007
|
-
|
|
7008
|
-
// src/server/graph/core/walk.ts
|
|
7009
6982
|
var import_node_fs3 = require("node:fs");
|
|
7010
6983
|
var import_node_path3 = require("node:path");
|
|
6984
|
+
|
|
6985
|
+
// src/server/graph/core/walk.ts
|
|
6986
|
+
var import_node_fs2 = require("node:fs");
|
|
6987
|
+
var import_node_path2 = require("node:path");
|
|
7011
6988
|
var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
7012
6989
|
"node_modules",
|
|
7013
6990
|
".git",
|
|
@@ -7023,12 +7000,12 @@ var DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
|
7023
7000
|
]);
|
|
7024
7001
|
function walk(dir, exts) {
|
|
7025
7002
|
const results = [];
|
|
7026
|
-
if (!(0,
|
|
7027
|
-
for (const entry of (0,
|
|
7028
|
-
const full = (0,
|
|
7003
|
+
if (!(0, import_node_fs2.existsSync)(dir)) return results;
|
|
7004
|
+
for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
|
|
7005
|
+
const full = (0, import_node_path2.join)(dir, entry.name);
|
|
7029
7006
|
if (entry.isDirectory()) {
|
|
7030
7007
|
results.push(...walk(full, exts));
|
|
7031
|
-
} else if (exts.includes((0,
|
|
7008
|
+
} else if (exts.includes((0, import_node_path2.extname)(entry.name))) {
|
|
7032
7009
|
results.push(full);
|
|
7033
7010
|
}
|
|
7034
7011
|
}
|
|
@@ -7036,19 +7013,205 @@ function walk(dir, exts) {
|
|
|
7036
7013
|
}
|
|
7037
7014
|
function walkWithIgnore(dir, exts, opts = {}) {
|
|
7038
7015
|
const results = [];
|
|
7039
|
-
if (!(0,
|
|
7016
|
+
if (!(0, import_node_fs2.existsSync)(dir)) return results;
|
|
7040
7017
|
const skip = opts.extraIgnore ? /* @__PURE__ */ new Set([...DEFAULT_IGNORE_DIRS, ...opts.extraIgnore]) : DEFAULT_IGNORE_DIRS;
|
|
7041
|
-
for (const entry of (0,
|
|
7018
|
+
for (const entry of (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true })) {
|
|
7042
7019
|
if (entry.isDirectory()) {
|
|
7043
7020
|
if (skip.has(entry.name)) continue;
|
|
7044
|
-
results.push(...walkWithIgnore((0,
|
|
7045
|
-
} else if (exts.includes((0,
|
|
7046
|
-
results.push((0,
|
|
7021
|
+
results.push(...walkWithIgnore((0, import_node_path2.join)(dir, entry.name), exts, opts));
|
|
7022
|
+
} else if (exts.includes((0, import_node_path2.extname)(entry.name))) {
|
|
7023
|
+
results.push((0, import_node_path2.join)(dir, entry.name));
|
|
7047
7024
|
}
|
|
7048
7025
|
}
|
|
7049
7026
|
return results;
|
|
7050
7027
|
}
|
|
7051
7028
|
|
|
7029
|
+
// src/server/graph/core/resolve-paths.ts
|
|
7030
|
+
function hasSqlFiles(dir) {
|
|
7031
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return false;
|
|
7032
|
+
try {
|
|
7033
|
+
return (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true }).some(
|
|
7034
|
+
(e) => e.isFile() && e.name.endsWith(".sql")
|
|
7035
|
+
);
|
|
7036
|
+
} catch {
|
|
7037
|
+
return false;
|
|
7038
|
+
}
|
|
7039
|
+
}
|
|
7040
|
+
function hasNestedMigrationSql(dir) {
|
|
7041
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return false;
|
|
7042
|
+
try {
|
|
7043
|
+
return (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true }).some(
|
|
7044
|
+
(e) => e.isDirectory() && (0, import_node_fs3.existsSync)((0, import_node_path3.join)(dir, e.name, "migration.sql"))
|
|
7045
|
+
);
|
|
7046
|
+
} catch {
|
|
7047
|
+
return false;
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
function resolveDbFromDir(dir) {
|
|
7051
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
7052
|
+
const schemaPath = (0, import_node_path3.join)(dir, "schema.prisma");
|
|
7053
|
+
if ((0, import_node_fs3.existsSync)(schemaPath)) {
|
|
7054
|
+
const migrationsDir2 = (0, import_node_path3.join)(dir, "migrations");
|
|
7055
|
+
return {
|
|
7056
|
+
kind: "prisma",
|
|
7057
|
+
schemaPath,
|
|
7058
|
+
migrationsDir: (0, import_node_fs3.existsSync)(migrationsDir2) ? migrationsDir2 : null
|
|
7059
|
+
};
|
|
7060
|
+
}
|
|
7061
|
+
const migrationsDir = (0, import_node_path3.join)(dir, "migrations");
|
|
7062
|
+
if (hasSqlFiles(migrationsDir) || hasNestedMigrationSql(migrationsDir)) {
|
|
7063
|
+
return { kind: "sql-migrations", migrationsDir, schemaPath: null };
|
|
7064
|
+
}
|
|
7065
|
+
if (hasSqlFiles(dir) || hasNestedMigrationSql(dir)) {
|
|
7066
|
+
return { kind: "sql-migrations", migrationsDir: dir, schemaPath: null };
|
|
7067
|
+
}
|
|
7068
|
+
return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
7069
|
+
}
|
|
7070
|
+
function detectDbConfig(rootDir, config) {
|
|
7071
|
+
if (config.paths?.dbDir) {
|
|
7072
|
+
return resolveDbFromDir((0, import_node_path3.join)(rootDir, config.paths.dbDir));
|
|
7073
|
+
}
|
|
7074
|
+
const candidates = ["prisma", "supabase", "drizzle", (0, import_node_path3.join)("db", "migrations"), "migrations"];
|
|
7075
|
+
for (const c of candidates) {
|
|
7076
|
+
const dir = (0, import_node_path3.join)(rootDir, c);
|
|
7077
|
+
const resolved = resolveDbFromDir(dir);
|
|
7078
|
+
if (resolved.kind !== "none") return resolved;
|
|
7079
|
+
}
|
|
7080
|
+
return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
7081
|
+
}
|
|
7082
|
+
function detectDbDir(rootDir, config, dbConfig) {
|
|
7083
|
+
if (config.paths?.dbDir) return (0, import_node_path3.join)(rootDir, config.paths.dbDir);
|
|
7084
|
+
if (dbConfig.kind === "prisma") return (0, import_node_path3.dirname)(dbConfig.schemaPath);
|
|
7085
|
+
if (dbConfig.kind === "sql-migrations") return dbConfig.migrationsDir;
|
|
7086
|
+
return null;
|
|
7087
|
+
}
|
|
7088
|
+
var NON_SOURCE_DIRS = /* @__PURE__ */ new Set([
|
|
7089
|
+
...DEFAULT_IGNORE_DIRS,
|
|
7090
|
+
// DB conventions (handled by db parsers)
|
|
7091
|
+
"prisma",
|
|
7092
|
+
"supabase",
|
|
7093
|
+
"drizzle",
|
|
7094
|
+
"migrations",
|
|
7095
|
+
// Web assets
|
|
7096
|
+
"public",
|
|
7097
|
+
"static",
|
|
7098
|
+
"assets",
|
|
7099
|
+
// Docs
|
|
7100
|
+
"docs",
|
|
7101
|
+
"documentation",
|
|
7102
|
+
// Test dirs (project tests aren't part of the structural graph)
|
|
7103
|
+
"tests",
|
|
7104
|
+
"__tests__",
|
|
7105
|
+
"e2e",
|
|
7106
|
+
"playwright",
|
|
7107
|
+
"cypress",
|
|
7108
|
+
// Monorepo workspace roots — separate graph projects per .launchchart.json
|
|
7109
|
+
"packages",
|
|
7110
|
+
"apps",
|
|
7111
|
+
"services",
|
|
7112
|
+
"libs"
|
|
7113
|
+
]);
|
|
7114
|
+
function dirHasTSFiles(dir) {
|
|
7115
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return false;
|
|
7116
|
+
try {
|
|
7117
|
+
const stack = [dir];
|
|
7118
|
+
while (stack.length > 0) {
|
|
7119
|
+
const cur = stack.pop();
|
|
7120
|
+
const entries = (0, import_node_fs3.readdirSync)(cur, { withFileTypes: true });
|
|
7121
|
+
for (const e of entries) {
|
|
7122
|
+
if (e.isFile() && (e.name.endsWith(".ts") || e.name.endsWith(".tsx"))) return true;
|
|
7123
|
+
if (e.isDirectory() && !e.name.startsWith(".") && !DEFAULT_IGNORE_DIRS.has(e.name)) {
|
|
7124
|
+
stack.push((0, import_node_path3.join)(cur, e.name));
|
|
7125
|
+
}
|
|
7126
|
+
}
|
|
7127
|
+
}
|
|
7128
|
+
} catch {
|
|
7129
|
+
}
|
|
7130
|
+
return false;
|
|
7131
|
+
}
|
|
7132
|
+
function collectCodeBearingChildren(dir, extraSkip) {
|
|
7133
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return [];
|
|
7134
|
+
const out = [];
|
|
7135
|
+
try {
|
|
7136
|
+
for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
|
|
7137
|
+
if (!entry.isDirectory()) continue;
|
|
7138
|
+
if (entry.name.startsWith(".")) continue;
|
|
7139
|
+
if (NON_SOURCE_DIRS.has(entry.name)) continue;
|
|
7140
|
+
if (extraSkip?.has(entry.name)) continue;
|
|
7141
|
+
const full = (0, import_node_path3.join)(dir, entry.name);
|
|
7142
|
+
if (dirHasTSFiles(full)) out.push(full);
|
|
7143
|
+
}
|
|
7144
|
+
} catch {
|
|
7145
|
+
}
|
|
7146
|
+
return out;
|
|
7147
|
+
}
|
|
7148
|
+
function detectSrcRoots(rootDir, srcDir, appDir, config) {
|
|
7149
|
+
if (config.paths?.srcRoots && config.paths.srcRoots.length > 0) {
|
|
7150
|
+
const roots2 = /* @__PURE__ */ new Set();
|
|
7151
|
+
roots2.add(appDir);
|
|
7152
|
+
for (const r of config.paths.srcRoots) {
|
|
7153
|
+
const abs = (0, import_node_path3.isAbsolute)(r) ? r : (0, import_node_path3.resolve)(rootDir, r);
|
|
7154
|
+
roots2.add(abs);
|
|
7155
|
+
}
|
|
7156
|
+
return [...roots2];
|
|
7157
|
+
}
|
|
7158
|
+
const roots = /* @__PURE__ */ new Set();
|
|
7159
|
+
roots.add(appDir);
|
|
7160
|
+
for (const c of collectCodeBearingChildren(srcDir)) roots.add(c);
|
|
7161
|
+
if (srcDir !== rootDir) {
|
|
7162
|
+
const skipSrcWrapper = /* @__PURE__ */ new Set([(0, import_node_path3.basename)(srcDir)]);
|
|
7163
|
+
for (const c of collectCodeBearingChildren(rootDir, skipSrcWrapper)) roots.add(c);
|
|
7164
|
+
}
|
|
7165
|
+
return [...roots];
|
|
7166
|
+
}
|
|
7167
|
+
var CONVENTION_NAMES = ["middleware.ts", "middleware.tsx", "instrumentation.ts", "instrumentation.tsx"];
|
|
7168
|
+
function detectConventionFiles(rootDir, srcDir) {
|
|
7169
|
+
const out = [];
|
|
7170
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7171
|
+
const dirs = srcDir === rootDir ? [rootDir] : [srcDir, rootDir];
|
|
7172
|
+
for (const dir of dirs) {
|
|
7173
|
+
for (const name of CONVENTION_NAMES) {
|
|
7174
|
+
const full = (0, import_node_path3.join)(dir, name);
|
|
7175
|
+
if (!seen.has(full) && (0, import_node_fs3.existsSync)(full)) {
|
|
7176
|
+
try {
|
|
7177
|
+
if ((0, import_node_fs3.statSync)(full).isFile()) {
|
|
7178
|
+
seen.add(full);
|
|
7179
|
+
out.push(full);
|
|
7180
|
+
}
|
|
7181
|
+
} catch {
|
|
7182
|
+
}
|
|
7183
|
+
}
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
7186
|
+
return out;
|
|
7187
|
+
}
|
|
7188
|
+
function resolveProjectPaths(rootDir, config) {
|
|
7189
|
+
let srcDir;
|
|
7190
|
+
let appDir;
|
|
7191
|
+
if (config.paths?.appDir) {
|
|
7192
|
+
appDir = (0, import_node_path3.join)(rootDir, config.paths.appDir);
|
|
7193
|
+
srcDir = config.paths.srcDir ? (0, import_node_path3.join)(rootDir, config.paths.srcDir) : (0, import_node_path3.dirname)(appDir);
|
|
7194
|
+
} else {
|
|
7195
|
+
const srcApp = (0, import_node_path3.join)(rootDir, "src", "app");
|
|
7196
|
+
const rootApp = (0, import_node_path3.join)(rootDir, "app");
|
|
7197
|
+
if ((0, import_node_fs3.existsSync)(srcApp)) {
|
|
7198
|
+
srcDir = (0, import_node_path3.join)(rootDir, "src");
|
|
7199
|
+
appDir = srcApp;
|
|
7200
|
+
} else if ((0, import_node_fs3.existsSync)(rootApp)) {
|
|
7201
|
+
srcDir = rootDir;
|
|
7202
|
+
appDir = rootApp;
|
|
7203
|
+
} else {
|
|
7204
|
+
return null;
|
|
7205
|
+
}
|
|
7206
|
+
}
|
|
7207
|
+
const apiDir = (0, import_node_path3.join)(appDir, "api");
|
|
7208
|
+
const dbConfig = detectDbConfig(rootDir, config);
|
|
7209
|
+
const dbDir = detectDbDir(rootDir, config, dbConfig);
|
|
7210
|
+
const srcRoots = detectSrcRoots(rootDir, srcDir, appDir, config);
|
|
7211
|
+
const conventionFiles = detectConventionFiles(rootDir, srcDir);
|
|
7212
|
+
return { srcDir, appDir, apiDir, dbDir, srcRoots, conventionFiles, dbConfig };
|
|
7213
|
+
}
|
|
7214
|
+
|
|
7052
7215
|
// src/server/graph/parsers/ts/typescript-project.ts
|
|
7053
7216
|
init_ts_extractor();
|
|
7054
7217
|
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]);
|
|
@@ -7065,8 +7228,12 @@ var CLASSIFICATION_TO_LAYER = {
|
|
|
7065
7228
|
"mcp-tool": "ui",
|
|
7066
7229
|
external: "ui"
|
|
7067
7230
|
};
|
|
7068
|
-
function toNodeId(srcDir, absPath) {
|
|
7069
|
-
|
|
7231
|
+
function toNodeId(srcDir, rootDir, absPath) {
|
|
7232
|
+
const relFromSrc = (0, import_node_path5.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
7233
|
+
if (relFromSrc.startsWith("..")) {
|
|
7234
|
+
return (0, import_node_path5.relative)(rootDir, absPath).replace(/\\/g, "/");
|
|
7235
|
+
}
|
|
7236
|
+
return relFromSrc;
|
|
7070
7237
|
}
|
|
7071
7238
|
function resolveImport(srcDir, specifier) {
|
|
7072
7239
|
if (!specifier.startsWith("@/")) return null;
|
|
@@ -7156,12 +7323,13 @@ function extractRoute(id) {
|
|
|
7156
7323
|
function nameFromFilename(absPath) {
|
|
7157
7324
|
return (0, import_node_path5.basename)(absPath, (0, import_node_path5.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
|
|
7158
7325
|
}
|
|
7159
|
-
function
|
|
7160
|
-
let route = "/" + (0, import_node_path5.relative)(
|
|
7326
|
+
function filePathToAppRoute(appDir, absPath) {
|
|
7327
|
+
let route = ("/" + (0, import_node_path5.relative)(appDir, absPath).replace(/\\/g, "/")).replace(/\/route\.tsx?$/, "");
|
|
7328
|
+
route = route.replace(/\/\([^)]+\)/g, "");
|
|
7329
|
+
route = route.replace(/\[\.\.\.([^\]]+)\]/g, "*$1");
|
|
7161
7330
|
route = route.replace(/\[([^\]]+)\]/g, ":$1");
|
|
7162
7331
|
route = route.replace(/\/+/g, "/");
|
|
7163
|
-
|
|
7164
|
-
return "/api" + route;
|
|
7332
|
+
return route === "" ? "/" : route;
|
|
7165
7333
|
}
|
|
7166
7334
|
function camelToPascal(s) {
|
|
7167
7335
|
if (!s) return s;
|
|
@@ -7246,7 +7414,7 @@ function matchRouteToPage(route, routeToNodeId) {
|
|
|
7246
7414
|
if (routeToNodeId.has(normalized)) return routeToNodeId.get(normalized);
|
|
7247
7415
|
return null;
|
|
7248
7416
|
}
|
|
7249
|
-
function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
7417
|
+
function extractEdges(srcDir, rootDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
7250
7418
|
const edges = [];
|
|
7251
7419
|
const flagged = [];
|
|
7252
7420
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7274,7 +7442,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
7274
7442
|
for (const name of names) {
|
|
7275
7443
|
const targetAbs = barrelMap.get(name);
|
|
7276
7444
|
if (targetAbs) {
|
|
7277
|
-
const targetId = toNodeId(srcDir, targetAbs);
|
|
7445
|
+
const targetId = toNodeId(srcDir, rootDir, targetAbs);
|
|
7278
7446
|
if (nodeIdSet.has(targetId)) {
|
|
7279
7447
|
if (!byTarget.has(targetId)) byTarget.set(targetId, []);
|
|
7280
7448
|
byTarget.get(targetId).push(name);
|
|
@@ -7288,7 +7456,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
7288
7456
|
} else {
|
|
7289
7457
|
const resolved = resolveImport(srcDir, specifier);
|
|
7290
7458
|
if (resolved) {
|
|
7291
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
7459
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
7292
7460
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
7293
7461
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
7294
7462
|
}
|
|
@@ -7297,7 +7465,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
7297
7465
|
} else if (specifier.startsWith(".")) {
|
|
7298
7466
|
const resolved = resolveRelativeImport(absPath, specifier);
|
|
7299
7467
|
if (resolved) {
|
|
7300
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
7468
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
7301
7469
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
7302
7470
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
7303
7471
|
}
|
|
@@ -7349,13 +7517,22 @@ function generate(rootDir) {
|
|
|
7349
7517
|
const config = loadConfig(rootDir);
|
|
7350
7518
|
const paths = resolveProjectPaths(rootDir, config);
|
|
7351
7519
|
const srcDir = paths.srcDir;
|
|
7352
|
-
const
|
|
7353
|
-
const
|
|
7354
|
-
const
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7520
|
+
const allDiscovered = [];
|
|
7521
|
+
const discoveredSet = /* @__PURE__ */ new Set();
|
|
7522
|
+
for (const root of paths.srcRoots) {
|
|
7523
|
+
for (const f of walk(root, [".tsx", ".ts"])) {
|
|
7524
|
+
if (!discoveredSet.has(f)) {
|
|
7525
|
+
discoveredSet.add(f);
|
|
7526
|
+
allDiscovered.push(f);
|
|
7527
|
+
}
|
|
7528
|
+
}
|
|
7529
|
+
}
|
|
7530
|
+
for (const conv of paths.conventionFiles) {
|
|
7531
|
+
if (!discoveredSet.has(conv)) {
|
|
7532
|
+
discoveredSet.add(conv);
|
|
7533
|
+
allDiscovered.push(conv);
|
|
7534
|
+
}
|
|
7535
|
+
}
|
|
7359
7536
|
const parsedByPath = /* @__PURE__ */ new Map();
|
|
7360
7537
|
for (const absPath of allDiscovered) {
|
|
7361
7538
|
parsedByPath.set(absPath, parseFileTS(absPath));
|
|
@@ -7367,7 +7544,7 @@ function generate(rootDir) {
|
|
|
7367
7544
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
7368
7545
|
const fileSet = allDiscovered.filter((f) => !(0, import_node_path5.basename)(f).startsWith("index."));
|
|
7369
7546
|
for (const absPath of fileSet) {
|
|
7370
|
-
const id = toNodeId(srcDir, absPath);
|
|
7547
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
7371
7548
|
const type = classifyType(absPath, id);
|
|
7372
7549
|
if (type === "test" || type === "story") continue;
|
|
7373
7550
|
const parsed = parsedByPath.get(absPath);
|
|
@@ -7382,7 +7559,7 @@ function generate(rootDir) {
|
|
|
7382
7559
|
const dbCalls = extractDbCallsTS(absPath);
|
|
7383
7560
|
const authWrappers = extractAuthWrappersTS(absPath);
|
|
7384
7561
|
const deep = extractDeep(absPath);
|
|
7385
|
-
const routePath = (
|
|
7562
|
+
const routePath = filePathToAppRoute(paths.appDir, absPath);
|
|
7386
7563
|
const mutations = dbCalls.filter((c) => c.isMutation);
|
|
7387
7564
|
const mutates = mutations.length > 0;
|
|
7388
7565
|
const authStrategy = [...authWrappers];
|
|
@@ -7426,11 +7603,12 @@ function generate(rootDir) {
|
|
|
7426
7603
|
const uiEdges = [];
|
|
7427
7604
|
const uiFlagged = [];
|
|
7428
7605
|
for (const absPath of fileSet) {
|
|
7429
|
-
const id = toNodeId(srcDir, absPath);
|
|
7606
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
7430
7607
|
if (!nodeIdSet.has(id)) continue;
|
|
7431
7608
|
const parsed = parsedByPath.get(absPath);
|
|
7432
7609
|
const { edges, flagged } = extractEdges(
|
|
7433
7610
|
srcDir,
|
|
7611
|
+
rootDir,
|
|
7434
7612
|
absPath,
|
|
7435
7613
|
id,
|
|
7436
7614
|
parsed,
|
|
@@ -7443,7 +7621,7 @@ function generate(rootDir) {
|
|
|
7443
7621
|
}
|
|
7444
7622
|
const fetchCallEntries = [];
|
|
7445
7623
|
for (const absPath of fileSet) {
|
|
7446
|
-
const sourceId = toNodeId(srcDir, absPath);
|
|
7624
|
+
const sourceId = toNodeId(srcDir, rootDir, absPath);
|
|
7447
7625
|
if (!nodeIdSet.has(sourceId)) continue;
|
|
7448
7626
|
const parsed = parsedByPath.get(absPath);
|
|
7449
7627
|
if (parsed.fetchCalls.length === 0) continue;
|
|
@@ -7482,7 +7660,7 @@ function generate(rootDir) {
|
|
|
7482
7660
|
for (const name of names) {
|
|
7483
7661
|
const targetAbs = barrelMap.get(name);
|
|
7484
7662
|
if (!targetAbs) continue;
|
|
7485
|
-
const targetId2 = toNodeId(srcDir, targetAbs);
|
|
7663
|
+
const targetId2 = toNodeId(srcDir, rootDir, targetAbs);
|
|
7486
7664
|
if (!nodeIdSet.has(targetId2)) continue;
|
|
7487
7665
|
const key2 = `${externalId}\u2192${targetId2}`;
|
|
7488
7666
|
if (seen.has(key2)) continue;
|
|
@@ -7496,7 +7674,7 @@ function generate(rootDir) {
|
|
|
7496
7674
|
resolved = resolveRelativeImport(absPath, specifier);
|
|
7497
7675
|
}
|
|
7498
7676
|
if (!resolved) continue;
|
|
7499
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
7677
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
7500
7678
|
if (!nodeIdSet.has(targetId)) continue;
|
|
7501
7679
|
if (targetId.endsWith("/index.ts") || targetId.endsWith("/index.tsx")) continue;
|
|
7502
7680
|
const key = `${externalId}\u2192${targetId}`;
|
|
@@ -7674,7 +7852,7 @@ var typescriptProjectParser = {
|
|
|
7674
7852
|
|
|
7675
7853
|
// src/server/graph/parsers/db/prisma-schema.ts
|
|
7676
7854
|
var import_node_fs6 = require("node:fs");
|
|
7677
|
-
|
|
7855
|
+
init_config();
|
|
7678
7856
|
function parseModels(content) {
|
|
7679
7857
|
const nodes = [];
|
|
7680
7858
|
const relations = [];
|
|
@@ -7765,10 +7943,24 @@ function parseEnums(content) {
|
|
|
7765
7943
|
return nodes;
|
|
7766
7944
|
}
|
|
7767
7945
|
function detect2(rootDir) {
|
|
7768
|
-
|
|
7946
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
7947
|
+
return paths?.dbConfig.kind === "prisma" && (0, import_node_fs6.existsSync)(paths.dbConfig.schemaPath);
|
|
7769
7948
|
}
|
|
7770
7949
|
function generate2(rootDir) {
|
|
7771
|
-
const
|
|
7950
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
7951
|
+
if (paths.dbConfig.kind !== "prisma") {
|
|
7952
|
+
return {
|
|
7953
|
+
metadata: { generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), layer: "db", source: "none" },
|
|
7954
|
+
nodes: [],
|
|
7955
|
+
edges: [],
|
|
7956
|
+
cross_refs: [],
|
|
7957
|
+
contradictions: [],
|
|
7958
|
+
warnings: [],
|
|
7959
|
+
flagged_edges: [],
|
|
7960
|
+
patterns: { total_tables: 0, total_enums: 0, total_relations: 0 }
|
|
7961
|
+
};
|
|
7962
|
+
}
|
|
7963
|
+
const schemaPath = paths.dbConfig.schemaPath;
|
|
7772
7964
|
const content = (0, import_node_fs6.readFileSync)(schemaPath, "utf-8");
|
|
7773
7965
|
const { nodes: modelNodes, relations } = parseModels(content);
|
|
7774
7966
|
const enumNodes = parseEnums(content);
|
|
@@ -7789,7 +7981,7 @@ function generate2(rootDir) {
|
|
|
7789
7981
|
metadata: {
|
|
7790
7982
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
7791
7983
|
scope: "prisma-schema",
|
|
7792
|
-
source:
|
|
7984
|
+
source: schemaPath,
|
|
7793
7985
|
provider: "postgresql",
|
|
7794
7986
|
layer: "db",
|
|
7795
7987
|
total_models: modelNodes.length,
|
|
@@ -7827,7 +8019,8 @@ var prismaSchemaParser = {
|
|
|
7827
8019
|
|
|
7828
8020
|
// src/server/graph/parsers/db/sql-migrations.ts
|
|
7829
8021
|
var import_node_fs7 = require("node:fs");
|
|
7830
|
-
var
|
|
8022
|
+
var import_node_path6 = require("node:path");
|
|
8023
|
+
init_config();
|
|
7831
8024
|
var PG_TO_PRISMA = {
|
|
7832
8025
|
"TEXT": "String",
|
|
7833
8026
|
"VARCHAR": "String",
|
|
@@ -7858,51 +8051,149 @@ function pgTypeToPrisma(pgType) {
|
|
|
7858
8051
|
const upper = pgType.toUpperCase().trim();
|
|
7859
8052
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
7860
8053
|
}
|
|
8054
|
+
var ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
8055
|
+
var QID = `(?:${ID}\\.)?${ID}`;
|
|
8056
|
+
function bareName(captured) {
|
|
8057
|
+
const parts = captured.split(".");
|
|
8058
|
+
const last = parts[parts.length - 1];
|
|
8059
|
+
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
8060
|
+
}
|
|
7861
8061
|
function parseCreateTable(sql, state) {
|
|
7862
|
-
const re =
|
|
8062
|
+
const re = new RegExp(
|
|
8063
|
+
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
8064
|
+
"gi"
|
|
8065
|
+
);
|
|
7863
8066
|
let m;
|
|
7864
8067
|
while ((m = re.exec(sql)) !== null) {
|
|
7865
|
-
const tableName = m[1];
|
|
8068
|
+
const tableName = bareName(m[1]);
|
|
7866
8069
|
const body = m[2];
|
|
7867
8070
|
const columns = /* @__PURE__ */ new Map();
|
|
7868
8071
|
let primaryCol = null;
|
|
7869
|
-
|
|
7870
|
-
|
|
8072
|
+
const inlineFks = [];
|
|
8073
|
+
const lines = splitTopLevelCommas(body);
|
|
8074
|
+
for (const raw of lines) {
|
|
8075
|
+
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
7871
8076
|
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
7872
|
-
const
|
|
7873
|
-
if (
|
|
7874
|
-
primaryCol =
|
|
8077
|
+
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
8078
|
+
if (namedPk) {
|
|
8079
|
+
primaryCol = bareName(namedPk[1]);
|
|
8080
|
+
continue;
|
|
8081
|
+
}
|
|
8082
|
+
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
8083
|
+
if (tablePk) {
|
|
8084
|
+
primaryCol = bareName(tablePk[1]);
|
|
8085
|
+
continue;
|
|
8086
|
+
}
|
|
8087
|
+
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
8088
|
+
const namedFk = trimmed.match(new RegExp(
|
|
8089
|
+
`^CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8090
|
+
"i"
|
|
8091
|
+
));
|
|
8092
|
+
if (namedFk) {
|
|
8093
|
+
inlineFks.push({
|
|
8094
|
+
constraintName: bareName(namedFk[1]),
|
|
8095
|
+
sourceTable: tableName,
|
|
8096
|
+
sourceColumn: bareName(namedFk[2]),
|
|
8097
|
+
targetTable: bareName(namedFk[3]),
|
|
8098
|
+
targetColumn: bareName(namedFk[4]),
|
|
8099
|
+
onDelete: namedFk[5] ?? null
|
|
8100
|
+
});
|
|
8101
|
+
continue;
|
|
8102
|
+
}
|
|
8103
|
+
const bareFk = trimmed.match(new RegExp(
|
|
8104
|
+
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8105
|
+
"i"
|
|
8106
|
+
));
|
|
8107
|
+
if (bareFk) {
|
|
8108
|
+
inlineFks.push({
|
|
8109
|
+
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
8110
|
+
sourceTable: tableName,
|
|
8111
|
+
sourceColumn: bareName(bareFk[1]),
|
|
8112
|
+
targetTable: bareName(bareFk[2]),
|
|
8113
|
+
targetColumn: bareName(bareFk[3]),
|
|
8114
|
+
onDelete: bareFk[4] ?? null
|
|
8115
|
+
});
|
|
7875
8116
|
continue;
|
|
7876
8117
|
}
|
|
7877
|
-
if (
|
|
7878
|
-
const colMatch = trimmed.match(
|
|
8118
|
+
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
8119
|
+
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
7879
8120
|
if (!colMatch) continue;
|
|
7880
|
-
const colName = colMatch[1];
|
|
8121
|
+
const colName = bareName(colMatch[1]);
|
|
7881
8122
|
let rest = colMatch[2];
|
|
8123
|
+
const inlineRefMatch = rest.match(new RegExp(
|
|
8124
|
+
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8125
|
+
"i"
|
|
8126
|
+
));
|
|
8127
|
+
if (inlineRefMatch) {
|
|
8128
|
+
inlineFks.push({
|
|
8129
|
+
constraintName: `${tableName}_${colName}_fkey`,
|
|
8130
|
+
sourceTable: tableName,
|
|
8131
|
+
sourceColumn: colName,
|
|
8132
|
+
targetTable: bareName(inlineRefMatch[1]),
|
|
8133
|
+
targetColumn: bareName(inlineRefMatch[2]),
|
|
8134
|
+
onDelete: inlineRefMatch[3] ?? null
|
|
8135
|
+
});
|
|
8136
|
+
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
8137
|
+
}
|
|
7882
8138
|
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
8139
|
+
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
8140
|
+
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
7883
8141
|
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
7884
8142
|
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
7885
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
8143
|
+
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bPRIMARY\s+KEY\b/gi, "").replace(/\bUNIQUE\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
7886
8144
|
columns.set(colName, {
|
|
7887
8145
|
name: colName,
|
|
7888
8146
|
type: colType,
|
|
7889
|
-
nullable: !isNotNull,
|
|
7890
|
-
primary:
|
|
7891
|
-
unique:
|
|
8147
|
+
nullable: !isNotNull && !isPrimaryKey,
|
|
8148
|
+
primary: isPrimaryKey,
|
|
8149
|
+
unique: isUnique,
|
|
7892
8150
|
default: defaultVal
|
|
7893
8151
|
});
|
|
8152
|
+
if (isPrimaryKey) primaryCol = colName;
|
|
7894
8153
|
}
|
|
7895
8154
|
if (primaryCol && columns.has(primaryCol)) {
|
|
7896
8155
|
columns.get(primaryCol).primary = true;
|
|
7897
8156
|
}
|
|
7898
8157
|
state.tables.set(tableName, { name: tableName, columns });
|
|
8158
|
+
state.fks.push(...inlineFks);
|
|
8159
|
+
}
|
|
8160
|
+
}
|
|
8161
|
+
function splitTopLevelCommas(body) {
|
|
8162
|
+
const out = [];
|
|
8163
|
+
let depth = 0;
|
|
8164
|
+
let buf = "";
|
|
8165
|
+
let inString = null;
|
|
8166
|
+
for (const ch of body) {
|
|
8167
|
+
if (inString) {
|
|
8168
|
+
buf += ch;
|
|
8169
|
+
if (ch === inString) inString = null;
|
|
8170
|
+
continue;
|
|
8171
|
+
}
|
|
8172
|
+
if (ch === "'" || ch === '"') {
|
|
8173
|
+
inString = ch;
|
|
8174
|
+
buf += ch;
|
|
8175
|
+
continue;
|
|
8176
|
+
}
|
|
8177
|
+
if (ch === "(") depth++;
|
|
8178
|
+
else if (ch === ")") depth--;
|
|
8179
|
+
if (ch === "," && depth === 0) {
|
|
8180
|
+
out.push(buf);
|
|
8181
|
+
buf = "";
|
|
8182
|
+
continue;
|
|
8183
|
+
}
|
|
8184
|
+
buf += ch;
|
|
7899
8185
|
}
|
|
8186
|
+
if (buf.trim()) out.push(buf);
|
|
8187
|
+
return out;
|
|
7900
8188
|
}
|
|
7901
8189
|
function parseCreateEnum(sql, state) {
|
|
7902
|
-
const re =
|
|
8190
|
+
const re = new RegExp(
|
|
8191
|
+
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
8192
|
+
"gi"
|
|
8193
|
+
);
|
|
7903
8194
|
let m;
|
|
7904
8195
|
while ((m = re.exec(sql)) !== null) {
|
|
7905
|
-
const enumName = m[1];
|
|
8196
|
+
const enumName = bareName(m[1]);
|
|
7906
8197
|
const valuesStr = m[2];
|
|
7907
8198
|
const values = new Set(
|
|
7908
8199
|
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
@@ -7911,11 +8202,14 @@ function parseCreateEnum(sql, state) {
|
|
|
7911
8202
|
}
|
|
7912
8203
|
}
|
|
7913
8204
|
function parseAlterTable(sql, state) {
|
|
7914
|
-
const addColRe =
|
|
8205
|
+
const addColRe = new RegExp(
|
|
8206
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
8207
|
+
"gi"
|
|
8208
|
+
);
|
|
7915
8209
|
let m;
|
|
7916
8210
|
while ((m = addColRe.exec(sql)) !== null) {
|
|
7917
|
-
const tableName = m[1];
|
|
7918
|
-
const colName = m[2];
|
|
8211
|
+
const tableName = bareName(m[1]);
|
|
8212
|
+
const colName = bareName(m[2]);
|
|
7919
8213
|
let rest = m[3];
|
|
7920
8214
|
const table = state.tables.get(tableName);
|
|
7921
8215
|
if (!table) continue;
|
|
@@ -7932,63 +8226,91 @@ function parseAlterTable(sql, state) {
|
|
|
7932
8226
|
default: defaultVal
|
|
7933
8227
|
});
|
|
7934
8228
|
}
|
|
7935
|
-
const dropColRe =
|
|
8229
|
+
const dropColRe = new RegExp(
|
|
8230
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
8231
|
+
"gi"
|
|
8232
|
+
);
|
|
7936
8233
|
while ((m = dropColRe.exec(sql)) !== null) {
|
|
7937
|
-
const table = state.tables.get(m[1]);
|
|
7938
|
-
if (table) table.columns.delete(m[2]);
|
|
8234
|
+
const table = state.tables.get(bareName(m[1]));
|
|
8235
|
+
if (table) table.columns.delete(bareName(m[2]));
|
|
7939
8236
|
}
|
|
7940
|
-
const fkRe =
|
|
8237
|
+
const fkRe = new RegExp(
|
|
8238
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+CONSTRAINT\\s+(${ID})\\s+FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
8239
|
+
"gi"
|
|
8240
|
+
);
|
|
7941
8241
|
while ((m = fkRe.exec(sql)) !== null) {
|
|
7942
8242
|
state.fks.push({
|
|
7943
|
-
constraintName: m[2],
|
|
7944
|
-
sourceTable: m[1],
|
|
7945
|
-
sourceColumn: m[3],
|
|
7946
|
-
targetTable: m[4],
|
|
7947
|
-
targetColumn: m[5],
|
|
8243
|
+
constraintName: bareName(m[2]),
|
|
8244
|
+
sourceTable: bareName(m[1]),
|
|
8245
|
+
sourceColumn: bareName(m[3]),
|
|
8246
|
+
targetTable: bareName(m[4]),
|
|
8247
|
+
targetColumn: bareName(m[5]),
|
|
7948
8248
|
onDelete: m[6] ?? null
|
|
7949
8249
|
});
|
|
7950
8250
|
}
|
|
7951
8251
|
}
|
|
7952
8252
|
function parseAlterEnum(sql, state) {
|
|
7953
|
-
const re =
|
|
8253
|
+
const re = new RegExp(
|
|
8254
|
+
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
8255
|
+
"gi"
|
|
8256
|
+
);
|
|
7954
8257
|
let m;
|
|
7955
8258
|
while ((m = re.exec(sql)) !== null) {
|
|
7956
|
-
const en = state.enums.get(m[1]);
|
|
8259
|
+
const en = state.enums.get(bareName(m[1]));
|
|
7957
8260
|
if (en) en.values.add(m[2]);
|
|
7958
8261
|
}
|
|
7959
8262
|
}
|
|
7960
8263
|
function parseDropTable(sql, state) {
|
|
7961
|
-
const re =
|
|
8264
|
+
const re = new RegExp(
|
|
8265
|
+
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
8266
|
+
"gi"
|
|
8267
|
+
);
|
|
7962
8268
|
let m;
|
|
7963
8269
|
while ((m = re.exec(sql)) !== null) {
|
|
7964
|
-
|
|
7965
|
-
state.
|
|
8270
|
+
const dropped = bareName(m[1]);
|
|
8271
|
+
state.tables.delete(dropped);
|
|
8272
|
+
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
7966
8273
|
}
|
|
7967
8274
|
}
|
|
7968
8275
|
function parseUniqueIndex(sql, state) {
|
|
7969
|
-
const re =
|
|
8276
|
+
const re = new RegExp(
|
|
8277
|
+
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
8278
|
+
"gi"
|
|
8279
|
+
);
|
|
7970
8280
|
let m;
|
|
7971
8281
|
while ((m = re.exec(sql)) !== null) {
|
|
7972
|
-
const
|
|
7973
|
-
const
|
|
8282
|
+
const tableName = bareName(m[1]);
|
|
8283
|
+
const colName = bareName(m[2]);
|
|
8284
|
+
const table = state.tables.get(tableName);
|
|
8285
|
+
const col = table?.columns.get(colName);
|
|
7974
8286
|
if (col) col.unique = true;
|
|
7975
|
-
if (!state.uniqueIndexes.has(
|
|
7976
|
-
state.uniqueIndexes.get(
|
|
8287
|
+
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
8288
|
+
state.uniqueIndexes.get(tableName).add(colName);
|
|
8289
|
+
}
|
|
8290
|
+
}
|
|
8291
|
+
function discoverMigrationFiles(migrationsDir) {
|
|
8292
|
+
if (!(0, import_node_fs7.existsSync)(migrationsDir)) return [];
|
|
8293
|
+
const out = [];
|
|
8294
|
+
const entries = (0, import_node_fs7.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
8295
|
+
for (const entry of entries) {
|
|
8296
|
+
if (entry.isDirectory()) {
|
|
8297
|
+
const sqlPath = (0, import_node_path6.join)(migrationsDir, entry.name, "migration.sql");
|
|
8298
|
+
if ((0, import_node_fs7.existsSync)(sqlPath)) out.push(sqlPath);
|
|
8299
|
+
} else if (entry.isFile() && entry.name.endsWith(".sql")) {
|
|
8300
|
+
out.push((0, import_node_path6.join)(migrationsDir, entry.name));
|
|
8301
|
+
}
|
|
7977
8302
|
}
|
|
8303
|
+
return out;
|
|
7978
8304
|
}
|
|
7979
|
-
function parseMigrations(
|
|
7980
|
-
const migrationsDir = (0, import_node_path7.join)(rootDir, "prisma", "migrations");
|
|
8305
|
+
function parseMigrations(migrationsDir) {
|
|
7981
8306
|
const state = {
|
|
7982
8307
|
tables: /* @__PURE__ */ new Map(),
|
|
7983
8308
|
enums: /* @__PURE__ */ new Map(),
|
|
7984
8309
|
fks: [],
|
|
7985
8310
|
uniqueIndexes: /* @__PURE__ */ new Map()
|
|
7986
8311
|
};
|
|
7987
|
-
if (!
|
|
7988
|
-
const
|
|
7989
|
-
for (const dir of dirs) {
|
|
7990
|
-
const sqlPath = (0, import_node_path7.join)(migrationsDir, dir, "migration.sql");
|
|
7991
|
-
if (!(0, import_node_fs7.existsSync)(sqlPath)) continue;
|
|
8312
|
+
if (!migrationsDir) return state;
|
|
8313
|
+
for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
|
|
7992
8314
|
const sql = (0, import_node_fs7.readFileSync)(sqlPath, "utf-8");
|
|
7993
8315
|
parseCreateEnum(sql, state);
|
|
7994
8316
|
parseCreateTable(sql, state);
|
|
@@ -7999,9 +8321,8 @@ function parseMigrations(rootDir) {
|
|
|
7999
8321
|
}
|
|
8000
8322
|
return state;
|
|
8001
8323
|
}
|
|
8002
|
-
function loadPrismaState(
|
|
8003
|
-
|
|
8004
|
-
if (!(0, import_node_fs7.existsSync)(schemaPath)) return null;
|
|
8324
|
+
function loadPrismaState(schemaPath) {
|
|
8325
|
+
if (!schemaPath || !(0, import_node_fs7.existsSync)(schemaPath)) return null;
|
|
8005
8326
|
const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
|
|
8006
8327
|
const tables = /* @__PURE__ */ new Map();
|
|
8007
8328
|
const enums = /* @__PURE__ */ new Map();
|
|
@@ -8166,14 +8487,28 @@ function verify(sqlState, prisma) {
|
|
|
8166
8487
|
}
|
|
8167
8488
|
return { contradictions, flaggedEdges };
|
|
8168
8489
|
}
|
|
8490
|
+
function migrationsDirFor(rootDir) {
|
|
8491
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8492
|
+
if (!paths) return null;
|
|
8493
|
+
if (paths.dbConfig.kind === "prisma" || paths.dbConfig.kind === "sql-migrations") {
|
|
8494
|
+
return paths.dbConfig.migrationsDir;
|
|
8495
|
+
}
|
|
8496
|
+
return null;
|
|
8497
|
+
}
|
|
8498
|
+
function schemaPathFor(rootDir) {
|
|
8499
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8500
|
+
if (!paths) return null;
|
|
8501
|
+
return paths.dbConfig.kind === "prisma" ? paths.dbConfig.schemaPath : null;
|
|
8502
|
+
}
|
|
8169
8503
|
function detect3(rootDir) {
|
|
8170
|
-
const
|
|
8171
|
-
if (!
|
|
8172
|
-
return (
|
|
8504
|
+
const dir = migrationsDirFor(rootDir);
|
|
8505
|
+
if (!dir) return false;
|
|
8506
|
+
return discoverMigrationFiles(dir).length > 0;
|
|
8173
8507
|
}
|
|
8174
8508
|
function generate3(rootDir) {
|
|
8175
|
-
const
|
|
8176
|
-
const
|
|
8509
|
+
const migrationsDir = migrationsDirFor(rootDir);
|
|
8510
|
+
const sqlState = parseMigrations(migrationsDir);
|
|
8511
|
+
const prisma = loadPrismaState(schemaPathFor(rootDir));
|
|
8177
8512
|
const prismaTableIds = prisma ? new Set(prisma.tables.keys()) : /* @__PURE__ */ new Set();
|
|
8178
8513
|
const prismaEnumIds = prisma ? new Set(prisma.enums.keys()) : /* @__PURE__ */ new Set();
|
|
8179
8514
|
const nodes = [];
|
|
@@ -8219,7 +8554,7 @@ function generate3(rootDir) {
|
|
|
8219
8554
|
metadata: {
|
|
8220
8555
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
8221
8556
|
scope: "sql-migrations",
|
|
8222
|
-
source: "
|
|
8557
|
+
source: migrationsDir ?? "none",
|
|
8223
8558
|
layer: "db",
|
|
8224
8559
|
sql_tables: sqlState.tables.size,
|
|
8225
8560
|
sql_enums: sqlState.enums.size,
|
|
@@ -8458,31 +8793,31 @@ var fetchResolverParser = {
|
|
|
8458
8793
|
|
|
8459
8794
|
// src/server/graph/parsers/crosslayer/api-annotations.ts
|
|
8460
8795
|
var import_node_fs8 = require("node:fs");
|
|
8461
|
-
var
|
|
8796
|
+
var import_node_path7 = require("node:path");
|
|
8462
8797
|
var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
|
|
8463
8798
|
function walk2(dir, exts) {
|
|
8464
8799
|
if (!(0, import_node_fs8.existsSync)(dir)) return [];
|
|
8465
8800
|
const results = [];
|
|
8466
8801
|
for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
|
|
8467
8802
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
8468
|
-
const full = (0,
|
|
8803
|
+
const full = (0, import_node_path7.join)(dir, entry.name);
|
|
8469
8804
|
if (entry.isDirectory()) {
|
|
8470
8805
|
results.push(...walk2(full, exts));
|
|
8471
|
-
} else if (exts.includes((0,
|
|
8806
|
+
} else if (exts.includes((0, import_node_path7.extname)(entry.name))) {
|
|
8472
8807
|
results.push(full);
|
|
8473
8808
|
}
|
|
8474
8809
|
}
|
|
8475
8810
|
return results;
|
|
8476
8811
|
}
|
|
8477
8812
|
function toNodeId2(srcDir, absPath) {
|
|
8478
|
-
return (0,
|
|
8813
|
+
return (0, import_node_path7.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
8479
8814
|
}
|
|
8480
8815
|
var apiAnnotationsParser = {
|
|
8481
8816
|
id: "api-annotations",
|
|
8482
8817
|
layer: "crosslayer",
|
|
8483
8818
|
concern: "api-binding",
|
|
8484
8819
|
detect(rootDir) {
|
|
8485
|
-
return (0, import_node_fs8.existsSync)((0,
|
|
8820
|
+
return (0, import_node_fs8.existsSync)((0, import_node_path7.join)(rootDir, "src"));
|
|
8486
8821
|
},
|
|
8487
8822
|
generate(rootDir, layerOutputs) {
|
|
8488
8823
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -8493,7 +8828,7 @@ var apiAnnotationsParser = {
|
|
|
8493
8828
|
const uiNodeIds = new Set(uiOutput?.nodes.map((n) => n.id) ?? []);
|
|
8494
8829
|
const apiRoutes = loadApiRoutesFromOutput(apiOutput);
|
|
8495
8830
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
8496
|
-
const srcDir = (0,
|
|
8831
|
+
const srcDir = (0, import_node_path7.join)(rootDir, "src");
|
|
8497
8832
|
const files = walk2(srcDir, [".ts", ".tsx"]);
|
|
8498
8833
|
const crossRefs = [];
|
|
8499
8834
|
const flaggedEdges = [];
|
|
@@ -8544,7 +8879,7 @@ var apiAnnotationsParser = {
|
|
|
8544
8879
|
|
|
8545
8880
|
// src/server/graph/parsers/crosslayer/url-literal-scanner.ts
|
|
8546
8881
|
var import_node_fs9 = require("node:fs");
|
|
8547
|
-
var
|
|
8882
|
+
var import_node_path8 = require("node:path");
|
|
8548
8883
|
init_config();
|
|
8549
8884
|
var URL_LITERAL_RE = /['"`](\/api\/[^'"`\s]+?)['"`]/g;
|
|
8550
8885
|
function walk3(dir, exts) {
|
|
@@ -8552,17 +8887,17 @@ function walk3(dir, exts) {
|
|
|
8552
8887
|
const results = [];
|
|
8553
8888
|
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
8554
8889
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
8555
|
-
const full = (0,
|
|
8890
|
+
const full = (0, import_node_path8.join)(dir, entry.name);
|
|
8556
8891
|
if (entry.isDirectory()) {
|
|
8557
8892
|
results.push(...walk3(full, exts));
|
|
8558
|
-
} else if (exts.includes((0,
|
|
8893
|
+
} else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
|
|
8559
8894
|
results.push(full);
|
|
8560
8895
|
}
|
|
8561
8896
|
}
|
|
8562
8897
|
return results;
|
|
8563
8898
|
}
|
|
8564
8899
|
function toNodeId3(srcDir, absPath) {
|
|
8565
|
-
return (0,
|
|
8900
|
+
return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
8566
8901
|
}
|
|
8567
8902
|
var urlLiteralScannerParser = {
|
|
8568
8903
|
id: "url-literal-scanner",
|
|
@@ -8583,7 +8918,7 @@ var urlLiteralScannerParser = {
|
|
|
8583
8918
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
8584
8919
|
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8585
8920
|
const srcDir = paths.srcDir;
|
|
8586
|
-
const clientDir = (0,
|
|
8921
|
+
const clientDir = (0, import_node_path8.join)(srcDir, "client");
|
|
8587
8922
|
const files = [
|
|
8588
8923
|
...walk3(clientDir, [".ts", ".tsx"]),
|
|
8589
8924
|
...walk3(paths.appDir, [".ts", ".tsx"])
|
|
@@ -8625,7 +8960,7 @@ var urlLiteralScannerParser = {
|
|
|
8625
8960
|
|
|
8626
8961
|
// src/server/graph/parsers/static/static-values.ts
|
|
8627
8962
|
var import_node_fs10 = require("node:fs");
|
|
8628
|
-
var
|
|
8963
|
+
var import_node_path9 = require("node:path");
|
|
8629
8964
|
var parseCode = null;
|
|
8630
8965
|
function tryLoadTreeSitter() {
|
|
8631
8966
|
if (parseCode) return true;
|
|
@@ -8658,8 +8993,8 @@ function extractEnumValues(rootDir) {
|
|
|
8658
8993
|
const nodes = [];
|
|
8659
8994
|
const edges = [];
|
|
8660
8995
|
const schemaPaths = [
|
|
8661
|
-
(0,
|
|
8662
|
-
(0,
|
|
8996
|
+
(0, import_node_path9.join)(rootDir, "prisma", "schema.prisma"),
|
|
8997
|
+
(0, import_node_path9.join)(rootDir, "prisma", "schema")
|
|
8663
8998
|
];
|
|
8664
8999
|
let content = "";
|
|
8665
9000
|
for (const p of schemaPaths) {
|
|
@@ -8670,7 +9005,7 @@ function extractEnumValues(rootDir) {
|
|
|
8670
9005
|
content = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
8671
9006
|
} else if (stat.isDirectory()) {
|
|
8672
9007
|
const files = (0, import_node_fs10.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
|
|
8673
|
-
content = files.map((f) => (0, import_node_fs10.readFileSync)((0,
|
|
9008
|
+
content = files.map((f) => (0, import_node_fs10.readFileSync)((0, import_node_path9.join)(p, f), "utf-8")).join("\n");
|
|
8674
9009
|
}
|
|
8675
9010
|
} catch {
|
|
8676
9011
|
continue;
|
|
@@ -8826,14 +9161,14 @@ function extractSeedData(rootDir) {
|
|
|
8826
9161
|
const nodes = [];
|
|
8827
9162
|
const edges = [];
|
|
8828
9163
|
const seedFiles = [
|
|
8829
|
-
(0,
|
|
8830
|
-
(0,
|
|
8831
|
-
(0,
|
|
9164
|
+
(0, import_node_path9.join)(rootDir, "prisma", "seed.ts"),
|
|
9165
|
+
(0, import_node_path9.join)(rootDir, "prisma", "seed.js"),
|
|
9166
|
+
(0, import_node_path9.join)(rootDir, "src", "server", "lib", "system-tags.ts")
|
|
8832
9167
|
].filter(import_node_fs10.existsSync);
|
|
8833
9168
|
const useTreeSitter = tryLoadTreeSitter();
|
|
8834
9169
|
for (const filePath of seedFiles) {
|
|
8835
9170
|
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
8836
|
-
const relPath = (0,
|
|
9171
|
+
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
8837
9172
|
const seeded = detectSeededArrays(content, relPath);
|
|
8838
9173
|
let astRoot = null;
|
|
8839
9174
|
if (useTreeSitter && parseCode) {
|
|
@@ -8931,7 +9266,7 @@ function walkDir(dir, exts) {
|
|
|
8931
9266
|
const results = [];
|
|
8932
9267
|
for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
|
|
8933
9268
|
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
|
|
8934
|
-
const full = (0,
|
|
9269
|
+
const full = (0, import_node_path9.join)(dir, entry.name);
|
|
8935
9270
|
if (entry.isDirectory()) results.push(...walkDir(full, exts));
|
|
8936
9271
|
else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
|
|
8937
9272
|
}
|
|
@@ -8939,11 +9274,11 @@ function walkDir(dir, exts) {
|
|
|
8939
9274
|
}
|
|
8940
9275
|
function extractConstants(rootDir) {
|
|
8941
9276
|
const nodes = [];
|
|
8942
|
-
const srcDir = (0,
|
|
9277
|
+
const srcDir = (0, import_node_path9.join)(rootDir, "src");
|
|
8943
9278
|
if (!(0, import_node_fs10.existsSync)(srcDir)) return { nodes };
|
|
8944
9279
|
for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
|
|
8945
9280
|
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
8946
|
-
const relPath = (0,
|
|
9281
|
+
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
8947
9282
|
const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
|
|
8948
9283
|
let cm;
|
|
8949
9284
|
while ((cm = constArrayRe.exec(content)) !== null) {
|
|
@@ -8976,7 +9311,7 @@ function extractConstants(rootDir) {
|
|
|
8976
9311
|
return { nodes };
|
|
8977
9312
|
}
|
|
8978
9313
|
function detect4(rootDir) {
|
|
8979
|
-
return (0, import_node_fs10.existsSync)((0,
|
|
9314
|
+
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"));
|
|
8980
9315
|
}
|
|
8981
9316
|
function generate4(rootDir) {
|
|
8982
9317
|
const enumResult = extractEnumValues(rootDir);
|
|
@@ -9052,7 +9387,7 @@ var staticValuesParser = {
|
|
|
9052
9387
|
|
|
9053
9388
|
// src/server/graph/parsers/crosslayer/static-ref-scanner.ts
|
|
9054
9389
|
var import_node_fs11 = require("node:fs");
|
|
9055
|
-
var
|
|
9390
|
+
var import_node_path10 = require("node:path");
|
|
9056
9391
|
init_config();
|
|
9057
9392
|
var MIN_VALUE_LENGTH = 4;
|
|
9058
9393
|
var SKIP_VALUES = /* @__PURE__ */ new Set([
|
|
@@ -9196,11 +9531,11 @@ var staticRefScannerParser = {
|
|
|
9196
9531
|
if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
|
|
9197
9532
|
const srcDir = paths.srcDir;
|
|
9198
9533
|
const files = [
|
|
9199
|
-
...walkWithIgnore((0,
|
|
9534
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "client"), [".ts", ".tsx"]),
|
|
9200
9535
|
...walkWithIgnore(paths.appDir, [".ts", ".tsx"]),
|
|
9201
|
-
...walkWithIgnore((0,
|
|
9202
|
-
...walkWithIgnore((0,
|
|
9203
|
-
...walkWithIgnore((0,
|
|
9536
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "server"), [".ts", ".tsx"]),
|
|
9537
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "lib"), [".ts", ".tsx"]),
|
|
9538
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "config"), [".ts", ".tsx"])
|
|
9204
9539
|
];
|
|
9205
9540
|
const uiOutput = layerOutputs.get("ui");
|
|
9206
9541
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -9218,7 +9553,7 @@ var staticRefScannerParser = {
|
|
|
9218
9553
|
const seen = /* @__PURE__ */ new Set();
|
|
9219
9554
|
let filesScanned = 0;
|
|
9220
9555
|
for (const absPath of files) {
|
|
9221
|
-
const sourceId = (0,
|
|
9556
|
+
const sourceId = (0, import_node_path10.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
9222
9557
|
const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
|
|
9223
9558
|
if (!sourceLayer) continue;
|
|
9224
9559
|
const content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
|
|
@@ -9337,7 +9672,7 @@ function registerBuiltins(registry, disabled) {
|
|
|
9337
9672
|
function loadCustomParsers(registry, config, rootDir, disabled) {
|
|
9338
9673
|
for (const entry of config.parsers?.custom ?? []) {
|
|
9339
9674
|
try {
|
|
9340
|
-
const absPath = (0,
|
|
9675
|
+
const absPath = (0, import_node_path11.resolve)(rootDir, entry.path);
|
|
9341
9676
|
const mod = require(absPath);
|
|
9342
9677
|
const parser = "default" in mod ? mod.default : mod;
|
|
9343
9678
|
if (disabled.has(parser.id)) continue;
|
|
@@ -9467,7 +9802,7 @@ function applyCrossLayerResults(uiOutput, results) {
|
|
|
9467
9802
|
|
|
9468
9803
|
// src/server/graph/core/graph-builder.ts
|
|
9469
9804
|
function readGraphFromDisk(rootDir, layer) {
|
|
9470
|
-
const filePath = (0,
|
|
9805
|
+
const filePath = (0, import_node_path12.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
9471
9806
|
if (!(0, import_node_fs12.existsSync)(filePath)) return null;
|
|
9472
9807
|
try {
|
|
9473
9808
|
return JSON.parse((0, import_node_fs12.readFileSync)(filePath, "utf-8"));
|
|
@@ -9571,11 +9906,11 @@ function generateAll(rootDir) {
|
|
|
9571
9906
|
init_config();
|
|
9572
9907
|
|
|
9573
9908
|
// src/server/graph/core/tagger-registry.ts
|
|
9574
|
-
var
|
|
9909
|
+
var import_node_path14 = require("node:path");
|
|
9575
9910
|
|
|
9576
9911
|
// src/server/graph/taggers/module-tagger.ts
|
|
9577
9912
|
var import_node_fs13 = require("node:fs");
|
|
9578
|
-
var
|
|
9913
|
+
var import_node_path13 = require("node:path");
|
|
9579
9914
|
function matchGlob(pattern, id) {
|
|
9580
9915
|
const patParts = pattern.split("/");
|
|
9581
9916
|
const idParts = id.split("/");
|
|
@@ -9608,13 +9943,13 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
|
|
|
9608
9943
|
const conventionDirs = [...CONVENTION_DIRS_BUILTIN, ...extraConventionDirs];
|
|
9609
9944
|
const searchDirs = [
|
|
9610
9945
|
rootDir,
|
|
9611
|
-
(0,
|
|
9612
|
-
(0,
|
|
9613
|
-
(0,
|
|
9946
|
+
(0, import_node_path13.join)(rootDir, "src"),
|
|
9947
|
+
(0, import_node_path13.join)(rootDir, "app"),
|
|
9948
|
+
(0, import_node_path13.join)(rootDir, "lib")
|
|
9614
9949
|
];
|
|
9615
9950
|
for (const base of searchDirs) {
|
|
9616
9951
|
for (const convention of conventionDirs) {
|
|
9617
|
-
const dir = (0,
|
|
9952
|
+
const dir = (0, import_node_path13.join)(base, convention);
|
|
9618
9953
|
if (!(0, import_node_fs13.existsSync)(dir)) continue;
|
|
9619
9954
|
try {
|
|
9620
9955
|
const stat = (0, import_node_fs13.statSync)(dir);
|
|
@@ -9913,7 +10248,7 @@ function loadCustomTaggers(registry, config, rootDir, disabled) {
|
|
|
9913
10248
|
for (const entry of config.taggers?.custom ?? []) {
|
|
9914
10249
|
if (disabled.has(entry.id)) continue;
|
|
9915
10250
|
try {
|
|
9916
|
-
const absPath = (0,
|
|
10251
|
+
const absPath = (0, import_node_path14.resolve)(rootDir, entry.path);
|
|
9917
10252
|
const mod = require(absPath);
|
|
9918
10253
|
const tagger = "default" in mod ? mod.default : mod;
|
|
9919
10254
|
const override = config.taggers?.trackUntagged?.[tagger.id];
|
|
@@ -9937,12 +10272,12 @@ function createTaggerRegistry(config, rootDir) {
|
|
|
9937
10272
|
|
|
9938
10273
|
// src/server/graph/core/tag-store.ts
|
|
9939
10274
|
var import_node_fs14 = require("node:fs");
|
|
9940
|
-
var
|
|
10275
|
+
var import_node_path15 = require("node:path");
|
|
9941
10276
|
var TAGS_FILENAME = "tags.json";
|
|
9942
10277
|
var GRAPHS_DIR = ".launchsecure/graphs";
|
|
9943
10278
|
var tagCache = /* @__PURE__ */ new Map();
|
|
9944
10279
|
function tagsFilePath(rootDir) {
|
|
9945
|
-
return (0,
|
|
10280
|
+
return (0, import_node_path15.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
|
|
9946
10281
|
}
|
|
9947
10282
|
function readTagStore(rootDir) {
|
|
9948
10283
|
const filePath = tagsFilePath(rootDir);
|
|
@@ -9963,7 +10298,7 @@ function readTagStore(rootDir) {
|
|
|
9963
10298
|
}
|
|
9964
10299
|
function writeTagStore(rootDir, store) {
|
|
9965
10300
|
const filePath = tagsFilePath(rootDir);
|
|
9966
|
-
const dir = (0,
|
|
10301
|
+
const dir = (0, import_node_path15.dirname)(filePath);
|
|
9967
10302
|
(0, import_node_fs14.mkdirSync)(dir, { recursive: true });
|
|
9968
10303
|
const cleaned = {};
|
|
9969
10304
|
for (const [nodeId, tags] of Object.entries(store)) {
|
|
@@ -9994,20 +10329,20 @@ function removeTag(rootDir, nodeId, key) {
|
|
|
9994
10329
|
init_ts_extractor();
|
|
9995
10330
|
var GRAPHS_DIR2 = ".launchsecure/graphs";
|
|
9996
10331
|
function getAvailableLayers(rootDir) {
|
|
9997
|
-
const dir = (0,
|
|
10332
|
+
const dir = (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
|
|
9998
10333
|
if (!(0, import_node_fs15.existsSync)(dir)) return [];
|
|
9999
10334
|
return (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
|
|
10000
10335
|
}
|
|
10001
10336
|
var graphCache = /* @__PURE__ */ new Map();
|
|
10002
10337
|
var taggedCache = /* @__PURE__ */ new Map();
|
|
10003
10338
|
function graphsDir(rootDir) {
|
|
10004
|
-
return (0,
|
|
10339
|
+
return (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
|
|
10005
10340
|
}
|
|
10006
10341
|
function graphFilePath(rootDir, layer) {
|
|
10007
|
-
return (0,
|
|
10342
|
+
return (0, import_node_path16.join)(graphsDir(rootDir), `${layer}.json`);
|
|
10008
10343
|
}
|
|
10009
10344
|
function tagsFilePath2(rootDir) {
|
|
10010
|
-
return (0,
|
|
10345
|
+
return (0, import_node_path16.join)(graphsDir(rootDir), "tags.json");
|
|
10011
10346
|
}
|
|
10012
10347
|
function getMtimeMs(filePath) {
|
|
10013
10348
|
if (!(0, import_node_fs15.existsSync)(filePath)) return 0;
|
|
@@ -10160,7 +10495,7 @@ async function handleGraphCommand(subcommand, args) {
|
|
|
10160
10495
|
|
|
10161
10496
|
// src/server/graph-mcp.ts
|
|
10162
10497
|
var import_node_fs19 = require("node:fs");
|
|
10163
|
-
var
|
|
10498
|
+
var import_node_path20 = require("node:path");
|
|
10164
10499
|
var import_node_child_process2 = require("node:child_process");
|
|
10165
10500
|
var import_node_os2 = require("node:os");
|
|
10166
10501
|
|
|
@@ -10168,15 +10503,15 @@ var import_node_os2 = require("node:os");
|
|
|
10168
10503
|
var import_node_child_process = require("node:child_process");
|
|
10169
10504
|
var import_node_fs16 = require("node:fs");
|
|
10170
10505
|
var import_node_os = require("node:os");
|
|
10171
|
-
var
|
|
10506
|
+
var import_node_path17 = require("node:path");
|
|
10172
10507
|
function lockDir(projectRoot) {
|
|
10173
10508
|
if (projectRoot) {
|
|
10174
|
-
return (0,
|
|
10509
|
+
return (0, import_node_path17.join)(projectRoot, ".launchsecure");
|
|
10175
10510
|
}
|
|
10176
|
-
return (0,
|
|
10511
|
+
return (0, import_node_path17.join)((0, import_node_os.homedir)(), ".launchsecure");
|
|
10177
10512
|
}
|
|
10178
10513
|
function lockPath(projectRoot) {
|
|
10179
|
-
return (0,
|
|
10514
|
+
return (0, import_node_path17.join)(lockDir(projectRoot), "launch-chart.lock");
|
|
10180
10515
|
}
|
|
10181
10516
|
var _activeProjectRoot;
|
|
10182
10517
|
function readLock(projectRoot) {
|
|
@@ -10255,7 +10590,7 @@ init_config();
|
|
|
10255
10590
|
|
|
10256
10591
|
// src/server/graph/core/language-detection.ts
|
|
10257
10592
|
var import_node_fs17 = require("node:fs");
|
|
10258
|
-
var
|
|
10593
|
+
var import_node_path18 = require("node:path");
|
|
10259
10594
|
var EXTENSION_TO_LANGUAGE = {
|
|
10260
10595
|
// Web / Frontend
|
|
10261
10596
|
".ts": "typescript",
|
|
@@ -10378,9 +10713,9 @@ function walkForExtensions(dir, extCounts, depth = 0) {
|
|
|
10378
10713
|
if (entry.name.startsWith(".") && entry.isDirectory()) continue;
|
|
10379
10714
|
if (entry.isDirectory()) {
|
|
10380
10715
|
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
10381
|
-
walkForExtensions((0,
|
|
10716
|
+
walkForExtensions((0, import_node_path18.join)(dir, entry.name), extCounts, depth + 1);
|
|
10382
10717
|
} else {
|
|
10383
|
-
const ext = (0,
|
|
10718
|
+
const ext = (0, import_node_path18.extname)(entry.name).toLowerCase();
|
|
10384
10719
|
if (ext && EXTENSION_TO_LANGUAGE[ext]) {
|
|
10385
10720
|
extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
|
|
10386
10721
|
}
|
|
@@ -10422,9 +10757,9 @@ function detectLanguages(rootDir, supportedLanguages) {
|
|
|
10422
10757
|
|
|
10423
10758
|
// src/server/graph/core/audit-core.ts
|
|
10424
10759
|
var import_node_fs18 = require("node:fs");
|
|
10425
|
-
var
|
|
10760
|
+
var import_node_path19 = require("node:path");
|
|
10426
10761
|
function readGraphFile(rootDir, layer) {
|
|
10427
|
-
const filePath = (0,
|
|
10762
|
+
const filePath = (0, import_node_path19.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
10428
10763
|
if (!(0, import_node_fs18.existsSync)(filePath)) return null;
|
|
10429
10764
|
try {
|
|
10430
10765
|
return JSON.parse((0, import_node_fs18.readFileSync)(filePath, "utf-8"));
|
|
@@ -10471,7 +10806,7 @@ function checkUnprotectedRoutes(rootDir) {
|
|
|
10471
10806
|
const api = readGraphFile(rootDir, "api");
|
|
10472
10807
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
10473
10808
|
if (!api) return buildReport("api", "unprotected_routes", findings);
|
|
10474
|
-
const routePermsPath = (0,
|
|
10809
|
+
const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
10475
10810
|
let routePermsContent = "";
|
|
10476
10811
|
if ((0, import_node_fs18.existsSync)(routePermsPath)) {
|
|
10477
10812
|
routePermsContent = (0, import_node_fs18.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -10551,7 +10886,7 @@ function checkUnenforcedPermissions(rootDir) {
|
|
|
10551
10886
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
10552
10887
|
if (!staticGraph) return buildReport("static", "unenforced_permissions", findings);
|
|
10553
10888
|
const permissions = staticGraph.nodes.filter((n) => n.type === "seed_permission").map((n) => ({ id: n.id, key: n.value, name: n.name }));
|
|
10554
|
-
const routePermsPath = (0,
|
|
10889
|
+
const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
10555
10890
|
let routePermsContent = "";
|
|
10556
10891
|
if ((0, import_node_fs18.existsSync)(routePermsPath)) {
|
|
10557
10892
|
routePermsContent = (0, import_node_fs18.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -10584,7 +10919,7 @@ function checkHardcodedValues(rootDir) {
|
|
|
10584
10919
|
const seen = /* @__PURE__ */ new Set();
|
|
10585
10920
|
for (const node of api.nodes) {
|
|
10586
10921
|
if (node.type !== "endpoint") continue;
|
|
10587
|
-
const filePath = (0,
|
|
10922
|
+
const filePath = (0, import_node_path19.join)(rootDir, "src", node.id);
|
|
10588
10923
|
if (!(0, import_node_fs18.existsSync)(filePath)) continue;
|
|
10589
10924
|
const content = (0, import_node_fs18.readFileSync)(filePath, "utf-8");
|
|
10590
10925
|
let m;
|
|
@@ -11489,11 +11824,11 @@ function handleReadGraph(args) {
|
|
|
11489
11824
|
return okJson(result);
|
|
11490
11825
|
}
|
|
11491
11826
|
function nodeToFilePath(rootDir, layer, nodeId) {
|
|
11492
|
-
if (layer === "ui" || layer === "api") return (0,
|
|
11493
|
-
if (layer === "db") return (0,
|
|
11494
|
-
const withSrc = (0,
|
|
11827
|
+
if (layer === "ui" || layer === "api") return (0, import_node_path20.join)(rootDir, "src", nodeId);
|
|
11828
|
+
if (layer === "db") return (0, import_node_path20.join)(rootDir, "prisma", "schema.prisma");
|
|
11829
|
+
const withSrc = (0, import_node_path20.join)(rootDir, "src", nodeId);
|
|
11495
11830
|
if ((0, import_node_fs19.existsSync)(withSrc)) return withSrc;
|
|
11496
|
-
const direct = (0,
|
|
11831
|
+
const direct = (0, import_node_path20.join)(rootDir, nodeId);
|
|
11497
11832
|
if ((0, import_node_fs19.existsSync)(direct)) return direct;
|
|
11498
11833
|
return null;
|
|
11499
11834
|
}
|
|
@@ -11706,9 +12041,9 @@ function handleStartChartServer(args) {
|
|
|
11706
12041
|
});
|
|
11707
12042
|
}
|
|
11708
12043
|
const entryPath = process.argv[1];
|
|
11709
|
-
const logDir = (0,
|
|
12044
|
+
const logDir = (0, import_node_path20.join)((0, import_node_os2.homedir)(), ".launchsecure");
|
|
11710
12045
|
(0, import_node_fs19.mkdirSync)(logDir, { recursive: true });
|
|
11711
|
-
const logPath = (0,
|
|
12046
|
+
const logPath = (0, import_node_path20.join)(logDir, "launch-chart.log");
|
|
11712
12047
|
const out = (0, import_node_fs19.openSync)(logPath, "a");
|
|
11713
12048
|
const err2 = (0, import_node_fs19.openSync)(logPath, "a");
|
|
11714
12049
|
const portArgs = args.port ? ["--port", String(args.port)] : [];
|
|
@@ -11830,18 +12165,18 @@ function handleDetectProjectStack() {
|
|
|
11830
12165
|
if (ref.type === "references_api") stats.references_api++;
|
|
11831
12166
|
}
|
|
11832
12167
|
}
|
|
11833
|
-
const srcDir = (0,
|
|
12168
|
+
const srcDir = (0, import_node_path20.join)(rootDir, "src");
|
|
11834
12169
|
if ((0, import_node_fs19.existsSync)(srcDir)) {
|
|
11835
12170
|
const scanDir = (dir) => {
|
|
11836
12171
|
if (!(0, import_node_fs19.existsSync)(dir)) return;
|
|
11837
12172
|
for (const entry of (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true })) {
|
|
11838
12173
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
11839
|
-
const full = (0,
|
|
12174
|
+
const full = (0, import_node_path20.join)(dir, entry.name);
|
|
11840
12175
|
if (entry.isDirectory()) {
|
|
11841
12176
|
scanDir(full);
|
|
11842
12177
|
continue;
|
|
11843
12178
|
}
|
|
11844
|
-
if (![".ts", ".tsx"].includes((0,
|
|
12179
|
+
if (![".ts", ".tsx"].includes((0, import_node_path20.extname)(entry.name))) continue;
|
|
11845
12180
|
try {
|
|
11846
12181
|
const content = (0, import_node_fs19.readFileSync)(full, "utf-8");
|
|
11847
12182
|
const matches = content.match(/@api\s+(GET|POST|PUT|DELETE|PATCH)\s+\/\S+/g);
|
|
@@ -12062,7 +12397,7 @@ function parseArgs() {
|
|
|
12062
12397
|
return { port, token, serverUrl: LAUNCHSECURE_URL, subcommand };
|
|
12063
12398
|
}
|
|
12064
12399
|
function tryListen(server, port, maxRetries = 10) {
|
|
12065
|
-
return new Promise((
|
|
12400
|
+
return new Promise((resolve4, reject) => {
|
|
12066
12401
|
let attempts = 0;
|
|
12067
12402
|
function attempt(p) {
|
|
12068
12403
|
server.once("error", (err2) => {
|
|
@@ -12073,7 +12408,7 @@ function tryListen(server, port, maxRetries = 10) {
|
|
|
12073
12408
|
reject(err2);
|
|
12074
12409
|
}
|
|
12075
12410
|
});
|
|
12076
|
-
server.listen(p, () =>
|
|
12411
|
+
server.listen(p, () => resolve4(p));
|
|
12077
12412
|
}
|
|
12078
12413
|
attempt(port);
|
|
12079
12414
|
});
|
|
@@ -12094,7 +12429,7 @@ function saveCredentials(creds) {
|
|
|
12094
12429
|
});
|
|
12095
12430
|
}
|
|
12096
12431
|
function verifyToken(serverUrl, token) {
|
|
12097
|
-
return new Promise((
|
|
12432
|
+
return new Promise((resolve4) => {
|
|
12098
12433
|
const url = new URL("/api/mcp/verify", serverUrl);
|
|
12099
12434
|
const body = JSON.stringify({ token });
|
|
12100
12435
|
const mod = url.protocol === "https:" ? import_https.default : import_http.default;
|
|
@@ -12109,30 +12444,30 @@ function verifyToken(serverUrl, token) {
|
|
|
12109
12444
|
res.on("data", (chunk) => data += chunk);
|
|
12110
12445
|
res.on("end", () => {
|
|
12111
12446
|
try {
|
|
12112
|
-
|
|
12447
|
+
resolve4(JSON.parse(data));
|
|
12113
12448
|
} catch {
|
|
12114
|
-
|
|
12449
|
+
resolve4({ valid: false, error: "Invalid response from server" });
|
|
12115
12450
|
}
|
|
12116
12451
|
});
|
|
12117
12452
|
});
|
|
12118
12453
|
req.on("error", (err2) => {
|
|
12119
|
-
|
|
12454
|
+
resolve4({ valid: false, error: `Cannot reach server: ${err2.message}` });
|
|
12120
12455
|
});
|
|
12121
12456
|
req.setTimeout(1e4, () => {
|
|
12122
12457
|
req.destroy();
|
|
12123
|
-
|
|
12458
|
+
resolve4({ valid: false, error: "Connection timed out" });
|
|
12124
12459
|
});
|
|
12125
12460
|
req.write(body);
|
|
12126
12461
|
req.end();
|
|
12127
12462
|
});
|
|
12128
12463
|
}
|
|
12129
12464
|
function httpRequest(reqUrl, options, body, timeout = 3e4) {
|
|
12130
|
-
return new Promise((
|
|
12465
|
+
return new Promise((resolve4, reject) => {
|
|
12131
12466
|
const mod = reqUrl.protocol === "https:" ? import_https.default : import_http.default;
|
|
12132
12467
|
const r = mod.request(reqUrl, options, (resp) => {
|
|
12133
12468
|
let data = "";
|
|
12134
12469
|
resp.on("data", (chunk) => data += chunk);
|
|
12135
|
-
resp.on("end", () =>
|
|
12470
|
+
resp.on("end", () => resolve4({ status: resp.statusCode || 0, headers: resp.headers, body: data }));
|
|
12136
12471
|
});
|
|
12137
12472
|
r.on("error", reject);
|
|
12138
12473
|
r.setTimeout(timeout, () => {
|