@saptools/service-flow 0.1.49 → 0.1.50
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/dist/{chunk-XOROZHW4.js → chunk-52OUS3MO.js} +303 -109
- package/dist/chunk-52OUS3MO.js.map +1 -0
- package/dist/cli.js +67 -16
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/cli/doctor.ts +59 -1
- package/src/db/migrations.ts +4 -1
- package/src/db/repositories.ts +2 -1
- package/src/db/schema.ts +1 -1
- package/src/linker/cross-repo-linker.ts +102 -5
- package/src/linker/operation-decorator-normalizer.ts +3 -3
- package/src/parsers/decorator-parser.ts +128 -22
- package/src/trace/selectors.ts +36 -0
- package/src/trace/trace-engine.ts +1 -20
- package/src/types.ts +12 -0
- package/dist/chunk-XOROZHW4.js.map +0 -1
|
@@ -315,6 +315,46 @@ import fs4 from "fs/promises";
|
|
|
315
315
|
import path5 from "path";
|
|
316
316
|
import ts2 from "typescript";
|
|
317
317
|
|
|
318
|
+
// src/linker/operation-decorator-normalizer.ts
|
|
319
|
+
function lowerFirst(value) {
|
|
320
|
+
return value ? `${value[0]?.toLowerCase() ?? ""}${value.slice(1)}` : value;
|
|
321
|
+
}
|
|
322
|
+
function normalizedOperationName(value) {
|
|
323
|
+
return value.replace(/^\//, "");
|
|
324
|
+
}
|
|
325
|
+
function clean(value) {
|
|
326
|
+
return value.replace(/^[`'"]|[`'"]$/g, "");
|
|
327
|
+
}
|
|
328
|
+
function generatedOperationNameFromConstant(value) {
|
|
329
|
+
for (const prefix of ["Action", "Func"]) {
|
|
330
|
+
if (value.startsWith(prefix) && value.length > prefix.length && /^[A-Z]/.test(value.slice(prefix.length))) return lowerFirst(value.slice(prefix.length));
|
|
331
|
+
}
|
|
332
|
+
return void 0;
|
|
333
|
+
}
|
|
334
|
+
function resolved(value, raw) {
|
|
335
|
+
const literal2 = clean(value);
|
|
336
|
+
const generated = generatedOperationNameFromConstant(literal2);
|
|
337
|
+
return { status: "resolved", operationName: generated ?? normalizedOperationName(literal2), raw };
|
|
338
|
+
}
|
|
339
|
+
function normalizeDecoratorOperationSignal(value, raw, candidateOperation) {
|
|
340
|
+
if (value) return resolved(value, raw);
|
|
341
|
+
if (!raw || raw.trim().length === 0) return { status: "none", raw };
|
|
342
|
+
const expression = raw.trim();
|
|
343
|
+
const nameMatch = /(?:^|\.)(Action[A-Z][\w$]*|Func[A-Z][\w$]*)\.name$/.exec(expression);
|
|
344
|
+
if (nameMatch?.[1]) return resolved(nameMatch[1], expression);
|
|
345
|
+
const stringMatch = /^String\(([A-Za-z_$][\w$]*)\)$/.exec(expression);
|
|
346
|
+
if (stringMatch?.[1]) {
|
|
347
|
+
const identifier = stringMatch[1];
|
|
348
|
+
const generated = generatedOperationNameFromConstant(identifier);
|
|
349
|
+
const normalizedCandidate2 = candidateOperation ? normalizedOperationName(candidateOperation) : void 0;
|
|
350
|
+
if (generated) return { status: "resolved", operationName: generated, raw: expression };
|
|
351
|
+
if (normalizedCandidate2 && identifier === normalizedCandidate2) return { status: "resolved", operationName: identifier, raw: expression };
|
|
352
|
+
return { status: "unsupported", raw: expression, reason: "string_wrapper_identifier_not_resolved" };
|
|
353
|
+
}
|
|
354
|
+
if (/^[`'"]/.test(expression) && !/[`'"]$/.test(expression)) return { status: "malformed", raw: expression, reason: "unterminated_literal" };
|
|
355
|
+
return { status: "unsupported", raw: expression, reason: "unsupported_decorator_expression" };
|
|
356
|
+
}
|
|
357
|
+
|
|
318
358
|
// src/parsers/ts-project.ts
|
|
319
359
|
import ts from "typescript";
|
|
320
360
|
function createSourceFile(filePath, text) {
|
|
@@ -340,16 +380,102 @@ function callName(d) {
|
|
|
340
380
|
}
|
|
341
381
|
function firstArg(d) {
|
|
342
382
|
const e = d.expression;
|
|
343
|
-
return ts2.isCallExpression(e)
|
|
383
|
+
return ts2.isCallExpression(e) ? e.arguments[0] : void 0;
|
|
384
|
+
}
|
|
385
|
+
function unwrapExpression(expression) {
|
|
386
|
+
let current = expression;
|
|
387
|
+
while (ts2.isParenthesizedExpression(current) || ts2.isAsExpression(current) || ts2.isTypeAssertionExpression(current) || ts2.isSatisfiesExpression(current)) current = current.expression;
|
|
388
|
+
return current;
|
|
389
|
+
}
|
|
390
|
+
function stringValue(expression) {
|
|
391
|
+
if (!expression) return void 0;
|
|
392
|
+
const unwrapped = unwrapExpression(expression);
|
|
393
|
+
return ts2.isStringLiteralLike(unwrapped) ? unwrapped.text : void 0;
|
|
394
|
+
}
|
|
395
|
+
function propertyName(node) {
|
|
396
|
+
if (ts2.isIdentifier(node) || ts2.isStringLiteralLike(node)) return node.text;
|
|
397
|
+
return void 0;
|
|
398
|
+
}
|
|
399
|
+
function collectEnumMembers(statement, lookups) {
|
|
400
|
+
for (const member of statement.members) {
|
|
401
|
+
const name = propertyName(member.name);
|
|
402
|
+
const value = stringValue(member.initializer);
|
|
403
|
+
if (name && value !== void 0)
|
|
404
|
+
lookups.enumMembers.set(`${statement.name.text}.${name}`, value);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function collectObjectProperties(name, initializer, lookups) {
|
|
408
|
+
const object = unwrapExpression(initializer);
|
|
409
|
+
if (!ts2.isObjectLiteralExpression(object)) return;
|
|
410
|
+
for (const property of object.properties) {
|
|
411
|
+
if (!ts2.isPropertyAssignment(property)) continue;
|
|
412
|
+
const key = propertyName(property.name);
|
|
413
|
+
const value = stringValue(property.initializer);
|
|
414
|
+
if (key && value !== void 0)
|
|
415
|
+
lookups.objectProperties.set(`${name}.${key}`, value);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function collectStringLookups(source) {
|
|
419
|
+
const lookups = {
|
|
420
|
+
identifiers: /* @__PURE__ */ new Map(),
|
|
421
|
+
enumMembers: /* @__PURE__ */ new Map(),
|
|
422
|
+
objectProperties: /* @__PURE__ */ new Map()
|
|
423
|
+
};
|
|
424
|
+
for (const statement of source.statements) {
|
|
425
|
+
if (ts2.isEnumDeclaration(statement)) collectEnumMembers(statement, lookups);
|
|
426
|
+
if (!ts2.isVariableStatement(statement) || !(statement.declarationList.flags & ts2.NodeFlags.Const)) continue;
|
|
427
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
428
|
+
if (!ts2.isIdentifier(declaration.name) || !declaration.initializer) continue;
|
|
429
|
+
const value = stringValue(declaration.initializer);
|
|
430
|
+
if (value !== void 0) lookups.identifiers.set(declaration.name.text, value);
|
|
431
|
+
collectObjectProperties(declaration.name.text, declaration.initializer, lookups);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return lookups;
|
|
435
|
+
}
|
|
436
|
+
function unresolved(rawExpression, reason) {
|
|
437
|
+
return { rawExpression, resolutionKind: "unresolved", unresolvedReason: reason };
|
|
438
|
+
}
|
|
439
|
+
function generatedConstant(rawExpression) {
|
|
440
|
+
const match = /(?:^|\.)(Action[A-Z][\w$]*|Func[A-Z][\w$]*)\.name$/.exec(rawExpression.trim());
|
|
441
|
+
return match?.[1] ? generatedOperationNameFromConstant(match[1]) : void 0;
|
|
442
|
+
}
|
|
443
|
+
function resolveDecoratorArgument(argument, lookups) {
|
|
444
|
+
if (!argument) return unresolved("", "decorator_argument_missing");
|
|
445
|
+
const rawExpression = argument.getText();
|
|
446
|
+
const expression = unwrapExpression(argument);
|
|
447
|
+
if (ts2.isStringLiteralLike(expression))
|
|
448
|
+
return { rawExpression, resolvedValue: expression.text, resolutionKind: "literal" };
|
|
449
|
+
if (ts2.isIdentifier(expression)) {
|
|
450
|
+
const value = lookups.identifiers.get(expression.text);
|
|
451
|
+
return value === void 0 ? unresolved(rawExpression, "identifier_not_resolved_to_local_const_string") : { rawExpression, resolvedValue: value, resolutionKind: "const_identifier" };
|
|
452
|
+
}
|
|
453
|
+
if (ts2.isPropertyAccessExpression(expression) && ts2.isIdentifier(expression.expression)) {
|
|
454
|
+
const key = `${expression.expression.text}.${expression.name.text}`;
|
|
455
|
+
const enumValue = lookups.enumMembers.get(key);
|
|
456
|
+
if (enumValue !== void 0)
|
|
457
|
+
return { rawExpression, resolvedValue: enumValue, resolutionKind: "enum_member" };
|
|
458
|
+
const objectValue2 = lookups.objectProperties.get(key);
|
|
459
|
+
if (objectValue2 !== void 0)
|
|
460
|
+
return { rawExpression, resolvedValue: objectValue2, resolutionKind: "const_object_property" };
|
|
461
|
+
}
|
|
462
|
+
const generatedValue = generatedConstant(rawExpression);
|
|
463
|
+
if (generatedValue !== void 0)
|
|
464
|
+
return {
|
|
465
|
+
rawExpression,
|
|
466
|
+
resolvedValue: generatedValue,
|
|
467
|
+
resolutionKind: "generated_constant_name"
|
|
468
|
+
};
|
|
469
|
+
if (ts2.isPropertyAccessExpression(expression))
|
|
470
|
+
return unresolved(rawExpression, "property_access_not_resolved_to_local_string");
|
|
471
|
+
return unresolved(rawExpression, "unsupported_decorator_expression");
|
|
344
472
|
}
|
|
345
473
|
async function parseDecorators(repoPath, filePath) {
|
|
346
474
|
const text = await fs4.readFile(path5.join(repoPath, filePath), "utf8");
|
|
347
475
|
const sf = createSourceFile(filePath, text);
|
|
348
|
-
const
|
|
476
|
+
const lookups = collectStringLookups(sf);
|
|
349
477
|
const handlers = [];
|
|
350
478
|
function visit(node) {
|
|
351
|
-
if (ts2.isVariableDeclaration(node) && ts2.isIdentifier(node.name) && node.initializer && ts2.isStringLiteralLike(node.initializer))
|
|
352
|
-
constants.set(node.name.text, node.initializer.text);
|
|
353
479
|
if (ts2.isClassDeclaration(node)) {
|
|
354
480
|
const className = node.name?.text ?? "AnonymousHandler";
|
|
355
481
|
const hasHandler = decs(node).some((d) => callName(d) === "Handler");
|
|
@@ -357,13 +483,13 @@ async function parseDecorators(repoPath, filePath) {
|
|
|
357
483
|
(m) => decs(m).filter(
|
|
358
484
|
(d) => ["Func", "Action", "On", "Event"].includes(callName(d))
|
|
359
485
|
).map((d) => {
|
|
360
|
-
const
|
|
361
|
-
const value = raw.startsWith('"') || raw.startsWith("'") || raw.startsWith("`") ? stripQuotes(raw) : constants.get(raw) ?? (raw.endsWith(".name") ? raw.split(".").at(-2) : void 0);
|
|
486
|
+
const decoratorResolution = resolveDecoratorArgument(firstArg(d), lookups);
|
|
362
487
|
return {
|
|
363
488
|
methodName: m.name.getText(),
|
|
364
489
|
decoratorKind: callName(d),
|
|
365
|
-
decoratorValue:
|
|
366
|
-
decoratorRawExpression:
|
|
490
|
+
decoratorValue: decoratorResolution.resolvedValue,
|
|
491
|
+
decoratorRawExpression: decoratorResolution.rawExpression,
|
|
492
|
+
decoratorResolution,
|
|
367
493
|
sourceFile: normalizePath(filePath),
|
|
368
494
|
sourceLine: line(sf, m.getStart())
|
|
369
495
|
};
|
|
@@ -588,7 +714,7 @@ import ts4 from "typescript";
|
|
|
588
714
|
function lineOf3(sf, node) {
|
|
589
715
|
return sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
|
|
590
716
|
}
|
|
591
|
-
function
|
|
717
|
+
function stringValue2(node) {
|
|
592
718
|
if (!node) return void 0;
|
|
593
719
|
if (ts4.isStringLiteralLike(node) || ts4.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
594
720
|
if (ts4.isTemplateExpression(node)) return node.getText().replace(/^`|`$/g, "");
|
|
@@ -609,7 +735,7 @@ function connectFactFromCall(call) {
|
|
|
609
735
|
let alias;
|
|
610
736
|
let aliasExpr;
|
|
611
737
|
if (ts4.isStringLiteralLike(first) || ts4.isNoSubstitutionTemplateLiteral(first)) alias = first.text;
|
|
612
|
-
else if (!ts4.isObjectLiteralExpression(first)) aliasExpr =
|
|
738
|
+
else if (!ts4.isObjectLiteralExpression(first)) aliasExpr = stringValue2(first);
|
|
613
739
|
if ((ts4.isStringLiteralLike(first) || ts4.isNoSubstitutionTemplateLiteral(first)) && !objectArg) return { alias: first.text, isDynamic: false, placeholders: [] };
|
|
614
740
|
if (!objectArg && aliasExpr) return { aliasExpr, isDynamic: true, placeholders: placeholders(aliasExpr) };
|
|
615
741
|
const expressions = objectArg ? objectExpressions(objectArg) : {};
|
|
@@ -622,8 +748,8 @@ function objectExpressions(objectArg) {
|
|
|
622
748
|
for (const prop of obj.properties) {
|
|
623
749
|
if (!ts4.isPropertyAssignment(prop)) continue;
|
|
624
750
|
const name = ts4.isIdentifier(prop.name) || ts4.isStringLiteralLike(prop.name) ? prop.name.text : void 0;
|
|
625
|
-
if (name === "destination") out.destinationExpr =
|
|
626
|
-
if (name === "path" || name === "servicePath") out.servicePathExpr =
|
|
751
|
+
if (name === "destination") out.destinationExpr = stringValue2(prop.initializer);
|
|
752
|
+
if (name === "path" || name === "servicePath") out.servicePathExpr = stringValue2(prop.initializer);
|
|
627
753
|
if (ts4.isObjectLiteralExpression(prop.initializer)) visitObject(prop.initializer);
|
|
628
754
|
}
|
|
629
755
|
}
|
|
@@ -733,8 +859,8 @@ function collectReturnedObjectBindings(fn) {
|
|
|
733
859
|
for (const prop of node.expression.properties) {
|
|
734
860
|
if (ts5.isShorthandPropertyAssignment(prop)) returns.set(prop.name.text, prop.name.text);
|
|
735
861
|
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.initializer)) {
|
|
736
|
-
const
|
|
737
|
-
if (
|
|
862
|
+
const propertyName3 = ts5.isIdentifier(prop.name) || ts5.isStringLiteralLike(prop.name) ? prop.name.text : void 0;
|
|
863
|
+
if (propertyName3) returns.set(propertyName3, prop.initializer.text);
|
|
738
864
|
}
|
|
739
865
|
}
|
|
740
866
|
}
|
|
@@ -742,9 +868,9 @@ function collectReturnedObjectBindings(fn) {
|
|
|
742
868
|
}
|
|
743
869
|
visit(fn);
|
|
744
870
|
const out = /* @__PURE__ */ new Map();
|
|
745
|
-
for (const [
|
|
871
|
+
for (const [propertyName3, variableName] of returns) {
|
|
746
872
|
const fact = bindings.get(variableName);
|
|
747
|
-
if (fact) out.set(
|
|
873
|
+
if (fact) out.set(propertyName3, fact);
|
|
748
874
|
}
|
|
749
875
|
return out;
|
|
750
876
|
}
|
|
@@ -1028,8 +1154,8 @@ async function parseServiceBindings(repoPath, filePath) {
|
|
|
1028
1154
|
if (helpers.length === 0) return;
|
|
1029
1155
|
for (const el of decl.name.elements) {
|
|
1030
1156
|
if (!ts5.isIdentifier(el.name)) continue;
|
|
1031
|
-
const
|
|
1032
|
-
const matches2 = helpers.filter((row) => row.helper.returnedProperty ===
|
|
1157
|
+
const propertyName3 = el.propertyName && ts5.isIdentifier(el.propertyName) ? el.propertyName.text : el.name.text;
|
|
1158
|
+
const matches2 = helpers.filter((row) => row.helper.returnedProperty === propertyName3);
|
|
1033
1159
|
if (matches2.length !== 1) continue;
|
|
1034
1160
|
const resolved2 = matches2[0];
|
|
1035
1161
|
out.push({
|
|
@@ -1042,7 +1168,7 @@ async function parseServiceBindings(repoPath, filePath) {
|
|
|
1042
1168
|
placeholders: resolved2.helper.placeholders,
|
|
1043
1169
|
sourceFile: normalizePath(filePath),
|
|
1044
1170
|
sourceLine: lineOf3(sourceFileAst, decl),
|
|
1045
|
-
helperChain: [...resolved2.helper.helperChain ?? [], { callerVariable: el.name.text, helperFunction: call.expression.getText(sourceFileAst), returnedProperty:
|
|
1171
|
+
helperChain: [...resolved2.helper.helperChain ?? [], { callerVariable: el.name.text, helperFunction: call.expression.getText(sourceFileAst), returnedProperty: propertyName3, importSource: resolved2.imp?.sourceFile, exportedSymbol: resolved2.imp?.exportedName, helperSourceFile: resolved2.helper.sourceFile, helperSourceLine: resolved2.helper.sourceLine }]
|
|
1046
1172
|
});
|
|
1047
1173
|
}
|
|
1048
1174
|
}
|
|
@@ -1052,17 +1178,17 @@ async function parseServiceBindings(repoPath, filePath) {
|
|
|
1052
1178
|
const helpers = await helpersForCall(call);
|
|
1053
1179
|
if (helpers.length === 0) return;
|
|
1054
1180
|
for (const prop of pattern.properties) {
|
|
1055
|
-
let
|
|
1181
|
+
let propertyName3;
|
|
1056
1182
|
let targetName;
|
|
1057
1183
|
if (ts5.isShorthandPropertyAssignment(prop)) {
|
|
1058
|
-
|
|
1184
|
+
propertyName3 = prop.name.text;
|
|
1059
1185
|
targetName = prop.name.text;
|
|
1060
1186
|
} else if (ts5.isPropertyAssignment(prop)) {
|
|
1061
|
-
|
|
1187
|
+
propertyName3 = ts5.isIdentifier(prop.name) || ts5.isStringLiteralLike(prop.name) ? prop.name.text : void 0;
|
|
1062
1188
|
targetName = ts5.isIdentifier(prop.initializer) ? prop.initializer.text : void 0;
|
|
1063
1189
|
}
|
|
1064
|
-
if (!
|
|
1065
|
-
const matches2 = helpers.filter((row) => row.helper.returnedProperty ===
|
|
1190
|
+
if (!propertyName3 || !targetName) continue;
|
|
1191
|
+
const matches2 = helpers.filter((row) => row.helper.returnedProperty === propertyName3);
|
|
1066
1192
|
if (matches2.length !== 1) continue;
|
|
1067
1193
|
const resolved2 = matches2[0];
|
|
1068
1194
|
out.push({
|
|
@@ -1075,7 +1201,7 @@ async function parseServiceBindings(repoPath, filePath) {
|
|
|
1075
1201
|
placeholders: resolved2.helper.placeholders,
|
|
1076
1202
|
sourceFile: normalizePath(filePath),
|
|
1077
1203
|
sourceLine: lineOf3(sourceFileAst, node),
|
|
1078
|
-
helperChain: [...resolved2.helper.helperChain ?? [], { callerVariable: targetName, assignedFrom: call.expression.getText(sourceFileAst), aliasKind: "assignment", scopeRule: "same-file-source-order", returnedProperty:
|
|
1204
|
+
helperChain: [...resolved2.helper.helperChain ?? [], { callerVariable: targetName, assignedFrom: call.expression.getText(sourceFileAst), aliasKind: "assignment", scopeRule: "same-file-source-order", returnedProperty: propertyName3, importSource: resolved2.imp?.sourceFile, exportedSymbol: resolved2.imp?.exportedName, helperSourceFile: resolved2.helper.sourceFile, helperSourceLine: resolved2.helper.sourceLine }]
|
|
1079
1205
|
});
|
|
1080
1206
|
}
|
|
1081
1207
|
}
|
|
@@ -1087,9 +1213,9 @@ async function parseServiceBindings(repoPath, filePath) {
|
|
|
1087
1213
|
if (target.expression.kind !== ts5.SyntaxKind.ThisKeyword) return;
|
|
1088
1214
|
for (const el of decl.name.elements) {
|
|
1089
1215
|
if (!ts5.isIdentifier(el.name)) continue;
|
|
1090
|
-
const
|
|
1216
|
+
const propertyName3 = el.propertyName && ts5.isIdentifier(el.propertyName) ? el.propertyName.text : el.name.text;
|
|
1091
1217
|
const helper = classHelpers.find(
|
|
1092
|
-
(h) => h.helperName === target.name.text && h.propertyName ===
|
|
1218
|
+
(h) => h.helperName === target.name.text && h.propertyName === propertyName3
|
|
1093
1219
|
);
|
|
1094
1220
|
if (!helper) continue;
|
|
1095
1221
|
out.push({
|
|
@@ -1242,13 +1368,13 @@ function collectClassHelpers(sf) {
|
|
|
1242
1368
|
});
|
|
1243
1369
|
}
|
|
1244
1370
|
if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.initializer)) {
|
|
1245
|
-
const
|
|
1246
|
-
const fact =
|
|
1247
|
-
if (
|
|
1371
|
+
const propertyName3 = ts5.isIdentifier(prop.name) || ts5.isStringLiteralLike(prop.name) ? prop.name.text : void 0;
|
|
1372
|
+
const fact = propertyName3 ? bindings.get(prop.initializer.text) : void 0;
|
|
1373
|
+
if (propertyName3 && fact)
|
|
1248
1374
|
helpers.push({
|
|
1249
1375
|
className,
|
|
1250
1376
|
helperName,
|
|
1251
|
-
propertyName:
|
|
1377
|
+
propertyName: propertyName3,
|
|
1252
1378
|
variableName: prop.initializer.text,
|
|
1253
1379
|
fact,
|
|
1254
1380
|
sourceLine: lineOf3(sf, prop)
|
|
@@ -1944,12 +2070,12 @@ function mappedParameterIndex(expr, parameters) {
|
|
|
1944
2070
|
}
|
|
1945
2071
|
function propertyExpression(object, key) {
|
|
1946
2072
|
for (const property of object.properties) {
|
|
1947
|
-
if (ts7.isPropertyAssignment(property) &&
|
|
2073
|
+
if (ts7.isPropertyAssignment(property) && propertyName2(property.name) === key) return property.initializer;
|
|
1948
2074
|
if (ts7.isShorthandPropertyAssignment(property) && property.name.text === key) return property.name;
|
|
1949
2075
|
}
|
|
1950
2076
|
return void 0;
|
|
1951
2077
|
}
|
|
1952
|
-
function
|
|
2078
|
+
function propertyName2(name) {
|
|
1953
2079
|
return ts7.isIdentifier(name) || ts7.isStringLiteralLike(name) ? name.text : void 0;
|
|
1954
2080
|
}
|
|
1955
2081
|
function literal(expr) {
|
|
@@ -2918,46 +3044,6 @@ function linkHelperPackages(db, workspaceId, generation) {
|
|
|
2918
3044
|
return summary;
|
|
2919
3045
|
}
|
|
2920
3046
|
|
|
2921
|
-
// src/linker/operation-decorator-normalizer.ts
|
|
2922
|
-
function lowerFirst(value) {
|
|
2923
|
-
return value ? `${value[0]?.toLowerCase() ?? ""}${value.slice(1)}` : value;
|
|
2924
|
-
}
|
|
2925
|
-
function normalizedOperationName(value) {
|
|
2926
|
-
return value.replace(/^\//, "");
|
|
2927
|
-
}
|
|
2928
|
-
function clean(value) {
|
|
2929
|
-
return value.replace(/^[`'"]|[`'"]$/g, "");
|
|
2930
|
-
}
|
|
2931
|
-
function generatedFromConstantName(value) {
|
|
2932
|
-
for (const prefix of ["Action", "Func"]) {
|
|
2933
|
-
if (value.startsWith(prefix) && value.length > prefix.length && /^[A-Z]/.test(value.slice(prefix.length))) return lowerFirst(value.slice(prefix.length));
|
|
2934
|
-
}
|
|
2935
|
-
return void 0;
|
|
2936
|
-
}
|
|
2937
|
-
function resolved(value, raw) {
|
|
2938
|
-
const literal2 = clean(value);
|
|
2939
|
-
const generated = generatedFromConstantName(literal2);
|
|
2940
|
-
return { status: "resolved", operationName: generated ?? normalizedOperationName(literal2), raw };
|
|
2941
|
-
}
|
|
2942
|
-
function normalizeDecoratorOperationSignal(value, raw, candidateOperation) {
|
|
2943
|
-
if (value) return resolved(value, raw);
|
|
2944
|
-
if (!raw || raw.trim().length === 0) return { status: "none", raw };
|
|
2945
|
-
const expression = raw.trim();
|
|
2946
|
-
const nameMatch = /(?:^|\.)(Action[A-Z][\w$]*|Func[A-Z][\w$]*)\.name$/.exec(expression);
|
|
2947
|
-
if (nameMatch?.[1]) return resolved(nameMatch[1], expression);
|
|
2948
|
-
const stringMatch = /^String\(([A-Za-z_$][\w$]*)\)$/.exec(expression);
|
|
2949
|
-
if (stringMatch?.[1]) {
|
|
2950
|
-
const identifier = stringMatch[1];
|
|
2951
|
-
const generated = generatedFromConstantName(identifier);
|
|
2952
|
-
const normalizedCandidate2 = candidateOperation ? normalizedOperationName(candidateOperation) : void 0;
|
|
2953
|
-
if (generated) return { status: "resolved", operationName: generated, raw: expression };
|
|
2954
|
-
if (normalizedCandidate2 && identifier === normalizedCandidate2) return { status: "resolved", operationName: identifier, raw: expression };
|
|
2955
|
-
return { status: "unsupported", raw: expression, reason: "string_wrapper_identifier_not_resolved" };
|
|
2956
|
-
}
|
|
2957
|
-
if (/^[`'"]/.test(expression) && !/[`'"]$/.test(expression)) return { status: "malformed", raw: expression, reason: "unterminated_literal" };
|
|
2958
|
-
return { status: "unsupported", raw: expression, reason: "unsupported_decorator_expression" };
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
3047
|
// src/linker/cross-repo-linker.ts
|
|
2962
3048
|
function linkWorkspace(db, workspaceId, vars = {}) {
|
|
2963
3049
|
return db.transaction(() => {
|
|
@@ -3140,7 +3226,7 @@ function objectJson(value) {
|
|
|
3140
3226
|
}
|
|
3141
3227
|
function callEvidence(call, resolution, servicePath, op, destination, normalized, odataPathIntent) {
|
|
3142
3228
|
const bindingHasDynamicExpression = Boolean(Number(call.isDynamic ?? 0));
|
|
3143
|
-
const routingPlaceholderKeys = placeholderKeys([servicePath, destination,
|
|
3229
|
+
const routingPlaceholderKeys = placeholderKeys([servicePath, destination, stringValue3(call.aliasExpr), stringValue3(call.alias)]);
|
|
3144
3230
|
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, invocationArguments: normalized?.wasInvocation ? normalized.invocationArguments : void 0, invocationArgumentPlaceholderKeys: normalized?.invocationArgumentPlaceholderKeys.length ? normalized.invocationArgumentPlaceholderKeys : void 0, routingPlaceholderKeys: routingPlaceholderKeys.length ? routingPlaceholderKeys : void 0, odataOperationNormalizationReason: normalized?.normalizationReason, odataOperationNormalizationRejectedReason: normalized?.normalizationRejectedReason, 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, candidateScores: compactCandidateScores(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 };
|
|
3145
3231
|
}
|
|
3146
3232
|
function compactCandidateScores(candidates) {
|
|
@@ -3157,7 +3243,7 @@ function placeholderKeys(values) {
|
|
|
3157
3243
|
function objectValue(value) {
|
|
3158
3244
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3159
3245
|
}
|
|
3160
|
-
function
|
|
3246
|
+
function stringValue3(value) {
|
|
3161
3247
|
return typeof value === "string" ? value : void 0;
|
|
3162
3248
|
}
|
|
3163
3249
|
function linkImplementations(db, workspaceId, generation) {
|
|
@@ -3212,13 +3298,54 @@ function implementationContextForOperation(db, operation) {
|
|
|
3212
3298
|
}
|
|
3213
3299
|
function rankedImplementationCandidates(db, workspaceId, operation) {
|
|
3214
3300
|
const rows2 = implementationCandidates(db, workspaceId, operation);
|
|
3215
|
-
|
|
3301
|
+
const invalid = rows2.filter((row) => !validRegistrationPair(row));
|
|
3302
|
+
recordRegistrationInvariantDiagnostics(db, invalid);
|
|
3303
|
+
return deduplicateCandidates(
|
|
3304
|
+
rows2.filter(validRegistrationPair).map((row) => scoreImplementationCandidate(row, operation))
|
|
3305
|
+
).sort((a, b) => b.score - a.score || String(a.className).localeCompare(String(b.className)) || a.methodId - b.methodId);
|
|
3306
|
+
}
|
|
3307
|
+
function validRegistrationPair(row) {
|
|
3308
|
+
if (row.registrationHandlerClassId === null || row.registrationHandlerClassId === void 0)
|
|
3309
|
+
return registrationPairingStrategy(row) !== "unproven";
|
|
3310
|
+
return Number(row.registrationHandlerClassId) === Number(row.classId);
|
|
3311
|
+
}
|
|
3312
|
+
function registrationPairingStrategy(row) {
|
|
3313
|
+
if (row.registrationHandlerClassId !== null && row.registrationHandlerClassId !== void 0)
|
|
3314
|
+
return "exact_handler_class_id";
|
|
3315
|
+
if (Number(row.applicationRepoId) === Number(row.handlerRepoId))
|
|
3316
|
+
return "same_repository_class_name_fallback";
|
|
3317
|
+
const source = stringValue3(row.importSource);
|
|
3318
|
+
const separator = source?.lastIndexOf("#") ?? -1;
|
|
3319
|
+
if (!source || separator <= 0) return "unproven";
|
|
3320
|
+
const moduleName = source.slice(0, separator);
|
|
3321
|
+
const importedName = source.slice(separator + 1);
|
|
3322
|
+
const matchesClass = importedName === row.className || importedName === "default" && row.registrationClassName === row.className;
|
|
3323
|
+
return moduleName === row.handlerPackage && matchesClass ? "explicit_package_import" : "unproven";
|
|
3324
|
+
}
|
|
3325
|
+
function recordRegistrationInvariantDiagnostics(db, rows2) {
|
|
3326
|
+
const insert = db.prepare(`INSERT INTO diagnostics(repo_id,severity,code,message,source_file,source_line)
|
|
3327
|
+
SELECT ?,'error','handler_registration_class_mismatch',
|
|
3328
|
+
'Implementation candidate registration did not match its persisted handler class id',?,?
|
|
3329
|
+
WHERE NOT EXISTS (
|
|
3330
|
+
SELECT 1 FROM diagnostics
|
|
3331
|
+
WHERE repo_id=? AND code='handler_registration_class_mismatch'
|
|
3332
|
+
AND source_file=? AND source_line=?
|
|
3333
|
+
)`);
|
|
3334
|
+
for (const row of rows2)
|
|
3335
|
+
insert.run(
|
|
3336
|
+
row.applicationRepoId,
|
|
3337
|
+
row.registrationFile,
|
|
3338
|
+
row.registrationLine,
|
|
3339
|
+
row.applicationRepoId,
|
|
3340
|
+
row.registrationFile,
|
|
3341
|
+
row.registrationLine
|
|
3342
|
+
);
|
|
3216
3343
|
}
|
|
3217
3344
|
function deduplicateCandidates(rows2) {
|
|
3218
3345
|
const merged = /* @__PURE__ */ new Map();
|
|
3219
3346
|
for (const row of rows2) {
|
|
3220
3347
|
const key = [row.methodId, row.classId, row.handlerRepoId].join(":");
|
|
3221
|
-
const registration =
|
|
3348
|
+
const registration = registrationEvidence(row);
|
|
3222
3349
|
const existing = merged.get(key);
|
|
3223
3350
|
if (!existing) {
|
|
3224
3351
|
merged.set(key, { ...row, registrations: [registration] });
|
|
@@ -3232,6 +3359,17 @@ function deduplicateCandidates(rows2) {
|
|
|
3232
3359
|
}
|
|
3233
3360
|
return [...merged.values()];
|
|
3234
3361
|
}
|
|
3362
|
+
function registrationEvidence(row) {
|
|
3363
|
+
return {
|
|
3364
|
+
id: row.registrationId,
|
|
3365
|
+
handlerClassId: row.registrationHandlerClassId,
|
|
3366
|
+
file: row.registrationFile,
|
|
3367
|
+
line: row.registrationLine,
|
|
3368
|
+
kind: row.registrationKind,
|
|
3369
|
+
importSource: row.importSource,
|
|
3370
|
+
pairingStrategy: registrationPairingStrategy(row)
|
|
3371
|
+
};
|
|
3372
|
+
}
|
|
3235
3373
|
function uniqueRegistrations(rows2) {
|
|
3236
3374
|
const seen = /* @__PURE__ */ new Set();
|
|
3237
3375
|
return rows2.filter((row) => {
|
|
@@ -3260,10 +3398,14 @@ function implementationCandidates(db, workspaceId, operation) {
|
|
|
3260
3398
|
hm.method_name methodName,
|
|
3261
3399
|
hm.decorator_value decoratorValue,
|
|
3262
3400
|
hm.decorator_raw_expression decoratorRawExpression,
|
|
3401
|
+
hm.decorator_resolution_json decoratorResolutionJson,
|
|
3263
3402
|
hc.id classId,
|
|
3264
3403
|
hc.class_name className,
|
|
3265
3404
|
hc.source_file sourceFile,
|
|
3266
3405
|
hc.source_line sourceLine,
|
|
3406
|
+
hr.id registrationId,
|
|
3407
|
+
hr.handler_class_id registrationHandlerClassId,
|
|
3408
|
+
hr.class_name registrationClassName,
|
|
3267
3409
|
hr.repo_id applicationRepoId,
|
|
3268
3410
|
hr.registration_file registrationFile,
|
|
3269
3411
|
hr.registration_line registrationLine,
|
|
@@ -3286,14 +3428,36 @@ function implementationCandidates(db, workspaceId, operation) {
|
|
|
3286
3428
|
CASE WHEN appRepo.id=handlerRepo.id THEN 1 ELSE 0 END sameRepoRegistration,
|
|
3287
3429
|
CASE WHEN EXISTS (SELECT 1 FROM cds_services localService WHERE localService.repo_id=appRepo.id AND localService.service_path=?) THEN 1 ELSE 0 END localServicePathMatch,
|
|
3288
3430
|
CASE WHEN EXISTS (SELECT 1 FROM cds_services localService WHERE localService.repo_id=appRepo.id) THEN 1 ELSE 0 END applicationHasLocalServices,
|
|
3289
|
-
CASE WHEN EXISTS (SELECT 1 FROM handler_registrations localReg JOIN handler_classes localClass ON (localClass.id=localReg.handler_class_id OR localClass.class_name=localReg.class_name) JOIN handler_methods localMethod ON localMethod.handler_class_id=localClass.id WHERE localReg.repo_id=appRepo.id AND (localMethod.decorator_value=? OR localMethod.decorator_value=? OR localMethod.method_name=? OR localMethod.decorator_raw_expression LIKE ?)) THEN 1 ELSE 0 END applicationHasLocalRegistrationForOperation,
|
|
3431
|
+
CASE WHEN EXISTS (SELECT 1 FROM handler_registrations localReg JOIN handler_classes localClass ON ((localReg.handler_class_id IS NOT NULL AND localClass.id=localReg.handler_class_id) OR (localReg.handler_class_id IS NULL AND localClass.class_name=localReg.class_name AND localClass.repo_id=localReg.repo_id)) JOIN handler_methods localMethod ON localMethod.handler_class_id=localClass.id WHERE localReg.repo_id=appRepo.id AND (localMethod.decorator_value=? OR localMethod.decorator_value=? OR localMethod.method_name=? OR localMethod.decorator_raw_expression LIKE ?)) THEN 1 ELSE 0 END applicationHasLocalRegistrationForOperation,
|
|
3290
3432
|
CASE WHEN EXISTS (SELECT 1 FROM graph_edges dep WHERE dep.edge_type='REPO_IMPORTS_HELPER_PACKAGE' AND dep.status='resolved' AND dep.from_kind='repo' AND dep.from_id=CAST(appRepo.id AS TEXT) AND dep.to_id=?) THEN 1 ELSE 0 END appDependsOnModel,
|
|
3291
3433
|
CASE WHEN EXISTS (SELECT 1 FROM graph_edges dep WHERE dep.edge_type='REPO_IMPORTS_HELPER_PACKAGE' AND dep.status='resolved' AND dep.from_kind='repo' AND dep.from_id=CAST(appRepo.id AS TEXT) AND dep.to_id=CAST(handlerRepo.id AS TEXT)) THEN 1 ELSE 0 END appDependsOnHandler,
|
|
3292
3434
|
CASE WHEN EXISTS (SELECT 1 FROM graph_edges dep WHERE dep.edge_type='REPO_IMPORTS_HELPER_PACKAGE' AND dep.status='resolved' AND dep.from_kind='repo' AND dep.from_id=CAST(handlerRepo.id AS TEXT) AND dep.to_id=?) THEN 1 ELSE 0 END handlerDependsOnModel
|
|
3293
3435
|
FROM handler_methods hm
|
|
3294
3436
|
JOIN handler_classes hc ON hc.id=hm.handler_class_id
|
|
3295
3437
|
JOIN repositories handlerRepo ON handlerRepo.id=hc.repo_id
|
|
3296
|
-
JOIN handler_registrations hr ON (
|
|
3438
|
+
JOIN handler_registrations hr ON (
|
|
3439
|
+
(hr.handler_class_id IS NOT NULL AND hr.handler_class_id=hc.id)
|
|
3440
|
+
OR (
|
|
3441
|
+
hr.handler_class_id IS NULL
|
|
3442
|
+
AND (
|
|
3443
|
+
(hr.class_name=hc.class_name AND hr.repo_id=hc.repo_id)
|
|
3444
|
+
OR (
|
|
3445
|
+
instr(hr.import_source,'#')>1
|
|
3446
|
+
AND substr(hr.import_source,1,instr(hr.import_source,'#')-1)
|
|
3447
|
+
=handlerRepo.package_name
|
|
3448
|
+
AND (
|
|
3449
|
+
substr(hr.import_source,instr(hr.import_source,'#')+1)
|
|
3450
|
+
=hc.class_name
|
|
3451
|
+
OR (
|
|
3452
|
+
substr(hr.import_source,instr(hr.import_source,'#')+1)
|
|
3453
|
+
='default'
|
|
3454
|
+
AND hr.class_name=hc.class_name
|
|
3455
|
+
)
|
|
3456
|
+
)
|
|
3457
|
+
)
|
|
3458
|
+
)
|
|
3459
|
+
)
|
|
3460
|
+
)
|
|
3297
3461
|
JOIN repositories appRepo ON appRepo.id=hr.repo_id
|
|
3298
3462
|
WHERE appRepo.workspace_id=?
|
|
3299
3463
|
AND (hm.decorator_value=? OR hm.decorator_value=? OR hm.method_name=? OR hm.decorator_raw_expression LIKE ?)`).all(
|
|
@@ -3395,8 +3559,16 @@ function candidateEvidence(candidate, rank) {
|
|
|
3395
3559
|
className: candidate.className,
|
|
3396
3560
|
sourceFile: candidate.sourceFile,
|
|
3397
3561
|
sourceLine: candidate.sourceLine,
|
|
3398
|
-
|
|
3562
|
+
decoratorResolution: objectJson(candidate.decoratorResolutionJson),
|
|
3563
|
+
registration: registrationEvidence(candidate),
|
|
3399
3564
|
registrations: candidate.registrations ?? [],
|
|
3565
|
+
registrationPairing: {
|
|
3566
|
+
strategy: registrationPairingStrategy(candidate),
|
|
3567
|
+
registrationId: candidate.registrationId,
|
|
3568
|
+
registrationHandlerClassId: candidate.registrationHandlerClassId,
|
|
3569
|
+
candidateHandlerClassId: candidate.classId,
|
|
3570
|
+
invariantStatus: validRegistrationPair(candidate) ? "valid" : "invalid"
|
|
3571
|
+
},
|
|
3400
3572
|
applicationPackage: { id: candidate.applicationRepoId, name: candidate.applicationRepo, packageName: candidate.applicationPackage },
|
|
3401
3573
|
handlerPackage: { id: candidate.handlerRepoId, name: candidate.handlerRepo, packageName: candidate.handlerPackage },
|
|
3402
3574
|
modelPackage: { id: candidate.modelRepoId, name: candidate.modelRepo, packageName: candidate.modelPackage },
|
|
@@ -3436,6 +3608,40 @@ function normalizedOperation(value) {
|
|
|
3436
3608
|
return value.startsWith("/") ? value.slice(1) : value;
|
|
3437
3609
|
}
|
|
3438
3610
|
|
|
3611
|
+
// src/trace/selectors.ts
|
|
3612
|
+
function parseVars(values) {
|
|
3613
|
+
const out = {};
|
|
3614
|
+
for (const value of values ?? []) {
|
|
3615
|
+
const [key, ...rest] = value.split("=");
|
|
3616
|
+
if (key && rest.length > 0) out[key] = rest.join("=");
|
|
3617
|
+
}
|
|
3618
|
+
return out;
|
|
3619
|
+
}
|
|
3620
|
+
function ambiguousStartDiagnostic(requested, candidates, message) {
|
|
3621
|
+
const serviceSuggestions = [...new Set(candidates.flatMap((row) => typeof row.servicePath === "string" ? [`--service ${row.servicePath}`] : []))].sort();
|
|
3622
|
+
return {
|
|
3623
|
+
severity: "warning",
|
|
3624
|
+
code: "trace_start_ambiguous",
|
|
3625
|
+
message,
|
|
3626
|
+
normalizedSelectorValue: requested,
|
|
3627
|
+
resolutionStage: "operation",
|
|
3628
|
+
resolutionStatus: "ambiguous_operation",
|
|
3629
|
+
candidates,
|
|
3630
|
+
serviceSuggestions,
|
|
3631
|
+
selectorSuggestions: fullSelectorSuggestions(candidates)
|
|
3632
|
+
};
|
|
3633
|
+
}
|
|
3634
|
+
function fullSelectorSuggestions(candidates) {
|
|
3635
|
+
const includeRepo = new Set(candidates.map((row) => row.repoName)).size > 1;
|
|
3636
|
+
return [...new Set(candidates.flatMap((row) => {
|
|
3637
|
+
if (typeof row.servicePath !== "string" || typeof row.operationPath !== "string") return [];
|
|
3638
|
+
const repoSelector = includeRepo && typeof row.repoName === "string" ? `--repo ${row.repoName} ` : "";
|
|
3639
|
+
return [
|
|
3640
|
+
`${repoSelector}--service ${row.servicePath} --path ${row.operationPath}`
|
|
3641
|
+
];
|
|
3642
|
+
}))].sort();
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3439
3645
|
// src/trace/evidence.ts
|
|
3440
3646
|
function baseTraceEvidence(row, call, persistedEvidence, contextualEvidence) {
|
|
3441
3647
|
const evidence = { ...persistedEvidence, ...contextualEvidence ?? {} };
|
|
@@ -3492,20 +3698,20 @@ function runtimeVariableDiagnostic(edges) {
|
|
|
3492
3698
|
}
|
|
3493
3699
|
function edgeTarget(row, evidence) {
|
|
3494
3700
|
const effective = parseObject(evidence.effectiveResolution);
|
|
3495
|
-
const targetServicePath =
|
|
3496
|
-
const targetOperationPath =
|
|
3701
|
+
const targetServicePath = stringValue4(effective.targetServicePath ?? evidence.targetServicePath);
|
|
3702
|
+
const targetOperationPath = stringValue4(effective.targetOperationPath ?? evidence.targetOperationPath);
|
|
3497
3703
|
if (targetServicePath && targetOperationPath) return `${targetServicePath}${targetOperationPath}`;
|
|
3498
3704
|
const runtimeCandidate = evidence.runtimeResolvedCandidate;
|
|
3499
3705
|
if (runtimeCandidate?.servicePath && runtimeCandidate.operationPath) return `${runtimeCandidate.servicePath}${runtimeCandidate.operationPath}`;
|
|
3500
|
-
const servicePath =
|
|
3501
|
-
const operationPath =
|
|
3502
|
-
const targetOperation =
|
|
3503
|
-
const targetRepo =
|
|
3706
|
+
const servicePath = stringValue4(evidence.servicePath);
|
|
3707
|
+
const operationPath = stringValue4(evidence.operationPath);
|
|
3708
|
+
const targetOperation = stringValue4(evidence.targetOperation);
|
|
3709
|
+
const targetRepo = stringValue4(evidence.targetRepo) ?? "";
|
|
3504
3710
|
if (row.edge_type === "HANDLER_RUNS_DB_QUERY") return `Entity: ${row.to_id || "unknown"}`;
|
|
3505
|
-
if (row.edge_type === "HANDLER_RUNS_REMOTE_QUERY") return
|
|
3711
|
+
if (row.edge_type === "HANDLER_RUNS_REMOTE_QUERY") return stringValue4(evidence.remoteQueryTarget) ?? `Remote query: ${row.to_id || "unknown"}`;
|
|
3506
3712
|
if (row.edge_type === "HANDLER_CALLS_EXTERNAL_HTTP") {
|
|
3507
3713
|
const target = parseObject(evidence.externalTarget);
|
|
3508
|
-
return
|
|
3714
|
+
return stringValue4(target.label) ?? `External endpoint: ${row.to_id || "unknown"}`;
|
|
3509
3715
|
}
|
|
3510
3716
|
if (servicePath && operationPath) return `${servicePath}${operationPath}`;
|
|
3511
3717
|
return targetOperation ? `${targetRepo}:${targetOperation}` : row.to_id;
|
|
@@ -3544,12 +3750,12 @@ function withEffectiveResolution(evidence, row, unresolvedReason, resolution) {
|
|
|
3544
3750
|
return { ...rest, effectiveResolution: current, linker: { status: current.status, confidence: current.confidence, reason: unresolvedReason, edgeType: current.edgeType } };
|
|
3545
3751
|
}
|
|
3546
3752
|
function resolveRuntimeOperation(db, evidence, workspaceId) {
|
|
3547
|
-
const servicePath =
|
|
3548
|
-
const rawOperationPath =
|
|
3753
|
+
const servicePath = stringValue4(evidence.servicePath);
|
|
3754
|
+
const rawOperationPath = stringValue4(evidence.operationPath);
|
|
3549
3755
|
const normalized = normalizeODataOperationInvocationPath(rawOperationPath);
|
|
3550
|
-
const operationPath = normalized?.wasInvocation ? normalized.normalizedOperationPath :
|
|
3551
|
-
const alias =
|
|
3552
|
-
const destination =
|
|
3756
|
+
const operationPath = normalized?.wasInvocation ? normalized.normalizedOperationPath : stringValue4(evidence.normalizedOperationPath) ?? rawOperationPath;
|
|
3757
|
+
const alias = stringValue4(evidence.serviceAliasExpr ?? evidence.serviceAlias);
|
|
3758
|
+
const destination = stringValue4(evidence.destination);
|
|
3553
3759
|
return resolveOperation(db, { servicePath, operationPath, alias, destination, hasExplicitOverride: true, isDynamic: true }, workspaceId);
|
|
3554
3760
|
}
|
|
3555
3761
|
function evidenceWithRuntimeVariables(evidence, vars) {
|
|
@@ -3570,7 +3776,7 @@ function runtimeSubstitutions(evidence, vars) {
|
|
|
3570
3776
|
return substitutions;
|
|
3571
3777
|
}
|
|
3572
3778
|
function substitutionValue(evidence, key) {
|
|
3573
|
-
const value =
|
|
3779
|
+
const value = stringValue4(evidence[key]);
|
|
3574
3780
|
if (key !== "operationPath") return value;
|
|
3575
3781
|
const normalized = normalizeODataOperationInvocationPath(value);
|
|
3576
3782
|
return normalized?.wasInvocation ? normalized.normalizedOperationPath : value;
|
|
@@ -3592,7 +3798,7 @@ function runtimeUnresolvedReason(resolution) {
|
|
|
3592
3798
|
function parseObject(value) {
|
|
3593
3799
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3594
3800
|
}
|
|
3595
|
-
function
|
|
3801
|
+
function stringValue4(value) {
|
|
3596
3802
|
return typeof value === "string" ? value : void 0;
|
|
3597
3803
|
}
|
|
3598
3804
|
|
|
@@ -3641,19 +3847,6 @@ function implementationRejectionReasons(evidence) {
|
|
|
3641
3847
|
const reasons = candidates.flatMap((candidate) => Array.isArray(candidate.rejectedReasons) ? candidate.rejectedReasons.filter((reason) => typeof reason === "string") : []);
|
|
3642
3848
|
return [...new Set(reasons)].sort();
|
|
3643
3849
|
}
|
|
3644
|
-
function ambiguousStartDiagnostic(requested, candidates, message) {
|
|
3645
|
-
const serviceSuggestions = [...new Set(candidates.flatMap((row) => typeof row.servicePath === "string" ? [`--service ${row.servicePath}`] : []))].sort();
|
|
3646
|
-
return {
|
|
3647
|
-
severity: "warning",
|
|
3648
|
-
code: "trace_start_ambiguous",
|
|
3649
|
-
message,
|
|
3650
|
-
normalizedSelectorValue: requested,
|
|
3651
|
-
resolutionStage: "operation",
|
|
3652
|
-
resolutionStatus: "ambiguous_operation",
|
|
3653
|
-
candidates,
|
|
3654
|
-
serviceSuggestions
|
|
3655
|
-
};
|
|
3656
|
-
}
|
|
3657
3850
|
function sourceFilesForStart(db, repoId, start) {
|
|
3658
3851
|
const handler = start.handler;
|
|
3659
3852
|
const operation = normalizeOperation(start.operation ?? start.operationPath);
|
|
@@ -4175,6 +4368,7 @@ export {
|
|
|
4175
4368
|
parseImplementationHint,
|
|
4176
4369
|
implementationHintSuggestions,
|
|
4177
4370
|
linkWorkspace,
|
|
4371
|
+
parseVars,
|
|
4178
4372
|
trace
|
|
4179
4373
|
};
|
|
4180
|
-
//# sourceMappingURL=chunk-
|
|
4374
|
+
//# sourceMappingURL=chunk-52OUS3MO.js.map
|