@launchsecure/launch-kit 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +392 -169
- package/dist/server/cli.js +384 -168
- 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 +430 -206
- 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",
|
|
@@ -7976,19 +8169,29 @@ function parseUniqueIndex(sql, state) {
|
|
|
7976
8169
|
state.uniqueIndexes.get(m[1]).add(m[2]);
|
|
7977
8170
|
}
|
|
7978
8171
|
}
|
|
7979
|
-
function
|
|
7980
|
-
|
|
8172
|
+
function discoverMigrationFiles(migrationsDir) {
|
|
8173
|
+
if (!(0, import_node_fs7.existsSync)(migrationsDir)) return [];
|
|
8174
|
+
const out = [];
|
|
8175
|
+
const entries = (0, import_node_fs7.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
8176
|
+
for (const entry of entries) {
|
|
8177
|
+
if (entry.isDirectory()) {
|
|
8178
|
+
const sqlPath = (0, import_node_path6.join)(migrationsDir, entry.name, "migration.sql");
|
|
8179
|
+
if ((0, import_node_fs7.existsSync)(sqlPath)) out.push(sqlPath);
|
|
8180
|
+
} else if (entry.isFile() && entry.name.endsWith(".sql")) {
|
|
8181
|
+
out.push((0, import_node_path6.join)(migrationsDir, entry.name));
|
|
8182
|
+
}
|
|
8183
|
+
}
|
|
8184
|
+
return out;
|
|
8185
|
+
}
|
|
8186
|
+
function parseMigrations(migrationsDir) {
|
|
7981
8187
|
const state = {
|
|
7982
8188
|
tables: /* @__PURE__ */ new Map(),
|
|
7983
8189
|
enums: /* @__PURE__ */ new Map(),
|
|
7984
8190
|
fks: [],
|
|
7985
8191
|
uniqueIndexes: /* @__PURE__ */ new Map()
|
|
7986
8192
|
};
|
|
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;
|
|
8193
|
+
if (!migrationsDir) return state;
|
|
8194
|
+
for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
|
|
7992
8195
|
const sql = (0, import_node_fs7.readFileSync)(sqlPath, "utf-8");
|
|
7993
8196
|
parseCreateEnum(sql, state);
|
|
7994
8197
|
parseCreateTable(sql, state);
|
|
@@ -7999,9 +8202,8 @@ function parseMigrations(rootDir) {
|
|
|
7999
8202
|
}
|
|
8000
8203
|
return state;
|
|
8001
8204
|
}
|
|
8002
|
-
function loadPrismaState(
|
|
8003
|
-
|
|
8004
|
-
if (!(0, import_node_fs7.existsSync)(schemaPath)) return null;
|
|
8205
|
+
function loadPrismaState(schemaPath) {
|
|
8206
|
+
if (!schemaPath || !(0, import_node_fs7.existsSync)(schemaPath)) return null;
|
|
8005
8207
|
const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
|
|
8006
8208
|
const tables = /* @__PURE__ */ new Map();
|
|
8007
8209
|
const enums = /* @__PURE__ */ new Map();
|
|
@@ -8166,14 +8368,28 @@ function verify(sqlState, prisma) {
|
|
|
8166
8368
|
}
|
|
8167
8369
|
return { contradictions, flaggedEdges };
|
|
8168
8370
|
}
|
|
8371
|
+
function migrationsDirFor(rootDir) {
|
|
8372
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8373
|
+
if (!paths) return null;
|
|
8374
|
+
if (paths.dbConfig.kind === "prisma" || paths.dbConfig.kind === "sql-migrations") {
|
|
8375
|
+
return paths.dbConfig.migrationsDir;
|
|
8376
|
+
}
|
|
8377
|
+
return null;
|
|
8378
|
+
}
|
|
8379
|
+
function schemaPathFor(rootDir) {
|
|
8380
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8381
|
+
if (!paths) return null;
|
|
8382
|
+
return paths.dbConfig.kind === "prisma" ? paths.dbConfig.schemaPath : null;
|
|
8383
|
+
}
|
|
8169
8384
|
function detect3(rootDir) {
|
|
8170
|
-
const
|
|
8171
|
-
if (!
|
|
8172
|
-
return (
|
|
8385
|
+
const dir = migrationsDirFor(rootDir);
|
|
8386
|
+
if (!dir) return false;
|
|
8387
|
+
return discoverMigrationFiles(dir).length > 0;
|
|
8173
8388
|
}
|
|
8174
8389
|
function generate3(rootDir) {
|
|
8175
|
-
const
|
|
8176
|
-
const
|
|
8390
|
+
const migrationsDir = migrationsDirFor(rootDir);
|
|
8391
|
+
const sqlState = parseMigrations(migrationsDir);
|
|
8392
|
+
const prisma = loadPrismaState(schemaPathFor(rootDir));
|
|
8177
8393
|
const prismaTableIds = prisma ? new Set(prisma.tables.keys()) : /* @__PURE__ */ new Set();
|
|
8178
8394
|
const prismaEnumIds = prisma ? new Set(prisma.enums.keys()) : /* @__PURE__ */ new Set();
|
|
8179
8395
|
const nodes = [];
|
|
@@ -8219,7 +8435,7 @@ function generate3(rootDir) {
|
|
|
8219
8435
|
metadata: {
|
|
8220
8436
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
8221
8437
|
scope: "sql-migrations",
|
|
8222
|
-
source: "
|
|
8438
|
+
source: migrationsDir ?? "none",
|
|
8223
8439
|
layer: "db",
|
|
8224
8440
|
sql_tables: sqlState.tables.size,
|
|
8225
8441
|
sql_enums: sqlState.enums.size,
|
|
@@ -8458,31 +8674,31 @@ var fetchResolverParser = {
|
|
|
8458
8674
|
|
|
8459
8675
|
// src/server/graph/parsers/crosslayer/api-annotations.ts
|
|
8460
8676
|
var import_node_fs8 = require("node:fs");
|
|
8461
|
-
var
|
|
8677
|
+
var import_node_path7 = require("node:path");
|
|
8462
8678
|
var API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
|
|
8463
8679
|
function walk2(dir, exts) {
|
|
8464
8680
|
if (!(0, import_node_fs8.existsSync)(dir)) return [];
|
|
8465
8681
|
const results = [];
|
|
8466
8682
|
for (const entry of (0, import_node_fs8.readdirSync)(dir, { withFileTypes: true })) {
|
|
8467
8683
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
8468
|
-
const full = (0,
|
|
8684
|
+
const full = (0, import_node_path7.join)(dir, entry.name);
|
|
8469
8685
|
if (entry.isDirectory()) {
|
|
8470
8686
|
results.push(...walk2(full, exts));
|
|
8471
|
-
} else if (exts.includes((0,
|
|
8687
|
+
} else if (exts.includes((0, import_node_path7.extname)(entry.name))) {
|
|
8472
8688
|
results.push(full);
|
|
8473
8689
|
}
|
|
8474
8690
|
}
|
|
8475
8691
|
return results;
|
|
8476
8692
|
}
|
|
8477
8693
|
function toNodeId2(srcDir, absPath) {
|
|
8478
|
-
return (0,
|
|
8694
|
+
return (0, import_node_path7.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
8479
8695
|
}
|
|
8480
8696
|
var apiAnnotationsParser = {
|
|
8481
8697
|
id: "api-annotations",
|
|
8482
8698
|
layer: "crosslayer",
|
|
8483
8699
|
concern: "api-binding",
|
|
8484
8700
|
detect(rootDir) {
|
|
8485
|
-
return (0, import_node_fs8.existsSync)((0,
|
|
8701
|
+
return (0, import_node_fs8.existsSync)((0, import_node_path7.join)(rootDir, "src"));
|
|
8486
8702
|
},
|
|
8487
8703
|
generate(rootDir, layerOutputs) {
|
|
8488
8704
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -8493,7 +8709,7 @@ var apiAnnotationsParser = {
|
|
|
8493
8709
|
const uiNodeIds = new Set(uiOutput?.nodes.map((n) => n.id) ?? []);
|
|
8494
8710
|
const apiRoutes = loadApiRoutesFromOutput(apiOutput);
|
|
8495
8711
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
8496
|
-
const srcDir = (0,
|
|
8712
|
+
const srcDir = (0, import_node_path7.join)(rootDir, "src");
|
|
8497
8713
|
const files = walk2(srcDir, [".ts", ".tsx"]);
|
|
8498
8714
|
const crossRefs = [];
|
|
8499
8715
|
const flaggedEdges = [];
|
|
@@ -8544,7 +8760,7 @@ var apiAnnotationsParser = {
|
|
|
8544
8760
|
|
|
8545
8761
|
// src/server/graph/parsers/crosslayer/url-literal-scanner.ts
|
|
8546
8762
|
var import_node_fs9 = require("node:fs");
|
|
8547
|
-
var
|
|
8763
|
+
var import_node_path8 = require("node:path");
|
|
8548
8764
|
init_config();
|
|
8549
8765
|
var URL_LITERAL_RE = /['"`](\/api\/[^'"`\s]+?)['"`]/g;
|
|
8550
8766
|
function walk3(dir, exts) {
|
|
@@ -8552,17 +8768,17 @@ function walk3(dir, exts) {
|
|
|
8552
8768
|
const results = [];
|
|
8553
8769
|
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
8554
8770
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
8555
|
-
const full = (0,
|
|
8771
|
+
const full = (0, import_node_path8.join)(dir, entry.name);
|
|
8556
8772
|
if (entry.isDirectory()) {
|
|
8557
8773
|
results.push(...walk3(full, exts));
|
|
8558
|
-
} else if (exts.includes((0,
|
|
8774
|
+
} else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
|
|
8559
8775
|
results.push(full);
|
|
8560
8776
|
}
|
|
8561
8777
|
}
|
|
8562
8778
|
return results;
|
|
8563
8779
|
}
|
|
8564
8780
|
function toNodeId3(srcDir, absPath) {
|
|
8565
|
-
return (0,
|
|
8781
|
+
return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
8566
8782
|
}
|
|
8567
8783
|
var urlLiteralScannerParser = {
|
|
8568
8784
|
id: "url-literal-scanner",
|
|
@@ -8583,7 +8799,7 @@ var urlLiteralScannerParser = {
|
|
|
8583
8799
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
8584
8800
|
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
8585
8801
|
const srcDir = paths.srcDir;
|
|
8586
|
-
const clientDir = (0,
|
|
8802
|
+
const clientDir = (0, import_node_path8.join)(srcDir, "client");
|
|
8587
8803
|
const files = [
|
|
8588
8804
|
...walk3(clientDir, [".ts", ".tsx"]),
|
|
8589
8805
|
...walk3(paths.appDir, [".ts", ".tsx"])
|
|
@@ -8625,7 +8841,7 @@ var urlLiteralScannerParser = {
|
|
|
8625
8841
|
|
|
8626
8842
|
// src/server/graph/parsers/static/static-values.ts
|
|
8627
8843
|
var import_node_fs10 = require("node:fs");
|
|
8628
|
-
var
|
|
8844
|
+
var import_node_path9 = require("node:path");
|
|
8629
8845
|
var parseCode = null;
|
|
8630
8846
|
function tryLoadTreeSitter() {
|
|
8631
8847
|
if (parseCode) return true;
|
|
@@ -8658,8 +8874,8 @@ function extractEnumValues(rootDir) {
|
|
|
8658
8874
|
const nodes = [];
|
|
8659
8875
|
const edges = [];
|
|
8660
8876
|
const schemaPaths = [
|
|
8661
|
-
(0,
|
|
8662
|
-
(0,
|
|
8877
|
+
(0, import_node_path9.join)(rootDir, "prisma", "schema.prisma"),
|
|
8878
|
+
(0, import_node_path9.join)(rootDir, "prisma", "schema")
|
|
8663
8879
|
];
|
|
8664
8880
|
let content = "";
|
|
8665
8881
|
for (const p of schemaPaths) {
|
|
@@ -8670,7 +8886,7 @@ function extractEnumValues(rootDir) {
|
|
|
8670
8886
|
content = (0, import_node_fs10.readFileSync)(p, "utf-8");
|
|
8671
8887
|
} else if (stat.isDirectory()) {
|
|
8672
8888
|
const files = (0, import_node_fs10.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
|
|
8673
|
-
content = files.map((f) => (0, import_node_fs10.readFileSync)((0,
|
|
8889
|
+
content = files.map((f) => (0, import_node_fs10.readFileSync)((0, import_node_path9.join)(p, f), "utf-8")).join("\n");
|
|
8674
8890
|
}
|
|
8675
8891
|
} catch {
|
|
8676
8892
|
continue;
|
|
@@ -8826,14 +9042,14 @@ function extractSeedData(rootDir) {
|
|
|
8826
9042
|
const nodes = [];
|
|
8827
9043
|
const edges = [];
|
|
8828
9044
|
const seedFiles = [
|
|
8829
|
-
(0,
|
|
8830
|
-
(0,
|
|
8831
|
-
(0,
|
|
9045
|
+
(0, import_node_path9.join)(rootDir, "prisma", "seed.ts"),
|
|
9046
|
+
(0, import_node_path9.join)(rootDir, "prisma", "seed.js"),
|
|
9047
|
+
(0, import_node_path9.join)(rootDir, "src", "server", "lib", "system-tags.ts")
|
|
8832
9048
|
].filter(import_node_fs10.existsSync);
|
|
8833
9049
|
const useTreeSitter = tryLoadTreeSitter();
|
|
8834
9050
|
for (const filePath of seedFiles) {
|
|
8835
9051
|
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
8836
|
-
const relPath = (0,
|
|
9052
|
+
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
8837
9053
|
const seeded = detectSeededArrays(content, relPath);
|
|
8838
9054
|
let astRoot = null;
|
|
8839
9055
|
if (useTreeSitter && parseCode) {
|
|
@@ -8931,7 +9147,7 @@ function walkDir(dir, exts) {
|
|
|
8931
9147
|
const results = [];
|
|
8932
9148
|
for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
|
|
8933
9149
|
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
|
|
8934
|
-
const full = (0,
|
|
9150
|
+
const full = (0, import_node_path9.join)(dir, entry.name);
|
|
8935
9151
|
if (entry.isDirectory()) results.push(...walkDir(full, exts));
|
|
8936
9152
|
else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
|
|
8937
9153
|
}
|
|
@@ -8939,11 +9155,11 @@ function walkDir(dir, exts) {
|
|
|
8939
9155
|
}
|
|
8940
9156
|
function extractConstants(rootDir) {
|
|
8941
9157
|
const nodes = [];
|
|
8942
|
-
const srcDir = (0,
|
|
9158
|
+
const srcDir = (0, import_node_path9.join)(rootDir, "src");
|
|
8943
9159
|
if (!(0, import_node_fs10.existsSync)(srcDir)) return { nodes };
|
|
8944
9160
|
for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
|
|
8945
9161
|
const content = (0, import_node_fs10.readFileSync)(filePath, "utf-8");
|
|
8946
|
-
const relPath = (0,
|
|
9162
|
+
const relPath = (0, import_node_path9.relative)(rootDir, filePath);
|
|
8947
9163
|
const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
|
|
8948
9164
|
let cm;
|
|
8949
9165
|
while ((cm = constArrayRe.exec(content)) !== null) {
|
|
@@ -8976,7 +9192,7 @@ function extractConstants(rootDir) {
|
|
|
8976
9192
|
return { nodes };
|
|
8977
9193
|
}
|
|
8978
9194
|
function detect4(rootDir) {
|
|
8979
|
-
return (0, import_node_fs10.existsSync)((0,
|
|
9195
|
+
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
9196
|
}
|
|
8981
9197
|
function generate4(rootDir) {
|
|
8982
9198
|
const enumResult = extractEnumValues(rootDir);
|
|
@@ -9052,7 +9268,7 @@ var staticValuesParser = {
|
|
|
9052
9268
|
|
|
9053
9269
|
// src/server/graph/parsers/crosslayer/static-ref-scanner.ts
|
|
9054
9270
|
var import_node_fs11 = require("node:fs");
|
|
9055
|
-
var
|
|
9271
|
+
var import_node_path10 = require("node:path");
|
|
9056
9272
|
init_config();
|
|
9057
9273
|
var MIN_VALUE_LENGTH = 4;
|
|
9058
9274
|
var SKIP_VALUES = /* @__PURE__ */ new Set([
|
|
@@ -9196,11 +9412,11 @@ var staticRefScannerParser = {
|
|
|
9196
9412
|
if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
|
|
9197
9413
|
const srcDir = paths.srcDir;
|
|
9198
9414
|
const files = [
|
|
9199
|
-
...walkWithIgnore((0,
|
|
9415
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "client"), [".ts", ".tsx"]),
|
|
9200
9416
|
...walkWithIgnore(paths.appDir, [".ts", ".tsx"]),
|
|
9201
|
-
...walkWithIgnore((0,
|
|
9202
|
-
...walkWithIgnore((0,
|
|
9203
|
-
...walkWithIgnore((0,
|
|
9417
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "server"), [".ts", ".tsx"]),
|
|
9418
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "lib"), [".ts", ".tsx"]),
|
|
9419
|
+
...walkWithIgnore((0, import_node_path10.join)(srcDir, "config"), [".ts", ".tsx"])
|
|
9204
9420
|
];
|
|
9205
9421
|
const uiOutput = layerOutputs.get("ui");
|
|
9206
9422
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -9218,7 +9434,7 @@ var staticRefScannerParser = {
|
|
|
9218
9434
|
const seen = /* @__PURE__ */ new Set();
|
|
9219
9435
|
let filesScanned = 0;
|
|
9220
9436
|
for (const absPath of files) {
|
|
9221
|
-
const sourceId = (0,
|
|
9437
|
+
const sourceId = (0, import_node_path10.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
9222
9438
|
const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
|
|
9223
9439
|
if (!sourceLayer) continue;
|
|
9224
9440
|
const content = (0, import_node_fs11.readFileSync)(absPath, "utf-8");
|
|
@@ -9337,7 +9553,7 @@ function registerBuiltins(registry, disabled) {
|
|
|
9337
9553
|
function loadCustomParsers(registry, config, rootDir, disabled) {
|
|
9338
9554
|
for (const entry of config.parsers?.custom ?? []) {
|
|
9339
9555
|
try {
|
|
9340
|
-
const absPath = (0,
|
|
9556
|
+
const absPath = (0, import_node_path11.resolve)(rootDir, entry.path);
|
|
9341
9557
|
const mod = require(absPath);
|
|
9342
9558
|
const parser = "default" in mod ? mod.default : mod;
|
|
9343
9559
|
if (disabled.has(parser.id)) continue;
|
|
@@ -9467,7 +9683,7 @@ function applyCrossLayerResults(uiOutput, results) {
|
|
|
9467
9683
|
|
|
9468
9684
|
// src/server/graph/core/graph-builder.ts
|
|
9469
9685
|
function readGraphFromDisk(rootDir, layer) {
|
|
9470
|
-
const filePath = (0,
|
|
9686
|
+
const filePath = (0, import_node_path12.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
9471
9687
|
if (!(0, import_node_fs12.existsSync)(filePath)) return null;
|
|
9472
9688
|
try {
|
|
9473
9689
|
return JSON.parse((0, import_node_fs12.readFileSync)(filePath, "utf-8"));
|
|
@@ -9571,11 +9787,11 @@ function generateAll(rootDir) {
|
|
|
9571
9787
|
init_config();
|
|
9572
9788
|
|
|
9573
9789
|
// src/server/graph/core/tagger-registry.ts
|
|
9574
|
-
var
|
|
9790
|
+
var import_node_path14 = require("node:path");
|
|
9575
9791
|
|
|
9576
9792
|
// src/server/graph/taggers/module-tagger.ts
|
|
9577
9793
|
var import_node_fs13 = require("node:fs");
|
|
9578
|
-
var
|
|
9794
|
+
var import_node_path13 = require("node:path");
|
|
9579
9795
|
function matchGlob(pattern, id) {
|
|
9580
9796
|
const patParts = pattern.split("/");
|
|
9581
9797
|
const idParts = id.split("/");
|
|
@@ -9608,13 +9824,13 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
|
|
|
9608
9824
|
const conventionDirs = [...CONVENTION_DIRS_BUILTIN, ...extraConventionDirs];
|
|
9609
9825
|
const searchDirs = [
|
|
9610
9826
|
rootDir,
|
|
9611
|
-
(0,
|
|
9612
|
-
(0,
|
|
9613
|
-
(0,
|
|
9827
|
+
(0, import_node_path13.join)(rootDir, "src"),
|
|
9828
|
+
(0, import_node_path13.join)(rootDir, "app"),
|
|
9829
|
+
(0, import_node_path13.join)(rootDir, "lib")
|
|
9614
9830
|
];
|
|
9615
9831
|
for (const base of searchDirs) {
|
|
9616
9832
|
for (const convention of conventionDirs) {
|
|
9617
|
-
const dir = (0,
|
|
9833
|
+
const dir = (0, import_node_path13.join)(base, convention);
|
|
9618
9834
|
if (!(0, import_node_fs13.existsSync)(dir)) continue;
|
|
9619
9835
|
try {
|
|
9620
9836
|
const stat = (0, import_node_fs13.statSync)(dir);
|
|
@@ -9913,7 +10129,7 @@ function loadCustomTaggers(registry, config, rootDir, disabled) {
|
|
|
9913
10129
|
for (const entry of config.taggers?.custom ?? []) {
|
|
9914
10130
|
if (disabled.has(entry.id)) continue;
|
|
9915
10131
|
try {
|
|
9916
|
-
const absPath = (0,
|
|
10132
|
+
const absPath = (0, import_node_path14.resolve)(rootDir, entry.path);
|
|
9917
10133
|
const mod = require(absPath);
|
|
9918
10134
|
const tagger = "default" in mod ? mod.default : mod;
|
|
9919
10135
|
const override = config.taggers?.trackUntagged?.[tagger.id];
|
|
@@ -9937,12 +10153,12 @@ function createTaggerRegistry(config, rootDir) {
|
|
|
9937
10153
|
|
|
9938
10154
|
// src/server/graph/core/tag-store.ts
|
|
9939
10155
|
var import_node_fs14 = require("node:fs");
|
|
9940
|
-
var
|
|
10156
|
+
var import_node_path15 = require("node:path");
|
|
9941
10157
|
var TAGS_FILENAME = "tags.json";
|
|
9942
10158
|
var GRAPHS_DIR = ".launchsecure/graphs";
|
|
9943
10159
|
var tagCache = /* @__PURE__ */ new Map();
|
|
9944
10160
|
function tagsFilePath(rootDir) {
|
|
9945
|
-
return (0,
|
|
10161
|
+
return (0, import_node_path15.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
|
|
9946
10162
|
}
|
|
9947
10163
|
function readTagStore(rootDir) {
|
|
9948
10164
|
const filePath = tagsFilePath(rootDir);
|
|
@@ -9963,7 +10179,7 @@ function readTagStore(rootDir) {
|
|
|
9963
10179
|
}
|
|
9964
10180
|
function writeTagStore(rootDir, store) {
|
|
9965
10181
|
const filePath = tagsFilePath(rootDir);
|
|
9966
|
-
const dir = (0,
|
|
10182
|
+
const dir = (0, import_node_path15.dirname)(filePath);
|
|
9967
10183
|
(0, import_node_fs14.mkdirSync)(dir, { recursive: true });
|
|
9968
10184
|
const cleaned = {};
|
|
9969
10185
|
for (const [nodeId, tags] of Object.entries(store)) {
|
|
@@ -9994,20 +10210,20 @@ function removeTag(rootDir, nodeId, key) {
|
|
|
9994
10210
|
init_ts_extractor();
|
|
9995
10211
|
var GRAPHS_DIR2 = ".launchsecure/graphs";
|
|
9996
10212
|
function getAvailableLayers(rootDir) {
|
|
9997
|
-
const dir = (0,
|
|
10213
|
+
const dir = (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
|
|
9998
10214
|
if (!(0, import_node_fs15.existsSync)(dir)) return [];
|
|
9999
10215
|
return (0, import_node_fs15.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
|
|
10000
10216
|
}
|
|
10001
10217
|
var graphCache = /* @__PURE__ */ new Map();
|
|
10002
10218
|
var taggedCache = /* @__PURE__ */ new Map();
|
|
10003
10219
|
function graphsDir(rootDir) {
|
|
10004
|
-
return (0,
|
|
10220
|
+
return (0, import_node_path16.join)(rootDir, GRAPHS_DIR2);
|
|
10005
10221
|
}
|
|
10006
10222
|
function graphFilePath(rootDir, layer) {
|
|
10007
|
-
return (0,
|
|
10223
|
+
return (0, import_node_path16.join)(graphsDir(rootDir), `${layer}.json`);
|
|
10008
10224
|
}
|
|
10009
10225
|
function tagsFilePath2(rootDir) {
|
|
10010
|
-
return (0,
|
|
10226
|
+
return (0, import_node_path16.join)(graphsDir(rootDir), "tags.json");
|
|
10011
10227
|
}
|
|
10012
10228
|
function getMtimeMs(filePath) {
|
|
10013
10229
|
if (!(0, import_node_fs15.existsSync)(filePath)) return 0;
|
|
@@ -10160,7 +10376,7 @@ async function handleGraphCommand(subcommand, args) {
|
|
|
10160
10376
|
|
|
10161
10377
|
// src/server/graph-mcp.ts
|
|
10162
10378
|
var import_node_fs19 = require("node:fs");
|
|
10163
|
-
var
|
|
10379
|
+
var import_node_path20 = require("node:path");
|
|
10164
10380
|
var import_node_child_process2 = require("node:child_process");
|
|
10165
10381
|
var import_node_os2 = require("node:os");
|
|
10166
10382
|
|
|
@@ -10168,15 +10384,15 @@ var import_node_os2 = require("node:os");
|
|
|
10168
10384
|
var import_node_child_process = require("node:child_process");
|
|
10169
10385
|
var import_node_fs16 = require("node:fs");
|
|
10170
10386
|
var import_node_os = require("node:os");
|
|
10171
|
-
var
|
|
10387
|
+
var import_node_path17 = require("node:path");
|
|
10172
10388
|
function lockDir(projectRoot) {
|
|
10173
10389
|
if (projectRoot) {
|
|
10174
|
-
return (0,
|
|
10390
|
+
return (0, import_node_path17.join)(projectRoot, ".launchsecure");
|
|
10175
10391
|
}
|
|
10176
|
-
return (0,
|
|
10392
|
+
return (0, import_node_path17.join)((0, import_node_os.homedir)(), ".launchsecure");
|
|
10177
10393
|
}
|
|
10178
10394
|
function lockPath(projectRoot) {
|
|
10179
|
-
return (0,
|
|
10395
|
+
return (0, import_node_path17.join)(lockDir(projectRoot), "launch-chart.lock");
|
|
10180
10396
|
}
|
|
10181
10397
|
var _activeProjectRoot;
|
|
10182
10398
|
function readLock(projectRoot) {
|
|
@@ -10255,7 +10471,7 @@ init_config();
|
|
|
10255
10471
|
|
|
10256
10472
|
// src/server/graph/core/language-detection.ts
|
|
10257
10473
|
var import_node_fs17 = require("node:fs");
|
|
10258
|
-
var
|
|
10474
|
+
var import_node_path18 = require("node:path");
|
|
10259
10475
|
var EXTENSION_TO_LANGUAGE = {
|
|
10260
10476
|
// Web / Frontend
|
|
10261
10477
|
".ts": "typescript",
|
|
@@ -10378,9 +10594,9 @@ function walkForExtensions(dir, extCounts, depth = 0) {
|
|
|
10378
10594
|
if (entry.name.startsWith(".") && entry.isDirectory()) continue;
|
|
10379
10595
|
if (entry.isDirectory()) {
|
|
10380
10596
|
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
10381
|
-
walkForExtensions((0,
|
|
10597
|
+
walkForExtensions((0, import_node_path18.join)(dir, entry.name), extCounts, depth + 1);
|
|
10382
10598
|
} else {
|
|
10383
|
-
const ext = (0,
|
|
10599
|
+
const ext = (0, import_node_path18.extname)(entry.name).toLowerCase();
|
|
10384
10600
|
if (ext && EXTENSION_TO_LANGUAGE[ext]) {
|
|
10385
10601
|
extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
|
|
10386
10602
|
}
|
|
@@ -10422,9 +10638,9 @@ function detectLanguages(rootDir, supportedLanguages) {
|
|
|
10422
10638
|
|
|
10423
10639
|
// src/server/graph/core/audit-core.ts
|
|
10424
10640
|
var import_node_fs18 = require("node:fs");
|
|
10425
|
-
var
|
|
10641
|
+
var import_node_path19 = require("node:path");
|
|
10426
10642
|
function readGraphFile(rootDir, layer) {
|
|
10427
|
-
const filePath = (0,
|
|
10643
|
+
const filePath = (0, import_node_path19.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
10428
10644
|
if (!(0, import_node_fs18.existsSync)(filePath)) return null;
|
|
10429
10645
|
try {
|
|
10430
10646
|
return JSON.parse((0, import_node_fs18.readFileSync)(filePath, "utf-8"));
|
|
@@ -10471,7 +10687,7 @@ function checkUnprotectedRoutes(rootDir) {
|
|
|
10471
10687
|
const api = readGraphFile(rootDir, "api");
|
|
10472
10688
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
10473
10689
|
if (!api) return buildReport("api", "unprotected_routes", findings);
|
|
10474
|
-
const routePermsPath = (0,
|
|
10690
|
+
const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
10475
10691
|
let routePermsContent = "";
|
|
10476
10692
|
if ((0, import_node_fs18.existsSync)(routePermsPath)) {
|
|
10477
10693
|
routePermsContent = (0, import_node_fs18.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -10551,7 +10767,7 @@ function checkUnenforcedPermissions(rootDir) {
|
|
|
10551
10767
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
10552
10768
|
if (!staticGraph) return buildReport("static", "unenforced_permissions", findings);
|
|
10553
10769
|
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,
|
|
10770
|
+
const routePermsPath = (0, import_node_path19.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
10555
10771
|
let routePermsContent = "";
|
|
10556
10772
|
if ((0, import_node_fs18.existsSync)(routePermsPath)) {
|
|
10557
10773
|
routePermsContent = (0, import_node_fs18.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -10584,7 +10800,7 @@ function checkHardcodedValues(rootDir) {
|
|
|
10584
10800
|
const seen = /* @__PURE__ */ new Set();
|
|
10585
10801
|
for (const node of api.nodes) {
|
|
10586
10802
|
if (node.type !== "endpoint") continue;
|
|
10587
|
-
const filePath = (0,
|
|
10803
|
+
const filePath = (0, import_node_path19.join)(rootDir, "src", node.id);
|
|
10588
10804
|
if (!(0, import_node_fs18.existsSync)(filePath)) continue;
|
|
10589
10805
|
const content = (0, import_node_fs18.readFileSync)(filePath, "utf-8");
|
|
10590
10806
|
let m;
|
|
@@ -11489,11 +11705,11 @@ function handleReadGraph(args) {
|
|
|
11489
11705
|
return okJson(result);
|
|
11490
11706
|
}
|
|
11491
11707
|
function nodeToFilePath(rootDir, layer, nodeId) {
|
|
11492
|
-
if (layer === "ui" || layer === "api") return (0,
|
|
11493
|
-
if (layer === "db") return (0,
|
|
11494
|
-
const withSrc = (0,
|
|
11708
|
+
if (layer === "ui" || layer === "api") return (0, import_node_path20.join)(rootDir, "src", nodeId);
|
|
11709
|
+
if (layer === "db") return (0, import_node_path20.join)(rootDir, "prisma", "schema.prisma");
|
|
11710
|
+
const withSrc = (0, import_node_path20.join)(rootDir, "src", nodeId);
|
|
11495
11711
|
if ((0, import_node_fs19.existsSync)(withSrc)) return withSrc;
|
|
11496
|
-
const direct = (0,
|
|
11712
|
+
const direct = (0, import_node_path20.join)(rootDir, nodeId);
|
|
11497
11713
|
if ((0, import_node_fs19.existsSync)(direct)) return direct;
|
|
11498
11714
|
return null;
|
|
11499
11715
|
}
|
|
@@ -11706,9 +11922,9 @@ function handleStartChartServer(args) {
|
|
|
11706
11922
|
});
|
|
11707
11923
|
}
|
|
11708
11924
|
const entryPath = process.argv[1];
|
|
11709
|
-
const logDir = (0,
|
|
11925
|
+
const logDir = (0, import_node_path20.join)((0, import_node_os2.homedir)(), ".launchsecure");
|
|
11710
11926
|
(0, import_node_fs19.mkdirSync)(logDir, { recursive: true });
|
|
11711
|
-
const logPath = (0,
|
|
11927
|
+
const logPath = (0, import_node_path20.join)(logDir, "launch-chart.log");
|
|
11712
11928
|
const out = (0, import_node_fs19.openSync)(logPath, "a");
|
|
11713
11929
|
const err2 = (0, import_node_fs19.openSync)(logPath, "a");
|
|
11714
11930
|
const portArgs = args.port ? ["--port", String(args.port)] : [];
|
|
@@ -11830,18 +12046,18 @@ function handleDetectProjectStack() {
|
|
|
11830
12046
|
if (ref.type === "references_api") stats.references_api++;
|
|
11831
12047
|
}
|
|
11832
12048
|
}
|
|
11833
|
-
const srcDir = (0,
|
|
12049
|
+
const srcDir = (0, import_node_path20.join)(rootDir, "src");
|
|
11834
12050
|
if ((0, import_node_fs19.existsSync)(srcDir)) {
|
|
11835
12051
|
const scanDir = (dir) => {
|
|
11836
12052
|
if (!(0, import_node_fs19.existsSync)(dir)) return;
|
|
11837
12053
|
for (const entry of (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true })) {
|
|
11838
12054
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
11839
|
-
const full = (0,
|
|
12055
|
+
const full = (0, import_node_path20.join)(dir, entry.name);
|
|
11840
12056
|
if (entry.isDirectory()) {
|
|
11841
12057
|
scanDir(full);
|
|
11842
12058
|
continue;
|
|
11843
12059
|
}
|
|
11844
|
-
if (![".ts", ".tsx"].includes((0,
|
|
12060
|
+
if (![".ts", ".tsx"].includes((0, import_node_path20.extname)(entry.name))) continue;
|
|
11845
12061
|
try {
|
|
11846
12062
|
const content = (0, import_node_fs19.readFileSync)(full, "utf-8");
|
|
11847
12063
|
const matches = content.match(/@api\s+(GET|POST|PUT|DELETE|PATCH)\s+\/\S+/g);
|
|
@@ -12062,7 +12278,7 @@ function parseArgs() {
|
|
|
12062
12278
|
return { port, token, serverUrl: LAUNCHSECURE_URL, subcommand };
|
|
12063
12279
|
}
|
|
12064
12280
|
function tryListen(server, port, maxRetries = 10) {
|
|
12065
|
-
return new Promise((
|
|
12281
|
+
return new Promise((resolve4, reject) => {
|
|
12066
12282
|
let attempts = 0;
|
|
12067
12283
|
function attempt(p) {
|
|
12068
12284
|
server.once("error", (err2) => {
|
|
@@ -12073,7 +12289,7 @@ function tryListen(server, port, maxRetries = 10) {
|
|
|
12073
12289
|
reject(err2);
|
|
12074
12290
|
}
|
|
12075
12291
|
});
|
|
12076
|
-
server.listen(p, () =>
|
|
12292
|
+
server.listen(p, () => resolve4(p));
|
|
12077
12293
|
}
|
|
12078
12294
|
attempt(port);
|
|
12079
12295
|
});
|
|
@@ -12094,7 +12310,7 @@ function saveCredentials(creds) {
|
|
|
12094
12310
|
});
|
|
12095
12311
|
}
|
|
12096
12312
|
function verifyToken(serverUrl, token) {
|
|
12097
|
-
return new Promise((
|
|
12313
|
+
return new Promise((resolve4) => {
|
|
12098
12314
|
const url = new URL("/api/mcp/verify", serverUrl);
|
|
12099
12315
|
const body = JSON.stringify({ token });
|
|
12100
12316
|
const mod = url.protocol === "https:" ? import_https.default : import_http.default;
|
|
@@ -12109,30 +12325,30 @@ function verifyToken(serverUrl, token) {
|
|
|
12109
12325
|
res.on("data", (chunk) => data += chunk);
|
|
12110
12326
|
res.on("end", () => {
|
|
12111
12327
|
try {
|
|
12112
|
-
|
|
12328
|
+
resolve4(JSON.parse(data));
|
|
12113
12329
|
} catch {
|
|
12114
|
-
|
|
12330
|
+
resolve4({ valid: false, error: "Invalid response from server" });
|
|
12115
12331
|
}
|
|
12116
12332
|
});
|
|
12117
12333
|
});
|
|
12118
12334
|
req.on("error", (err2) => {
|
|
12119
|
-
|
|
12335
|
+
resolve4({ valid: false, error: `Cannot reach server: ${err2.message}` });
|
|
12120
12336
|
});
|
|
12121
12337
|
req.setTimeout(1e4, () => {
|
|
12122
12338
|
req.destroy();
|
|
12123
|
-
|
|
12339
|
+
resolve4({ valid: false, error: "Connection timed out" });
|
|
12124
12340
|
});
|
|
12125
12341
|
req.write(body);
|
|
12126
12342
|
req.end();
|
|
12127
12343
|
});
|
|
12128
12344
|
}
|
|
12129
12345
|
function httpRequest(reqUrl, options, body, timeout = 3e4) {
|
|
12130
|
-
return new Promise((
|
|
12346
|
+
return new Promise((resolve4, reject) => {
|
|
12131
12347
|
const mod = reqUrl.protocol === "https:" ? import_https.default : import_http.default;
|
|
12132
12348
|
const r = mod.request(reqUrl, options, (resp) => {
|
|
12133
12349
|
let data = "";
|
|
12134
12350
|
resp.on("data", (chunk) => data += chunk);
|
|
12135
|
-
resp.on("end", () =>
|
|
12351
|
+
resp.on("end", () => resolve4({ status: resp.statusCode || 0, headers: resp.headers, body: data }));
|
|
12136
12352
|
});
|
|
12137
12353
|
r.on("error", reject);
|
|
12138
12354
|
r.setTimeout(timeout, () => {
|