@launchsecure/launch-kit 0.0.14 → 0.0.16

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.
@@ -624,19 +624,26 @@ init_config();
624
624
  // src/server/graph/core/resolve-paths.ts
625
625
  var import_node_fs2 = require("node:fs");
626
626
  var import_node_path2 = require("node:path");
627
+ function detectDbDir(rootDir, config) {
628
+ if (config.paths?.dbDir) return (0, import_node_path2.join)(rootDir, config.paths.dbDir);
629
+ const prismaDir = (0, import_node_path2.join)(rootDir, "prisma");
630
+ if ((0, import_node_fs2.existsSync)(prismaDir)) return prismaDir;
631
+ return null;
632
+ }
627
633
  function resolveProjectPaths(rootDir, config) {
634
+ const dbDir = detectDbDir(rootDir, config);
628
635
  if (config.paths?.appDir) {
629
636
  const appDir = (0, import_node_path2.join)(rootDir, config.paths.appDir);
630
637
  const srcDir = config.paths.srcDir ? (0, import_node_path2.join)(rootDir, config.paths.srcDir) : (0, import_node_path2.dirname)(appDir);
631
- return { srcDir, appDir, apiDir: (0, import_node_path2.join)(appDir, "api") };
638
+ return { srcDir, appDir, apiDir: (0, import_node_path2.join)(appDir, "api"), dbDir };
632
639
  }
633
640
  const srcApp = (0, import_node_path2.join)(rootDir, "src", "app");
634
641
  if ((0, import_node_fs2.existsSync)(srcApp)) {
635
- return { srcDir: (0, import_node_path2.join)(rootDir, "src"), appDir: srcApp, apiDir: (0, import_node_path2.join)(srcApp, "api") };
642
+ return { srcDir: (0, import_node_path2.join)(rootDir, "src"), appDir: srcApp, apiDir: (0, import_node_path2.join)(srcApp, "api"), dbDir };
636
643
  }
637
644
  const rootApp = (0, import_node_path2.join)(rootDir, "app");
638
645
  if ((0, import_node_fs2.existsSync)(rootApp)) {
639
- return { srcDir: rootDir, appDir: rootApp, apiDir: (0, import_node_path2.join)(rootApp, "api") };
646
+ return { srcDir: rootDir, appDir: rootApp, apiDir: (0, import_node_path2.join)(rootApp, "api"), dbDir };
640
647
  }
641
648
  return null;
642
649
  }
@@ -2000,6 +2007,7 @@ function resolveUrlPath(urlPath, apiPathMap, apiRoutes) {
2000
2007
  var fetchResolverParser = {
2001
2008
  id: "fetch-resolver",
2002
2009
  layer: "crosslayer",
2010
+ concern: "api-binding",
2003
2011
  detect(_rootDir) {
2004
2012
  return true;
2005
2013
  },
@@ -2113,6 +2121,7 @@ function toNodeId2(srcDir, absPath) {
2113
2121
  var apiAnnotationsParser = {
2114
2122
  id: "api-annotations",
2115
2123
  layer: "crosslayer",
2124
+ concern: "api-binding",
2116
2125
  detect(rootDir) {
2117
2126
  return (0, import_node_fs7.existsSync)((0, import_node_path7.join)(rootDir, "src"));
2118
2127
  },
@@ -2199,6 +2208,7 @@ function toNodeId3(srcDir, absPath) {
2199
2208
  var urlLiteralScannerParser = {
2200
2209
  id: "url-literal-scanner",
2201
2210
  layer: "crosslayer",
2211
+ concern: "api-binding",
2202
2212
  detect(rootDir) {
2203
2213
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2204
2214
  return paths !== null;
@@ -2810,6 +2820,7 @@ function collectStaticRefsRegex(content, valueLookup, allValues) {
2810
2820
  var staticRefScannerParser = {
2811
2821
  id: "static-ref-scanner",
2812
2822
  layer: "crosslayer",
2823
+ concern: "static-ref",
2813
2824
  detect(rootDir) {
2814
2825
  const paths = resolveProjectPaths(rootDir, loadConfig(rootDir));
2815
2826
  return paths !== null;
@@ -2994,6 +3005,9 @@ function loadCustomParsers(registry, config, rootDir, disabled) {
2994
3005
  `
2995
3006
  );
2996
3007
  }
3008
+ if (parser.layer === "crosslayer" && entry.concern && !("concern" in parser && parser.concern)) {
3009
+ parser.concern = entry.concern;
3010
+ }
2997
3011
  registry.register(parser);
2998
3012
  } catch (err) {
2999
3013
  process.stderr.write(`[launch-chart] failed to load custom parser from ${entry.path}: ${err}
@@ -3091,44 +3105,21 @@ function dedupCrossRefs(refs) {
3091
3105
  }
3092
3106
  return result;
3093
3107
  }
3094
- function applyCrossLayerResults(uiOutput, results, primaryId) {
3095
- const allCrossRefs = [...uiOutput.cross_refs];
3096
- const allFlagged = [...uiOutput.flagged_edges];
3097
- const allWarnings = [...uiOutput.warnings];
3098
- const primaryResult = results.find((r) => r.parserId === primaryId);
3099
- const secondaryResults = results.filter((r) => r.parserId !== primaryId);
3100
- if (primaryResult) {
3101
- allCrossRefs.push(...primaryResult.output.cross_refs);
3102
- allFlagged.push(...primaryResult.output.flagged_edges);
3103
- allWarnings.push(...primaryResult.output.warnings);
3104
- }
3105
- const primarySet = new Set(
3106
- (primaryResult?.output.cross_refs ?? []).map((r) => `${r.source}|${r.target}|${r.type}`)
3107
- );
3108
- for (const sec of secondaryResults) {
3109
- for (const ref of sec.output.cross_refs) {
3110
- const key = `${ref.source}|${ref.target}|${ref.type}`;
3111
- if (primarySet.has(key)) {
3112
- allCrossRefs.push(ref);
3113
- } else {
3114
- allFlagged.push({
3115
- source: ref.source,
3116
- target: ref.target,
3117
- type: "out_of_pattern",
3118
- label: `API call detected by ${sec.parserId} but not by primary (${primaryId})`,
3119
- confidence: "medium"
3120
- });
3121
- allCrossRefs.push(ref);
3122
- }
3123
- }
3124
- allFlagged.push(...sec.output.flagged_edges);
3125
- allWarnings.push(...sec.output.warnings);
3126
- }
3108
+ function applyCrossLayerResults(uiOutput, results) {
3127
3109
  return {
3128
3110
  ...uiOutput,
3129
- cross_refs: dedupCrossRefs(allCrossRefs),
3130
- flagged_edges: allFlagged,
3131
- warnings: allWarnings
3111
+ cross_refs: dedupCrossRefs([
3112
+ ...uiOutput.cross_refs,
3113
+ ...results.flatMap((r) => r.output.cross_refs)
3114
+ ]),
3115
+ flagged_edges: [
3116
+ ...uiOutput.flagged_edges,
3117
+ ...results.flatMap((r) => r.output.flagged_edges)
3118
+ ],
3119
+ warnings: [
3120
+ ...uiOutput.warnings,
3121
+ ...results.flatMap((r) => r.output.warnings)
3122
+ ]
3132
3123
  };
3133
3124
  }
3134
3125
 
@@ -3167,10 +3158,9 @@ function generateLayer(rootDir, layer) {
3167
3158
  if (existing) layerOutputs.set(otherLayer, existing);
3168
3159
  }
3169
3160
  const crossParsers = registry.getCrossLayerParsers();
3170
- const primaryId = config.parsers?.primary?.crosslayer ?? crossParsers[0]?.id ?? null;
3171
3161
  const crossResults = crossParsers.filter((p) => p.detect(rootDir)).map((p) => ({ parserId: p.id, output: p.generate(rootDir, layerOutputs) }));
3172
3162
  if (crossResults.length > 0) {
3173
- merged = applyCrossLayerResults(merged, crossResults, primaryId);
3163
+ merged = applyCrossLayerResults(merged, crossResults);
3174
3164
  }
3175
3165
  }
3176
3166
  return {
@@ -3217,11 +3207,10 @@ function generateAll(rootDir) {
3217
3207
  });
3218
3208
  }
3219
3209
  const crossParsers = registry.getCrossLayerParsers();
3220
- const primaryId = config.parsers?.primary?.crosslayer ?? crossParsers[0]?.id ?? null;
3221
3210
  const crossResults = crossParsers.filter((p) => p.detect(rootDir)).map((p) => ({ parserId: p.id, output: p.generate(rootDir, layerOutputs) }));
3222
3211
  if (crossResults.length > 0 && layerOutputs.has("ui")) {
3223
3212
  const uiOutput = layerOutputs.get("ui");
3224
- const merged = applyCrossLayerResults(uiOutput, crossResults, primaryId);
3213
+ const merged = applyCrossLayerResults(uiOutput, crossResults);
3225
3214
  layerOutputs.set("ui", merged);
3226
3215
  const uiResult = results.find((r) => r.layer === "ui");
3227
3216
  if (uiResult) {
@@ -4386,17 +4375,23 @@ async function startChartServer(opts = {}) {
4386
4375
  if (req.method === "GET" && url2.pathname === "/api/parser-config") {
4387
4376
  const config2 = loadConfig(reqRoot);
4388
4377
  const registry = createRegistry(config2, reqRoot);
4378
+ const toLabel = (id) => id.split("-").map((w) => w[0].toUpperCase() + w.slice(1)).join(" ");
4389
4379
  const detection = [];
4390
4380
  for (const parser of registry.getAll()) {
4391
4381
  if ("layers" in parser && Array.isArray(parser.layers)) {
4392
4382
  const mp = parser;
4393
- detection.push({ id: mp.id, layers: mp.layers, detected: mp.detect(reqRoot) });
4383
+ detection.push({ id: mp.id, layers: mp.layers, label: toLabel(mp.id), detected: mp.detect(reqRoot) });
4394
4384
  } else if ("layer" in parser && parser.layer !== "crosslayer") {
4395
4385
  const sp = parser;
4396
- detection.push({ id: sp.id, layers: [sp.layer], detected: sp.detect(reqRoot) });
4386
+ detection.push({ id: sp.id, layers: [sp.layer], label: toLabel(sp.id), detected: sp.detect(reqRoot) });
4397
4387
  }
4398
4388
  }
4399
- const crosslayerParsers = registry.getCrossLayerParsers().map((p) => ({ id: p.id }));
4389
+ const crosslayerParsers = {};
4390
+ for (const p of registry.getCrossLayerParsers()) {
4391
+ const concern = p.concern ?? "api-binding";
4392
+ if (!crosslayerParsers[concern]) crosslayerParsers[concern] = [];
4393
+ crosslayerParsers[concern].push({ id: p.id, label: toLabel(p.id) });
4394
+ }
4400
4395
  res.writeHead(200, { "Content-Type": "application/json" });
4401
4396
  res.end(JSON.stringify({ config: config2, detection, crosslayerParsers }));
4402
4397
  return;
@@ -4509,16 +4504,21 @@ async function startChartServer(opts = {}) {
4509
4504
  if (req.method === "GET" && url2.pathname === "/api/detected-paths") {
4510
4505
  const config2 = loadConfig(reqRoot);
4511
4506
  const paths = resolveProjectPaths(reqRoot, config2);
4512
- const isOverride = !!config2.paths?.appDir;
4507
+ const overrides = {
4508
+ appDir: !!config2.paths?.appDir,
4509
+ dbDir: !!config2.paths?.dbDir
4510
+ };
4513
4511
  res.writeHead(200, { "Content-Type": "application/json" });
4514
4512
  res.end(JSON.stringify({
4515
4513
  projectRoot: reqRoot,
4516
4514
  detected: paths ? {
4517
4515
  srcDir: import_node_path19.default.relative(reqRoot, paths.srcDir) || ".",
4518
4516
  appDir: import_node_path19.default.relative(reqRoot, paths.appDir),
4519
- apiDir: import_node_path19.default.relative(reqRoot, paths.apiDir)
4517
+ apiDir: import_node_path19.default.relative(reqRoot, paths.apiDir),
4518
+ dbDir: paths.dbDir ? import_node_path19.default.relative(reqRoot, paths.dbDir) : null
4520
4519
  } : null,
4521
- isOverride
4520
+ overrides,
4521
+ isOverride: overrides.appDir
4522
4522
  }));
4523
4523
  return;
4524
4524
  }