@saptools/service-flow 0.1.26 → 0.1.27
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.27
|
|
4
|
+
|
|
5
|
+
- Enrich trace-time contextual service-client bindings from package-level CAP `cds.requires` aliases so helper-internal sends resolve through require-derived service paths and destinations.
|
|
6
|
+
- Preserve contextual binding attempt evidence for unresolved helper sends, including effective service path, destination, candidate counts, and resolution reasons.
|
|
7
|
+
- Refine strict doctor diagnostics for contextual helper sends to distinguish resolved contextual opportunities, missing `cds.requires` rows, require-backed unresolved sends, remaining runtime variables, and workspaces with no contextual opportunity.
|
|
8
|
+
- Expand neutral CAP coverage for positional helper arguments, destructured object helper parameters, renamed properties, late assignments, table output, Mermaid output, and require-derived target operations.
|
|
9
|
+
|
|
3
10
|
## 0.1.26
|
|
4
11
|
|
|
5
12
|
- Resolve helper-internal remote sends contextually in trace output when service clients are passed through positional arguments or one-level destructured object parameters.
|
|
@@ -2266,21 +2266,33 @@ function receiverFromEvidence(value) {
|
|
|
2266
2266
|
const evidence = parseEvidence(value);
|
|
2267
2267
|
return typeof evidence.receiver === "string" ? evidence.receiver : void 0;
|
|
2268
2268
|
}
|
|
2269
|
+
function hasDynamicPlaceholder(value) {
|
|
2270
|
+
return extractPlaceholders(value).length > 0;
|
|
2271
|
+
}
|
|
2272
|
+
function enrichBinding(row) {
|
|
2273
|
+
const effectiveServicePath = row.servicePathExpr && !hasDynamicPlaceholder(row.servicePathExpr) ? row.servicePathExpr : !row.servicePathExpr ? row.requireServicePath : void 0;
|
|
2274
|
+
const effectiveDestination = row.destinationExpr && !hasDynamicPlaceholder(row.destinationExpr) ? row.destinationExpr : !row.destinationExpr ? row.requireDestination : void 0;
|
|
2275
|
+
return { ...row, effectiveServicePath, effectiveDestination };
|
|
2276
|
+
}
|
|
2269
2277
|
function knownBindingsForCalls(db, calls) {
|
|
2270
2278
|
const map = /* @__PURE__ */ new Map();
|
|
2271
2279
|
for (const call of calls) {
|
|
2272
2280
|
const receiver = receiverFromEvidence(call.evidence_json);
|
|
2273
2281
|
const bindingId = Number(call.service_binding_id ?? 0);
|
|
2274
2282
|
if (!receiver || !bindingId) continue;
|
|
2275
|
-
const row = db.prepare(
|
|
2276
|
-
|
|
2283
|
+
const row = db.prepare(`SELECT b.id,b.alias,b.alias_expr aliasExpr,b.destination_expr destinationExpr,b.service_path_expr servicePathExpr,b.source_file sourceFile,b.source_line sourceLine,req.service_path requireServicePath,req.destination requireDestination
|
|
2284
|
+
FROM service_bindings b LEFT JOIN cds_requires req ON req.repo_id=b.repo_id AND req.alias=b.alias
|
|
2285
|
+
WHERE b.id=?`).get(bindingId);
|
|
2286
|
+
if (row) map.set(receiver, enrichBinding({ ...row, bindingId, source: "local_service_binding", calleeReceiver: receiver }));
|
|
2277
2287
|
}
|
|
2278
2288
|
return map;
|
|
2279
2289
|
}
|
|
2280
2290
|
function knownBindingsForScope(db, repoId, symbolIds, files) {
|
|
2281
2291
|
const map = /* @__PURE__ */ new Map();
|
|
2282
2292
|
if (repoId === void 0) return map;
|
|
2283
|
-
const rows2 = db.prepare(
|
|
2293
|
+
const rows2 = db.prepare(`SELECT b.id,b.variable_name variableName,b.alias,b.alias_expr aliasExpr,b.destination_expr destinationExpr,b.service_path_expr servicePathExpr,b.source_file sourceFile,b.source_line sourceLine,req.service_path requireServicePath,req.destination requireDestination
|
|
2294
|
+
FROM service_bindings b LEFT JOIN cds_requires req ON req.repo_id=b.repo_id AND req.alias=b.alias
|
|
2295
|
+
WHERE b.repo_id=?`).all(repoId);
|
|
2284
2296
|
for (const row of rows2) {
|
|
2285
2297
|
if (!row.variableName) continue;
|
|
2286
2298
|
if (files && !files.has(String(row.sourceFile))) continue;
|
|
@@ -2288,7 +2300,7 @@ function knownBindingsForScope(db, repoId, symbolIds, files) {
|
|
|
2288
2300
|
const owner = db.prepare("SELECT id FROM symbols WHERE id IN (" + [...symbolIds].map(() => "?").join(",") + ") AND source_file=? AND start_line<=? AND end_line>=? LIMIT 1").get(...symbolIds, row.sourceFile, row.sourceLine, row.sourceLine);
|
|
2289
2301
|
if (!owner) continue;
|
|
2290
2302
|
}
|
|
2291
|
-
map.set(row.variableName, { ...row, bindingId: Number(row.id), source: "local_service_binding", calleeReceiver: row.variableName });
|
|
2303
|
+
map.set(row.variableName, enrichBinding({ ...row, bindingId: Number(row.id), source: "local_service_binding", calleeReceiver: row.variableName }));
|
|
2292
2304
|
}
|
|
2293
2305
|
return map;
|
|
2294
2306
|
}
|
|
@@ -2324,10 +2336,13 @@ function contextForSymbolCall(db, symbolCall, callerBindings) {
|
|
|
2324
2336
|
function contextualRuntimeResolution(db, call, binding, workspaceId) {
|
|
2325
2337
|
if (!binding || String(call.call_type) !== "remote_action" || call.operation_path_expr === void 0 || call.operation_path_expr === null) return {};
|
|
2326
2338
|
const op = normalizeODataOperationInvocationPathForTrace(String(call.operation_path_expr));
|
|
2327
|
-
const
|
|
2328
|
-
const
|
|
2329
|
-
|
|
2330
|
-
|
|
2339
|
+
const servicePath = binding.effectiveServicePath ?? binding.servicePathExpr ?? binding.requireServicePath;
|
|
2340
|
+
const destination = binding.effectiveDestination ?? binding.destinationExpr ?? binding.requireDestination;
|
|
2341
|
+
const resolution = resolveOperation(db, { servicePath, operationPath: op, alias: binding.aliasExpr ?? binding.alias, destination, hasExplicitOverride: true, isDynamic: false }, workspaceId);
|
|
2342
|
+
const evidence = { contextualServiceBindingAttempted: true, contextualBinding: { source: binding.source, callerArgument: binding.callerArgument, callerProperty: binding.callerProperty, calleeParameter: binding.calleeParameter, calleeReceiver: binding.calleeReceiver, bindingSourceFile: binding.sourceFile, bindingSourceLine: binding.sourceLine, alias: binding.alias, aliasExpr: binding.aliasExpr, requireServicePath: binding.requireServicePath, requireDestination: binding.requireDestination, effectiveServicePath: binding.effectiveServicePath, effectiveDestination: binding.effectiveDestination }, operationPath: op, servicePath, serviceAlias: binding.alias, serviceAliasExpr: binding.aliasExpr, destination, requireServicePath: binding.requireServicePath, requireDestination: binding.requireDestination, effectiveServicePath: binding.effectiveServicePath, effectiveDestination: binding.effectiveDestination, contextualResolutionStatus: resolution.status, contextualCandidateCount: resolution.candidates.length, candidates: resolution.candidates, contextualResolutionReasons: resolution.reasons, resolutionReasons: resolution.reasons };
|
|
2343
|
+
if (!resolution.target) return { evidence, unresolvedReason: resolution.status === "ambiguous" ? "Ambiguous contextual operation candidates" : resolution.status === "dynamic" ? `Dynamic contextual target is missing runtime variables: ${resolution.reasons.join(", ")}` : "No contextual operation candidate matched" };
|
|
2344
|
+
const resolvedEvidence = { ...evidence, contextualServiceBindingSelected: true, targetRepo: resolution.target.repoName, targetServicePath: resolution.target.servicePath, targetOperationPath: resolution.target.operationPath, targetOperation: resolution.target.operationName };
|
|
2345
|
+
return { row: { id: -Number(call.id), edge_type: "REMOTE_CALL_RESOLVES_TO_OPERATION", from_id: String(call.id), to_kind: "operation", to_id: String(resolution.target.operationId), confidence: resolution.target.score, evidence_json: JSON.stringify(resolvedEvidence), status: "resolved" }, evidence: resolvedEvidence, unresolvedReason: void 0 };
|
|
2331
2346
|
}
|
|
2332
2347
|
function normalizeODataOperationInvocationPathForTrace(raw) {
|
|
2333
2348
|
return raw.startsWith("/") ? raw : `/${raw}`;
|
|
@@ -2434,9 +2449,10 @@ function trace(db, start, options) {
|
|
|
2434
2449
|
for (const row of graphRows) {
|
|
2435
2450
|
if (seenEdges.has(Number(row.id))) continue;
|
|
2436
2451
|
seenEdges.add(Number(row.id));
|
|
2437
|
-
const
|
|
2452
|
+
const persistedEvidence = JSON.parse(
|
|
2438
2453
|
String(row.evidence_json || "{}")
|
|
2439
2454
|
);
|
|
2455
|
+
const rawEvidence = contextual.evidence ? { ...persistedEvidence, ...contextual.evidence } : persistedEvidence;
|
|
2440
2456
|
const effective = runtimeResolution(db, row, rawEvidence, options.vars);
|
|
2441
2457
|
const evidence = effective.evidence;
|
|
2442
2458
|
const effectiveRow = effective.row;
|
|
@@ -2531,4 +2547,4 @@ export {
|
|
|
2531
2547
|
linkWorkspace,
|
|
2532
2548
|
trace
|
|
2533
2549
|
};
|
|
2534
|
-
//# sourceMappingURL=chunk-
|
|
2550
|
+
//# sourceMappingURL=chunk-VDJTNOEI.js.map
|