@launchsecure/launch-kit 0.0.33 → 0.0.35

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.
@@ -246,6 +246,7 @@ function emptyParsedFile(absPath) {
246
246
  return {
247
247
  name: absPath.split("/").pop() ?? absPath,
248
248
  exports: [],
249
+ defines: [],
249
250
  imports: [],
250
251
  reExports: [],
251
252
  jsxElements: /* @__PURE__ */ new Set(),
@@ -358,6 +359,34 @@ function parseFileTS(absPath) {
358
359
  reExports.push({ name: "*", from: caps["reexport.wildcard.source"], isWildcard: true });
359
360
  }
360
361
  }
362
+ const definesSet = /* @__PURE__ */ new Set();
363
+ function recordCallable(decl) {
364
+ if (decl.type === "function_declaration" || decl.type === "generator_function_declaration") {
365
+ const id = childOfType(decl, "identifier");
366
+ if (id) definesSet.add(id.text);
367
+ return;
368
+ }
369
+ if (decl.type === "class_declaration") {
370
+ const id = childOfType(decl, "type_identifier") ?? childOfType(decl, "identifier");
371
+ if (id) definesSet.add(id.text);
372
+ return;
373
+ }
374
+ if (decl.type === "lexical_declaration" || decl.type === "variable_declaration") {
375
+ for (const d of childrenOfType(decl, "variable_declarator")) {
376
+ const id = childOfType(d, "identifier");
377
+ if (!id) continue;
378
+ const isCallable = !!childOfType(d, "arrow_function") || !!childOfType(d, "function_expression") || !!childOfType(d, "function") || !!childOfType(d, "generator_function");
379
+ if (isCallable) definesSet.add(id.text);
380
+ }
381
+ }
382
+ }
383
+ for (const child of root.children) {
384
+ if (child.type === "export_statement") {
385
+ for (const gc of child.children) recordCallable(gc);
386
+ } else {
387
+ recordCallable(child);
388
+ }
389
+ }
361
390
  const jsxElements = /* @__PURE__ */ new Set();
362
391
  const jsxQuery = getQuery("jsx-elements");
363
392
  const jsxCaptures = jsxQuery.captures(root);
@@ -446,7 +475,7 @@ function parseFileTS(absPath) {
446
475
  }
447
476
  }
448
477
  const name = defaultName ?? firstValueExport ?? firstTypeExport ?? "";
449
- return { name, exports: exportsOrdered, imports, reExports, jsxElements, navigations, fetchCalls };
478
+ return { name, exports: exportsOrdered, defines: [...definesSet], imports, reExports, jsxElements, navigations, fetchCalls };
450
479
  }
451
480
  function extractDbCallsTS(absPath) {
452
481
  const tree = parseSource(absPath);
@@ -2884,6 +2913,11 @@ function generate(rootDir) {
2884
2913
  const parsed = parsedByPath.get(absPath);
2885
2914
  const name = parsed.name || nameFromFilename(absPath);
2886
2915
  const layer = CLASSIFICATION_TO_LAYER[type] ?? "ui";
2916
+ const importedNames = [...new Set(
2917
+ parsed.imports.flatMap(
2918
+ (imp) => imp.isTypeOnly ? [] : imp.names.filter((n) => !imp.typeNames.has(n))
2919
+ )
2920
+ )];
2887
2921
  nodeIdSet.add(id);
2888
2922
  if (layer === "api") {
2889
2923
  const dbCalls = extractDbCallsTS(absPath);
@@ -2922,6 +2956,8 @@ function generate(rootDir) {
2922
2956
  responses: deep.responses,
2923
2957
  params: deep.params,
2924
2958
  ...deep.effects ? { effects: deep.effects } : {},
2959
+ ...parsed.defines.length > 0 ? { defines: parsed.defines } : {},
2960
+ ...importedNames.length > 0 ? { imported_names: importedNames } : {},
2925
2961
  ...deep.notes ? { notes: deep.notes } : {},
2926
2962
  _dbCalls: dbCalls
2927
2963
  // temp: used for cross-ref building below
@@ -2938,6 +2974,8 @@ function generate(rootDir) {
2938
2974
  layer: "ui",
2939
2975
  route,
2940
2976
  exports: parsed.exports,
2977
+ ...parsed.defines.length > 0 ? { defines: parsed.defines } : {},
2978
+ ...importedNames.length > 0 ? { imported_names: importedNames } : {},
2941
2979
  elements: deep.elements,
2942
2980
  stateVars: deep.stateVars,
2943
2981
  conditions: deep.conditions,
@@ -5898,6 +5936,132 @@ var middlewareGatesParser = {
5898
5936
  }
5899
5937
  };
5900
5938
 
5939
+ // src/server/graph/parsers/crosslayer/call-resolver.ts
5940
+ var BARE_IDENT = /^[A-Za-z_$][\w$]*$/;
5941
+ var callResolverParser = {
5942
+ id: "call-resolver",
5943
+ layer: "crosslayer",
5944
+ concern: "call-graph",
5945
+ detect(_rootDir) {
5946
+ return true;
5947
+ },
5948
+ generate(_rootDir, layerOutputs) {
5949
+ const definers = /* @__PURE__ */ new Map();
5950
+ const addDef = (sym, entry) => {
5951
+ if (!BARE_IDENT.test(sym)) return;
5952
+ const list = definers.get(sym);
5953
+ if (!list) {
5954
+ definers.set(sym, [entry]);
5955
+ } else if (!list.some((d) => d.nodeId === entry.nodeId)) {
5956
+ list.push(entry);
5957
+ }
5958
+ };
5959
+ const nodeLayer = /* @__PURE__ */ new Map();
5960
+ for (const [layer, output] of layerOutputs) {
5961
+ if (layer === "db" || layer === "static") continue;
5962
+ for (const node of output.nodes) {
5963
+ nodeLayer.set(node.id, layer);
5964
+ const entry = { nodeId: node.id, layer };
5965
+ for (const s of node.exports ?? []) addDef(s, entry);
5966
+ for (const s of node.defines ?? []) addDef(s, entry);
5967
+ }
5968
+ }
5969
+ const importTargets = /* @__PURE__ */ new Map();
5970
+ for (const [, output] of layerOutputs) {
5971
+ for (const e of output.edges) {
5972
+ if (e.type !== "imports" && e.type !== "imports_type" && e.type !== "renders") continue;
5973
+ let set = importTargets.get(e.source);
5974
+ if (!set) {
5975
+ set = /* @__PURE__ */ new Set();
5976
+ importTargets.set(e.source, set);
5977
+ }
5978
+ set.add(e.target);
5979
+ }
5980
+ }
5981
+ const crossRefs = [];
5982
+ const seen = /* @__PURE__ */ new Set();
5983
+ let resolvedSelf = 0;
5984
+ let resolvedImport = 0;
5985
+ let ambiguous = 0;
5986
+ let dropped = 0;
5987
+ for (const [, output] of layerOutputs) {
5988
+ for (const node of output.nodes) {
5989
+ const calls = node.effects?.calls;
5990
+ if (!calls || calls.length === 0) continue;
5991
+ const selfSyms = /* @__PURE__ */ new Set([
5992
+ ...node.exports ?? [],
5993
+ ...node.defines ?? []
5994
+ ]);
5995
+ const importedSyms = new Set(node.imported_names ?? []);
5996
+ const myImports = importTargets.get(node.id);
5997
+ const localSeen = /* @__PURE__ */ new Set();
5998
+ for (const callee of calls) {
5999
+ if (!BARE_IDENT.test(callee)) continue;
6000
+ if (localSeen.has(callee)) continue;
6001
+ localSeen.add(callee);
6002
+ const key = `${node.id}\u2192${callee}`;
6003
+ if (selfSyms.has(callee)) {
6004
+ if (seen.has(key)) continue;
6005
+ seen.add(key);
6006
+ crossRefs.push({
6007
+ source: node.id,
6008
+ target: callee,
6009
+ type: "calls",
6010
+ layer: nodeLayer.get(node.id) ?? "ui",
6011
+ defined_in: node.id
6012
+ });
6013
+ resolvedSelf++;
6014
+ continue;
6015
+ }
6016
+ if (!importedSyms.has(callee)) {
6017
+ dropped++;
6018
+ continue;
6019
+ }
6020
+ const defs = (definers.get(callee) ?? []).filter((d) => d.nodeId !== node.id);
6021
+ if (defs.length === 0) {
6022
+ dropped++;
6023
+ continue;
6024
+ }
6025
+ const fromImported = myImports ? defs.filter((d) => myImports.has(d.nodeId)) : [];
6026
+ const chosen = fromImported.length > 0 ? fromImported : defs;
6027
+ const owner = chosen[0];
6028
+ const isAmbiguous = chosen.length > 1;
6029
+ if (isAmbiguous) ambiguous++;
6030
+ if (seen.has(key)) continue;
6031
+ seen.add(key);
6032
+ const ref = {
6033
+ source: node.id,
6034
+ target: callee,
6035
+ type: "calls",
6036
+ layer: owner.layer,
6037
+ defined_in: owner.nodeId
6038
+ };
6039
+ if (isAmbiguous) ref.ambiguous = true;
6040
+ crossRefs.push(ref);
6041
+ resolvedImport++;
6042
+ }
6043
+ }
6044
+ }
6045
+ crossRefs.sort(
6046
+ (a, b) => a.source.localeCompare(b.source) || a.target.localeCompare(b.target)
6047
+ );
6048
+ return {
6049
+ cross_refs: crossRefs,
6050
+ flagged_edges: [],
6051
+ warnings: [],
6052
+ patterns: {
6053
+ call_resolution: {
6054
+ resolved_self: resolvedSelf,
6055
+ resolved_import: resolvedImport,
6056
+ ambiguous,
6057
+ dropped,
6058
+ symbols_defined: definers.size
6059
+ }
6060
+ }
6061
+ };
6062
+ }
6063
+ };
6064
+
5901
6065
  // src/server/graph/core/parser-registry.ts
5902
6066
  function isMultiLayerParser(p) {
5903
6067
  return "layers" in p && Array.isArray(p.layers);
@@ -5964,7 +6128,8 @@ function registerBuiltins2(registry, disabled) {
5964
6128
  apiAnnotationsParser,
5965
6129
  urlLiteralScannerParser,
5966
6130
  staticRefScannerParser,
5967
- middlewareGatesParser
6131
+ middlewareGatesParser,
6132
+ callResolverParser
5968
6133
  ];
5969
6134
  for (const parser of builtins) {
5970
6135
  if (disabled.has(parser.id)) continue;