@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
|
@@ -155,48 +155,15 @@ var init_config = __esm({
|
|
|
155
155
|
}
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
// src/server/graph/core/resolve-paths.ts
|
|
159
|
-
function detectDbDir(rootDir, config) {
|
|
160
|
-
if (config.paths?.dbDir) return (0, import_node_path3.join)(rootDir, config.paths.dbDir);
|
|
161
|
-
const prismaDir = (0, import_node_path3.join)(rootDir, "prisma");
|
|
162
|
-
if ((0, import_node_fs3.existsSync)(prismaDir)) return prismaDir;
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
function resolveProjectPaths(rootDir, config) {
|
|
166
|
-
const dbDir = detectDbDir(rootDir, config);
|
|
167
|
-
if (config.paths?.appDir) {
|
|
168
|
-
const appDir = (0, import_node_path3.join)(rootDir, config.paths.appDir);
|
|
169
|
-
const srcDir = config.paths.srcDir ? (0, import_node_path3.join)(rootDir, config.paths.srcDir) : (0, import_node_path3.dirname)(appDir);
|
|
170
|
-
return { srcDir, appDir, apiDir: (0, import_node_path3.join)(appDir, "api"), dbDir };
|
|
171
|
-
}
|
|
172
|
-
const srcApp = (0, import_node_path3.join)(rootDir, "src", "app");
|
|
173
|
-
if ((0, import_node_fs3.existsSync)(srcApp)) {
|
|
174
|
-
return { srcDir: (0, import_node_path3.join)(rootDir, "src"), appDir: srcApp, apiDir: (0, import_node_path3.join)(srcApp, "api"), dbDir };
|
|
175
|
-
}
|
|
176
|
-
const rootApp = (0, import_node_path3.join)(rootDir, "app");
|
|
177
|
-
if ((0, import_node_fs3.existsSync)(rootApp)) {
|
|
178
|
-
return { srcDir: rootDir, appDir: rootApp, apiDir: (0, import_node_path3.join)(rootApp, "api"), dbDir };
|
|
179
|
-
}
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
var import_node_fs3, import_node_path3;
|
|
183
|
-
var init_resolve_paths = __esm({
|
|
184
|
-
"src/server/graph/core/resolve-paths.ts"() {
|
|
185
|
-
"use strict";
|
|
186
|
-
import_node_fs3 = require("node:fs");
|
|
187
|
-
import_node_path3 = require("node:path");
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
158
|
// src/server/graph/core/walk.ts
|
|
192
159
|
function walk(dir, exts) {
|
|
193
160
|
const results = [];
|
|
194
|
-
if (!(0,
|
|
195
|
-
for (const entry of (0,
|
|
196
|
-
const full = (0,
|
|
161
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return results;
|
|
162
|
+
for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
|
|
163
|
+
const full = (0, import_node_path3.join)(dir, entry.name);
|
|
197
164
|
if (entry.isDirectory()) {
|
|
198
165
|
results.push(...walk(full, exts));
|
|
199
|
-
} else if (exts.includes((0,
|
|
166
|
+
} else if (exts.includes((0, import_node_path3.extname)(entry.name))) {
|
|
200
167
|
results.push(full);
|
|
201
168
|
}
|
|
202
169
|
}
|
|
@@ -204,24 +171,24 @@ function walk(dir, exts) {
|
|
|
204
171
|
}
|
|
205
172
|
function walkWithIgnore(dir, exts, opts = {}) {
|
|
206
173
|
const results = [];
|
|
207
|
-
if (!(0,
|
|
174
|
+
if (!(0, import_node_fs3.existsSync)(dir)) return results;
|
|
208
175
|
const skip = opts.extraIgnore ? /* @__PURE__ */ new Set([...DEFAULT_IGNORE_DIRS, ...opts.extraIgnore]) : DEFAULT_IGNORE_DIRS;
|
|
209
|
-
for (const entry of (0,
|
|
176
|
+
for (const entry of (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true })) {
|
|
210
177
|
if (entry.isDirectory()) {
|
|
211
178
|
if (skip.has(entry.name)) continue;
|
|
212
|
-
results.push(...walkWithIgnore((0,
|
|
213
|
-
} else if (exts.includes((0,
|
|
214
|
-
results.push((0,
|
|
179
|
+
results.push(...walkWithIgnore((0, import_node_path3.join)(dir, entry.name), exts, opts));
|
|
180
|
+
} else if (exts.includes((0, import_node_path3.extname)(entry.name))) {
|
|
181
|
+
results.push((0, import_node_path3.join)(dir, entry.name));
|
|
215
182
|
}
|
|
216
183
|
}
|
|
217
184
|
return results;
|
|
218
185
|
}
|
|
219
|
-
var
|
|
186
|
+
var import_node_fs3, import_node_path3, DEFAULT_IGNORE_DIRS;
|
|
220
187
|
var init_walk = __esm({
|
|
221
188
|
"src/server/graph/core/walk.ts"() {
|
|
222
189
|
"use strict";
|
|
223
|
-
|
|
224
|
-
|
|
190
|
+
import_node_fs3 = require("node:fs");
|
|
191
|
+
import_node_path3 = require("node:path");
|
|
225
192
|
DEFAULT_IGNORE_DIRS = /* @__PURE__ */ new Set([
|
|
226
193
|
"node_modules",
|
|
227
194
|
".git",
|
|
@@ -238,6 +205,201 @@ var init_walk = __esm({
|
|
|
238
205
|
}
|
|
239
206
|
});
|
|
240
207
|
|
|
208
|
+
// src/server/graph/core/resolve-paths.ts
|
|
209
|
+
function hasSqlFiles(dir) {
|
|
210
|
+
if (!(0, import_node_fs4.existsSync)(dir)) return false;
|
|
211
|
+
try {
|
|
212
|
+
return (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true }).some(
|
|
213
|
+
(e) => e.isFile() && e.name.endsWith(".sql")
|
|
214
|
+
);
|
|
215
|
+
} catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function hasNestedMigrationSql(dir) {
|
|
220
|
+
if (!(0, import_node_fs4.existsSync)(dir)) return false;
|
|
221
|
+
try {
|
|
222
|
+
return (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true }).some(
|
|
223
|
+
(e) => e.isDirectory() && (0, import_node_fs4.existsSync)((0, import_node_path4.join)(dir, e.name, "migration.sql"))
|
|
224
|
+
);
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function resolveDbFromDir(dir) {
|
|
230
|
+
if (!(0, import_node_fs4.existsSync)(dir)) return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
231
|
+
const schemaPath = (0, import_node_path4.join)(dir, "schema.prisma");
|
|
232
|
+
if ((0, import_node_fs4.existsSync)(schemaPath)) {
|
|
233
|
+
const migrationsDir2 = (0, import_node_path4.join)(dir, "migrations");
|
|
234
|
+
return {
|
|
235
|
+
kind: "prisma",
|
|
236
|
+
schemaPath,
|
|
237
|
+
migrationsDir: (0, import_node_fs4.existsSync)(migrationsDir2) ? migrationsDir2 : null
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const migrationsDir = (0, import_node_path4.join)(dir, "migrations");
|
|
241
|
+
if (hasSqlFiles(migrationsDir) || hasNestedMigrationSql(migrationsDir)) {
|
|
242
|
+
return { kind: "sql-migrations", migrationsDir, schemaPath: null };
|
|
243
|
+
}
|
|
244
|
+
if (hasSqlFiles(dir) || hasNestedMigrationSql(dir)) {
|
|
245
|
+
return { kind: "sql-migrations", migrationsDir: dir, schemaPath: null };
|
|
246
|
+
}
|
|
247
|
+
return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
248
|
+
}
|
|
249
|
+
function detectDbConfig(rootDir, config) {
|
|
250
|
+
if (config.paths?.dbDir) {
|
|
251
|
+
return resolveDbFromDir((0, import_node_path4.join)(rootDir, config.paths.dbDir));
|
|
252
|
+
}
|
|
253
|
+
const candidates = ["prisma", "supabase", "drizzle", (0, import_node_path4.join)("db", "migrations"), "migrations"];
|
|
254
|
+
for (const c of candidates) {
|
|
255
|
+
const dir = (0, import_node_path4.join)(rootDir, c);
|
|
256
|
+
const resolved = resolveDbFromDir(dir);
|
|
257
|
+
if (resolved.kind !== "none") return resolved;
|
|
258
|
+
}
|
|
259
|
+
return { kind: "none", schemaPath: null, migrationsDir: null };
|
|
260
|
+
}
|
|
261
|
+
function detectDbDir(rootDir, config, dbConfig) {
|
|
262
|
+
if (config.paths?.dbDir) return (0, import_node_path4.join)(rootDir, config.paths.dbDir);
|
|
263
|
+
if (dbConfig.kind === "prisma") return (0, import_node_path4.dirname)(dbConfig.schemaPath);
|
|
264
|
+
if (dbConfig.kind === "sql-migrations") return dbConfig.migrationsDir;
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
function dirHasTSFiles(dir) {
|
|
268
|
+
if (!(0, import_node_fs4.existsSync)(dir)) return false;
|
|
269
|
+
try {
|
|
270
|
+
const stack = [dir];
|
|
271
|
+
while (stack.length > 0) {
|
|
272
|
+
const cur = stack.pop();
|
|
273
|
+
const entries = (0, import_node_fs4.readdirSync)(cur, { withFileTypes: true });
|
|
274
|
+
for (const e of entries) {
|
|
275
|
+
if (e.isFile() && (e.name.endsWith(".ts") || e.name.endsWith(".tsx"))) return true;
|
|
276
|
+
if (e.isDirectory() && !e.name.startsWith(".") && !DEFAULT_IGNORE_DIRS.has(e.name)) {
|
|
277
|
+
stack.push((0, import_node_path4.join)(cur, e.name));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
} catch {
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
function collectCodeBearingChildren(dir, extraSkip) {
|
|
286
|
+
if (!(0, import_node_fs4.existsSync)(dir)) return [];
|
|
287
|
+
const out = [];
|
|
288
|
+
try {
|
|
289
|
+
for (const entry of (0, import_node_fs4.readdirSync)(dir, { withFileTypes: true })) {
|
|
290
|
+
if (!entry.isDirectory()) continue;
|
|
291
|
+
if (entry.name.startsWith(".")) continue;
|
|
292
|
+
if (NON_SOURCE_DIRS.has(entry.name)) continue;
|
|
293
|
+
if (extraSkip?.has(entry.name)) continue;
|
|
294
|
+
const full = (0, import_node_path4.join)(dir, entry.name);
|
|
295
|
+
if (dirHasTSFiles(full)) out.push(full);
|
|
296
|
+
}
|
|
297
|
+
} catch {
|
|
298
|
+
}
|
|
299
|
+
return out;
|
|
300
|
+
}
|
|
301
|
+
function detectSrcRoots(rootDir, srcDir, appDir, config) {
|
|
302
|
+
if (config.paths?.srcRoots && config.paths.srcRoots.length > 0) {
|
|
303
|
+
const roots2 = /* @__PURE__ */ new Set();
|
|
304
|
+
roots2.add(appDir);
|
|
305
|
+
for (const r of config.paths.srcRoots) {
|
|
306
|
+
const abs = (0, import_node_path4.isAbsolute)(r) ? r : (0, import_node_path4.resolve)(rootDir, r);
|
|
307
|
+
roots2.add(abs);
|
|
308
|
+
}
|
|
309
|
+
return [...roots2];
|
|
310
|
+
}
|
|
311
|
+
const roots = /* @__PURE__ */ new Set();
|
|
312
|
+
roots.add(appDir);
|
|
313
|
+
for (const c of collectCodeBearingChildren(srcDir)) roots.add(c);
|
|
314
|
+
if (srcDir !== rootDir) {
|
|
315
|
+
const skipSrcWrapper = /* @__PURE__ */ new Set([(0, import_node_path4.basename)(srcDir)]);
|
|
316
|
+
for (const c of collectCodeBearingChildren(rootDir, skipSrcWrapper)) roots.add(c);
|
|
317
|
+
}
|
|
318
|
+
return [...roots];
|
|
319
|
+
}
|
|
320
|
+
function detectConventionFiles(rootDir, srcDir) {
|
|
321
|
+
const out = [];
|
|
322
|
+
const seen = /* @__PURE__ */ new Set();
|
|
323
|
+
const dirs = srcDir === rootDir ? [rootDir] : [srcDir, rootDir];
|
|
324
|
+
for (const dir of dirs) {
|
|
325
|
+
for (const name of CONVENTION_NAMES) {
|
|
326
|
+
const full = (0, import_node_path4.join)(dir, name);
|
|
327
|
+
if (!seen.has(full) && (0, import_node_fs4.existsSync)(full)) {
|
|
328
|
+
try {
|
|
329
|
+
if ((0, import_node_fs4.statSync)(full).isFile()) {
|
|
330
|
+
seen.add(full);
|
|
331
|
+
out.push(full);
|
|
332
|
+
}
|
|
333
|
+
} catch {
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return out;
|
|
339
|
+
}
|
|
340
|
+
function resolveProjectPaths(rootDir, config) {
|
|
341
|
+
let srcDir;
|
|
342
|
+
let appDir;
|
|
343
|
+
if (config.paths?.appDir) {
|
|
344
|
+
appDir = (0, import_node_path4.join)(rootDir, config.paths.appDir);
|
|
345
|
+
srcDir = config.paths.srcDir ? (0, import_node_path4.join)(rootDir, config.paths.srcDir) : (0, import_node_path4.dirname)(appDir);
|
|
346
|
+
} else {
|
|
347
|
+
const srcApp = (0, import_node_path4.join)(rootDir, "src", "app");
|
|
348
|
+
const rootApp = (0, import_node_path4.join)(rootDir, "app");
|
|
349
|
+
if ((0, import_node_fs4.existsSync)(srcApp)) {
|
|
350
|
+
srcDir = (0, import_node_path4.join)(rootDir, "src");
|
|
351
|
+
appDir = srcApp;
|
|
352
|
+
} else if ((0, import_node_fs4.existsSync)(rootApp)) {
|
|
353
|
+
srcDir = rootDir;
|
|
354
|
+
appDir = rootApp;
|
|
355
|
+
} else {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const apiDir = (0, import_node_path4.join)(appDir, "api");
|
|
360
|
+
const dbConfig = detectDbConfig(rootDir, config);
|
|
361
|
+
const dbDir = detectDbDir(rootDir, config, dbConfig);
|
|
362
|
+
const srcRoots = detectSrcRoots(rootDir, srcDir, appDir, config);
|
|
363
|
+
const conventionFiles = detectConventionFiles(rootDir, srcDir);
|
|
364
|
+
return { srcDir, appDir, apiDir, dbDir, srcRoots, conventionFiles, dbConfig };
|
|
365
|
+
}
|
|
366
|
+
var import_node_fs4, import_node_path4, NON_SOURCE_DIRS, CONVENTION_NAMES;
|
|
367
|
+
var init_resolve_paths = __esm({
|
|
368
|
+
"src/server/graph/core/resolve-paths.ts"() {
|
|
369
|
+
"use strict";
|
|
370
|
+
import_node_fs4 = require("node:fs");
|
|
371
|
+
import_node_path4 = require("node:path");
|
|
372
|
+
init_walk();
|
|
373
|
+
NON_SOURCE_DIRS = /* @__PURE__ */ new Set([
|
|
374
|
+
...DEFAULT_IGNORE_DIRS,
|
|
375
|
+
// DB conventions (handled by db parsers)
|
|
376
|
+
"prisma",
|
|
377
|
+
"supabase",
|
|
378
|
+
"drizzle",
|
|
379
|
+
"migrations",
|
|
380
|
+
// Web assets
|
|
381
|
+
"public",
|
|
382
|
+
"static",
|
|
383
|
+
"assets",
|
|
384
|
+
// Docs
|
|
385
|
+
"docs",
|
|
386
|
+
"documentation",
|
|
387
|
+
// Test dirs (project tests aren't part of the structural graph)
|
|
388
|
+
"tests",
|
|
389
|
+
"__tests__",
|
|
390
|
+
"e2e",
|
|
391
|
+
"playwright",
|
|
392
|
+
"cypress",
|
|
393
|
+
// Monorepo workspace roots — separate graph projects per .launchchart.json
|
|
394
|
+
"packages",
|
|
395
|
+
"apps",
|
|
396
|
+
"services",
|
|
397
|
+
"libs"
|
|
398
|
+
]);
|
|
399
|
+
CONVENTION_NAMES = ["middleware.ts", "middleware.tsx", "instrumentation.ts", "instrumentation.tsx"];
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
241
403
|
// src/server/graph/core/ts-extractor.ts
|
|
242
404
|
var ts_extractor_exports = {};
|
|
243
405
|
__export(ts_extractor_exports, {
|
|
@@ -778,8 +940,12 @@ var init_ts_extractor = __esm({
|
|
|
778
940
|
});
|
|
779
941
|
|
|
780
942
|
// src/server/graph/parsers/ts/typescript-project.ts
|
|
781
|
-
function toNodeId(srcDir, absPath) {
|
|
782
|
-
|
|
943
|
+
function toNodeId(srcDir, rootDir, absPath) {
|
|
944
|
+
const relFromSrc = (0, import_node_path6.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
945
|
+
if (relFromSrc.startsWith("..")) {
|
|
946
|
+
return (0, import_node_path6.relative)(rootDir, absPath).replace(/\\/g, "/");
|
|
947
|
+
}
|
|
948
|
+
return relFromSrc;
|
|
783
949
|
}
|
|
784
950
|
function resolveImport(srcDir, specifier) {
|
|
785
951
|
if (!specifier.startsWith("@/")) return null;
|
|
@@ -869,12 +1035,13 @@ function extractRoute(id) {
|
|
|
869
1035
|
function nameFromFilename(absPath) {
|
|
870
1036
|
return (0, import_node_path6.basename)(absPath, (0, import_node_path6.extname)(absPath)).replace(/[-_](\w)/g, (_, c) => c.toUpperCase()).replace(/^(\w)/, (_, c) => c.toUpperCase());
|
|
871
1037
|
}
|
|
872
|
-
function
|
|
873
|
-
let route = "/" + (0, import_node_path6.relative)(
|
|
1038
|
+
function filePathToAppRoute(appDir, absPath) {
|
|
1039
|
+
let route = ("/" + (0, import_node_path6.relative)(appDir, absPath).replace(/\\/g, "/")).replace(/\/route\.tsx?$/, "");
|
|
1040
|
+
route = route.replace(/\/\([^)]+\)/g, "");
|
|
1041
|
+
route = route.replace(/\[\.\.\.([^\]]+)\]/g, "*$1");
|
|
874
1042
|
route = route.replace(/\[([^\]]+)\]/g, ":$1");
|
|
875
1043
|
route = route.replace(/\/+/g, "/");
|
|
876
|
-
|
|
877
|
-
return "/api" + route;
|
|
1044
|
+
return route === "" ? "/" : route;
|
|
878
1045
|
}
|
|
879
1046
|
function camelToPascal(s) {
|
|
880
1047
|
if (!s) return s;
|
|
@@ -959,7 +1126,7 @@ function matchRouteToPage(route, routeToNodeId) {
|
|
|
959
1126
|
if (routeToNodeId.has(normalized)) return routeToNodeId.get(normalized);
|
|
960
1127
|
return null;
|
|
961
1128
|
}
|
|
962
|
-
function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
1129
|
+
function extractEdges(srcDir, rootDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps, routeToNodeId) {
|
|
963
1130
|
const edges = [];
|
|
964
1131
|
const flagged = [];
|
|
965
1132
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -987,7 +1154,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
987
1154
|
for (const name of names) {
|
|
988
1155
|
const targetAbs = barrelMap.get(name);
|
|
989
1156
|
if (targetAbs) {
|
|
990
|
-
const targetId = toNodeId(srcDir, targetAbs);
|
|
1157
|
+
const targetId = toNodeId(srcDir, rootDir, targetAbs);
|
|
991
1158
|
if (nodeIdSet.has(targetId)) {
|
|
992
1159
|
if (!byTarget.has(targetId)) byTarget.set(targetId, []);
|
|
993
1160
|
byTarget.get(targetId).push(name);
|
|
@@ -1001,7 +1168,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
1001
1168
|
} else {
|
|
1002
1169
|
const resolved = resolveImport(srcDir, specifier);
|
|
1003
1170
|
if (resolved) {
|
|
1004
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1171
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
1005
1172
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
1006
1173
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
1007
1174
|
}
|
|
@@ -1010,7 +1177,7 @@ function extractEdges(srcDir, absPath, sourceId, parsed, nodeIdSet, barrelMaps,
|
|
|
1010
1177
|
} else if (specifier.startsWith(".")) {
|
|
1011
1178
|
const resolved = resolveRelativeImport(absPath, specifier);
|
|
1012
1179
|
if (resolved) {
|
|
1013
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1180
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
1014
1181
|
if (nodeIdSet.has(targetId) && !targetId.endsWith("/index.ts") && !targetId.endsWith("/index.tsx")) {
|
|
1015
1182
|
addEdge(targetId, edgeTypeFor(isTypeOnly, names));
|
|
1016
1183
|
}
|
|
@@ -1062,13 +1229,22 @@ function generate(rootDir) {
|
|
|
1062
1229
|
const config = loadConfig(rootDir);
|
|
1063
1230
|
const paths = resolveProjectPaths(rootDir, config);
|
|
1064
1231
|
const srcDir = paths.srcDir;
|
|
1065
|
-
const
|
|
1066
|
-
const
|
|
1067
|
-
const
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1232
|
+
const allDiscovered = [];
|
|
1233
|
+
const discoveredSet = /* @__PURE__ */ new Set();
|
|
1234
|
+
for (const root of paths.srcRoots) {
|
|
1235
|
+
for (const f of walk(root, [".tsx", ".ts"])) {
|
|
1236
|
+
if (!discoveredSet.has(f)) {
|
|
1237
|
+
discoveredSet.add(f);
|
|
1238
|
+
allDiscovered.push(f);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
for (const conv of paths.conventionFiles) {
|
|
1243
|
+
if (!discoveredSet.has(conv)) {
|
|
1244
|
+
discoveredSet.add(conv);
|
|
1245
|
+
allDiscovered.push(conv);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1072
1248
|
const parsedByPath = /* @__PURE__ */ new Map();
|
|
1073
1249
|
for (const absPath of allDiscovered) {
|
|
1074
1250
|
parsedByPath.set(absPath, parseFileTS(absPath));
|
|
@@ -1080,7 +1256,7 @@ function generate(rootDir) {
|
|
|
1080
1256
|
const routeToNodeId = /* @__PURE__ */ new Map();
|
|
1081
1257
|
const fileSet = allDiscovered.filter((f) => !(0, import_node_path6.basename)(f).startsWith("index."));
|
|
1082
1258
|
for (const absPath of fileSet) {
|
|
1083
|
-
const id = toNodeId(srcDir, absPath);
|
|
1259
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
1084
1260
|
const type = classifyType(absPath, id);
|
|
1085
1261
|
if (type === "test" || type === "story") continue;
|
|
1086
1262
|
const parsed = parsedByPath.get(absPath);
|
|
@@ -1095,7 +1271,7 @@ function generate(rootDir) {
|
|
|
1095
1271
|
const dbCalls = extractDbCallsTS(absPath);
|
|
1096
1272
|
const authWrappers = extractAuthWrappersTS(absPath);
|
|
1097
1273
|
const deep = extractDeep(absPath);
|
|
1098
|
-
const routePath = (
|
|
1274
|
+
const routePath = filePathToAppRoute(paths.appDir, absPath);
|
|
1099
1275
|
const mutations = dbCalls.filter((c) => c.isMutation);
|
|
1100
1276
|
const mutates = mutations.length > 0;
|
|
1101
1277
|
const authStrategy = [...authWrappers];
|
|
@@ -1139,11 +1315,12 @@ function generate(rootDir) {
|
|
|
1139
1315
|
const uiEdges = [];
|
|
1140
1316
|
const uiFlagged = [];
|
|
1141
1317
|
for (const absPath of fileSet) {
|
|
1142
|
-
const id = toNodeId(srcDir, absPath);
|
|
1318
|
+
const id = toNodeId(srcDir, rootDir, absPath);
|
|
1143
1319
|
if (!nodeIdSet.has(id)) continue;
|
|
1144
1320
|
const parsed = parsedByPath.get(absPath);
|
|
1145
1321
|
const { edges, flagged } = extractEdges(
|
|
1146
1322
|
srcDir,
|
|
1323
|
+
rootDir,
|
|
1147
1324
|
absPath,
|
|
1148
1325
|
id,
|
|
1149
1326
|
parsed,
|
|
@@ -1156,7 +1333,7 @@ function generate(rootDir) {
|
|
|
1156
1333
|
}
|
|
1157
1334
|
const fetchCallEntries = [];
|
|
1158
1335
|
for (const absPath of fileSet) {
|
|
1159
|
-
const sourceId = toNodeId(srcDir, absPath);
|
|
1336
|
+
const sourceId = toNodeId(srcDir, rootDir, absPath);
|
|
1160
1337
|
if (!nodeIdSet.has(sourceId)) continue;
|
|
1161
1338
|
const parsed = parsedByPath.get(absPath);
|
|
1162
1339
|
if (parsed.fetchCalls.length === 0) continue;
|
|
@@ -1195,7 +1372,7 @@ function generate(rootDir) {
|
|
|
1195
1372
|
for (const name of names) {
|
|
1196
1373
|
const targetAbs = barrelMap.get(name);
|
|
1197
1374
|
if (!targetAbs) continue;
|
|
1198
|
-
const targetId2 = toNodeId(srcDir, targetAbs);
|
|
1375
|
+
const targetId2 = toNodeId(srcDir, rootDir, targetAbs);
|
|
1199
1376
|
if (!nodeIdSet.has(targetId2)) continue;
|
|
1200
1377
|
const key2 = `${externalId}\u2192${targetId2}`;
|
|
1201
1378
|
if (seen.has(key2)) continue;
|
|
@@ -1209,7 +1386,7 @@ function generate(rootDir) {
|
|
|
1209
1386
|
resolved = resolveRelativeImport(absPath, specifier);
|
|
1210
1387
|
}
|
|
1211
1388
|
if (!resolved) continue;
|
|
1212
|
-
const targetId = toNodeId(srcDir, resolved);
|
|
1389
|
+
const targetId = toNodeId(srcDir, rootDir, resolved);
|
|
1213
1390
|
if (!nodeIdSet.has(targetId)) continue;
|
|
1214
1391
|
if (targetId.endsWith("/index.ts") || targetId.endsWith("/index.tsx")) continue;
|
|
1215
1392
|
const key = `${externalId}\u2192${targetId}`;
|
|
@@ -1502,10 +1679,24 @@ function parseEnums(content) {
|
|
|
1502
1679
|
return nodes;
|
|
1503
1680
|
}
|
|
1504
1681
|
function detect2(rootDir) {
|
|
1505
|
-
|
|
1682
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
1683
|
+
return paths?.dbConfig.kind === "prisma" && (0, import_node_fs7.existsSync)(paths.dbConfig.schemaPath);
|
|
1506
1684
|
}
|
|
1507
1685
|
function generate2(rootDir) {
|
|
1508
|
-
const
|
|
1686
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
1687
|
+
if (paths.dbConfig.kind !== "prisma") {
|
|
1688
|
+
return {
|
|
1689
|
+
metadata: { generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), layer: "db", source: "none" },
|
|
1690
|
+
nodes: [],
|
|
1691
|
+
edges: [],
|
|
1692
|
+
cross_refs: [],
|
|
1693
|
+
contradictions: [],
|
|
1694
|
+
warnings: [],
|
|
1695
|
+
flagged_edges: [],
|
|
1696
|
+
patterns: { total_tables: 0, total_enums: 0, total_relations: 0 }
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
const schemaPath = paths.dbConfig.schemaPath;
|
|
1509
1700
|
const content = (0, import_node_fs7.readFileSync)(schemaPath, "utf-8");
|
|
1510
1701
|
const { nodes: modelNodes, relations } = parseModels(content);
|
|
1511
1702
|
const enumNodes = parseEnums(content);
|
|
@@ -1526,7 +1717,7 @@ function generate2(rootDir) {
|
|
|
1526
1717
|
metadata: {
|
|
1527
1718
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1528
1719
|
scope: "prisma-schema",
|
|
1529
|
-
source:
|
|
1720
|
+
source: schemaPath,
|
|
1530
1721
|
provider: "postgresql",
|
|
1531
1722
|
layer: "db",
|
|
1532
1723
|
total_models: modelNodes.length,
|
|
@@ -1555,12 +1746,13 @@ function generate2(rootDir) {
|
|
|
1555
1746
|
}
|
|
1556
1747
|
};
|
|
1557
1748
|
}
|
|
1558
|
-
var import_node_fs7,
|
|
1749
|
+
var import_node_fs7, prismaSchemaParser;
|
|
1559
1750
|
var init_prisma_schema = __esm({
|
|
1560
1751
|
"src/server/graph/parsers/db/prisma-schema.ts"() {
|
|
1561
1752
|
"use strict";
|
|
1562
1753
|
import_node_fs7 = require("node:fs");
|
|
1563
|
-
|
|
1754
|
+
init_config();
|
|
1755
|
+
init_resolve_paths();
|
|
1564
1756
|
prismaSchemaParser = {
|
|
1565
1757
|
id: "prisma-schema",
|
|
1566
1758
|
layer: "db",
|
|
@@ -1575,51 +1767,147 @@ function pgTypeToPrisma(pgType) {
|
|
|
1575
1767
|
const upper = pgType.toUpperCase().trim();
|
|
1576
1768
|
return PG_TO_PRISMA[upper] ?? upper;
|
|
1577
1769
|
}
|
|
1770
|
+
function bareName(captured) {
|
|
1771
|
+
const parts = captured.split(".");
|
|
1772
|
+
const last = parts[parts.length - 1];
|
|
1773
|
+
return last.replace(/^"(.*)"$/, "$1").trim();
|
|
1774
|
+
}
|
|
1578
1775
|
function parseCreateTable(sql, state) {
|
|
1579
|
-
const re =
|
|
1776
|
+
const re = new RegExp(
|
|
1777
|
+
`CREATE\\s+TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s*\\(([\\s\\S]*?)\\);`,
|
|
1778
|
+
"gi"
|
|
1779
|
+
);
|
|
1580
1780
|
let m;
|
|
1581
1781
|
while ((m = re.exec(sql)) !== null) {
|
|
1582
|
-
const tableName = m[1];
|
|
1782
|
+
const tableName = bareName(m[1]);
|
|
1583
1783
|
const body = m[2];
|
|
1584
1784
|
const columns = /* @__PURE__ */ new Map();
|
|
1585
1785
|
let primaryCol = null;
|
|
1586
|
-
|
|
1587
|
-
|
|
1786
|
+
const inlineFks = [];
|
|
1787
|
+
const lines = splitTopLevelCommas(body);
|
|
1788
|
+
for (const raw of lines) {
|
|
1789
|
+
const trimmed = raw.trim().replace(/,\s*$/, "");
|
|
1588
1790
|
if (!trimmed || trimmed.startsWith("--")) continue;
|
|
1589
|
-
const
|
|
1590
|
-
if (
|
|
1591
|
-
primaryCol =
|
|
1791
|
+
const namedPk = trimmed.match(new RegExp(`^CONSTRAINT\\s+${ID}\\s+PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1792
|
+
if (namedPk) {
|
|
1793
|
+
primaryCol = bareName(namedPk[1]);
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
const tablePk = trimmed.match(new RegExp(`^PRIMARY\\s+KEY\\s*\\(\\s*(${QID})`, "i"));
|
|
1797
|
+
if (tablePk) {
|
|
1798
|
+
primaryCol = bareName(tablePk[1]);
|
|
1799
|
+
continue;
|
|
1800
|
+
}
|
|
1801
|
+
if (/^UNIQUE\s*\(/i.test(trimmed)) continue;
|
|
1802
|
+
const namedFk = trimmed.match(new RegExp(
|
|
1803
|
+
`^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+)?))?`,
|
|
1804
|
+
"i"
|
|
1805
|
+
));
|
|
1806
|
+
if (namedFk) {
|
|
1807
|
+
inlineFks.push({
|
|
1808
|
+
constraintName: bareName(namedFk[1]),
|
|
1809
|
+
sourceTable: tableName,
|
|
1810
|
+
sourceColumn: bareName(namedFk[2]),
|
|
1811
|
+
targetTable: bareName(namedFk[3]),
|
|
1812
|
+
targetColumn: bareName(namedFk[4]),
|
|
1813
|
+
onDelete: namedFk[5] ?? null
|
|
1814
|
+
});
|
|
1592
1815
|
continue;
|
|
1593
1816
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1817
|
+
const bareFk = trimmed.match(new RegExp(
|
|
1818
|
+
`^FOREIGN\\s+KEY\\s*\\(\\s*(${QID})\\s*\\)\\s+REFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1819
|
+
"i"
|
|
1820
|
+
));
|
|
1821
|
+
if (bareFk) {
|
|
1822
|
+
inlineFks.push({
|
|
1823
|
+
constraintName: `${tableName}_${bareName(bareFk[1])}_fkey`,
|
|
1824
|
+
sourceTable: tableName,
|
|
1825
|
+
sourceColumn: bareName(bareFk[1]),
|
|
1826
|
+
targetTable: bareName(bareFk[2]),
|
|
1827
|
+
targetColumn: bareName(bareFk[3]),
|
|
1828
|
+
onDelete: bareFk[4] ?? null
|
|
1829
|
+
});
|
|
1830
|
+
continue;
|
|
1831
|
+
}
|
|
1832
|
+
if (/^CONSTRAINT\s/i.test(trimmed)) continue;
|
|
1833
|
+
const colMatch = trimmed.match(new RegExp(`^(${ID})\\s+(.+)`, "i"));
|
|
1596
1834
|
if (!colMatch) continue;
|
|
1597
|
-
const colName = colMatch[1];
|
|
1835
|
+
const colName = bareName(colMatch[1]);
|
|
1598
1836
|
let rest = colMatch[2];
|
|
1837
|
+
const inlineRefMatch = rest.match(new RegExp(
|
|
1838
|
+
`\\bREFERENCES\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)(?:\\s+ON\\s+DELETE\\s+(\\w+(?:\\s+\\w+)?))?`,
|
|
1839
|
+
"i"
|
|
1840
|
+
));
|
|
1841
|
+
if (inlineRefMatch) {
|
|
1842
|
+
inlineFks.push({
|
|
1843
|
+
constraintName: `${tableName}_${colName}_fkey`,
|
|
1844
|
+
sourceTable: tableName,
|
|
1845
|
+
sourceColumn: colName,
|
|
1846
|
+
targetTable: bareName(inlineRefMatch[1]),
|
|
1847
|
+
targetColumn: bareName(inlineRefMatch[2]),
|
|
1848
|
+
onDelete: inlineRefMatch[3] ?? null
|
|
1849
|
+
});
|
|
1850
|
+
rest = rest.replace(inlineRefMatch[0], "").trim();
|
|
1851
|
+
}
|
|
1599
1852
|
const isNotNull = /\bNOT\s+NULL\b/i.test(rest);
|
|
1853
|
+
const isPrimaryKey = /\bPRIMARY\s+KEY\b/i.test(rest);
|
|
1854
|
+
const isUnique = /\bUNIQUE\b/i.test(rest);
|
|
1600
1855
|
const defaultMatch = rest.match(/\bDEFAULT\s+(.+?)(?:\s*,?\s*$)/i);
|
|
1601
1856
|
const defaultVal = defaultMatch ? defaultMatch[1].trim() : null;
|
|
1602
|
-
let colType = rest.replace(/\bNOT\s+NULL\b/gi, "").replace(/\bDEFAULT\s+.*/gi, "").trim().replace(/,\s*$/, "").trim();
|
|
1857
|
+
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();
|
|
1603
1858
|
columns.set(colName, {
|
|
1604
1859
|
name: colName,
|
|
1605
1860
|
type: colType,
|
|
1606
|
-
nullable: !isNotNull,
|
|
1607
|
-
primary:
|
|
1608
|
-
unique:
|
|
1861
|
+
nullable: !isNotNull && !isPrimaryKey,
|
|
1862
|
+
primary: isPrimaryKey,
|
|
1863
|
+
unique: isUnique,
|
|
1609
1864
|
default: defaultVal
|
|
1610
1865
|
});
|
|
1866
|
+
if (isPrimaryKey) primaryCol = colName;
|
|
1611
1867
|
}
|
|
1612
1868
|
if (primaryCol && columns.has(primaryCol)) {
|
|
1613
1869
|
columns.get(primaryCol).primary = true;
|
|
1614
1870
|
}
|
|
1615
1871
|
state.tables.set(tableName, { name: tableName, columns });
|
|
1872
|
+
state.fks.push(...inlineFks);
|
|
1616
1873
|
}
|
|
1617
1874
|
}
|
|
1875
|
+
function splitTopLevelCommas(body) {
|
|
1876
|
+
const out = [];
|
|
1877
|
+
let depth = 0;
|
|
1878
|
+
let buf = "";
|
|
1879
|
+
let inString = null;
|
|
1880
|
+
for (const ch of body) {
|
|
1881
|
+
if (inString) {
|
|
1882
|
+
buf += ch;
|
|
1883
|
+
if (ch === inString) inString = null;
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1886
|
+
if (ch === "'" || ch === '"') {
|
|
1887
|
+
inString = ch;
|
|
1888
|
+
buf += ch;
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1891
|
+
if (ch === "(") depth++;
|
|
1892
|
+
else if (ch === ")") depth--;
|
|
1893
|
+
if (ch === "," && depth === 0) {
|
|
1894
|
+
out.push(buf);
|
|
1895
|
+
buf = "";
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
buf += ch;
|
|
1899
|
+
}
|
|
1900
|
+
if (buf.trim()) out.push(buf);
|
|
1901
|
+
return out;
|
|
1902
|
+
}
|
|
1618
1903
|
function parseCreateEnum(sql, state) {
|
|
1619
|
-
const re =
|
|
1904
|
+
const re = new RegExp(
|
|
1905
|
+
`CREATE\\s+TYPE\\s+(${QID})\\s+AS\\s+ENUM\\s*\\(([^)]+)\\)`,
|
|
1906
|
+
"gi"
|
|
1907
|
+
);
|
|
1620
1908
|
let m;
|
|
1621
1909
|
while ((m = re.exec(sql)) !== null) {
|
|
1622
|
-
const enumName = m[1];
|
|
1910
|
+
const enumName = bareName(m[1]);
|
|
1623
1911
|
const valuesStr = m[2];
|
|
1624
1912
|
const values = new Set(
|
|
1625
1913
|
valuesStr.split(",").map((v) => v.trim().replace(/^'(.*)'$/, "$1")).filter(Boolean)
|
|
@@ -1628,11 +1916,14 @@ function parseCreateEnum(sql, state) {
|
|
|
1628
1916
|
}
|
|
1629
1917
|
}
|
|
1630
1918
|
function parseAlterTable(sql, state) {
|
|
1631
|
-
const addColRe =
|
|
1919
|
+
const addColRe = new RegExp(
|
|
1920
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+ADD\\s+COLUMN\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QID})\\s+(.+?);`,
|
|
1921
|
+
"gi"
|
|
1922
|
+
);
|
|
1632
1923
|
let m;
|
|
1633
1924
|
while ((m = addColRe.exec(sql)) !== null) {
|
|
1634
|
-
const tableName = m[1];
|
|
1635
|
-
const colName = m[2];
|
|
1925
|
+
const tableName = bareName(m[1]);
|
|
1926
|
+
const colName = bareName(m[2]);
|
|
1636
1927
|
let rest = m[3];
|
|
1637
1928
|
const table = state.tables.get(tableName);
|
|
1638
1929
|
if (!table) continue;
|
|
@@ -1649,63 +1940,91 @@ function parseAlterTable(sql, state) {
|
|
|
1649
1940
|
default: defaultVal
|
|
1650
1941
|
});
|
|
1651
1942
|
}
|
|
1652
|
-
const dropColRe =
|
|
1943
|
+
const dropColRe = new RegExp(
|
|
1944
|
+
`ALTER\\s+TABLE\\s+(${QID})\\s+DROP\\s+COLUMN\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1945
|
+
"gi"
|
|
1946
|
+
);
|
|
1653
1947
|
while ((m = dropColRe.exec(sql)) !== null) {
|
|
1654
|
-
const table = state.tables.get(m[1]);
|
|
1655
|
-
if (table) table.columns.delete(m[2]);
|
|
1948
|
+
const table = state.tables.get(bareName(m[1]));
|
|
1949
|
+
if (table) table.columns.delete(bareName(m[2]));
|
|
1656
1950
|
}
|
|
1657
|
-
const fkRe =
|
|
1951
|
+
const fkRe = new RegExp(
|
|
1952
|
+
`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+)?))?`,
|
|
1953
|
+
"gi"
|
|
1954
|
+
);
|
|
1658
1955
|
while ((m = fkRe.exec(sql)) !== null) {
|
|
1659
1956
|
state.fks.push({
|
|
1660
|
-
constraintName: m[2],
|
|
1661
|
-
sourceTable: m[1],
|
|
1662
|
-
sourceColumn: m[3],
|
|
1663
|
-
targetTable: m[4],
|
|
1664
|
-
targetColumn: m[5],
|
|
1957
|
+
constraintName: bareName(m[2]),
|
|
1958
|
+
sourceTable: bareName(m[1]),
|
|
1959
|
+
sourceColumn: bareName(m[3]),
|
|
1960
|
+
targetTable: bareName(m[4]),
|
|
1961
|
+
targetColumn: bareName(m[5]),
|
|
1665
1962
|
onDelete: m[6] ?? null
|
|
1666
1963
|
});
|
|
1667
1964
|
}
|
|
1668
1965
|
}
|
|
1669
1966
|
function parseAlterEnum(sql, state) {
|
|
1670
|
-
const re =
|
|
1967
|
+
const re = new RegExp(
|
|
1968
|
+
`ALTER\\s+TYPE\\s+(${QID})\\s+ADD\\s+VALUE\\s+'([^']+)'`,
|
|
1969
|
+
"gi"
|
|
1970
|
+
);
|
|
1671
1971
|
let m;
|
|
1672
1972
|
while ((m = re.exec(sql)) !== null) {
|
|
1673
|
-
const en = state.enums.get(m[1]);
|
|
1973
|
+
const en = state.enums.get(bareName(m[1]));
|
|
1674
1974
|
if (en) en.values.add(m[2]);
|
|
1675
1975
|
}
|
|
1676
1976
|
}
|
|
1677
1977
|
function parseDropTable(sql, state) {
|
|
1678
|
-
const re =
|
|
1978
|
+
const re = new RegExp(
|
|
1979
|
+
`DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(${QID})`,
|
|
1980
|
+
"gi"
|
|
1981
|
+
);
|
|
1679
1982
|
let m;
|
|
1680
1983
|
while ((m = re.exec(sql)) !== null) {
|
|
1681
|
-
|
|
1682
|
-
state.
|
|
1984
|
+
const dropped = bareName(m[1]);
|
|
1985
|
+
state.tables.delete(dropped);
|
|
1986
|
+
state.fks = state.fks.filter((fk) => fk.sourceTable !== dropped && fk.targetTable !== dropped);
|
|
1683
1987
|
}
|
|
1684
1988
|
}
|
|
1685
1989
|
function parseUniqueIndex(sql, state) {
|
|
1686
|
-
const re =
|
|
1990
|
+
const re = new RegExp(
|
|
1991
|
+
`CREATE\\s+UNIQUE\\s+INDEX\\s+(?:(?:IF\\s+NOT\\s+EXISTS\\s+)?(?:${ID}\\s+)?)?ON\\s+(${QID})\\s*\\(\\s*(${QID})\\s*\\)`,
|
|
1992
|
+
"gi"
|
|
1993
|
+
);
|
|
1687
1994
|
let m;
|
|
1688
1995
|
while ((m = re.exec(sql)) !== null) {
|
|
1689
|
-
const
|
|
1690
|
-
const
|
|
1996
|
+
const tableName = bareName(m[1]);
|
|
1997
|
+
const colName = bareName(m[2]);
|
|
1998
|
+
const table = state.tables.get(tableName);
|
|
1999
|
+
const col = table?.columns.get(colName);
|
|
1691
2000
|
if (col) col.unique = true;
|
|
1692
|
-
if (!state.uniqueIndexes.has(
|
|
1693
|
-
state.uniqueIndexes.get(
|
|
2001
|
+
if (!state.uniqueIndexes.has(tableName)) state.uniqueIndexes.set(tableName, /* @__PURE__ */ new Set());
|
|
2002
|
+
state.uniqueIndexes.get(tableName).add(colName);
|
|
1694
2003
|
}
|
|
1695
2004
|
}
|
|
1696
|
-
function
|
|
1697
|
-
|
|
2005
|
+
function discoverMigrationFiles(migrationsDir) {
|
|
2006
|
+
if (!(0, import_node_fs8.existsSync)(migrationsDir)) return [];
|
|
2007
|
+
const out = [];
|
|
2008
|
+
const entries = (0, import_node_fs8.readdirSync)(migrationsDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
2009
|
+
for (const entry of entries) {
|
|
2010
|
+
if (entry.isDirectory()) {
|
|
2011
|
+
const sqlPath = (0, import_node_path7.join)(migrationsDir, entry.name, "migration.sql");
|
|
2012
|
+
if ((0, import_node_fs8.existsSync)(sqlPath)) out.push(sqlPath);
|
|
2013
|
+
} else if (entry.isFile() && entry.name.endsWith(".sql")) {
|
|
2014
|
+
out.push((0, import_node_path7.join)(migrationsDir, entry.name));
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
return out;
|
|
2018
|
+
}
|
|
2019
|
+
function parseMigrations(migrationsDir) {
|
|
1698
2020
|
const state = {
|
|
1699
2021
|
tables: /* @__PURE__ */ new Map(),
|
|
1700
2022
|
enums: /* @__PURE__ */ new Map(),
|
|
1701
2023
|
fks: [],
|
|
1702
2024
|
uniqueIndexes: /* @__PURE__ */ new Map()
|
|
1703
2025
|
};
|
|
1704
|
-
if (!
|
|
1705
|
-
const
|
|
1706
|
-
for (const dir of dirs) {
|
|
1707
|
-
const sqlPath = (0, import_node_path8.join)(migrationsDir, dir, "migration.sql");
|
|
1708
|
-
if (!(0, import_node_fs8.existsSync)(sqlPath)) continue;
|
|
2026
|
+
if (!migrationsDir) return state;
|
|
2027
|
+
for (const sqlPath of discoverMigrationFiles(migrationsDir)) {
|
|
1709
2028
|
const sql = (0, import_node_fs8.readFileSync)(sqlPath, "utf-8");
|
|
1710
2029
|
parseCreateEnum(sql, state);
|
|
1711
2030
|
parseCreateTable(sql, state);
|
|
@@ -1716,9 +2035,8 @@ function parseMigrations(rootDir) {
|
|
|
1716
2035
|
}
|
|
1717
2036
|
return state;
|
|
1718
2037
|
}
|
|
1719
|
-
function loadPrismaState(
|
|
1720
|
-
|
|
1721
|
-
if (!(0, import_node_fs8.existsSync)(schemaPath)) return null;
|
|
2038
|
+
function loadPrismaState(schemaPath) {
|
|
2039
|
+
if (!schemaPath || !(0, import_node_fs8.existsSync)(schemaPath)) return null;
|
|
1722
2040
|
const content = (0, import_node_fs8.readFileSync)(schemaPath, "utf-8");
|
|
1723
2041
|
const tables = /* @__PURE__ */ new Map();
|
|
1724
2042
|
const enums = /* @__PURE__ */ new Map();
|
|
@@ -1883,14 +2201,28 @@ function verify(sqlState, prisma) {
|
|
|
1883
2201
|
}
|
|
1884
2202
|
return { contradictions, flaggedEdges };
|
|
1885
2203
|
}
|
|
2204
|
+
function migrationsDirFor(rootDir) {
|
|
2205
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
2206
|
+
if (!paths) return null;
|
|
2207
|
+
if (paths.dbConfig.kind === "prisma" || paths.dbConfig.kind === "sql-migrations") {
|
|
2208
|
+
return paths.dbConfig.migrationsDir;
|
|
2209
|
+
}
|
|
2210
|
+
return null;
|
|
2211
|
+
}
|
|
2212
|
+
function schemaPathFor(rootDir) {
|
|
2213
|
+
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
2214
|
+
if (!paths) return null;
|
|
2215
|
+
return paths.dbConfig.kind === "prisma" ? paths.dbConfig.schemaPath : null;
|
|
2216
|
+
}
|
|
1886
2217
|
function detect3(rootDir) {
|
|
1887
|
-
const
|
|
1888
|
-
if (!
|
|
1889
|
-
return (
|
|
2218
|
+
const dir = migrationsDirFor(rootDir);
|
|
2219
|
+
if (!dir) return false;
|
|
2220
|
+
return discoverMigrationFiles(dir).length > 0;
|
|
1890
2221
|
}
|
|
1891
2222
|
function generate3(rootDir) {
|
|
1892
|
-
const
|
|
1893
|
-
const
|
|
2223
|
+
const migrationsDir = migrationsDirFor(rootDir);
|
|
2224
|
+
const sqlState = parseMigrations(migrationsDir);
|
|
2225
|
+
const prisma = loadPrismaState(schemaPathFor(rootDir));
|
|
1894
2226
|
const prismaTableIds = prisma ? new Set(prisma.tables.keys()) : /* @__PURE__ */ new Set();
|
|
1895
2227
|
const prismaEnumIds = prisma ? new Set(prisma.enums.keys()) : /* @__PURE__ */ new Set();
|
|
1896
2228
|
const nodes = [];
|
|
@@ -1936,7 +2268,7 @@ function generate3(rootDir) {
|
|
|
1936
2268
|
metadata: {
|
|
1937
2269
|
generated: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
1938
2270
|
scope: "sql-migrations",
|
|
1939
|
-
source: "
|
|
2271
|
+
source: migrationsDir ?? "none",
|
|
1940
2272
|
layer: "db",
|
|
1941
2273
|
sql_tables: sqlState.tables.size,
|
|
1942
2274
|
sql_enums: sqlState.enums.size,
|
|
@@ -1953,12 +2285,14 @@ function generate3(rootDir) {
|
|
|
1953
2285
|
flagged_edges: flaggedEdges
|
|
1954
2286
|
};
|
|
1955
2287
|
}
|
|
1956
|
-
var import_node_fs8,
|
|
2288
|
+
var import_node_fs8, import_node_path7, PG_TO_PRISMA, ID, QID, sqlMigrationsParser;
|
|
1957
2289
|
var init_sql_migrations = __esm({
|
|
1958
2290
|
"src/server/graph/parsers/db/sql-migrations.ts"() {
|
|
1959
2291
|
"use strict";
|
|
1960
2292
|
import_node_fs8 = require("node:fs");
|
|
1961
|
-
|
|
2293
|
+
import_node_path7 = require("node:path");
|
|
2294
|
+
init_config();
|
|
2295
|
+
init_resolve_paths();
|
|
1962
2296
|
PG_TO_PRISMA = {
|
|
1963
2297
|
"TEXT": "String",
|
|
1964
2298
|
"VARCHAR": "String",
|
|
@@ -1985,6 +2319,8 @@ var init_sql_migrations = __esm({
|
|
|
1985
2319
|
"UUID": "String",
|
|
1986
2320
|
"TEXT[]": "String[]"
|
|
1987
2321
|
};
|
|
2322
|
+
ID = `(?:"[\\w$]+"|[\\w$]+)`;
|
|
2323
|
+
QID = `(?:${ID}\\.)?${ID}`;
|
|
1988
2324
|
sqlMigrationsParser = {
|
|
1989
2325
|
id: "sql-migrations",
|
|
1990
2326
|
layer: "db",
|
|
@@ -2225,24 +2561,24 @@ function walk2(dir, exts) {
|
|
|
2225
2561
|
const results = [];
|
|
2226
2562
|
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
2227
2563
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
2228
|
-
const full = (0,
|
|
2564
|
+
const full = (0, import_node_path8.join)(dir, entry.name);
|
|
2229
2565
|
if (entry.isDirectory()) {
|
|
2230
2566
|
results.push(...walk2(full, exts));
|
|
2231
|
-
} else if (exts.includes((0,
|
|
2567
|
+
} else if (exts.includes((0, import_node_path8.extname)(entry.name))) {
|
|
2232
2568
|
results.push(full);
|
|
2233
2569
|
}
|
|
2234
2570
|
}
|
|
2235
2571
|
return results;
|
|
2236
2572
|
}
|
|
2237
2573
|
function toNodeId2(srcDir, absPath) {
|
|
2238
|
-
return (0,
|
|
2574
|
+
return (0, import_node_path8.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
2239
2575
|
}
|
|
2240
|
-
var import_node_fs9,
|
|
2576
|
+
var import_node_fs9, import_node_path8, API_ANNOTATION_RE, apiAnnotationsParser;
|
|
2241
2577
|
var init_api_annotations = __esm({
|
|
2242
2578
|
"src/server/graph/parsers/crosslayer/api-annotations.ts"() {
|
|
2243
2579
|
"use strict";
|
|
2244
2580
|
import_node_fs9 = require("node:fs");
|
|
2245
|
-
|
|
2581
|
+
import_node_path8 = require("node:path");
|
|
2246
2582
|
init_api_route_matching();
|
|
2247
2583
|
API_ANNOTATION_RE = /@api\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\/\S+)/g;
|
|
2248
2584
|
apiAnnotationsParser = {
|
|
@@ -2250,7 +2586,7 @@ var init_api_annotations = __esm({
|
|
|
2250
2586
|
layer: "crosslayer",
|
|
2251
2587
|
concern: "api-binding",
|
|
2252
2588
|
detect(rootDir) {
|
|
2253
|
-
return (0, import_node_fs9.existsSync)((0,
|
|
2589
|
+
return (0, import_node_fs9.existsSync)((0, import_node_path8.join)(rootDir, "src"));
|
|
2254
2590
|
},
|
|
2255
2591
|
generate(rootDir, layerOutputs) {
|
|
2256
2592
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -2261,7 +2597,7 @@ var init_api_annotations = __esm({
|
|
|
2261
2597
|
const uiNodeIds = new Set(uiOutput?.nodes.map((n) => n.id) ?? []);
|
|
2262
2598
|
const apiRoutes = loadApiRoutesFromOutput(apiOutput);
|
|
2263
2599
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
2264
|
-
const srcDir = (0,
|
|
2600
|
+
const srcDir = (0, import_node_path8.join)(rootDir, "src");
|
|
2265
2601
|
const files = walk2(srcDir, [".ts", ".tsx"]);
|
|
2266
2602
|
const crossRefs = [];
|
|
2267
2603
|
const flaggedEdges = [];
|
|
@@ -2318,24 +2654,24 @@ function walk3(dir, exts) {
|
|
|
2318
2654
|
const results = [];
|
|
2319
2655
|
for (const entry of (0, import_node_fs10.readdirSync)(dir, { withFileTypes: true })) {
|
|
2320
2656
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
2321
|
-
const full = (0,
|
|
2657
|
+
const full = (0, import_node_path9.join)(dir, entry.name);
|
|
2322
2658
|
if (entry.isDirectory()) {
|
|
2323
2659
|
results.push(...walk3(full, exts));
|
|
2324
|
-
} else if (exts.includes((0,
|
|
2660
|
+
} else if (exts.includes((0, import_node_path9.extname)(entry.name))) {
|
|
2325
2661
|
results.push(full);
|
|
2326
2662
|
}
|
|
2327
2663
|
}
|
|
2328
2664
|
return results;
|
|
2329
2665
|
}
|
|
2330
2666
|
function toNodeId3(srcDir, absPath) {
|
|
2331
|
-
return (0,
|
|
2667
|
+
return (0, import_node_path9.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
2332
2668
|
}
|
|
2333
|
-
var import_node_fs10,
|
|
2669
|
+
var import_node_fs10, import_node_path9, URL_LITERAL_RE, urlLiteralScannerParser;
|
|
2334
2670
|
var init_url_literal_scanner = __esm({
|
|
2335
2671
|
"src/server/graph/parsers/crosslayer/url-literal-scanner.ts"() {
|
|
2336
2672
|
"use strict";
|
|
2337
2673
|
import_node_fs10 = require("node:fs");
|
|
2338
|
-
|
|
2674
|
+
import_node_path9 = require("node:path");
|
|
2339
2675
|
init_api_route_matching();
|
|
2340
2676
|
init_config();
|
|
2341
2677
|
init_resolve_paths();
|
|
@@ -2359,7 +2695,7 @@ var init_url_literal_scanner = __esm({
|
|
|
2359
2695
|
const apiPathMap = buildApiPathMap(apiRoutes);
|
|
2360
2696
|
const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
|
|
2361
2697
|
const srcDir = paths.srcDir;
|
|
2362
|
-
const clientDir = (0,
|
|
2698
|
+
const clientDir = (0, import_node_path9.join)(srcDir, "client");
|
|
2363
2699
|
const files = [
|
|
2364
2700
|
...walk3(clientDir, [".ts", ".tsx"]),
|
|
2365
2701
|
...walk3(paths.appDir, [".ts", ".tsx"])
|
|
@@ -2431,8 +2767,8 @@ function extractEnumValues(rootDir) {
|
|
|
2431
2767
|
const nodes = [];
|
|
2432
2768
|
const edges = [];
|
|
2433
2769
|
const schemaPaths = [
|
|
2434
|
-
(0,
|
|
2435
|
-
(0,
|
|
2770
|
+
(0, import_node_path10.join)(rootDir, "prisma", "schema.prisma"),
|
|
2771
|
+
(0, import_node_path10.join)(rootDir, "prisma", "schema")
|
|
2436
2772
|
];
|
|
2437
2773
|
let content = "";
|
|
2438
2774
|
for (const p of schemaPaths) {
|
|
@@ -2443,7 +2779,7 @@ function extractEnumValues(rootDir) {
|
|
|
2443
2779
|
content = (0, import_node_fs11.readFileSync)(p, "utf-8");
|
|
2444
2780
|
} else if (stat.isDirectory()) {
|
|
2445
2781
|
const files = (0, import_node_fs11.readdirSync)(p).filter((f) => f.endsWith(".prisma"));
|
|
2446
|
-
content = files.map((f) => (0, import_node_fs11.readFileSync)((0,
|
|
2782
|
+
content = files.map((f) => (0, import_node_fs11.readFileSync)((0, import_node_path10.join)(p, f), "utf-8")).join("\n");
|
|
2447
2783
|
}
|
|
2448
2784
|
} catch {
|
|
2449
2785
|
continue;
|
|
@@ -2599,14 +2935,14 @@ function extractSeedData(rootDir) {
|
|
|
2599
2935
|
const nodes = [];
|
|
2600
2936
|
const edges = [];
|
|
2601
2937
|
const seedFiles = [
|
|
2602
|
-
(0,
|
|
2603
|
-
(0,
|
|
2604
|
-
(0,
|
|
2938
|
+
(0, import_node_path10.join)(rootDir, "prisma", "seed.ts"),
|
|
2939
|
+
(0, import_node_path10.join)(rootDir, "prisma", "seed.js"),
|
|
2940
|
+
(0, import_node_path10.join)(rootDir, "src", "server", "lib", "system-tags.ts")
|
|
2605
2941
|
].filter(import_node_fs11.existsSync);
|
|
2606
2942
|
const useTreeSitter = tryLoadTreeSitter();
|
|
2607
2943
|
for (const filePath of seedFiles) {
|
|
2608
2944
|
const content = (0, import_node_fs11.readFileSync)(filePath, "utf-8");
|
|
2609
|
-
const relPath = (0,
|
|
2945
|
+
const relPath = (0, import_node_path10.relative)(rootDir, filePath);
|
|
2610
2946
|
const seeded = detectSeededArrays(content, relPath);
|
|
2611
2947
|
let astRoot = null;
|
|
2612
2948
|
if (useTreeSitter && parseCode) {
|
|
@@ -2704,7 +3040,7 @@ function walkDir(dir, exts) {
|
|
|
2704
3040
|
const results = [];
|
|
2705
3041
|
for (const entry of (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true })) {
|
|
2706
3042
|
if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist") continue;
|
|
2707
|
-
const full = (0,
|
|
3043
|
+
const full = (0, import_node_path10.join)(dir, entry.name);
|
|
2708
3044
|
if (entry.isDirectory()) results.push(...walkDir(full, exts));
|
|
2709
3045
|
else if (exts.some((ext) => entry.name.endsWith(ext))) results.push(full);
|
|
2710
3046
|
}
|
|
@@ -2712,11 +3048,11 @@ function walkDir(dir, exts) {
|
|
|
2712
3048
|
}
|
|
2713
3049
|
function extractConstants(rootDir) {
|
|
2714
3050
|
const nodes = [];
|
|
2715
|
-
const srcDir = (0,
|
|
3051
|
+
const srcDir = (0, import_node_path10.join)(rootDir, "src");
|
|
2716
3052
|
if (!(0, import_node_fs11.existsSync)(srcDir)) return { nodes };
|
|
2717
3053
|
for (const filePath of walkDir(srcDir, [".ts", ".tsx"])) {
|
|
2718
3054
|
const content = (0, import_node_fs11.readFileSync)(filePath, "utf-8");
|
|
2719
|
-
const relPath = (0,
|
|
3055
|
+
const relPath = (0, import_node_path10.relative)(rootDir, filePath);
|
|
2720
3056
|
const constArrayRe = /export\s+const\s+([A-Z][A-Z_0-9]+)\s*(?::[^=]+)?\s*=\s*\[/g;
|
|
2721
3057
|
let cm;
|
|
2722
3058
|
while ((cm = constArrayRe.exec(content)) !== null) {
|
|
@@ -2749,7 +3085,7 @@ function extractConstants(rootDir) {
|
|
|
2749
3085
|
return { nodes };
|
|
2750
3086
|
}
|
|
2751
3087
|
function detect4(rootDir) {
|
|
2752
|
-
return (0, import_node_fs11.existsSync)((0,
|
|
3088
|
+
return (0, import_node_fs11.existsSync)((0, import_node_path10.join)(rootDir, "prisma", "schema.prisma")) || (0, import_node_fs11.existsSync)((0, import_node_path10.join)(rootDir, "prisma", "seed.ts"));
|
|
2753
3089
|
}
|
|
2754
3090
|
function generate4(rootDir) {
|
|
2755
3091
|
const enumResult = extractEnumValues(rootDir);
|
|
@@ -2816,12 +3152,12 @@ function generate4(rootDir) {
|
|
|
2816
3152
|
}
|
|
2817
3153
|
};
|
|
2818
3154
|
}
|
|
2819
|
-
var import_node_fs11,
|
|
3155
|
+
var import_node_fs11, import_node_path10, parseCode, SHARED_MODELS, DB_MODELS, staticValuesParser;
|
|
2820
3156
|
var init_static_values = __esm({
|
|
2821
3157
|
"src/server/graph/parsers/static/static-values.ts"() {
|
|
2822
3158
|
"use strict";
|
|
2823
3159
|
import_node_fs11 = require("node:fs");
|
|
2824
|
-
|
|
3160
|
+
import_node_path10 = require("node:path");
|
|
2825
3161
|
parseCode = null;
|
|
2826
3162
|
SHARED_MODELS = /* @__PURE__ */ new Set(["permission", "role", "tag"]);
|
|
2827
3163
|
DB_MODELS = /* @__PURE__ */ new Set(["subscriptionPlan", "providerDefinition", "pipelineMasterTemplate"]);
|
|
@@ -2919,12 +3255,12 @@ function collectStaticRefsRegex(content, valueLookup, allValues) {
|
|
|
2919
3255
|
}
|
|
2920
3256
|
return refs;
|
|
2921
3257
|
}
|
|
2922
|
-
var import_node_fs12,
|
|
3258
|
+
var import_node_fs12, import_node_path11, MIN_VALUE_LENGTH, SKIP_VALUES, staticRefScannerParser;
|
|
2923
3259
|
var init_static_ref_scanner = __esm({
|
|
2924
3260
|
"src/server/graph/parsers/crosslayer/static-ref-scanner.ts"() {
|
|
2925
3261
|
"use strict";
|
|
2926
3262
|
import_node_fs12 = require("node:fs");
|
|
2927
|
-
|
|
3263
|
+
import_node_path11 = require("node:path");
|
|
2928
3264
|
init_config();
|
|
2929
3265
|
init_resolve_paths();
|
|
2930
3266
|
init_walk();
|
|
@@ -2986,11 +3322,11 @@ var init_static_ref_scanner = __esm({
|
|
|
2986
3322
|
if (!paths) return { cross_refs: [], flagged_edges: [], warnings: [] };
|
|
2987
3323
|
const srcDir = paths.srcDir;
|
|
2988
3324
|
const files = [
|
|
2989
|
-
...walkWithIgnore((0,
|
|
3325
|
+
...walkWithIgnore((0, import_node_path11.join)(srcDir, "client"), [".ts", ".tsx"]),
|
|
2990
3326
|
...walkWithIgnore(paths.appDir, [".ts", ".tsx"]),
|
|
2991
|
-
...walkWithIgnore((0,
|
|
2992
|
-
...walkWithIgnore((0,
|
|
2993
|
-
...walkWithIgnore((0,
|
|
3327
|
+
...walkWithIgnore((0, import_node_path11.join)(srcDir, "server"), [".ts", ".tsx"]),
|
|
3328
|
+
...walkWithIgnore((0, import_node_path11.join)(srcDir, "lib"), [".ts", ".tsx"]),
|
|
3329
|
+
...walkWithIgnore((0, import_node_path11.join)(srcDir, "config"), [".ts", ".tsx"])
|
|
2994
3330
|
];
|
|
2995
3331
|
const uiOutput = layerOutputs.get("ui");
|
|
2996
3332
|
const apiOutput = layerOutputs.get("api");
|
|
@@ -3008,7 +3344,7 @@ var init_static_ref_scanner = __esm({
|
|
|
3008
3344
|
const seen = /* @__PURE__ */ new Set();
|
|
3009
3345
|
let filesScanned = 0;
|
|
3010
3346
|
for (const absPath of files) {
|
|
3011
|
-
const sourceId = (0,
|
|
3347
|
+
const sourceId = (0, import_node_path11.relative)(srcDir, absPath).replace(/\\/g, "/");
|
|
3012
3348
|
const sourceLayer = uiNodeIds.has(sourceId) ? "ui" : apiNodeIds.has(sourceId) ? "api" : null;
|
|
3013
3349
|
if (!sourceLayer) continue;
|
|
3014
3350
|
const content = (0, import_node_fs12.readFileSync)(absPath, "utf-8");
|
|
@@ -3077,7 +3413,7 @@ function registerBuiltins(registry, disabled) {
|
|
|
3077
3413
|
function loadCustomParsers(registry, config, rootDir, disabled) {
|
|
3078
3414
|
for (const entry of config.parsers?.custom ?? []) {
|
|
3079
3415
|
try {
|
|
3080
|
-
const absPath = (0,
|
|
3416
|
+
const absPath = (0, import_node_path12.resolve)(rootDir, entry.path);
|
|
3081
3417
|
const mod = require(absPath);
|
|
3082
3418
|
const parser = "default" in mod ? mod.default : mod;
|
|
3083
3419
|
if (disabled.has(parser.id)) continue;
|
|
@@ -3104,11 +3440,11 @@ function createRegistry(config, rootDir) {
|
|
|
3104
3440
|
loadCustomParsers(registry, config, rootDir, disabled);
|
|
3105
3441
|
return registry;
|
|
3106
3442
|
}
|
|
3107
|
-
var
|
|
3443
|
+
var import_node_path12, ParserRegistry;
|
|
3108
3444
|
var init_parser_registry = __esm({
|
|
3109
3445
|
"src/server/graph/core/parser-registry.ts"() {
|
|
3110
3446
|
"use strict";
|
|
3111
|
-
|
|
3447
|
+
import_node_path12 = require("node:path");
|
|
3112
3448
|
init_typescript_project();
|
|
3113
3449
|
init_prisma_schema();
|
|
3114
3450
|
init_sql_migrations();
|
|
@@ -3279,7 +3615,7 @@ var init_merge = __esm({
|
|
|
3279
3615
|
|
|
3280
3616
|
// src/server/graph/core/graph-builder.ts
|
|
3281
3617
|
function readGraphFromDisk(rootDir, layer) {
|
|
3282
|
-
const filePath = (0,
|
|
3618
|
+
const filePath = (0, import_node_path13.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
3283
3619
|
if (!(0, import_node_fs13.existsSync)(filePath)) return null;
|
|
3284
3620
|
try {
|
|
3285
3621
|
return JSON.parse((0, import_node_fs13.readFileSync)(filePath, "utf-8"));
|
|
@@ -3378,12 +3714,12 @@ function generateAll(rootDir) {
|
|
|
3378
3714
|
const extras = [...byLayer.keys()].filter((l) => !wellKnownOrder.includes(l)).sort();
|
|
3379
3715
|
return [...wellKnownOrder, ...extras].map((l) => byLayer.get(l)).filter((r) => !!r);
|
|
3380
3716
|
}
|
|
3381
|
-
var import_node_fs13,
|
|
3717
|
+
var import_node_fs13, import_node_path13;
|
|
3382
3718
|
var init_graph_builder = __esm({
|
|
3383
3719
|
"src/server/graph/core/graph-builder.ts"() {
|
|
3384
3720
|
"use strict";
|
|
3385
3721
|
import_node_fs13 = require("node:fs");
|
|
3386
|
-
|
|
3722
|
+
import_node_path13 = require("node:path");
|
|
3387
3723
|
init_config();
|
|
3388
3724
|
init_parser_registry();
|
|
3389
3725
|
init_merge();
|
|
@@ -3422,13 +3758,13 @@ function detectConventionDirs(rootDir, extraConventionDirs = []) {
|
|
|
3422
3758
|
const conventionDirs = [...CONVENTION_DIRS_BUILTIN, ...extraConventionDirs];
|
|
3423
3759
|
const searchDirs = [
|
|
3424
3760
|
rootDir,
|
|
3425
|
-
(0,
|
|
3426
|
-
(0,
|
|
3427
|
-
(0,
|
|
3761
|
+
(0, import_node_path14.join)(rootDir, "src"),
|
|
3762
|
+
(0, import_node_path14.join)(rootDir, "app"),
|
|
3763
|
+
(0, import_node_path14.join)(rootDir, "lib")
|
|
3428
3764
|
];
|
|
3429
3765
|
for (const base of searchDirs) {
|
|
3430
3766
|
for (const convention of conventionDirs) {
|
|
3431
|
-
const dir = (0,
|
|
3767
|
+
const dir = (0, import_node_path14.join)(base, convention);
|
|
3432
3768
|
if (!(0, import_node_fs14.existsSync)(dir)) continue;
|
|
3433
3769
|
try {
|
|
3434
3770
|
const stat = (0, import_node_fs14.statSync)(dir);
|
|
@@ -3505,12 +3841,12 @@ function extractModuleFromPath(id, extraTrivial, extraSkipSegments) {
|
|
|
3505
3841
|
}
|
|
3506
3842
|
return "root";
|
|
3507
3843
|
}
|
|
3508
|
-
var import_node_fs14,
|
|
3844
|
+
var import_node_fs14, import_node_path14, CONVENTION_DIRS_BUILTIN, GENERIC_ROLE_NAMES_BUILTIN, SKIP_SEGMENTS_BUILTIN, TRIVIAL_GROUPS, cachedRootDir, cachedConventionDirs, moduleTagger;
|
|
3509
3845
|
var init_module_tagger = __esm({
|
|
3510
3846
|
"src/server/graph/taggers/module-tagger.ts"() {
|
|
3511
3847
|
"use strict";
|
|
3512
3848
|
import_node_fs14 = require("node:fs");
|
|
3513
|
-
|
|
3849
|
+
import_node_path14 = require("node:path");
|
|
3514
3850
|
CONVENTION_DIRS_BUILTIN = ["features", "modules", "domains", "areas"];
|
|
3515
3851
|
GENERIC_ROLE_NAMES_BUILTIN = /* @__PURE__ */ new Set([
|
|
3516
3852
|
// JS/TS
|
|
@@ -3722,7 +4058,7 @@ function loadCustomTaggers(registry, config, rootDir, disabled) {
|
|
|
3722
4058
|
for (const entry of config.taggers?.custom ?? []) {
|
|
3723
4059
|
if (disabled.has(entry.id)) continue;
|
|
3724
4060
|
try {
|
|
3725
|
-
const absPath = (0,
|
|
4061
|
+
const absPath = (0, import_node_path15.resolve)(rootDir, entry.path);
|
|
3726
4062
|
const mod = require(absPath);
|
|
3727
4063
|
const tagger = "default" in mod ? mod.default : mod;
|
|
3728
4064
|
const override = config.taggers?.trackUntagged?.[tagger.id];
|
|
@@ -3743,11 +4079,11 @@ function createTaggerRegistry(config, rootDir) {
|
|
|
3743
4079
|
loadCustomTaggers(registry, config, rootDir, disabled);
|
|
3744
4080
|
return registry;
|
|
3745
4081
|
}
|
|
3746
|
-
var
|
|
4082
|
+
var import_node_path15, TaggerRegistry, BUILTIN_TAGGERS;
|
|
3747
4083
|
var init_tagger_registry = __esm({
|
|
3748
4084
|
"src/server/graph/core/tagger-registry.ts"() {
|
|
3749
4085
|
"use strict";
|
|
3750
|
-
|
|
4086
|
+
import_node_path15 = require("node:path");
|
|
3751
4087
|
init_module_tagger();
|
|
3752
4088
|
init_screen_tagger();
|
|
3753
4089
|
TaggerRegistry = class {
|
|
@@ -3775,7 +4111,7 @@ var init_tagger_registry = __esm({
|
|
|
3775
4111
|
|
|
3776
4112
|
// src/server/graph/core/tag-store.ts
|
|
3777
4113
|
function tagsFilePath(rootDir) {
|
|
3778
|
-
return (0,
|
|
4114
|
+
return (0, import_node_path16.join)(rootDir, GRAPHS_DIR, TAGS_FILENAME);
|
|
3779
4115
|
}
|
|
3780
4116
|
function readTagStore(rootDir) {
|
|
3781
4117
|
const filePath = tagsFilePath(rootDir);
|
|
@@ -3796,7 +4132,7 @@ function readTagStore(rootDir) {
|
|
|
3796
4132
|
}
|
|
3797
4133
|
function writeTagStore(rootDir, store) {
|
|
3798
4134
|
const filePath = tagsFilePath(rootDir);
|
|
3799
|
-
const dir = (0,
|
|
4135
|
+
const dir = (0, import_node_path16.dirname)(filePath);
|
|
3800
4136
|
(0, import_node_fs15.mkdirSync)(dir, { recursive: true });
|
|
3801
4137
|
const cleaned = {};
|
|
3802
4138
|
for (const [nodeId, tags] of Object.entries(store)) {
|
|
@@ -3822,12 +4158,12 @@ function removeTag(rootDir, nodeId, key) {
|
|
|
3822
4158
|
}
|
|
3823
4159
|
writeTagStore(rootDir, store);
|
|
3824
4160
|
}
|
|
3825
|
-
var import_node_fs15,
|
|
4161
|
+
var import_node_fs15, import_node_path16, TAGS_FILENAME, GRAPHS_DIR, tagCache;
|
|
3826
4162
|
var init_tag_store = __esm({
|
|
3827
4163
|
"src/server/graph/core/tag-store.ts"() {
|
|
3828
4164
|
"use strict";
|
|
3829
4165
|
import_node_fs15 = require("node:fs");
|
|
3830
|
-
|
|
4166
|
+
import_node_path16 = require("node:path");
|
|
3831
4167
|
TAGS_FILENAME = "tags.json";
|
|
3832
4168
|
GRAPHS_DIR = ".launchsecure/graphs";
|
|
3833
4169
|
tagCache = /* @__PURE__ */ new Map();
|
|
@@ -3836,18 +4172,18 @@ var init_tag_store = __esm({
|
|
|
3836
4172
|
|
|
3837
4173
|
// src/server/graph/index.ts
|
|
3838
4174
|
function getAvailableLayers(rootDir) {
|
|
3839
|
-
const dir = (0,
|
|
4175
|
+
const dir = (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
|
|
3840
4176
|
if (!(0, import_node_fs16.existsSync)(dir)) return [];
|
|
3841
4177
|
return (0, import_node_fs16.readdirSync)(dir).filter((f) => f.endsWith(".json") && f !== "tags.json").map((f) => f.replace(".json", ""));
|
|
3842
4178
|
}
|
|
3843
4179
|
function graphsDir(rootDir) {
|
|
3844
|
-
return (0,
|
|
4180
|
+
return (0, import_node_path17.join)(rootDir, GRAPHS_DIR2);
|
|
3845
4181
|
}
|
|
3846
4182
|
function graphFilePath(rootDir, layer) {
|
|
3847
|
-
return (0,
|
|
4183
|
+
return (0, import_node_path17.join)(graphsDir(rootDir), `${layer}.json`);
|
|
3848
4184
|
}
|
|
3849
4185
|
function tagsFilePath2(rootDir) {
|
|
3850
|
-
return (0,
|
|
4186
|
+
return (0, import_node_path17.join)(graphsDir(rootDir), "tags.json");
|
|
3851
4187
|
}
|
|
3852
4188
|
function getMtimeMs(filePath) {
|
|
3853
4189
|
if (!(0, import_node_fs16.existsSync)(filePath)) return 0;
|
|
@@ -3943,12 +4279,12 @@ async function generateGraph(rootDir, layer) {
|
|
|
3943
4279
|
}
|
|
3944
4280
|
return results;
|
|
3945
4281
|
}
|
|
3946
|
-
var import_node_fs16,
|
|
4282
|
+
var import_node_fs16, import_node_path17, GRAPHS_DIR2, graphCache, taggedCache;
|
|
3947
4283
|
var init_graph = __esm({
|
|
3948
4284
|
"src/server/graph/index.ts"() {
|
|
3949
4285
|
"use strict";
|
|
3950
4286
|
import_node_fs16 = require("node:fs");
|
|
3951
|
-
|
|
4287
|
+
import_node_path17 = require("node:path");
|
|
3952
4288
|
init_graph_builder();
|
|
3953
4289
|
init_config();
|
|
3954
4290
|
init_tagger_registry();
|
|
@@ -3963,7 +4299,7 @@ var init_graph = __esm({
|
|
|
3963
4299
|
|
|
3964
4300
|
// src/server/graph/core/audit-core.ts
|
|
3965
4301
|
function readGraphFile(rootDir, layer) {
|
|
3966
|
-
const filePath = (0,
|
|
4302
|
+
const filePath = (0, import_node_path18.join)(rootDir, ".launchsecure", "graphs", `${layer}.json`);
|
|
3967
4303
|
if (!(0, import_node_fs17.existsSync)(filePath)) return null;
|
|
3968
4304
|
try {
|
|
3969
4305
|
return JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
|
|
@@ -4010,7 +4346,7 @@ function checkUnprotectedRoutes(rootDir) {
|
|
|
4010
4346
|
const api = readGraphFile(rootDir, "api");
|
|
4011
4347
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
4012
4348
|
if (!api) return buildReport("api", "unprotected_routes", findings);
|
|
4013
|
-
const routePermsPath = (0,
|
|
4349
|
+
const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
4014
4350
|
let routePermsContent = "";
|
|
4015
4351
|
if ((0, import_node_fs17.existsSync)(routePermsPath)) {
|
|
4016
4352
|
routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -4090,7 +4426,7 @@ function checkUnenforcedPermissions(rootDir) {
|
|
|
4090
4426
|
const staticGraph = readGraphFile(rootDir, "static");
|
|
4091
4427
|
if (!staticGraph) return buildReport("static", "unenforced_permissions", findings);
|
|
4092
4428
|
const permissions = staticGraph.nodes.filter((n) => n.type === "seed_permission").map((n) => ({ id: n.id, key: n.value, name: n.name }));
|
|
4093
|
-
const routePermsPath = (0,
|
|
4429
|
+
const routePermsPath = (0, import_node_path18.join)(rootDir, "src", "config", "route-permissions.ts");
|
|
4094
4430
|
let routePermsContent = "";
|
|
4095
4431
|
if ((0, import_node_fs17.existsSync)(routePermsPath)) {
|
|
4096
4432
|
routePermsContent = (0, import_node_fs17.readFileSync)(routePermsPath, "utf-8");
|
|
@@ -4123,7 +4459,7 @@ function checkHardcodedValues(rootDir) {
|
|
|
4123
4459
|
const seen = /* @__PURE__ */ new Set();
|
|
4124
4460
|
for (const node of api.nodes) {
|
|
4125
4461
|
if (node.type !== "endpoint") continue;
|
|
4126
|
-
const filePath = (0,
|
|
4462
|
+
const filePath = (0, import_node_path18.join)(rootDir, "src", node.id);
|
|
4127
4463
|
if (!(0, import_node_fs17.existsSync)(filePath)) continue;
|
|
4128
4464
|
const content = (0, import_node_fs17.readFileSync)(filePath, "utf-8");
|
|
4129
4465
|
let m;
|
|
@@ -4219,12 +4555,12 @@ function formatAsPrompt(reports) {
|
|
|
4219
4555
|
if (lines.length === 0) return "No audit findings.";
|
|
4220
4556
|
return lines.join("\n");
|
|
4221
4557
|
}
|
|
4222
|
-
var import_node_fs17,
|
|
4558
|
+
var import_node_fs17, import_node_path18, CHECKS;
|
|
4223
4559
|
var init_audit_core = __esm({
|
|
4224
4560
|
"src/server/graph/core/audit-core.ts"() {
|
|
4225
4561
|
"use strict";
|
|
4226
4562
|
import_node_fs17 = require("node:fs");
|
|
4227
|
-
|
|
4563
|
+
import_node_path18 = require("node:path");
|
|
4228
4564
|
CHECKS = {
|
|
4229
4565
|
db: {
|
|
4230
4566
|
schema_drift: checkSchemaDrift,
|
|
@@ -4256,16 +4592,16 @@ function randomPort() {
|
|
|
4256
4592
|
function findProjectRoot(startDir) {
|
|
4257
4593
|
let dir = startDir;
|
|
4258
4594
|
for (let i = 0; i < 8; i++) {
|
|
4259
|
-
const graphsDir2 =
|
|
4260
|
-
if (import_node_fs18.default.existsSync(
|
|
4261
|
-
const parent =
|
|
4595
|
+
const graphsDir2 = import_node_path19.default.join(dir, ".launchsecure", "graphs");
|
|
4596
|
+
if (import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "ui.json")) || import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "api.json")) || import_node_fs18.default.existsSync(import_node_path19.default.join(graphsDir2, "db.json"))) return dir;
|
|
4597
|
+
const parent = import_node_path19.default.dirname(dir);
|
|
4262
4598
|
if (parent === dir) break;
|
|
4263
4599
|
dir = parent;
|
|
4264
4600
|
}
|
|
4265
4601
|
dir = startDir;
|
|
4266
4602
|
for (let i = 0; i < 8; i++) {
|
|
4267
|
-
if (import_node_fs18.default.existsSync(
|
|
4268
|
-
const parent =
|
|
4603
|
+
if (import_node_fs18.default.existsSync(import_node_path19.default.join(dir, ".git"))) return dir;
|
|
4604
|
+
const parent = import_node_path19.default.dirname(dir);
|
|
4269
4605
|
if (parent === dir) break;
|
|
4270
4606
|
dir = parent;
|
|
4271
4607
|
}
|
|
@@ -4274,7 +4610,7 @@ function findProjectRoot(startDir) {
|
|
|
4274
4610
|
function resolveRequestRoot(url, monorepoRoot, projects) {
|
|
4275
4611
|
const projectParam = url.searchParams.get("project");
|
|
4276
4612
|
if (!projectParam || projects.length === 0) return monorepoRoot;
|
|
4277
|
-
const resolved =
|
|
4613
|
+
const resolved = import_node_path19.default.resolve(monorepoRoot, projectParam);
|
|
4278
4614
|
if (!resolved.startsWith(monorepoRoot)) {
|
|
4279
4615
|
throw new Error("Project path outside monorepo root");
|
|
4280
4616
|
}
|
|
@@ -4326,14 +4662,14 @@ async function buildMergedGraph(root) {
|
|
|
4326
4662
|
}
|
|
4327
4663
|
function serveStatic(res, filePath) {
|
|
4328
4664
|
if (!import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) return false;
|
|
4329
|
-
const ext =
|
|
4665
|
+
const ext = import_node_path19.default.extname(filePath).toLowerCase();
|
|
4330
4666
|
const mime = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
4331
4667
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
|
|
4332
4668
|
import_node_fs18.default.createReadStream(filePath).pipe(res);
|
|
4333
4669
|
return true;
|
|
4334
4670
|
}
|
|
4335
4671
|
function serveIndex(res, clientDir) {
|
|
4336
|
-
const indexPath =
|
|
4672
|
+
const indexPath = import_node_path19.default.join(clientDir, "index.html");
|
|
4337
4673
|
if (!import_node_fs18.default.existsSync(indexPath)) {
|
|
4338
4674
|
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
4339
4675
|
res.end(`LaunchChart client bundle not found at ${clientDir}. Run 'npm run build:chart-client'.`);
|
|
@@ -4342,14 +4678,14 @@ function serveIndex(res, clientDir) {
|
|
|
4342
4678
|
serveStatic(res, indexPath);
|
|
4343
4679
|
}
|
|
4344
4680
|
function tryListen(server, port) {
|
|
4345
|
-
return new Promise((
|
|
4681
|
+
return new Promise((resolve4, reject) => {
|
|
4346
4682
|
const onError = (err2) => {
|
|
4347
4683
|
server.off("listening", onListening);
|
|
4348
4684
|
reject(err2);
|
|
4349
4685
|
};
|
|
4350
4686
|
const onListening = () => {
|
|
4351
4687
|
server.off("error", onError);
|
|
4352
|
-
|
|
4688
|
+
resolve4(port);
|
|
4353
4689
|
};
|
|
4354
4690
|
server.once("error", onError);
|
|
4355
4691
|
server.once("listening", onListening);
|
|
@@ -4386,7 +4722,7 @@ async function startChartServer(opts = {}) {
|
|
|
4386
4722
|
}
|
|
4387
4723
|
return { port: existing.port, url: existing.url };
|
|
4388
4724
|
}
|
|
4389
|
-
const clientDir = opts.clientDir ??
|
|
4725
|
+
const clientDir = opts.clientDir ?? import_node_path19.default.join(__dirname, "..", "chart-client");
|
|
4390
4726
|
const rootConfig = loadConfig(projectRoot);
|
|
4391
4727
|
const projects = rootConfig.projects ?? [];
|
|
4392
4728
|
const server = import_node_http.default.createServer((req, res) => {
|
|
@@ -4402,11 +4738,11 @@ async function startChartServer(opts = {}) {
|
|
|
4402
4738
|
}
|
|
4403
4739
|
if (req.method === "GET" && url2.pathname === "/api/projects") {
|
|
4404
4740
|
const projectList = projects.length > 0 ? projects.map((p) => {
|
|
4405
|
-
const absRoot =
|
|
4406
|
-
const hasGraphs = import_node_fs18.default.existsSync(
|
|
4407
|
-
const hasNextConfig = import_node_fs18.default.existsSync(
|
|
4741
|
+
const absRoot = import_node_path19.default.resolve(projectRoot, p.root);
|
|
4742
|
+
const hasGraphs = import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, ".launchsecure", "graphs"));
|
|
4743
|
+
const hasNextConfig = import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.ts")) || import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.js")) || import_node_fs18.default.existsSync(import_node_path19.default.join(absRoot, "next.config.mjs"));
|
|
4408
4744
|
return { name: p.name, root: p.root, hasGraphs, hasNextConfig };
|
|
4409
|
-
}) : [{ name:
|
|
4745
|
+
}) : [{ name: import_node_path19.default.basename(projectRoot), root: ".", hasGraphs: import_node_fs18.default.existsSync(import_node_path19.default.join(projectRoot, ".launchsecure", "graphs")), hasNextConfig: true }];
|
|
4410
4746
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4411
4747
|
res.end(JSON.stringify({ projects: projectList, monorepoRoot: projectRoot }));
|
|
4412
4748
|
return;
|
|
@@ -4452,18 +4788,18 @@ async function startChartServer(opts = {}) {
|
|
|
4452
4788
|
}
|
|
4453
4789
|
if (req.method === "GET" && url2.pathname === "/api/file-content") {
|
|
4454
4790
|
const relPath = url2.searchParams.get("path");
|
|
4455
|
-
if (!relPath || relPath.includes("..") ||
|
|
4791
|
+
if (!relPath || relPath.includes("..") || import_node_path19.default.isAbsolute(relPath)) {
|
|
4456
4792
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
4457
4793
|
res.end(JSON.stringify({ error: "Invalid path" }));
|
|
4458
4794
|
return;
|
|
4459
4795
|
}
|
|
4460
|
-
const filePath =
|
|
4796
|
+
const filePath = import_node_path19.default.join(reqRoot, relPath);
|
|
4461
4797
|
if (!filePath.startsWith(reqRoot) || !import_node_fs18.default.existsSync(filePath) || !import_node_fs18.default.statSync(filePath).isFile()) {
|
|
4462
4798
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
4463
4799
|
res.end(JSON.stringify({ error: "File not found" }));
|
|
4464
4800
|
return;
|
|
4465
4801
|
}
|
|
4466
|
-
const ext =
|
|
4802
|
+
const ext = import_node_path19.default.extname(filePath).toLowerCase();
|
|
4467
4803
|
const langMap = { ".ts": "typescript", ".tsx": "tsx", ".js": "javascript", ".jsx": "jsx", ".prisma": "prisma", ".json": "json", ".css": "css" };
|
|
4468
4804
|
const content = import_node_fs18.default.readFileSync(filePath, "utf-8");
|
|
4469
4805
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -4507,7 +4843,7 @@ async function startChartServer(opts = {}) {
|
|
|
4507
4843
|
req.on("end", () => {
|
|
4508
4844
|
try {
|
|
4509
4845
|
const newConfig = JSON.parse(body);
|
|
4510
|
-
const configPath =
|
|
4846
|
+
const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
|
|
4511
4847
|
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(newConfig, null, 2) + "\n", "utf-8");
|
|
4512
4848
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4513
4849
|
res.end(JSON.stringify({ ok: true }));
|
|
@@ -4541,7 +4877,7 @@ async function startChartServer(opts = {}) {
|
|
|
4541
4877
|
const taggerConfig = JSON.parse(body);
|
|
4542
4878
|
const config2 = loadConfig(reqRoot);
|
|
4543
4879
|
config2.taggers = taggerConfig;
|
|
4544
|
-
const configPath =
|
|
4880
|
+
const configPath = import_node_path19.default.join(reqRoot, ".launchchart.json");
|
|
4545
4881
|
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
4546
4882
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4547
4883
|
res.end(JSON.stringify({ ok: true }));
|
|
@@ -4609,16 +4945,23 @@ async function startChartServer(opts = {}) {
|
|
|
4609
4945
|
const paths = resolveProjectPaths(reqRoot, config2);
|
|
4610
4946
|
const overrides = {
|
|
4611
4947
|
appDir: !!config2.paths?.appDir,
|
|
4612
|
-
dbDir: !!config2.paths?.dbDir
|
|
4948
|
+
dbDir: !!config2.paths?.dbDir,
|
|
4949
|
+
srcRoots: !!(config2.paths?.srcRoots && config2.paths.srcRoots.length > 0)
|
|
4613
4950
|
};
|
|
4951
|
+
const relFromRoot = (abs) => import_node_path19.default.relative(reqRoot, abs) || ".";
|
|
4614
4952
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4615
4953
|
res.end(JSON.stringify({
|
|
4616
4954
|
projectRoot: reqRoot,
|
|
4617
4955
|
detected: paths ? {
|
|
4618
|
-
srcDir:
|
|
4619
|
-
appDir:
|
|
4620
|
-
apiDir:
|
|
4621
|
-
dbDir: paths.dbDir ?
|
|
4956
|
+
srcDir: relFromRoot(paths.srcDir),
|
|
4957
|
+
appDir: relFromRoot(paths.appDir),
|
|
4958
|
+
apiDir: relFromRoot(paths.apiDir),
|
|
4959
|
+
dbDir: paths.dbDir ? relFromRoot(paths.dbDir) : null,
|
|
4960
|
+
dbKind: paths.dbConfig.kind,
|
|
4961
|
+
dbSchemaPath: paths.dbConfig.schemaPath ? relFromRoot(paths.dbConfig.schemaPath) : null,
|
|
4962
|
+
dbMigrationsDir: paths.dbConfig.migrationsDir ? relFromRoot(paths.dbConfig.migrationsDir) : null,
|
|
4963
|
+
srcRoots: paths.srcRoots.map(relFromRoot),
|
|
4964
|
+
conventionFiles: paths.conventionFiles.map(relFromRoot)
|
|
4622
4965
|
} : null,
|
|
4623
4966
|
overrides,
|
|
4624
4967
|
isOverride: overrides.appDir
|
|
@@ -4627,8 +4970,8 @@ async function startChartServer(opts = {}) {
|
|
|
4627
4970
|
}
|
|
4628
4971
|
if (req.method === "GET" && url2.pathname === "/api/browse-dir") {
|
|
4629
4972
|
const browsePath = url2.searchParams.get("path") || projectRoot;
|
|
4630
|
-
const abs =
|
|
4631
|
-
const twoUp =
|
|
4973
|
+
const abs = import_node_path19.default.resolve(browsePath);
|
|
4974
|
+
const twoUp = import_node_path19.default.resolve(projectRoot, "..", "..");
|
|
4632
4975
|
if (!abs.startsWith(twoUp)) {
|
|
4633
4976
|
res.writeHead(403, { "Content-Type": "application/json" });
|
|
4634
4977
|
res.end(JSON.stringify({ ok: false, error: "Path outside allowed range" }));
|
|
@@ -4637,9 +4980,9 @@ async function startChartServer(opts = {}) {
|
|
|
4637
4980
|
try {
|
|
4638
4981
|
const entries = import_node_fs18.default.readdirSync(abs, { withFileTypes: true });
|
|
4639
4982
|
const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules" && e.name !== "dist" && e.name !== ".next").map((e) => e.name).sort();
|
|
4640
|
-
const parent = abs !== twoUp ?
|
|
4983
|
+
const parent = abs !== twoUp ? import_node_path19.default.dirname(abs) : null;
|
|
4641
4984
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4642
|
-
res.end(JSON.stringify({ current: abs, parent, dirs, relative:
|
|
4985
|
+
res.end(JSON.stringify({ current: abs, parent, dirs, relative: import_node_path19.default.relative(projectRoot, abs) || "." }));
|
|
4643
4986
|
} catch (err2) {
|
|
4644
4987
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
4645
4988
|
res.end(JSON.stringify({ ok: false, error: String(err2) }));
|
|
@@ -4665,7 +5008,7 @@ async function startChartServer(opts = {}) {
|
|
|
4665
5008
|
const { projects: newProjects } = JSON.parse(body);
|
|
4666
5009
|
const config2 = loadConfig(projectRoot);
|
|
4667
5010
|
config2.projects = newProjects.length > 0 ? newProjects : void 0;
|
|
4668
|
-
const configPath =
|
|
5011
|
+
const configPath = import_node_path19.default.join(projectRoot, ".launchchart.json");
|
|
4669
5012
|
import_node_fs18.default.writeFileSync(configPath, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
4670
5013
|
projects.length = 0;
|
|
4671
5014
|
if (config2.projects) projects.push(...config2.projects);
|
|
@@ -4679,7 +5022,7 @@ async function startChartServer(opts = {}) {
|
|
|
4679
5022
|
return;
|
|
4680
5023
|
}
|
|
4681
5024
|
if (url2.pathname !== "/") {
|
|
4682
|
-
const staticPath =
|
|
5025
|
+
const staticPath = import_node_path19.default.join(clientDir, url2.pathname);
|
|
4683
5026
|
if (serveStatic(res, staticPath)) return;
|
|
4684
5027
|
}
|
|
4685
5028
|
serveIndex(res, clientDir);
|
|
@@ -4739,13 +5082,13 @@ function runServeCli(argv) {
|
|
|
4739
5082
|
process.exit(1);
|
|
4740
5083
|
});
|
|
4741
5084
|
}
|
|
4742
|
-
var import_node_http, import_node_fs18,
|
|
5085
|
+
var import_node_http, import_node_fs18, import_node_path19, MAX_PORT_SCAN, MIME_TYPES;
|
|
4743
5086
|
var init_chart_serve = __esm({
|
|
4744
5087
|
"src/server/chart-serve.ts"() {
|
|
4745
5088
|
"use strict";
|
|
4746
5089
|
import_node_http = __toESM(require("node:http"));
|
|
4747
5090
|
import_node_fs18 = __toESM(require("node:fs"));
|
|
4748
|
-
|
|
5091
|
+
import_node_path19 = __toESM(require("node:path"));
|
|
4749
5092
|
init_graph();
|
|
4750
5093
|
init_lockfile();
|
|
4751
5094
|
init_config();
|
|
@@ -4781,9 +5124,9 @@ function walkForExtensions(dir, extCounts, depth = 0) {
|
|
|
4781
5124
|
if (entry.name.startsWith(".") && entry.isDirectory()) continue;
|
|
4782
5125
|
if (entry.isDirectory()) {
|
|
4783
5126
|
if (IGNORE_DIRS.has(entry.name)) continue;
|
|
4784
|
-
walkForExtensions((0,
|
|
5127
|
+
walkForExtensions((0, import_node_path20.join)(dir, entry.name), extCounts, depth + 1);
|
|
4785
5128
|
} else {
|
|
4786
|
-
const ext = (0,
|
|
5129
|
+
const ext = (0, import_node_path20.extname)(entry.name).toLowerCase();
|
|
4787
5130
|
if (ext && EXTENSION_TO_LANGUAGE[ext]) {
|
|
4788
5131
|
extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
|
|
4789
5132
|
}
|
|
@@ -4822,12 +5165,12 @@ function detectLanguages(rootDir, supportedLanguages) {
|
|
|
4822
5165
|
});
|
|
4823
5166
|
return results;
|
|
4824
5167
|
}
|
|
4825
|
-
var import_node_fs19,
|
|
5168
|
+
var import_node_fs19, import_node_path20, EXTENSION_TO_LANGUAGE, IGNORE_DIRS, AUXILIARY_LANGUAGES;
|
|
4826
5169
|
var init_language_detection = __esm({
|
|
4827
5170
|
"src/server/graph/core/language-detection.ts"() {
|
|
4828
5171
|
"use strict";
|
|
4829
5172
|
import_node_fs19 = require("node:fs");
|
|
4830
|
-
|
|
5173
|
+
import_node_path20 = require("node:path");
|
|
4831
5174
|
EXTENSION_TO_LANGUAGE = {
|
|
4832
5175
|
// Web / Frontend
|
|
4833
5176
|
".ts": "typescript",
|
|
@@ -5388,11 +5731,11 @@ function handleReadGraph(args) {
|
|
|
5388
5731
|
return okJson(result);
|
|
5389
5732
|
}
|
|
5390
5733
|
function nodeToFilePath(rootDir, layer, nodeId) {
|
|
5391
|
-
if (layer === "ui" || layer === "api") return (0,
|
|
5392
|
-
if (layer === "db") return (0,
|
|
5393
|
-
const withSrc = (0,
|
|
5734
|
+
if (layer === "ui" || layer === "api") return (0, import_node_path21.join)(rootDir, "src", nodeId);
|
|
5735
|
+
if (layer === "db") return (0, import_node_path21.join)(rootDir, "prisma", "schema.prisma");
|
|
5736
|
+
const withSrc = (0, import_node_path21.join)(rootDir, "src", nodeId);
|
|
5394
5737
|
if ((0, import_node_fs20.existsSync)(withSrc)) return withSrc;
|
|
5395
|
-
const direct = (0,
|
|
5738
|
+
const direct = (0, import_node_path21.join)(rootDir, nodeId);
|
|
5396
5739
|
if ((0, import_node_fs20.existsSync)(direct)) return direct;
|
|
5397
5740
|
return null;
|
|
5398
5741
|
}
|
|
@@ -5605,9 +5948,9 @@ function handleStartChartServer(args) {
|
|
|
5605
5948
|
});
|
|
5606
5949
|
}
|
|
5607
5950
|
const entryPath = process.argv[1];
|
|
5608
|
-
const logDir = (0,
|
|
5951
|
+
const logDir = (0, import_node_path21.join)((0, import_node_os2.homedir)(), ".launchsecure");
|
|
5609
5952
|
(0, import_node_fs20.mkdirSync)(logDir, { recursive: true });
|
|
5610
|
-
const logPath = (0,
|
|
5953
|
+
const logPath = (0, import_node_path21.join)(logDir, "launch-chart.log");
|
|
5611
5954
|
const out = (0, import_node_fs20.openSync)(logPath, "a");
|
|
5612
5955
|
const err2 = (0, import_node_fs20.openSync)(logPath, "a");
|
|
5613
5956
|
const portArgs = args.port ? ["--port", String(args.port)] : [];
|
|
@@ -5729,18 +6072,18 @@ function handleDetectProjectStack() {
|
|
|
5729
6072
|
if (ref.type === "references_api") stats.references_api++;
|
|
5730
6073
|
}
|
|
5731
6074
|
}
|
|
5732
|
-
const srcDir = (0,
|
|
6075
|
+
const srcDir = (0, import_node_path21.join)(rootDir, "src");
|
|
5733
6076
|
if ((0, import_node_fs20.existsSync)(srcDir)) {
|
|
5734
6077
|
const scanDir = (dir) => {
|
|
5735
6078
|
if (!(0, import_node_fs20.existsSync)(dir)) return;
|
|
5736
6079
|
for (const entry of (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true })) {
|
|
5737
6080
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
5738
|
-
const full = (0,
|
|
6081
|
+
const full = (0, import_node_path21.join)(dir, entry.name);
|
|
5739
6082
|
if (entry.isDirectory()) {
|
|
5740
6083
|
scanDir(full);
|
|
5741
6084
|
continue;
|
|
5742
6085
|
}
|
|
5743
|
-
if (![".ts", ".tsx"].includes((0,
|
|
6086
|
+
if (![".ts", ".tsx"].includes((0, import_node_path21.extname)(entry.name))) continue;
|
|
5744
6087
|
try {
|
|
5745
6088
|
const content = (0, import_node_fs20.readFileSync)(full, "utf-8");
|
|
5746
6089
|
const matches = content.match(/@api\s+(GET|POST|PUT|DELETE|PATCH)\s+\/\S+/g);
|
|
@@ -5896,12 +6239,12 @@ function startGraphMcpServer() {
|
|
|
5896
6239
|
process.stderr.write(`[launchsecure-graph] MCP server started (cwd: ${process.cwd()})
|
|
5897
6240
|
`);
|
|
5898
6241
|
}
|
|
5899
|
-
var import_node_fs20,
|
|
6242
|
+
var import_node_fs20, import_node_path21, import_node_child_process2, import_node_os2, SERVER_INFO, TOOLS, COMPACT_SCHEMA, COMPACT_NODE_KNOWN_KEYS, DEEP_FIELDS, EST_CHARS_PER_NODE_FULL, EST_CHARS_PER_NODE_MIN, EST_CHARS_PER_EDGE, DEFAULT_EST_NODE_FULL, DEFAULT_EST_NODE_MIN, DEFAULT_EST_EDGE, NEIGHBORHOOD_BUDGET_CHARS, BATCH_BUDGET_CHARS;
|
|
5900
6243
|
var init_graph_mcp = __esm({
|
|
5901
6244
|
"src/server/graph-mcp.ts"() {
|
|
5902
6245
|
"use strict";
|
|
5903
6246
|
import_node_fs20 = require("node:fs");
|
|
5904
|
-
|
|
6247
|
+
import_node_path21 = require("node:path");
|
|
5905
6248
|
import_node_child_process2 = require("node:child_process");
|
|
5906
6249
|
import_node_os2 = require("node:os");
|
|
5907
6250
|
init_graph();
|
|
@@ -6288,7 +6631,7 @@ Example: blast_points(node_id: "server/auth/middleware.ts", hops: 2) \u2192 retu
|
|
|
6288
6631
|
// src/server/graph-mcp-entry.ts
|
|
6289
6632
|
var import_node_child_process3 = require("node:child_process");
|
|
6290
6633
|
var import_node_fs21 = require("node:fs");
|
|
6291
|
-
var
|
|
6634
|
+
var import_node_path22 = __toESM(require("node:path"));
|
|
6292
6635
|
var import_node_os3 = require("node:os");
|
|
6293
6636
|
var import_node_fs22 = require("node:fs");
|
|
6294
6637
|
init_lockfile();
|
|
@@ -6306,9 +6649,9 @@ function maybeAutoServe() {
|
|
|
6306
6649
|
return;
|
|
6307
6650
|
}
|
|
6308
6651
|
try {
|
|
6309
|
-
const logDir =
|
|
6652
|
+
const logDir = import_node_path22.default.join((0, import_node_os3.homedir)(), ".launchsecure");
|
|
6310
6653
|
(0, import_node_fs22.mkdirSync)(logDir, { recursive: true });
|
|
6311
|
-
const logPath =
|
|
6654
|
+
const logPath = import_node_path22.default.join(logDir, "launch-chart.log");
|
|
6312
6655
|
const out = (0, import_node_fs21.openSync)(logPath, "a");
|
|
6313
6656
|
const err2 = (0, import_node_fs21.openSync)(logPath, "a");
|
|
6314
6657
|
const entryPath = process.argv[1];
|