@saptools/service-flow 0.1.28 → 0.1.29
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 +7 -0
- package/README.md +1 -1
- package/TECHNICAL-NOTE.md +6 -0
- package/dist/{chunk-SWPGRM7Z.js → chunk-GOE6ZK6I.js} +106 -56
- package/dist/chunk-GOE6ZK6I.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-SWPGRM7Z.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.29
|
|
4
|
+
|
|
5
|
+
- Classify GET OData entity/query paths with query strings, filter functions, key predicates, navigation reads, and query placeholders as terminal remote query/entity edges when no strong indexed CDS operation candidate resolves them.
|
|
6
|
+
- Preserve raw path, entity segment, query-string presence, query placeholders, method, and classifier reason in link evidence without creating dynamic operation edges from query parameters.
|
|
7
|
+
- Keep balanced top-level OData action/function invocation normalization for real operation imports while avoiding truncation at parentheses inside query strings.
|
|
8
|
+
- Document the conservative entity-query versus operation-invocation distinction for neutral CAP service-client calls.
|
|
9
|
+
|
|
3
10
|
## 0.1.28
|
|
4
11
|
|
|
5
12
|
- Propagate contextual service-client bindings through one-level object-parameter destructuring aliases, including renamed and assignment destructuring in neutral CAP helpers.
|
package/README.md
CHANGED
|
@@ -419,7 +419,7 @@ Run `service-flow index` after source, CDS, package metadata, or helper-package
|
|
|
419
419
|
<summary><b>Why is an expected call unresolved?</b></summary>
|
|
420
420
|
|
|
421
421
|
Check `service-flow doctor`, then inspect the facts with `service-flow list services`, `service-flow list operations`, and `service-flow list calls`. Dynamic destinations may need `--var key=value`; the key is the full trimmed expression inside `${...}` and is matched literally without JavaScript evaluation. Operation-path-only ambiguous remote actions usually mean the call had no service binding id; same-file identity aliases are propagated, while property/call-expression aliases and ambiguous wrapper flows remain conservative; inspect `list calls`, `inspect operation`, and `doctor --strict` to determine whether helper-return propagation or wrapper support is missing. Contextual implementation selection only continues into a handler when static evidence such as caller repository, resolved service path, destination/alias expression, dependency edges, registration package, and local service ownership makes exactly one candidate stronger; ties remain ambiguous with reasons.
|
|
422
|
-
Default doctor output is intended to focus on actionable indexing or trace-impacting issues; use `--strict` when you need exhaustive model-shape diagnostics for entity-only or extension-heavy CDS models. Strict mode also reports normalized OData invocation ambiguity, remote-action target quality, likely missed identity aliases, no-binding remote actions, contextual implementation stops, and wrapper dynamic-path candidates, including whether unresolved unknown/dynamic paths are semantic instead of numeric call ids.
|
|
422
|
+
Default doctor output is intended to focus on actionable indexing or trace-impacting issues; use `--strict` when you need exhaustive model-shape diagnostics for entity-only or extension-heavy CDS models. Strict mode also reports normalized OData invocation ambiguity, remote-action target quality, likely missed identity aliases, no-binding remote actions, contextual implementation stops, and wrapper dynamic-path candidates, including whether unresolved unknown/dynamic paths are semantic instead of numeric call ids. GET OData entity/query reads such as `/Books?$filter=contains(title,'A')`, `/Books(ID='1000')`, and navigation queries are terminal remote query/entity edges unless strong indexed CDS operation evidence resolves them; placeholders inside query strings are preserved as query evidence rather than dynamic operation selectors.
|
|
423
423
|
|
|
424
424
|
</details>
|
|
425
425
|
|
package/TECHNICAL-NOTE.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Service Flow Resolution Notes
|
|
2
2
|
|
|
3
|
+
## 0.1.29 OData entity-query intent notes
|
|
4
|
+
|
|
5
|
+
- Service-client `GET` paths with OData collection queries, filter/search functions in the query string, entity key predicates, navigation reads, or query-string placeholders are classified conservatively as terminal remote entity/query reads when no strong indexed CDS operation candidate resolves the path. Examples include `/Books?$filter=contains(title,'A')`, `/Books(ID='1000')`, and `/Authors('A1')/books?$select=ID`.
|
|
6
|
+
- Query-string placeholders are recorded as query evidence and do not make the operation target dynamic. Runtime variables in service paths, destinations, aliases, and true operation paths still keep the existing dynamic-edge behavior.
|
|
7
|
+
- OData invocation normalization no longer truncates paths at parentheses that appear inside query strings. Balanced top-level operation imports such as `/calculateScore(input='A')` continue to normalize and resolve against indexed CDS functions/actions when service evidence is strong.
|
|
8
|
+
|
|
3
9
|
## 0.1.22 alias, wrapper, contextual trace, and strict doctor notes
|
|
4
10
|
|
|
5
11
|
- Same-file service-client identity aliases now create their own service binding rows when the right-hand side is a known connected client variable. The parser accepts direct identifier aliases plus typed, `as`, and `satisfies` forms, supports source-order transitive aliases, and records `aliasKind: identity` helper-chain evidence. It still does not infer aliases from property reads, indexed access, function calls, object metadata, or cross-scope guesses.
|
|
@@ -521,6 +521,96 @@ function summarizeExpression(text) {
|
|
|
521
521
|
return redactText(text).slice(0, 240);
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
+
// src/linker/odata-path-normalizer.ts
|
|
525
|
+
function normalizeODataOperationInvocationPath(path9) {
|
|
526
|
+
if (path9 === void 0) return void 0;
|
|
527
|
+
const raw = path9.trim();
|
|
528
|
+
if (!raw) return void 0;
|
|
529
|
+
const open = raw.indexOf("(");
|
|
530
|
+
if (open < 0) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
531
|
+
const query = raw.indexOf("?");
|
|
532
|
+
if (query >= 0) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
533
|
+
if (!raw.startsWith("/") || raw.slice(1, open).includes("/")) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
534
|
+
const close = matchingClose(raw, open);
|
|
535
|
+
if (close === void 0 || raw.slice(close + 1).trim().length > 0) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
536
|
+
const operationSegment = raw.slice(0, open).trim();
|
|
537
|
+
if (operationSegment.length <= 1) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
538
|
+
return { rawOperationPath: raw, normalizedOperationPath: operationSegment, wasInvocation: true };
|
|
539
|
+
}
|
|
540
|
+
function classifyODataPathIntent(path9, method) {
|
|
541
|
+
const rawPath = (path9 ?? "").trim();
|
|
542
|
+
const normalizedMethod = (method ?? "GET").trim().toUpperCase() || "GET";
|
|
543
|
+
const queryIndex = rawPath.indexOf("?");
|
|
544
|
+
const pathWithoutQuery = queryIndex >= 0 ? rawPath.slice(0, queryIndex) : rawPath;
|
|
545
|
+
const queryString = queryIndex >= 0 ? rawPath.slice(queryIndex + 1) : void 0;
|
|
546
|
+
const segments = pathWithoutQuery.replace(/^\//, "").split("/").filter(Boolean);
|
|
547
|
+
const firstSegment = segments[0] ?? "";
|
|
548
|
+
const hasNavigationSegments = segments.length > 1;
|
|
549
|
+
const entitySegment = entitySegmentFromPath(pathWithoutQuery);
|
|
550
|
+
const placeholderKeys = [...new Set(extractTemplatePlaceholders(rawPath))];
|
|
551
|
+
const base = { rawPath, method: normalizedMethod, pathWithoutQuery, queryString, hasQueryString: queryIndex >= 0, entitySegment, placeholderKeys };
|
|
552
|
+
if (!rawPath || !rawPath.startsWith("/")) return { ...base, kind: "unknown", reason: "path_missing_or_not_absolute" };
|
|
553
|
+
if (normalizedMethod !== "GET") return { ...base, kind: "operation_invocation", reason: "non_get_service_send_defaults_to_operation" };
|
|
554
|
+
if (queryIndex >= 0) {
|
|
555
|
+
if (hasNavigationSegments) return { ...base, kind: "entity_navigation_query", reason: "get_path_has_navigation_and_query_string" };
|
|
556
|
+
if (looksLikeLowerCamelInvocation(firstSegment)) return { ...base, kind: "unknown", reason: "get_invocation_with_query_string_requires_indexed_operation_evidence" };
|
|
557
|
+
return { ...base, kind: "entity_query", reason: "get_collection_path_has_query_string" };
|
|
558
|
+
}
|
|
559
|
+
if (hasNavigationSegments) return { ...base, kind: "entity_navigation_query", reason: "get_path_has_navigation_segments" };
|
|
560
|
+
if (firstSegment.includes("(")) {
|
|
561
|
+
return looksLikeLowerCamelInvocation(firstSegment) ? { ...base, kind: "operation_invocation", reason: "get_single_lower_camel_segment_has_top_level_invocation" } : { ...base, kind: "entity_key_read", reason: "get_entity_segment_has_key_predicate" };
|
|
562
|
+
}
|
|
563
|
+
return { ...base, kind: "unknown", reason: "get_path_has_no_query_key_or_navigation_signal" };
|
|
564
|
+
}
|
|
565
|
+
function entitySegmentFromPath(path9) {
|
|
566
|
+
const first = path9.replace(/^\//, "").split("/")[0]?.trim();
|
|
567
|
+
if (!first) return void 0;
|
|
568
|
+
const open = first.indexOf("(");
|
|
569
|
+
const entity = (open >= 0 ? first.slice(0, open) : first).trim();
|
|
570
|
+
return entity || void 0;
|
|
571
|
+
}
|
|
572
|
+
function looksLikeLowerCamelInvocation(segment) {
|
|
573
|
+
const open = segment.indexOf("(");
|
|
574
|
+
if (open <= 0) return false;
|
|
575
|
+
const name = segment.slice(0, open).split(".").at(-1) ?? segment.slice(0, open);
|
|
576
|
+
return /^[a-z][A-Za-z0-9_]*$/.test(name);
|
|
577
|
+
}
|
|
578
|
+
function extractTemplatePlaceholders(text) {
|
|
579
|
+
return [...text.matchAll(/\$\{([^}]*)\}/g)].map((match) => (match[1] ?? "").trim()).filter(Boolean);
|
|
580
|
+
}
|
|
581
|
+
function matchingClose(text, openIndex) {
|
|
582
|
+
let depth = 0;
|
|
583
|
+
let quote;
|
|
584
|
+
for (let index = openIndex; index < text.length; index += 1) {
|
|
585
|
+
const char = text[index];
|
|
586
|
+
const prev = text[index - 1];
|
|
587
|
+
if (quote) {
|
|
588
|
+
if (prev === "\\") continue;
|
|
589
|
+
if (quote === "single" && char === "'" || quote === "double" && char === '"' || quote === "template" && char === "`") quote = void 0;
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
if (char === "'") {
|
|
593
|
+
quote = "single";
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
if (char === '"') {
|
|
597
|
+
quote = "double";
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
if (char === "`") {
|
|
601
|
+
quote = "template";
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (char === "(") depth += 1;
|
|
605
|
+
if (char === ")") {
|
|
606
|
+
depth -= 1;
|
|
607
|
+
if (depth === 0) return index;
|
|
608
|
+
if (depth < 0) return void 0;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return void 0;
|
|
612
|
+
}
|
|
613
|
+
|
|
524
614
|
// src/parsers/outbound-call-parser.ts
|
|
525
615
|
import fs6 from "fs/promises";
|
|
526
616
|
import path7 from "path";
|
|
@@ -708,9 +798,13 @@ function classifyOutboundCallsInSource(source, filePath) {
|
|
|
708
798
|
if (objectArg && ts4.isObjectLiteralExpression(objectArg)) {
|
|
709
799
|
const receiver = receiverName(expr.expression);
|
|
710
800
|
const query = objectPropertyText(objectArg, "query");
|
|
801
|
+
const method = stripQuotes(objectPropertyText(objectArg, "method") ?? "POST");
|
|
711
802
|
const op = objectPropertyText(objectArg, "path") ?? objectPropertyText(objectArg, "event");
|
|
712
803
|
const shorthandPath = objectPropertyIsShorthand(objectArg, "path");
|
|
713
|
-
|
|
804
|
+
const operationPathExpr = op && !shorthandPath ? `/${stripQuotes(op).replace(/^\//, "")}` : void 0;
|
|
805
|
+
const intent = classifyODataPathIntent(operationPathExpr, method);
|
|
806
|
+
const isODataQueryRead = method.toUpperCase() === "GET" && ["entity_query", "entity_key_read", "entity_navigation_query"].includes(intent.kind);
|
|
807
|
+
add(node, { callType: query || isODataQueryRead ? "remote_query" : "remote_action", serviceVariableName: receiver, method, operationPathExpr, queryEntity: query ? extractQueryEntity(query) : isODataQueryRead ? intent.entitySegment : void 0, payloadSummary: summarizeExpression(objectArg.getText(source)), confidence: op || query ? 0.8 : 0.4, unresolvedReason: !query && shorthandPath ? "dynamic_operation_path_identifier" : void 0 }, { receiver, classifier: "service_client_send_object", operationPathExpression: shorthandPath ? op : void 0, odataPathIntent: operationPathExpr ? intent : void 0, parserWarning: shorthandPath ? "dynamic_operation_path_identifier" : void 0 });
|
|
714
808
|
}
|
|
715
809
|
} else if (ts4.isCallExpression(expr) && ts4.isIdentifier(expr.expression) && wrapperSpecs.has(expr.expression.text) || ts4.isIdentifier(expr) && wrapperSpecs.has(expr.text)) {
|
|
716
810
|
const wrapperName = ts4.isIdentifier(expr) ? expr.text : ts4.isCallExpression(expr) && ts4.isIdentifier(expr.expression) ? expr.expression.text : "";
|
|
@@ -1433,53 +1527,6 @@ function substituteVariables(template, vars) {
|
|
|
1433
1527
|
};
|
|
1434
1528
|
}
|
|
1435
1529
|
|
|
1436
|
-
// src/linker/odata-path-normalizer.ts
|
|
1437
|
-
function normalizeODataOperationInvocationPath(path9) {
|
|
1438
|
-
if (path9 === void 0) return void 0;
|
|
1439
|
-
const raw = path9.trim();
|
|
1440
|
-
if (!raw) return void 0;
|
|
1441
|
-
const open = raw.indexOf("(");
|
|
1442
|
-
if (open < 0) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
1443
|
-
if (!raw.startsWith("/") || raw.slice(1, open).includes("/")) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
1444
|
-
const close = matchingClose(raw, open);
|
|
1445
|
-
if (close === void 0 || raw.slice(close + 1).trim().length > 0) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
1446
|
-
const operationSegment = raw.slice(0, open).trim();
|
|
1447
|
-
if (operationSegment.length <= 1) return { rawOperationPath: raw, normalizedOperationPath: raw, wasInvocation: false };
|
|
1448
|
-
return { rawOperationPath: raw, normalizedOperationPath: operationSegment, wasInvocation: true };
|
|
1449
|
-
}
|
|
1450
|
-
function matchingClose(text, openIndex) {
|
|
1451
|
-
let depth = 0;
|
|
1452
|
-
let quote;
|
|
1453
|
-
for (let index = openIndex; index < text.length; index += 1) {
|
|
1454
|
-
const char = text[index];
|
|
1455
|
-
const prev = text[index - 1];
|
|
1456
|
-
if (quote) {
|
|
1457
|
-
if (prev === "\\") continue;
|
|
1458
|
-
if (quote === "single" && char === "'" || quote === "double" && char === '"' || quote === "template" && char === "`") quote = void 0;
|
|
1459
|
-
continue;
|
|
1460
|
-
}
|
|
1461
|
-
if (char === "'") {
|
|
1462
|
-
quote = "single";
|
|
1463
|
-
continue;
|
|
1464
|
-
}
|
|
1465
|
-
if (char === '"') {
|
|
1466
|
-
quote = "double";
|
|
1467
|
-
continue;
|
|
1468
|
-
}
|
|
1469
|
-
if (char === "`") {
|
|
1470
|
-
quote = "template";
|
|
1471
|
-
continue;
|
|
1472
|
-
}
|
|
1473
|
-
if (char === "(") depth += 1;
|
|
1474
|
-
if (char === ")") {
|
|
1475
|
-
depth -= 1;
|
|
1476
|
-
if (depth === 0) return index;
|
|
1477
|
-
if (depth < 0) return void 0;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
return void 0;
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
1530
|
// src/linker/remote-query-target.ts
|
|
1484
1531
|
function buildRemoteQueryTarget(input) {
|
|
1485
1532
|
const entity = typeof input.queryEntity === "string" && input.queryEntity.trim() ? input.queryEntity.trim() : void 0;
|
|
@@ -1751,15 +1798,18 @@ function linkCalls(db, workspaceId, vars, generation) {
|
|
|
1751
1798
|
function insertCallEdge(db, workspaceId, call, vars, generation) {
|
|
1752
1799
|
const callType = String(call.call_type);
|
|
1753
1800
|
const rawOp = applyVariables(String(call.operation_path_expr ?? ""), vars);
|
|
1754
|
-
const
|
|
1755
|
-
const
|
|
1801
|
+
const intent = classifyODataPathIntent(rawOp, call.method);
|
|
1802
|
+
const isEntityQueryIntent = ["entity_query", "entity_key_read", "entity_navigation_query"].includes(intent.kind);
|
|
1803
|
+
const resolutionRawOp = callType === "remote_query" && isEntityQueryIntent ? intent.pathWithoutQuery : rawOp;
|
|
1804
|
+
const normalized = normalizeODataOperationInvocationPath(resolutionRawOp);
|
|
1805
|
+
const op = normalized?.normalizedOperationPath ?? resolutionRawOp;
|
|
1756
1806
|
const servicePath = applyVariables(call.servicePathExpr ?? call.requireServicePath, vars);
|
|
1757
1807
|
const destination = call.destinationExpr ?? call.requireDestination;
|
|
1758
1808
|
const isDynamic = Boolean(Number(call.isDynamic ?? 0));
|
|
1759
1809
|
const isOperationCall = callType === "remote_action" || callType === "local_service_call" || callType === "remote_query" && Boolean(op);
|
|
1760
1810
|
const resolution = isOperationCall ? resolveOperation(db, { servicePath, operationPath: op, serviceName: call.local_service_name, repoId: callType === "local_service_call" ? Number(call.repo_id) : void 0, alias: applyVariables(call.aliasExpr ?? call.alias, vars), destination: destination ? applyVariables(destination, vars) : void 0, isDynamic, hasExplicitOverride: Object.keys(vars).length > 0 || callType === "local_service_call" }, workspaceId) : { status: "unresolved", candidates: [], reasons: [] };
|
|
1761
|
-
const evidence = callEvidence(call, resolution, servicePath, op, destination ? applyVariables(destination, vars) : void 0, normalized);
|
|
1762
|
-
if (callType === "remote_query" && !op) {
|
|
1811
|
+
const evidence = callEvidence(call, resolution, servicePath, op, destination ? applyVariables(destination, vars) : void 0, normalized, intent);
|
|
1812
|
+
if (callType === "remote_query" && (isEntityQueryIntent || !op) && !resolution.target) {
|
|
1763
1813
|
const target = buildRemoteQueryTarget({ queryEntity: call.query_entity, servicePath, serviceAlias: call.alias, serviceAliasExpr: call.aliasExpr, destination: destination ? applyVariables(destination, vars) : void 0, isDynamic, parserWarning: evidence.parserWarning });
|
|
1764
1814
|
db.prepare("INSERT INTO graph_edges(workspace_id,edge_type,status,from_kind,from_id,to_kind,to_id,confidence,evidence_json,is_dynamic,generation) VALUES(?,?,?,?,?,?,?,?,?,?,?)").run(workspaceId, "HANDLER_RUNS_REMOTE_QUERY", "terminal", "call", String(call.id), target.toKind, target.toId, Number(call.confidence ?? 0.5), JSON.stringify({ ...evidence, ...target.evidence }), 0, generation);
|
|
1765
1815
|
return { status: "terminal", callType };
|
|
@@ -1801,9 +1851,9 @@ function objectJson(value) {
|
|
|
1801
1851
|
const parsed = parseJson(value);
|
|
1802
1852
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
1803
1853
|
}
|
|
1804
|
-
function callEvidence(call, resolution, servicePath, op, destination, normalized) {
|
|
1854
|
+
function callEvidence(call, resolution, servicePath, op, destination, normalized, odataPathIntent) {
|
|
1805
1855
|
const bindingHasDynamicExpression = Boolean(Number(call.isDynamic ?? 0));
|
|
1806
|
-
return { sourceFile: call.source_file, sourceLine: call.source_line, file: call.source_file, line: call.source_line, callId: call.id, repo: call.repoName, serviceAlias: call.alias, serviceAliasExpr: call.aliasExpr, destination, servicePath, operationPath: op, rawOperationPath: normalized?.wasInvocation ? normalized.rawOperationPath :
|
|
1856
|
+
return { sourceFile: call.source_file, sourceLine: call.source_line, file: call.source_file, line: call.source_line, callId: call.id, repo: call.repoName, serviceAlias: call.alias, serviceAliasExpr: call.aliasExpr, destination, servicePath, operationPath: op, rawOperationPath: normalized?.wasInvocation ? normalized.rawOperationPath : odataPathIntent?.rawPath, normalizedOperationPath: normalized?.wasInvocation ? normalized.normalizedOperationPath : void 0, localServiceName: call.local_service_name, localServiceLookup: call.local_service_lookup, aliasChain: parseJson(call.alias_chain_json), transport: call.call_type === "local_service_call" ? "local" : void 0, targetRepo: resolution.target?.repoName, targetServicePath: resolution.target?.servicePath, targetOperationPath: resolution.target?.operationPath, targetOperation: resolution.target?.operationName, helperChain: parseJson(call.helperChainJson), candidates: resolution.candidates, candidateCount: resolution.candidates.length, resolutionStatus: resolution.status, resolutionReasons: resolution.reasons, odataPathIntent, queryStringPresent: odataPathIntent?.hasQueryString || void 0, queryPlaceholderKeys: odataPathIntent?.placeholderKeys.length ? odataPathIntent.placeholderKeys : void 0, bindingHasDynamicExpression: bindingHasDynamicExpression || void 0, outboundEvidence: objectJson(call.evidence_json), analysisCompleteness: call.unresolved_reason ? "partial" : "complete", parserWarning: call.unresolved_reason ? { code: "parser_warning", message: call.unresolved_reason } : void 0 };
|
|
1807
1857
|
}
|
|
1808
1858
|
function linkImplementations(db, workspaceId, generation) {
|
|
1809
1859
|
const operations = db.prepare(`SELECT o.id operationId,o.operation_path operationPath,o.operation_name operationName,s.service_path servicePath,s.repo_id modelRepoId,r.name modelRepo,r.package_name modelPackage,r.kind modelKind FROM cds_operations o JOIN cds_services s ON s.id=o.service_id JOIN repositories r ON r.id=s.repo_id WHERE r.workspace_id=?`).all(workspaceId);
|
|
@@ -2554,14 +2604,14 @@ export {
|
|
|
2554
2604
|
parseHandlerRegistrations,
|
|
2555
2605
|
redactText,
|
|
2556
2606
|
redactValue,
|
|
2607
|
+
normalizeODataOperationInvocationPath,
|
|
2557
2608
|
containsSupportedOutboundCall,
|
|
2558
2609
|
parseOutboundCalls,
|
|
2559
2610
|
parseServiceBindings,
|
|
2560
2611
|
applyVariables,
|
|
2561
2612
|
extractPlaceholders,
|
|
2562
2613
|
substituteVariables,
|
|
2563
|
-
normalizeODataOperationInvocationPath,
|
|
2564
2614
|
linkWorkspace,
|
|
2565
2615
|
trace
|
|
2566
2616
|
};
|
|
2567
|
-
//# sourceMappingURL=chunk-
|
|
2617
|
+
//# sourceMappingURL=chunk-GOE6ZK6I.js.map
|