@saptools/service-flow 0.1.0 → 0.1.2

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.
@@ -104,57 +104,131 @@ import path4 from "path";
104
104
  function lineOf(text, index) {
105
105
  return text.slice(0, index).split("\n").length;
106
106
  }
107
- function pathAnno(prefix) {
108
- return /@\s*\(?\s*path\s*:\s*['"]([^'"]+)['"]\s*\)?/.exec(prefix)?.[1];
107
+ function maskCommentsAndStrings(text) {
108
+ let out = "";
109
+ let mode = "code";
110
+ for (let i = 0; i < text.length; i += 1) {
111
+ const c = text[i] ?? "";
112
+ const n = text[i + 1] ?? "";
113
+ if (mode === "code" && c === "/" && n === "/") {
114
+ mode = "line";
115
+ out += " ";
116
+ i += 1;
117
+ continue;
118
+ }
119
+ if (mode === "code" && c === "/" && n === "*") {
120
+ mode = "block";
121
+ out += " ";
122
+ i += 1;
123
+ continue;
124
+ }
125
+ if (mode === "line" && c === "\n") mode = "code";
126
+ if (mode === "block" && c === "*" && n === "/") {
127
+ mode = "code";
128
+ out += " ";
129
+ i += 1;
130
+ continue;
131
+ }
132
+ if (mode === "code" && (c === "'" || c === '"' || c === "`")) {
133
+ mode = c === "'" ? "single" : c === '"' ? "double" : "template";
134
+ out += " ";
135
+ continue;
136
+ }
137
+ if (mode === "single" && c === "'" || mode === "double" && c === '"' || mode === "template" && c === "`")
138
+ mode = "code";
139
+ out += mode === "code" || c === "\n" ? c : " ";
140
+ }
141
+ return out;
142
+ }
143
+ function readAnnotation(text, index) {
144
+ if (text[index] !== "@") return void 0;
145
+ let i = index + 1;
146
+ while (/\s/.test(text[i] ?? "")) i += 1;
147
+ if (text[i] !== "(") return void 0;
148
+ let depth = 0;
149
+ for (; i < text.length; i += 1) {
150
+ if (text[i] === "(") depth += 1;
151
+ if (text[i] === ")") depth -= 1;
152
+ if (depth === 0) return { end: i + 1, raw: text.slice(index, i + 1) };
153
+ }
154
+ return void 0;
155
+ }
156
+ function collectAnnotations(text, index) {
157
+ let i = index;
158
+ let raw = "";
159
+ while (i < text.length) {
160
+ while (/\s/.test(text[i] ?? "")) i += 1;
161
+ const annotation = readAnnotation(text, i);
162
+ if (!annotation) break;
163
+ raw += annotation.raw;
164
+ i = annotation.end;
165
+ }
166
+ return { end: i, raw };
167
+ }
168
+ function pathAnnotation(raw) {
169
+ return /path\s*:\s*['"]([^'"]+)['"]/s.exec(raw)?.[1];
170
+ }
171
+ function matchingBrace(text, open) {
172
+ let depth = 0;
173
+ for (let i = open; i < text.length; i += 1) {
174
+ if (text[i] === "{") depth += 1;
175
+ if (text[i] === "}") depth -= 1;
176
+ if (depth === 0) return i;
177
+ }
178
+ return text.length - 1;
179
+ }
180
+ function operationsFromBody(text, maskedBody, bodyOffset, filePath) {
181
+ return [...maskedBody.matchAll(/\b(action|function|event)\s+(\w+)\s*(?:\(([^)]*)\))?\s*(?:returns\s+([^;{]+))?/g)].map((m) => ({
182
+ operationType: m[1] ?? "action",
183
+ operationName: m[2] ?? "unknown",
184
+ operationPath: ensureLeadingSlash(m[2] ?? "unknown"),
185
+ paramsJson: JSON.stringify((m[3] ?? "").split(",").map((part) => part.trim()).filter(Boolean)),
186
+ returnType: m[4]?.trim(),
187
+ sourceFile: normalizePath(filePath),
188
+ sourceLine: lineOf(text, bodyOffset + (m.index ?? 0))
189
+ }));
109
190
  }
110
191
  async function parseCdsFile(repoPath, filePath) {
111
192
  const absolute = path4.join(repoPath, filePath);
112
193
  const text = await fs3.readFile(absolute, "utf8");
113
- const namespace = /namespace\s+([\w.]+)\s*;/.exec(text)?.[1];
194
+ const masked = maskCommentsAndStrings(text);
195
+ const namespace = /namespace\s+([\w.]+)\s*;/.exec(masked)?.[1];
114
196
  const services = [];
115
- const serviceRegex = /((?:@\s*\(?\s*path\s*:\s*['"][^'"]+['"]\s*\)?\s*)?)(extend\s+)?service\s+(\w+)\s*(?:@\s*\(?\s*path\s*:\s*['"]([^'"]+)['"]\s*\)?\s*)?\{/g;
197
+ const pendingAnnotations = [];
198
+ for (const a of masked.matchAll(/@\s*\(/g)) {
199
+ const annotation = collectAnnotations(masked, a.index ?? 0);
200
+ pendingAnnotations.push(annotation);
201
+ }
202
+ const serviceRegex = /\b(extend\s+)?service\s+([\w.]+)\b/g;
116
203
  let match;
117
- while (match = serviceRegex.exec(text)) {
118
- const serviceName = match[3] ?? "UnknownService";
119
- const start = match.index + match[0].length;
120
- let depth = 1;
121
- let end = start;
122
- for (; end < text.length; end += 1) {
123
- const c = text[end];
124
- if (c === "{") depth += 1;
125
- if (c === "}") depth -= 1;
126
- if (depth === 0) break;
127
- }
128
- const body = text.slice(start, end);
129
- const servicePath = ensureLeadingSlash(
130
- match[4] ?? pathAnno(match[1] ?? "") ?? serviceName
131
- );
132
- const ops = [
133
- ...body.matchAll(
134
- /\b(action|function|event)\s+(\w+)\s*(?:\(([^)]*)\))?\s*(?:returns\s+([^;{]+))?/g
135
- )
136
- ].map((m) => ({
137
- operationType: m[1] ?? "action",
138
- operationName: m[2] ?? "unknown",
139
- operationPath: ensureLeadingSlash(m[2] ?? "unknown"),
140
- paramsJson: JSON.stringify(
141
- (m[3] ?? "").split(",").map((p) => p.trim()).filter(Boolean)
142
- ),
143
- returnType: m[4]?.trim(),
144
- sourceFile: normalizePath(filePath),
145
- sourceLine: lineOf(text, start + (m.index ?? 0))
146
- }));
204
+ while (match = serviceRegex.exec(masked)) {
205
+ const afterName = collectAnnotations(masked, serviceRegex.lastIndex);
206
+ const open = masked.indexOf("{", afterName.end);
207
+ if (open === -1) continue;
208
+ const matchIndex = match.index;
209
+ const prefix = pendingAnnotations.filter((a) => a.end <= matchIndex && matchIndex - a.end < 8).map((a) => a.raw).join("");
210
+ const annotations = `${prefix}${afterName.raw}`;
211
+ const end = matchingBrace(masked, open);
212
+ const body = masked.slice(open + 1, end);
213
+ const name = match[2] ?? "UnknownService";
214
+ const serviceName = name.split(".").pop() ?? name;
215
+ const servicePath = ensureLeadingSlash(pathAnnotation(annotations) ?? serviceName);
147
216
  services.push({
148
217
  namespace,
149
218
  serviceName,
150
- qualifiedName: namespace ? `${namespace}.${serviceName}` : serviceName,
219
+ qualifiedName: name.includes(".") ? name : namespace ? `${namespace}.${name}` : name,
151
220
  servicePath,
152
- isExtend: Boolean(match[2]),
221
+ isExtend: Boolean(match[1]),
153
222
  sourceFile: normalizePath(filePath),
154
223
  sourceLine: lineOf(text, match.index),
155
- operations: ops
224
+ operations: operationsFromBody(text, body, open + 1, filePath)
156
225
  });
157
- serviceRegex.lastIndex = end;
226
+ serviceRegex.lastIndex = end + 1;
227
+ }
228
+ const baseOps = new Map(services.filter((s) => !s.isExtend).map((s) => [s.qualifiedName, s.operations]));
229
+ for (const service of services.filter((s) => s.isExtend && s.operations.length === 0)) {
230
+ const inherited = baseOps.get(service.qualifiedName) ?? baseOps.get(service.serviceName);
231
+ if (inherited) service.operations = inherited.map((op) => ({ ...op, sourceFile: service.sourceFile, sourceLine: service.sourceLine }));
158
232
  }
159
233
  return services;
160
234
  }
@@ -307,7 +381,7 @@ async function parseOutboundCalls(repoPath, filePath) {
307
381
  serviceVariableName: m[1],
308
382
  method: stripQuotes(firstArg2(body, "method") ?? "POST"),
309
383
  operationPathExpr: op ? stripQuotes(op) : void 0,
310
- queryEntity: /SELECT\.from\((\w+)\)/.exec(query ?? "")?.[1],
384
+ queryEntity: /SELECT(?:\.one)?\.from\(([\w.]+)\)/.exec(query ?? "")?.[1],
311
385
  payloadSummary: summarizeExpression(body),
312
386
  sourceFile: normalizePath(filePath),
313
387
  sourceLine: lineOf3(text, m.index ?? 0),
@@ -317,9 +391,7 @@ async function parseOutboundCalls(repoPath, filePath) {
317
391
  for (const m of text.matchAll(/cds\.run\s*\(([\s\S]*?)\)/g))
318
392
  out.push({
319
393
  callType: "local_db_query",
320
- queryEntity: /(?:SELECT\.from|INSERT\.into)\((\w+)\)/.exec(
321
- m[1] ?? ""
322
- )?.[1],
394
+ queryEntity: /(?:SELECT(?:\.one)?\.from|INSERT\.into|UPDATE|DELETE\.from)\(([\w.]+)\)/.exec(m[1] ?? "")?.[1],
323
395
  payloadSummary: summarizeExpression(m[1] ?? ""),
324
396
  sourceFile: normalizePath(filePath),
325
397
  sourceLine: lineOf3(text, m.index ?? 0),
@@ -404,16 +476,27 @@ async function parseServiceBindings(repoPath, filePath) {
404
476
  });
405
477
  }
406
478
  for (const m of text.matchAll(
407
- /function\s+(\w+)\s*\([^)]*\)\s*\{[\s\S]*?return\s+cds\.connect\.to\((['"])([^'"]+)\2\)/g
479
+ /(?:function\s+(\w+)\s*\([^)]*\)\s*\{[\s\S]*?return|const\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\)\s*=>)\s+(?:await\s*)?cds\.connect\.to\((['"`])([^'"`]+)\3\)/g
408
480
  ))
409
481
  out.push({
410
- variableName: m[1] ?? "connect",
411
- alias: m[3],
482
+ variableName: m[1] ?? m[2] ?? "connect",
483
+ alias: m[4],
412
484
  isDynamic: false,
413
485
  placeholders: [],
414
486
  sourceFile: normalizePath(filePath),
415
487
  sourceLine: lineOf4(text, m.index ?? 0)
416
488
  });
489
+ const helperAliases = new Map(out.filter((b) => b.alias).map((b) => [b.variableName, b]));
490
+ for (const m of text.matchAll(/(?:const|let)\s+(\w+)\s*=\s*(?:await\s*)?(\w+)\s*\(/g)) {
491
+ const helper = helperAliases.get(m[2] ?? "");
492
+ if (!helper) continue;
493
+ out.push({
494
+ ...helper,
495
+ variableName: m[1] ?? "service",
496
+ sourceFile: normalizePath(filePath),
497
+ sourceLine: lineOf4(text, m.index ?? 0)
498
+ });
499
+ }
417
500
  return out;
418
501
  }
419
502
 
@@ -546,11 +629,6 @@ function linkWorkspace(db, workspaceId, vars = {}) {
546
629
  return { edgeCount: edges, unresolvedCount: unresolved };
547
630
  }
548
631
 
549
- // src/trace/traversal.ts
550
- function limitDepth(edges, depth) {
551
- return edges.filter((edge) => edge.step <= depth);
552
- }
553
-
554
632
  // src/trace/trace-engine.ts
555
633
  function normalizeOperation(value) {
556
634
  if (!value) return void 0;
@@ -563,108 +641,86 @@ function sourceFilesForStart(db, repoId, start) {
563
641
  const handler = start.handler;
564
642
  const operation = normalizeOperation(start.operation ?? start.operationPath);
565
643
  if (!handler && !operation) return void 0;
566
- const rows = db.prepare(
567
- `SELECT DISTINCT hc.source_file sourceFile
568
- FROM handler_classes hc
569
- LEFT JOIN handler_methods hm ON hm.handler_class_id=hc.id
570
- WHERE (? IS NULL OR hc.repo_id=?)
571
- AND (? IS NULL OR hc.class_name=? OR hm.method_name=?)
572
- AND (? IS NULL OR hm.decorator_value=? OR hm.method_name=?)`
573
- ).all(
574
- repoId,
575
- repoId,
576
- handler,
577
- handler,
578
- handler,
579
- operation,
580
- operation,
581
- operation
582
- );
644
+ const rows = db.prepare(`SELECT DISTINCT hc.source_file sourceFile
645
+ FROM handler_classes hc LEFT JOIN handler_methods hm ON hm.handler_class_id=hc.id
646
+ WHERE (? IS NULL OR hc.repo_id=?) AND (? IS NULL OR hc.class_name=? OR hm.method_name=?)
647
+ AND (? IS NULL OR hm.decorator_value=? OR hm.method_name=?)`).all(repoId, repoId, handler, handler, handler, operation, operation, operation);
583
648
  if (rows.length === 0) return void 0;
584
- return new Set(
585
- rows.map((row) => row.sourceFile).filter(Boolean)
586
- );
649
+ return new Set(rows.map((row) => row.sourceFile).filter(Boolean));
587
650
  }
588
651
  function startScope(db, start) {
589
- const repo = start.repo ? db.prepare(
590
- "SELECT id,name FROM repositories WHERE name=? OR package_name=?"
591
- ).get(start.repo, start.repo) : void 0;
592
- if (start.repo && !repo)
593
- return {
594
- repo,
595
- selectorMatched: false
596
- };
652
+ const repo = start.repo ? db.prepare("SELECT id,name FROM repositories WHERE name=? OR package_name=?").get(start.repo, start.repo) : void 0;
653
+ if (start.repo && !repo) return { repo, selectorMatched: false };
597
654
  const sourceFiles = sourceFilesForStart(db, repo?.id, start);
598
- const hasSelector = Boolean(
599
- start.handler ?? start.operation ?? start.operationPath
600
- );
601
- return {
602
- repo,
603
- sourceFiles,
604
- selectorMatched: !hasSelector || sourceFiles !== void 0
605
- };
655
+ const hasSelector = Boolean(start.handler ?? start.operation ?? start.operationPath);
656
+ return { repo, sourceFiles, selectorMatched: !hasSelector || sourceFiles !== void 0 };
657
+ }
658
+ function handlerFilesForOperation(db, operationId) {
659
+ const op = db.prepare(`SELECT o.operation_name operationName,o.operation_path operationPath,s.repo_id repoId
660
+ FROM cds_operations o JOIN cds_services s ON s.id=o.service_id WHERE o.id=?`).get(operationId);
661
+ if (!op) return /* @__PURE__ */ new Set();
662
+ const operation = normalizeOperation(op.operationPath ?? op.operationName);
663
+ const rows = db.prepare(`SELECT DISTINCT hc.source_file sourceFile FROM handler_classes hc
664
+ JOIN handler_methods hm ON hm.handler_class_id=hc.id
665
+ WHERE hc.repo_id=? AND (hm.decorator_value=? OR hm.method_name=? OR hm.decorator_value=?)`).all(op.repoId, operation, operation, op.operationName);
666
+ return new Set(rows.map((row) => row.sourceFile).filter(Boolean));
667
+ }
668
+ function includeCall(type, options) {
669
+ if (!options.includeDb && type === "local_db_query") return false;
670
+ if (!options.includeExternal && type === "external_http") return false;
671
+ if (!options.includeAsync && type.startsWith("async_")) return false;
672
+ return true;
673
+ }
674
+ function graphForCalls(db, callIds) {
675
+ const map = /* @__PURE__ */ new Map();
676
+ if (callIds.length === 0) return map;
677
+ const rows = db.prepare(`SELECT * FROM graph_edges WHERE from_kind='call' AND from_id IN (${callIds.map(() => "?").join(",")}) ORDER BY id`).all(...callIds);
678
+ for (const row of rows) {
679
+ const id = Number(row.from_id);
680
+ map.set(id, [...map.get(id) ?? [], row]);
681
+ }
682
+ return map;
606
683
  }
607
684
  function trace(db, start, options) {
608
685
  const scope = startScope(db, start);
609
- const calls = db.prepare(
610
- `SELECT c.*,r.name repoName,b.alias,b.destination_expr destinationExpr,b.service_path_expr servicePathExpr,b.is_dynamic isDynamic,req.service_path requireServicePath,req.destination requireDestination FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id LEFT JOIN service_bindings b ON b.id=c.service_binding_id LEFT JOIN cds_requires req ON req.repo_id=c.repo_id AND req.alias=b.alias WHERE (? IS NULL OR c.repo_id=?) ORDER BY c.source_file,c.source_line`
611
- ).all(scope.repo?.id, scope.repo?.id);
612
- const vars = options.vars ?? {};
613
- const filtered = calls.filter((c) => {
614
- if (!scope.selectorMatched) return false;
615
- if (scope.sourceFiles && !scope.sourceFiles.has(String(c.source_file)))
616
- return false;
617
- const type = String(c.call_type);
618
- if (!options.includeDb && type === "local_db_query") return false;
619
- if (!options.includeExternal && type === "external_http") return false;
620
- if (!options.includeAsync && type.startsWith("async_")) return false;
621
- return true;
622
- });
623
- const edges = filtered.map((c, index) => {
624
- const operation = applyVariables(
625
- c.operation_path_expr,
626
- vars
627
- );
628
- const servicePath = applyVariables(
629
- c.servicePathExpr ?? c.requireServicePath,
630
- vars
631
- );
632
- const type = String(c.call_type);
633
- const to = type === "local_db_query" ? `Entity: ${String(c.query_entity ?? "unknown")}` : type === "async_emit" ? `Topic: ${String(c.event_name_expr ?? "unknown")}` : type === "async_subscribe" ? `Topic: ${String(c.event_name_expr ?? "unknown")}` : type === "external_http" ? "External HTTP destination" : `${servicePath ?? ""}${operation ?? ""}` || String(c.event_name_expr ?? "unknown");
634
- return {
635
- step: index + 1,
636
- type: c.isDynamic ? "dynamic_action" : type,
637
- from: `${String(c.repoName)}:${String(c.source_file)}`,
638
- to,
639
- evidence: {
640
- file: c.source_file,
641
- line: c.source_line,
642
- alias: c.alias,
643
- destination: c.destinationExpr ?? c.requireDestination,
644
- servicePath,
645
- operationPath: operation,
646
- method: c.method,
647
- payloadSummary: c.payload_summary
648
- },
649
- confidence: Number(c.confidence ?? 0.5),
650
- unresolvedReason: c.unresolved_reason
651
- };
652
- });
653
- const diagnostics = db.prepare(
654
- "SELECT severity,code,message,source_file sourceFile,source_line sourceLine FROM diagnostics WHERE (? IS NULL OR repo_id=?)"
655
- ).all(scope.repo?.id, scope.repo?.id);
656
- if (!scope.selectorMatched)
657
- diagnostics.unshift({
658
- severity: "warning",
659
- code: "trace_start_not_found",
660
- message: "No handler source matched the requested trace start selector"
661
- });
662
- return {
663
- start,
664
- nodes: [],
665
- edges: limitDepth(edges, positiveDepth(options.depth)),
666
- diagnostics
667
- };
686
+ const diagnostics = db.prepare("SELECT severity,code,message,source_file sourceFile,source_line sourceLine FROM diagnostics WHERE (? IS NULL OR repo_id=?)").all(scope.repo?.id, scope.repo?.id);
687
+ if (!scope.selectorMatched) diagnostics.unshift({ severity: "warning", code: "trace_start_not_found", message: "No handler source matched the requested trace start selector" });
688
+ const maxDepth = positiveDepth(options.depth);
689
+ const edges = [];
690
+ const nodes = /* @__PURE__ */ new Map();
691
+ const queue = scope.selectorMatched ? [{ repoId: scope.repo?.id, files: scope.sourceFiles, depth: 1 }] : [];
692
+ const seenScopes = /* @__PURE__ */ new Set();
693
+ while (queue.length > 0) {
694
+ const current = queue.shift();
695
+ if (!current || current.depth > maxDepth) continue;
696
+ const key = `${current.repoId ?? "*"}:${[...current.files ?? /* @__PURE__ */ new Set(["*"])].sort().join(",")}:${current.depth}`;
697
+ if (seenScopes.has(key)) continue;
698
+ seenScopes.add(key);
699
+ const calls = db.prepare(`SELECT c.*,r.name repoName FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id WHERE (? IS NULL OR c.repo_id=?) ORDER BY c.source_file,c.source_line`).all(current.repoId, current.repoId);
700
+ const filtered = calls.filter((c) => (!current.files || current.files.has(String(c.source_file))) && includeCall(String(c.call_type), options));
701
+ const graph = graphForCalls(db, filtered.map((c) => Number(c.id)));
702
+ for (const call of filtered) {
703
+ const callNode = `call:${call.id}`;
704
+ nodes.set(callNode, { id: callNode, kind: "outbound_call", repo: call.repoName, file: call.source_file, line: call.source_line, callType: call.call_type });
705
+ const graphRows = graph.get(Number(call.id)) ?? [];
706
+ for (const row of graphRows) {
707
+ const evidence = JSON.parse(String(row.evidence_json || "{}"));
708
+ const targetNode = `${row.to_kind}:${row.to_id}`;
709
+ nodes.set(targetNode, { id: targetNode, kind: row.to_kind, label: row.to_id, ...evidence });
710
+ const servicePath = typeof evidence.servicePath === "string" ? evidence.servicePath : void 0;
711
+ const operationPath = typeof evidence.operationPath === "string" ? evidence.operationPath : void 0;
712
+ const targetOperation = typeof evidence.targetOperation === "string" ? evidence.targetOperation : void 0;
713
+ const targetRepo = typeof evidence.targetRepo === "string" ? evidence.targetRepo : "";
714
+ const to = servicePath && operationPath ? `${servicePath}${operationPath}` : targetOperation ? `${targetRepo}:${targetOperation}` : row.to_id;
715
+ edges.push({ step: current.depth, type: String(call.call_type), from: `${call.repoName}:${call.source_file}`, to, evidence, confidence: Number(row.confidence ?? call.confidence), unresolvedReason: row.unresolved_reason });
716
+ if (row.to_kind === "operation" && current.depth < maxDepth) {
717
+ const files = handlerFilesForOperation(db, row.to_id);
718
+ if (files.size > 0) queue.push({ files, depth: current.depth + 1 });
719
+ }
720
+ }
721
+ }
722
+ }
723
+ return { start, nodes: [...nodes.values()], edges, diagnostics };
668
724
  }
669
725
 
670
726
  export {
@@ -683,4 +739,4 @@ export {
683
739
  linkWorkspace,
684
740
  trace
685
741
  };
686
- //# sourceMappingURL=chunk-RFBHT6BQ.js.map
742
+ //# sourceMappingURL=chunk-6U4QKQEL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/discovery/discover-repositories.ts","../src/utils/path-utils.ts","../src/parsers/package-json-parser.ts","../src/parsers/cds-parser.ts","../src/parsers/decorator-parser.ts","../src/parsers/ts-project.ts","../src/parsers/handler-registration-parser.ts","../src/utils/redaction.ts","../src/parsers/outbound-call-parser.ts","../src/parsers/service-binding-parser.ts","../src/linker/dynamic-edge-resolver.ts","../src/linker/service-resolver.ts","../src/linker/helper-package-linker.ts","../src/linker/cross-repo-linker.ts","../src/trace/trace-engine.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { DiscoveredRepository } from '../types.js';\nimport { relativePath } from '../utils/path-utils.js';\nexport async function discoverRepositories(\n rootPath: string,\n ignore: readonly string[]\n): Promise<DiscoveredRepository[]> {\n const root = path.resolve(rootPath);\n const ignored = new Set(ignore);\n const found: DiscoveredRepository[] = [];\n async function walk(dir: string): Promise<void> {\n const rel = relativePath(root, dir);\n if (rel !== '.' && rel.split('/').some((part) => ignored.has(part))) return;\n let entries: Array<{ name: string; isDirectory: () => boolean }>;\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n if (entries.some((e) => e.name === '.git' || e.name === '.git-fixture')) {\n found.push({\n name: path.basename(dir),\n absolutePath: dir,\n relativePath: relativePath(root, dir),\n isGitRepo: true\n });\n return;\n }\n for (const entry of entries)\n if (entry.isDirectory() && !ignore.includes(entry.name))\n await walk(path.join(dir, entry.name));\n }\n await walk(root);\n return found.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n}\n","import path from 'node:path';\nexport function normalizePath(value: string): string {\n return value.split(path.sep).join('/');\n}\nexport function relativePath(root: string, value: string): string {\n return normalizePath(path.relative(root, value) || '.');\n}\nexport function ensureLeadingSlash(value: string): string {\n return value.startsWith('/') ? value : `/${value}`;\n}\nexport function stripQuotes(value: string): string {\n return value.replace(/^['\"`]|['\"`]$/g, '');\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CdsRequire, PackageFacts } from '../types.js';\nfunction recordOfString(value: unknown): Record<string, string> {\n if (!value || typeof value !== 'object') return {};\n return Object.fromEntries(\n Object.entries(value).filter(([, v]) => typeof v === 'string')\n ) as Record<string, string>;\n}\nfunction readRequires(cds: unknown): CdsRequire[] {\n const requires =\n cds && typeof cds === 'object' && 'requires' in cds\n ? (cds as { requires?: unknown }).requires\n : undefined;\n if (!requires || typeof requires !== 'object') return [];\n return Object.entries(requires).flatMap(([alias, raw]) => {\n if (!raw || typeof raw !== 'object') return [];\n const obj = raw as Record<string, unknown>;\n const credentials =\n obj.credentials && typeof obj.credentials === 'object'\n ? (obj.credentials as Record<string, unknown>)\n : {};\n return [\n {\n alias,\n kind: typeof obj.kind === 'string' ? obj.kind : undefined,\n model: typeof obj.model === 'string' ? obj.model : undefined,\n destination:\n typeof credentials.destination === 'string'\n ? credentials.destination\n : undefined,\n servicePath:\n typeof credentials.path === 'string' ? credentials.path : undefined,\n requestTimeout:\n typeof credentials.requestTimeout === 'number'\n ? credentials.requestTimeout\n : undefined,\n rawJson: JSON.stringify(raw)\n }\n ];\n });\n}\nexport async function parsePackageJson(\n repoPath: string\n): Promise<PackageFacts> {\n try {\n const raw = await fs.readFile(path.join(repoPath, 'package.json'), 'utf8');\n const json = JSON.parse(raw) as Record<string, unknown>;\n return {\n packageName: typeof json.name === 'string' ? json.name : undefined,\n packageVersion:\n typeof json.version === 'string' ? json.version : undefined,\n dependencies: {\n ...recordOfString(json.dependencies),\n ...recordOfString(json.devDependencies)\n },\n cdsRequires: readRequires(json.cds),\n scripts: recordOfString(json.scripts)\n };\n } catch {\n return { dependencies: {}, cdsRequires: [], scripts: {} };\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CdsOperationFact, CdsServiceFact } from '../types.js';\nimport { ensureLeadingSlash, normalizePath } from '../utils/path-utils.js';\n\nfunction lineOf(text: string, index: number): number {\n return text.slice(0, index).split('\\n').length;\n}\n\nfunction maskCommentsAndStrings(text: string): string {\n let out = '';\n let mode: 'code' | 'line' | 'block' | 'single' | 'double' | 'template' =\n 'code';\n for (let i = 0; i < text.length; i += 1) {\n const c = text[i] ?? '';\n const n = text[i + 1] ?? '';\n if (mode === 'code' && c === '/' && n === '/') {\n mode = 'line';\n out += ' ';\n i += 1;\n continue;\n }\n if (mode === 'code' && c === '/' && n === '*') {\n mode = 'block';\n out += ' ';\n i += 1;\n continue;\n }\n if (mode === 'line' && c === '\\n') mode = 'code';\n if (mode === 'block' && c === '*' && n === '/') {\n mode = 'code';\n out += ' ';\n i += 1;\n continue;\n }\n if (mode === 'code' && (c === \"'\" || c === '\"' || c === '`')) {\n mode = c === \"'\" ? 'single' : c === '\"' ? 'double' : 'template';\n out += ' ';\n continue;\n }\n if ((mode === 'single' && c === \"'\") || (mode === 'double' && c === '\"') || (mode === 'template' && c === '`'))\n mode = 'code';\n out += mode === 'code' || c === '\\n' ? c : ' ';\n }\n return out;\n}\n\nfunction readAnnotation(text: string, index: number): { end: number; raw: string } | undefined {\n if (text[index] !== '@') return undefined;\n let i = index + 1;\n while (/\\s/.test(text[i] ?? '')) i += 1;\n if (text[i] !== '(') return undefined;\n let depth = 0;\n for (; i < text.length; i += 1) {\n if (text[i] === '(') depth += 1;\n if (text[i] === ')') depth -= 1;\n if (depth === 0) return { end: i + 1, raw: text.slice(index, i + 1) };\n }\n return undefined;\n}\n\nfunction collectAnnotations(text: string, index: number): { end: number; raw: string } {\n let i = index;\n let raw = '';\n while (i < text.length) {\n while (/\\s/.test(text[i] ?? '')) i += 1;\n const annotation = readAnnotation(text, i);\n if (!annotation) break;\n raw += annotation.raw;\n i = annotation.end;\n }\n return { end: i, raw };\n}\n\nfunction pathAnnotation(raw: string): string | undefined {\n return /path\\s*:\\s*['\"]([^'\"]+)['\"]/s.exec(raw)?.[1];\n}\n\nfunction matchingBrace(text: string, open: number): number {\n let depth = 0;\n for (let i = open; i < text.length; i += 1) {\n if (text[i] === '{') depth += 1;\n if (text[i] === '}') depth -= 1;\n if (depth === 0) return i;\n }\n return text.length - 1;\n}\n\nfunction operationsFromBody(text: string, maskedBody: string, bodyOffset: number, filePath: string): CdsOperationFact[] {\n return [...maskedBody.matchAll(/\\b(action|function|event)\\s+(\\w+)\\s*(?:\\(([^)]*)\\))?\\s*(?:returns\\s+([^;{]+))?/g)].map((m) => ({\n operationType: (m[1] as 'action' | 'function' | 'event') ?? 'action',\n operationName: m[2] ?? 'unknown',\n operationPath: ensureLeadingSlash(m[2] ?? 'unknown'),\n paramsJson: JSON.stringify((m[3] ?? '').split(',').map((part) => part.trim()).filter(Boolean)),\n returnType: m[4]?.trim(),\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, bodyOffset + (m.index ?? 0))\n }));\n}\n\nexport async function parseCdsFile(repoPath: string, filePath: string): Promise<CdsServiceFact[]> {\n const absolute = path.join(repoPath, filePath);\n const text = await fs.readFile(absolute, 'utf8');\n const masked = maskCommentsAndStrings(text);\n const namespace = /namespace\\s+([\\w.]+)\\s*;/.exec(masked)?.[1];\n const services: CdsServiceFact[] = [];\n const pendingAnnotations: Array<{ end: number; raw: string }> = [];\n for (const a of masked.matchAll(/@\\s*\\(/g)) {\n const annotation = collectAnnotations(masked, a.index ?? 0);\n pendingAnnotations.push(annotation);\n }\n const serviceRegex = /\\b(extend\\s+)?service\\s+([\\w.]+)\\b/g;\n let match: RegExpExecArray | null;\n while ((match = serviceRegex.exec(masked))) {\n const afterName = collectAnnotations(masked, serviceRegex.lastIndex);\n const open = masked.indexOf('{', afterName.end);\n if (open === -1) continue;\n const matchIndex = match.index;\n const prefix = pendingAnnotations\n .filter((a) => a.end <= matchIndex && matchIndex - a.end < 8)\n .map((a) => a.raw)\n .join('');\n const annotations = `${prefix}${afterName.raw}`;\n const end = matchingBrace(masked, open);\n const body = masked.slice(open + 1, end);\n const name = match[2] ?? 'UnknownService';\n const serviceName = name.split('.').pop() ?? name;\n const servicePath = ensureLeadingSlash(pathAnnotation(annotations) ?? serviceName);\n services.push({\n namespace,\n serviceName,\n qualifiedName: name.includes('.') ? name : namespace ? `${namespace}.${name}` : name,\n servicePath,\n isExtend: Boolean(match[1]),\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, match.index),\n operations: operationsFromBody(text, body, open + 1, filePath)\n });\n serviceRegex.lastIndex = end + 1;\n }\n const baseOps = new Map(services.filter((s) => !s.isExtend).map((s) => [s.qualifiedName, s.operations]));\n for (const service of services.filter((s) => s.isExtend && s.operations.length === 0)) {\n const inherited = baseOps.get(service.qualifiedName) ?? baseOps.get(service.serviceName);\n if (inherited) service.operations = inherited.map((op) => ({ ...op, sourceFile: service.sourceFile, sourceLine: service.sourceLine }));\n }\n return services;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport ts from 'typescript';\nimport type { HandlerClassFact } from '../types.js';\nimport { createSourceFile } from './ts-project.js';\nimport { normalizePath, stripQuotes } from '../utils/path-utils.js';\nfunction line(sf: ts.SourceFile, pos: number): number {\n return sf.getLineAndCharacterOfPosition(pos).line + 1;\n}\nfunction decs(node: ts.Node): ts.Decorator[] {\n return ts.canHaveDecorators(node) ? [...(ts.getDecorators(node) ?? [])] : [];\n}\nfunction callName(d: ts.Decorator): string {\n const e = d.expression;\n return ts.isCallExpression(e) ? e.expression.getText() : e.getText();\n}\nfunction firstArg(d: ts.Decorator): string {\n const e = d.expression;\n return ts.isCallExpression(e) && e.arguments[0]\n ? e.arguments[0].getText()\n : '';\n}\nexport async function parseDecorators(\n repoPath: string,\n filePath: string\n): Promise<HandlerClassFact[]> {\n const text = await fs.readFile(path.join(repoPath, filePath), 'utf8');\n const sf = createSourceFile(filePath, text);\n const constants = new Map<string, string>();\n const handlers: HandlerClassFact[] = [];\n function visit(node: ts.Node): void {\n if (\n ts.isVariableDeclaration(node) &&\n ts.isIdentifier(node.name) &&\n node.initializer &&\n ts.isStringLiteralLike(node.initializer)\n )\n constants.set(node.name.text, node.initializer.text);\n if (ts.isClassDeclaration(node)) {\n const className = node.name?.text ?? 'AnonymousHandler';\n const hasHandler = decs(node).some((d) => callName(d) === 'Handler');\n const methods = node.members.filter(ts.isMethodDeclaration).flatMap((m) =>\n decs(m)\n .filter((d) =>\n ['Func', 'Action', 'On', 'Event'].includes(callName(d))\n )\n .map((d) => {\n const raw = firstArg(d);\n const value =\n raw.startsWith('\"') || raw.startsWith(\"'\") || raw.startsWith('`')\n ? stripQuotes(raw)\n : (constants.get(raw) ??\n (raw.endsWith('.name') ? raw.split('.').at(-2) : undefined));\n return {\n methodName: m.name.getText(),\n decoratorKind: callName(d),\n decoratorValue: value,\n decoratorRawExpression: raw,\n sourceFile: normalizePath(filePath),\n sourceLine: line(sf, m.getStart())\n };\n })\n );\n if (hasHandler || methods.length > 0)\n handlers.push({\n className,\n sourceFile: normalizePath(filePath),\n sourceLine: line(sf, node.getStart()),\n methods\n });\n }\n ts.forEachChild(node, visit);\n }\n visit(sf);\n return handlers;\n}\n","import ts from 'typescript';\nexport function createSourceFile(\n filePath: string,\n text: string\n): ts.SourceFile {\n return ts.createSourceFile(\n filePath,\n text,\n ts.ScriptTarget.Latest,\n true,\n filePath.endsWith('.js') ? ts.ScriptKind.JS : ts.ScriptKind.TS\n );\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { HandlerRegistrationFact } from '../types.js';\nimport { normalizePath } from '../utils/path-utils.js';\nfunction lineOf(text: string, idx: number): number {\n return text.slice(0, idx).split('\\n').length;\n}\nexport async function parseHandlerRegistrations(\n repoPath: string,\n filePath: string\n): Promise<HandlerRegistrationFact[]> {\n const text = await fs.readFile(path.join(repoPath, filePath), 'utf8');\n const out: HandlerRegistrationFact[] = [];\n for (const m of text.matchAll(\n /createCombinedHandler\\s*\\(|srv\\.prepend\\s*\\(|cds\\.serve\\s*\\(/g\n ))\n out.push({\n registrationFile: normalizePath(filePath),\n registrationLine: lineOf(text, m.index ?? 0),\n registrationKind: m[0].startsWith('cds')\n ? 'cds.serve'\n : 'combined-handler',\n confidence: 0.8\n });\n for (const m of text.matchAll(\n /(?:const|export\\s+const)\\s+handlers\\s*=\\s*\\[([\\s\\S]*?)\\]/g\n ))\n for (const c of (m[1] ?? '').matchAll(/\\b(\\w+Handler)\\b/g))\n out.push({\n className: c[1],\n registrationFile: normalizePath(filePath),\n registrationLine: lineOf(text, (m.index ?? 0) + (c.index ?? 0)),\n registrationKind: 'handler-array',\n confidence: 0.9\n });\n return out;\n}\n","const SENSITIVE = /authorization|cookie|token|secret|password|key|credential/i;\nexport function redactText(text: string): string {\n return text.replace(\n /(authorization|cookie|token|secret|password|key|credential)\\s*[:=]\\s*(['\"`]?)[^,'\"`}\\s]+\\2/gi,\n '$1: [REDACTED]'\n );\n}\nexport function redactValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(redactValue);\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value))\n out[k] = SENSITIVE.test(k) ? '[REDACTED]' : redactValue(v);\n return out;\n }\n return typeof value === 'string' ? redactText(value) : value;\n}\nexport function summarizeExpression(text: string): string {\n return redactText(text).slice(0, 240);\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { OutboundCallFact } from '../types.js';\nimport { normalizePath, stripQuotes } from '../utils/path-utils.js';\nimport { summarizeExpression } from '../utils/redaction.js';\nfunction lineOf(text: string, idx: number): number {\n return text.slice(0, idx).split('\\n').length;\n}\nfunction firstArg(body: string, key: string): string | undefined {\n return new RegExp(`${key}\\\\s*:\\\\s*([^,}\\\\n]+)`).exec(body)?.[1]?.trim();\n}\nexport async function parseOutboundCalls(\n repoPath: string,\n filePath: string\n): Promise<OutboundCallFact[]> {\n const text = await fs.readFile(path.join(repoPath, filePath), 'utf8');\n const out: OutboundCallFact[] = [];\n for (const m of text.matchAll(/(\\w+)\\.send\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)/g)) {\n const body = m[2] ?? '';\n const query = firstArg(body, 'query');\n const op = firstArg(body, 'path');\n out.push({\n callType: query ? 'remote_query' : 'remote_action',\n serviceVariableName: m[1],\n method: stripQuotes(firstArg(body, 'method') ?? 'POST'),\n operationPathExpr: op ? stripQuotes(op) : undefined,\n queryEntity: /SELECT(?:\\.one)?\\.from\\(([\\w.]+)\\)/.exec(query ?? '')?.[1],\n payloadSummary: summarizeExpression(body),\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0),\n confidence: op || query ? 0.8 : 0.4\n });\n }\n for (const m of text.matchAll(/cds\\.run\\s*\\(([\\s\\S]*?)\\)/g))\n out.push({\n callType: 'local_db_query',\n queryEntity: /(?:SELECT(?:\\.one)?\\.from|INSERT\\.into|UPDATE|DELETE\\.from)\\(([\\w.]+)\\)/.exec(m[1] ?? '')?.[1],\n payloadSummary: summarizeExpression(m[1] ?? ''),\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0),\n confidence: 0.85\n });\n for (const m of text.matchAll(\n /(\\w+)\\.(emit|publish|on)\\s*\\(\\s*(['\"`])([^'\"`]+)\\3/g\n ))\n out.push({\n callType: m[2] === 'on' ? 'async_subscribe' : 'async_emit',\n serviceVariableName: m[1],\n eventNameExpr: m[4],\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0),\n confidence: 0.8\n });\n for (const m of text.matchAll(\n /(?:axios\\s*\\(|executeHttpRequest\\s*\\(|useOrFetchDestination\\s*\\()([\\s\\S]*?)\\)/g\n ))\n out.push({\n callType: 'external_http',\n payloadSummary: summarizeExpression(m[1] ?? ''),\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0),\n confidence: 0.7,\n unresolvedReason:\n 'External HTTP destination is outside indexed CAP services'\n });\n for (const m of text.matchAll(\n /cds\\.services(?:\\[['\"]([^'\"]+)['\"]\\]|\\.(\\w+))\\.(\\w+)\\s*\\(/g\n ))\n out.push({\n callType: 'local_service_call',\n operationPathExpr: `/${m[3] ?? ''}`,\n payloadSummary: m[1] ?? m[2],\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0),\n confidence: 0.75\n });\n return out;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { ServiceBindingFact } from '../types.js';\nimport { normalizePath, stripQuotes } from '../utils/path-utils.js';\nfunction lineOf(text: string, idx: number): number {\n return text.slice(0, idx).split('\\n').length;\n}\nfunction placeholders(value?: string): string[] {\n return [...(value ?? '').matchAll(/\\$\\{\\s*(\\w+)\\s*\\}/g)]\n .map((m) => m[1] ?? '')\n .filter(Boolean);\n}\nexport async function parseServiceBindings(\n repoPath: string,\n filePath: string\n): Promise<ServiceBindingFact[]> {\n const text = await fs.readFile(path.join(repoPath, filePath), 'utf8');\n const out: ServiceBindingFact[] = [];\n for (const m of text.matchAll(\n /(?:const|let|this\\.)\\s*(\\w+)\\s*=\\s*(?:await\\s*)?cds\\.connect\\.to\\((['\"`])([^'\"`]+)\\2\\)/g\n ))\n out.push({\n variableName: m[1] ?? 'service',\n alias: m[3],\n isDynamic: false,\n placeholders: [],\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0)\n });\n for (const m of text.matchAll(\n /(?:const|let|this\\.)\\s*(\\w+)\\s*=\\s*(?:await\\s*)?cds\\.connect\\.to\\(\\{([\\s\\S]*?)\\}\\s*\\)/g\n )) {\n const body = m[2] ?? '';\n const destination = /destination\\s*:\\s*([^,\\n]+)/.exec(body)?.[1];\n const servicePath = /path\\s*:\\s*([^,\\n]+)/.exec(body)?.[1];\n const dest = destination ? stripQuotes(destination.trim()) : undefined;\n const svc = servicePath ? stripQuotes(servicePath.trim()) : undefined;\n const ph = [...placeholders(dest), ...placeholders(svc)];\n out.push({\n variableName: m[1] ?? 'service',\n destinationExpr: dest,\n servicePathExpr: svc,\n isDynamic: ph.length > 0,\n placeholders: ph,\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0)\n });\n }\n for (const m of text.matchAll(\n /(?:function\\s+(\\w+)\\s*\\([^)]*\\)\\s*\\{[\\s\\S]*?return|const\\s+(\\w+)\\s*=\\s*(?:async\\s*)?\\([^)]*\\)\\s*=>)\\s+(?:await\\s*)?cds\\.connect\\.to\\((['\"`])([^'\"`]+)\\3\\)/g\n ))\n out.push({\n variableName: m[1] ?? m[2] ?? 'connect',\n alias: m[4],\n isDynamic: false,\n placeholders: [],\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0)\n });\n\n const helperAliases = new Map(out.filter((b) => b.alias).map((b) => [b.variableName, b]));\n for (const m of text.matchAll(/(?:const|let)\\s+(\\w+)\\s*=\\s*(?:await\\s*)?(\\w+)\\s*\\(/g)) {\n const helper = helperAliases.get(m[2] ?? '');\n if (!helper) continue;\n out.push({\n ...helper,\n variableName: m[1] ?? 'service',\n sourceFile: normalizePath(filePath),\n sourceLine: lineOf(text, m.index ?? 0)\n });\n }\n return out;\n}\n","export function applyVariables(\n template: string | undefined,\n vars: Record<string, string>\n): string | undefined {\n if (!template) return undefined;\n return template.replace(\n /\\$\\{\\s*(\\w+)\\s*\\}/g,\n (_m, key: string) => vars[key] ?? `\\${${key}}`\n );\n}\nexport function extractPlaceholders(template: string | undefined): string[] {\n return [...(template ?? '').matchAll(/\\$\\{\\s*(\\w+)\\s*\\}/g)]\n .map((m) => m[1] ?? '')\n .filter(Boolean);\n}\n","import type { Db } from '../db/connection.js';\nexport interface OperationTarget {\n operationId: number;\n repoName: string;\n servicePath: string;\n operationPath: string;\n operationName: string;\n sourceFile: string;\n sourceLine: number;\n}\nexport function findOperation(\n db: Db,\n servicePath: string | undefined,\n operationPath: string | undefined,\n workspaceId?: number\n): OperationTarget | undefined {\n if (!operationPath) return undefined;\n const row = db\n .prepare(\n `SELECT o.id operationId,r.name repoName,s.service_path servicePath,o.operation_path operationPath,o.operation_name operationName,o.source_file sourceFile,o.source_line sourceLine\n FROM cds_operations o\n JOIN cds_services s ON s.id=o.service_id\n JOIN repositories r ON r.id=s.repo_id\n WHERE (? IS NULL OR r.workspace_id=?)\n AND (? IS NULL OR s.service_path=?)\n AND (o.operation_path=? OR o.operation_name=?)\n ORDER BY CASE WHEN s.service_path=? THEN 0 ELSE 1 END\n LIMIT 1`\n )\n .get(\n workspaceId,\n workspaceId,\n servicePath,\n servicePath,\n operationPath,\n operationPath.replace(/^\\//, ''),\n servicePath\n ) as OperationTarget | undefined;\n return row;\n}\n","import type { Db } from '../db/connection.js';\nexport function linkHelperPackages(db: Db, workspaceId: number): number {\n const repos = db\n .prepare(\n 'SELECT id,name,dependencies_json FROM repositories WHERE workspace_id=?'\n )\n .all(workspaceId) as Array<{\n id: number;\n name: string;\n dependencies_json: string;\n }>;\n let count = 0;\n for (const repo of repos) {\n const deps = JSON.parse(repo.dependencies_json) as Record<string, string>;\n for (const dep of Object.keys(deps)) {\n const helper = repos.find((r) => r.name === dep || dep.endsWith(r.name));\n if (helper) {\n db.prepare(\n 'INSERT INTO graph_edges(workspace_id,edge_type,from_kind,from_id,to_kind,to_id,confidence,evidence_json,is_dynamic) VALUES(?,?,?,?,?,?,?,?,?)'\n ).run(\n workspaceId,\n 'REPO_IMPORTS_HELPER_PACKAGE',\n 'repo',\n String(repo.id),\n 'repo',\n String(helper.id),\n 0.9,\n JSON.stringify({ dependency: dep }),\n 0\n );\n count += 1;\n }\n }\n }\n return count;\n}\n","import type { Db } from '../db/connection.js';\nimport { applyVariables } from './dynamic-edge-resolver.js';\nimport { findOperation } from './service-resolver.js';\nimport { linkHelperPackages } from './helper-package-linker.js';\nexport function linkWorkspace(\n db: Db,\n workspaceId: number,\n vars: Record<string, string> = {}\n): { edgeCount: number; unresolvedCount: number } {\n db.prepare('DELETE FROM graph_edges WHERE workspace_id=?').run(workspaceId);\n let edges = linkHelperPackages(db, workspaceId);\n let unresolved = 0;\n const calls = db\n .prepare(\n `SELECT c.*,r.name repoName,b.alias,b.destination_expr destinationExpr,b.service_path_expr servicePathExpr,b.is_dynamic isDynamic,b.placeholders_json placeholdersJson,req.service_path requireServicePath,req.destination requireDestination FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id LEFT JOIN service_bindings b ON b.id=c.service_binding_id LEFT JOIN cds_requires req ON req.repo_id=c.repo_id AND req.alias=b.alias WHERE r.workspace_id=?`\n )\n .all(workspaceId) as Array<Record<string, unknown>>;\n for (const call of calls) {\n const callType = String(call.call_type);\n const op = applyVariables(String(call.operation_path_expr ?? ''), vars);\n const servicePath = applyVariables(\n (call.servicePathExpr as string | undefined) ??\n (call.requireServicePath as string | undefined),\n vars\n );\n const target = callType.startsWith('remote')\n ? findOperation(db, servicePath, op, workspaceId)\n : undefined;\n const evidence = {\n sourceFile: call.source_file,\n sourceLine: call.source_line,\n serviceAlias: call.alias,\n destination: call.destinationExpr ?? call.requireDestination,\n servicePath,\n operationPath: op,\n targetRepo: target?.repoName,\n targetOperation: target?.operationName\n };\n if (target) {\n db.prepare(\n 'INSERT INTO graph_edges(workspace_id,edge_type,from_kind,from_id,to_kind,to_id,confidence,evidence_json,is_dynamic) VALUES(?,?,?,?,?,?,?,?,?)'\n ).run(\n workspaceId,\n 'REMOTE_CALL_RESOLVES_TO_OPERATION',\n 'call',\n String(call.id),\n 'operation',\n String(target.operationId),\n call.isDynamic ? 0.6 : 0.9,\n JSON.stringify(evidence),\n call.isDynamic ? 1 : 0\n );\n edges += 1;\n } else {\n const edgeType =\n callType === 'local_db_query'\n ? 'HANDLER_RUNS_DB_QUERY'\n : callType === 'external_http'\n ? 'HANDLER_CALLS_EXTERNAL_HTTP'\n : callType === 'async_emit'\n ? 'HANDLER_EMITS_EVENT'\n : callType === 'async_subscribe'\n ? 'EVENT_CONSUMED_BY_HANDLER'\n : call.isDynamic\n ? 'DYNAMIC_EDGE_CANDIDATE'\n : 'UNRESOLVED_EDGE';\n db.prepare(\n 'INSERT INTO graph_edges(workspace_id,edge_type,from_kind,from_id,to_kind,to_id,confidence,evidence_json,is_dynamic,unresolved_reason) VALUES(?,?,?,?,?,?,?,?,?,?)'\n ).run(\n workspaceId,\n edgeType,\n 'call',\n String(call.id),\n callType.startsWith('async_') ? 'event' : 'external',\n String(call.event_name_expr ?? call.query_entity ?? op ?? call.id),\n Number(call.confidence ?? 0.2),\n JSON.stringify(evidence),\n call.isDynamic ? 1 : 0,\n String(call.unresolved_reason ?? 'No indexed target operation matched')\n );\n edges += 1;\n unresolved += edgeType === 'UNRESOLVED_EDGE' ? 1 : 0;\n }\n }\n return { edgeCount: edges, unresolvedCount: unresolved };\n}\n","import type { Db } from '../db/connection.js';\nimport type { TraceEdge, TraceResult, TraceStart } from '../types.js';\n\ninterface RepoRef { id: number; name: string }\ninterface StartScope { repo?: RepoRef; sourceFiles?: Set<string>; selectorMatched: boolean }\ninterface CallRow extends Record<string, unknown> { id: number; repo_id: number; repoName: string; source_file: string; source_line: number; call_type: string; confidence: number }\ninterface GraphRow extends Record<string, unknown> { edge_type: string; from_id: string; to_kind: string; to_id: string; confidence: number; evidence_json: string; unresolved_reason?: string }\n\nfunction normalizeOperation(value: string | undefined): string | undefined {\n if (!value) return undefined;\n return value.startsWith('/') ? value.slice(1) : value;\n}\nfunction positiveDepth(value: number): number { return Number.isFinite(value) && value > 0 ? Math.floor(value) : 25; }\nfunction sourceFilesForStart(db: Db, repoId: number | undefined, start: TraceStart): Set<string> | undefined {\n const handler = start.handler;\n const operation = normalizeOperation(start.operation ?? start.operationPath);\n if (!handler && !operation) return undefined;\n const rows = db.prepare(`SELECT DISTINCT hc.source_file sourceFile\n FROM handler_classes hc LEFT JOIN handler_methods hm ON hm.handler_class_id=hc.id\n WHERE (? IS NULL OR hc.repo_id=?) AND (? IS NULL OR hc.class_name=? OR hm.method_name=?)\n AND (? IS NULL OR hm.decorator_value=? OR hm.method_name=?)`).all(repoId, repoId, handler, handler, handler, operation, operation, operation) as Array<{ sourceFile?: string }>;\n if (rows.length === 0) return undefined;\n return new Set(rows.map((row) => row.sourceFile).filter(Boolean) as string[]);\n}\nfunction startScope(db: Db, start: TraceStart): StartScope {\n const repo = start.repo ? (db.prepare('SELECT id,name FROM repositories WHERE name=? OR package_name=?').get(start.repo, start.repo) as RepoRef | undefined) : undefined;\n if (start.repo && !repo) return { repo, selectorMatched: false };\n const sourceFiles = sourceFilesForStart(db, repo?.id, start);\n const hasSelector = Boolean(start.handler ?? start.operation ?? start.operationPath);\n return { repo, sourceFiles, selectorMatched: !hasSelector || sourceFiles !== undefined };\n}\nfunction handlerFilesForOperation(db: Db, operationId: string): Set<string> {\n const op = db.prepare(`SELECT o.operation_name operationName,o.operation_path operationPath,s.repo_id repoId\n FROM cds_operations o JOIN cds_services s ON s.id=o.service_id WHERE o.id=?`).get(operationId) as { operationName?: string; operationPath?: string; repoId?: number } | undefined;\n if (!op) return new Set();\n const operation = normalizeOperation(op.operationPath ?? op.operationName);\n const rows = db.prepare(`SELECT DISTINCT hc.source_file sourceFile FROM handler_classes hc\n JOIN handler_methods hm ON hm.handler_class_id=hc.id\n WHERE hc.repo_id=? AND (hm.decorator_value=? OR hm.method_name=? OR hm.decorator_value=?)`).all(op.repoId, operation, operation, op.operationName) as Array<{ sourceFile?: string }>;\n return new Set(rows.map((row) => row.sourceFile).filter(Boolean) as string[]);\n}\nfunction includeCall(type: string, options: { includeExternal?: boolean; includeDb?: boolean; includeAsync?: boolean }): boolean {\n if (!options.includeDb && type === 'local_db_query') return false;\n if (!options.includeExternal && type === 'external_http') return false;\n if (!options.includeAsync && type.startsWith('async_')) return false;\n return true;\n}\nfunction graphForCalls(db: Db, callIds: number[]): Map<number, GraphRow[]> {\n const map = new Map<number, GraphRow[]>();\n if (callIds.length === 0) return map;\n const rows = db.prepare(`SELECT * FROM graph_edges WHERE from_kind='call' AND from_id IN (${callIds.map(() => '?').join(',')}) ORDER BY id`).all(...callIds) as GraphRow[];\n for (const row of rows) {\n const id = Number(row.from_id);\n map.set(id, [...(map.get(id) ?? []), row]);\n }\n return map;\n}\nexport function trace(db: Db, start: TraceStart, options: { depth: number; vars?: Record<string, string>; includeExternal?: boolean; includeDb?: boolean; includeAsync?: boolean }): TraceResult {\n const scope = startScope(db, start);\n const diagnostics = db.prepare('SELECT severity,code,message,source_file sourceFile,source_line sourceLine FROM diagnostics WHERE (? IS NULL OR repo_id=?)').all(scope.repo?.id, scope.repo?.id) as Array<Record<string, unknown>>;\n if (!scope.selectorMatched) diagnostics.unshift({ severity: 'warning', code: 'trace_start_not_found', message: 'No handler source matched the requested trace start selector' });\n const maxDepth = positiveDepth(options.depth);\n const edges: TraceEdge[] = [];\n const nodes = new Map<string, Record<string, unknown>>();\n const queue: Array<{ repoId?: number; files?: Set<string>; depth: number }> = scope.selectorMatched ? [{ repoId: scope.repo?.id, files: scope.sourceFiles, depth: 1 }] : [];\n const seenScopes = new Set<string>();\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current || current.depth > maxDepth) continue;\n const key = `${current.repoId ?? '*'}:${[...(current.files ?? new Set(['*']))].sort().join(',')}:${current.depth}`;\n if (seenScopes.has(key)) continue;\n seenScopes.add(key);\n const calls = db.prepare(`SELECT c.*,r.name repoName FROM outbound_calls c JOIN repositories r ON r.id=c.repo_id WHERE (? IS NULL OR c.repo_id=?) ORDER BY c.source_file,c.source_line`).all(current.repoId, current.repoId) as CallRow[];\n const filtered = calls.filter((c) => (!current.files || current.files.has(String(c.source_file))) && includeCall(String(c.call_type), options));\n const graph = graphForCalls(db, filtered.map((c) => Number(c.id)));\n for (const call of filtered) {\n const callNode = `call:${call.id}`;\n nodes.set(callNode, { id: callNode, kind: 'outbound_call', repo: call.repoName, file: call.source_file, line: call.source_line, callType: call.call_type });\n const graphRows = graph.get(Number(call.id)) ?? [];\n for (const row of graphRows) {\n const evidence = JSON.parse(String(row.evidence_json || '{}')) as Record<string, unknown>;\n const targetNode = `${row.to_kind}:${row.to_id}`;\n nodes.set(targetNode, { id: targetNode, kind: row.to_kind, label: row.to_id, ...evidence });\n const servicePath = typeof evidence.servicePath === 'string' ? evidence.servicePath : undefined;\n const operationPath = typeof evidence.operationPath === 'string' ? evidence.operationPath : undefined;\n const targetOperation = typeof evidence.targetOperation === 'string' ? evidence.targetOperation : undefined;\n const targetRepo = typeof evidence.targetRepo === 'string' ? evidence.targetRepo : '';\n const to = servicePath && operationPath ? `${servicePath}${operationPath}` : targetOperation ? `${targetRepo}:${targetOperation}` : row.to_id;\n edges.push({ step: current.depth, type: String(call.call_type), from: `${call.repoName}:${call.source_file}`, to, evidence, confidence: Number(row.confidence ?? call.confidence), unresolvedReason: row.unresolved_reason });\n if (row.to_kind === 'operation' && current.depth < maxDepth) {\n const files = handlerFilesForOperation(db, row.to_id);\n if (files.size > 0) queue.push({ files, depth: current.depth + 1 });\n }\n }\n }\n }\n return { start, nodes: [...nodes.values()], edges, diagnostics };\n}\n"],"mappings":"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","names":["path","path","fs","path","fs","path","path","fs","fs","path","ts","ts","fs","path","fs","path","lineOf","fs","path","fs","path","lineOf","firstArg","fs","path","fs","path","lineOf","fs","path"]}