@saptools/service-flow 0.1.58 → 0.1.60

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.
@@ -2358,7 +2358,7 @@ function collectClassHelpers(sf) {
2358
2358
  // src/parsers/outbound-call-parser.ts
2359
2359
  import fs8 from "fs/promises";
2360
2360
  import path11 from "path";
2361
- import ts9 from "typescript";
2361
+ import ts10 from "typescript";
2362
2362
 
2363
2363
  // src/linker/external-http-target.ts
2364
2364
  import { createHash } from "crypto";
@@ -3080,6 +3080,8 @@ var capQueryBuilderRoots = /* @__PURE__ */ new Set([
3080
3080
  "SELECT.from",
3081
3081
  "SELECT.one.from",
3082
3082
  "SELECT.one",
3083
+ "SELECT.distinct.from",
3084
+ "SELECT.distinct.one.from",
3083
3085
  "INSERT.into",
3084
3086
  "UPSERT.into",
3085
3087
  "UPDATE.entity",
@@ -3280,20 +3282,15 @@ function nodeIsPromise(name) {
3280
3282
  return Boolean(name && ts8.isIdentifier(name) && name.text === "Promise");
3281
3283
  }
3282
3284
 
3283
- // src/parsers/outbound-call-parser.ts
3284
- function lineOf4(text, idx) {
3285
- return text.slice(0, idx).split("\n").length;
3286
- }
3287
- function entityFromExpression(expr) {
3288
- if (!expr) return void 0;
3289
- if (ts9.isIdentifier(expr) || ts9.isStringLiteral(expr) || ts9.isNoSubstitutionTemplateLiteral(expr)) return expr.text;
3290
- if (ts9.isPropertyAccessExpression(expr) && expr.expression.kind === ts9.SyntaxKind.ThisKeyword) return expr.name.text;
3291
- if (ts9.isElementAccessExpression(expr) && expr.argumentExpression && (ts9.isStringLiteral(expr.argumentExpression) || ts9.isNoSubstitutionTemplateLiteral(expr.argumentExpression))) return expr.argumentExpression.text;
3292
- return void 0;
3293
- }
3285
+ // src/parsers/001-query-entity-resolution.ts
3286
+ import ts9 from "typescript";
3287
+ var maxAliasDepth2 = 5;
3288
+ var cdsModelSpecifier = /^#cds-models(?:\/|$)/;
3289
+ var modelNamespaceCache = /* @__PURE__ */ new WeakMap();
3294
3290
  function expressionName2(expr) {
3295
3291
  if (ts9.isIdentifier(expr)) return expr.text;
3296
- if (ts9.isPropertyAccessExpression(expr)) return `${expressionName2(expr.expression)}.${expr.name.text}`;
3292
+ if (ts9.isPropertyAccessExpression(expr))
3293
+ return `${expressionName2(expr.expression)}.${expr.name.text}`;
3297
3294
  return expr.getText();
3298
3295
  }
3299
3296
  function variableInitializers(source) {
@@ -3301,7 +3298,8 @@ function variableInitializers(source) {
3301
3298
  for (const statement of source.statements) {
3302
3299
  if (!ts9.isVariableStatement(statement) || (statement.declarationList.flags & ts9.NodeFlags.Const) === 0) continue;
3303
3300
  for (const declaration of statement.declarationList.declarations) {
3304
- if (ts9.isIdentifier(declaration.name) && declaration.initializer) initializers.set(declaration.name.text, declaration.initializer);
3301
+ if (ts9.isIdentifier(declaration.name) && declaration.initializer)
3302
+ initializers.set(declaration.name.text, declaration.initializer);
3305
3303
  }
3306
3304
  }
3307
3305
  return initializers;
@@ -3311,18 +3309,349 @@ function unwrapQueryExpression2(expr) {
3311
3309
  return unwrapQueryExpression2(expr.expression);
3312
3310
  return expr;
3313
3311
  }
3314
- function queryEntityFromAst(expr, initializers = /* @__PURE__ */ new Map()) {
3315
- const unwrapped = unwrapQueryExpression2(expr);
3316
- if (ts9.isIdentifier(unwrapped) && initializers.has(unwrapped.text)) return queryEntityFromAst(initializers.get(unwrapped.text), initializers);
3317
- if (ts9.isCallExpression(unwrapped)) {
3318
- const name = expressionName2(unwrapped.expression);
3319
- if (name === "cds.run") return queryEntityFromAst(unwrapped.arguments[0], initializers);
3320
- if (isCapQueryBuilderRootName(name)) return entityFromExpression(unwrapped.arguments[0]);
3321
- const receiver = ts9.isPropertyAccessExpression(unwrapped.expression) ? unwrapped.expression.expression : void 0;
3322
- if (receiver) return queryEntityFromAst(receiver, initializers);
3312
+ function isFunctionLikeScope(node) {
3313
+ return ts9.isFunctionLike(node) || ts9.isSourceFile(node);
3314
+ }
3315
+ function nodeContains(parent, child) {
3316
+ const source = child.getSourceFile();
3317
+ return child.getStart(source) >= parent.getStart(source) && child.getEnd() <= parent.getEnd();
3318
+ }
3319
+ function isLoopInitializerScope(declaration, scope) {
3320
+ const list = declaration.parent;
3321
+ return ts9.isForStatement(scope) && scope.initializer === list || (ts9.isForInStatement(scope) || ts9.isForOfStatement(scope)) && scope.initializer === list;
3322
+ }
3323
+ function isLexicalScopeBoundary(node, declaration) {
3324
+ return ts9.isBlock(node) || ts9.isSourceFile(node) || ts9.isModuleBlock(node) || ts9.isCaseBlock(node) || isLoopInitializerScope(declaration, node) || isFunctionLikeScope(node);
3325
+ }
3326
+ function declarationScope2(node) {
3327
+ if (ts9.isParameter(node)) return node.parent;
3328
+ if (ts9.isCatchClause(node.parent) && node.parent.variableDeclaration === node)
3329
+ return node.parent;
3330
+ const list = node.parent;
3331
+ const blockScoped = (list.flags & (ts9.NodeFlags.Const | ts9.NodeFlags.Let)) !== 0;
3332
+ let current = list.parent;
3333
+ if (!blockScoped) {
3334
+ while (current.parent && !isFunctionLikeScope(current)) current = current.parent;
3335
+ return current;
3336
+ }
3337
+ while (current.parent && !isLexicalScopeBoundary(current, node))
3338
+ current = current.parent;
3339
+ return current;
3340
+ }
3341
+ function catchBindingScope(declaration) {
3342
+ if (ts9.isParameter(declaration)) return void 0;
3343
+ return ts9.isCatchClause(declaration.parent) && declaration.parent.variableDeclaration === declaration ? declaration.parent : void 0;
3344
+ }
3345
+ function declarationIsInScope(declaration, use) {
3346
+ const catchScope = catchBindingScope(declaration);
3347
+ if (catchScope) return nodeContains(catchScope.block, use);
3348
+ const scope = declarationScope2(declaration);
3349
+ if (ts9.isForStatement(scope) || ts9.isForInStatement(scope) || ts9.isForOfStatement(scope)) return nodeContains(scope.statement, use);
3350
+ return ts9.isSourceFile(scope) || nodeContains(scope, use);
3351
+ }
3352
+ function isAccessibleDeclaration(declaration, use) {
3353
+ return declaration.name.getStart(use.getSourceFile()) < use.getStart() && declarationIsInScope(declaration, use);
3354
+ }
3355
+ function resolveBinding2(identifier, use) {
3356
+ const source = use.getSourceFile();
3357
+ let best;
3358
+ const visit = (node) => {
3359
+ if (ts9.isVariableDeclaration(node) && ts9.isIdentifier(node.name) && node.name.text === identifier.text && isAccessibleDeclaration(node, use))
3360
+ best = node;
3361
+ if (ts9.isParameter(node) && ts9.isIdentifier(node.name) && node.name.text === identifier.text && isAccessibleDeclaration(node, use))
3362
+ best = node;
3363
+ ts9.forEachChild(node, visit);
3364
+ };
3365
+ visit(source);
3366
+ if (!best) return { immutable: false, evidence: ["binding_not_found"] };
3367
+ const immutable = ts9.isVariableDeclaration(best) && (best.parent.flags & ts9.NodeFlags.Const) !== 0;
3368
+ return {
3369
+ declaration: best,
3370
+ initializer: ts9.isVariableDeclaration(best) ? best.initializer : void 0,
3371
+ immutable,
3372
+ evidence: [immutable ? "lexical_const_binding_before_use" : "lexical_mutable_or_parameter_binding"]
3373
+ };
3374
+ }
3375
+ function directBindingElement(name, identifier) {
3376
+ if (ts9.isIdentifier(name)) return void 0;
3377
+ for (const element of name.elements) {
3378
+ if (ts9.isOmittedExpression(element) || element.dotDotDotToken || element.initializer || !ts9.isIdentifier(element.name)) continue;
3379
+ if (element.name.text === identifier.text) return element;
3323
3380
  }
3324
3381
  return void 0;
3325
3382
  }
3383
+ function bindingNameContains(name, target) {
3384
+ if (ts9.isIdentifier(name)) return name.text === target;
3385
+ return name.elements.some((element) => ts9.isBindingElement(element) && bindingNameContains(element.name, target));
3386
+ }
3387
+ function bindingScope(node) {
3388
+ if (ts9.isVariableDeclaration(node) || ts9.isParameter(node))
3389
+ return declarationScope2(node);
3390
+ if (ts9.isFunctionExpression(node) || ts9.isClassExpression(node)) return node;
3391
+ return node.parent;
3392
+ }
3393
+ function bindingIsCloser(candidate, current, use) {
3394
+ const source = use.getSourceFile();
3395
+ const candidateScope = bindingScope(candidate);
3396
+ const currentScope = bindingScope(current);
3397
+ const candidateSpan = candidateScope.getEnd() - candidateScope.getStart(source);
3398
+ const currentSpan = currentScope.getEnd() - currentScope.getStart(source);
3399
+ return candidateSpan < currentSpan || candidateSpan === currentSpan && candidate.getStart(source) > current.getStart(source);
3400
+ }
3401
+ function nearestScopedVariableDeclaration(identifier) {
3402
+ let best;
3403
+ const visit = (node) => {
3404
+ if ((ts9.isVariableDeclaration(node) || ts9.isParameter(node)) && bindingNameContains(node.name, identifier.text) && declarationIsInScope(node, identifier) && (!best || bindingIsCloser(node, best, identifier))) best = node;
3405
+ ts9.forEachChild(node, visit);
3406
+ };
3407
+ visit(identifier.getSourceFile());
3408
+ return best;
3409
+ }
3410
+ function hasScopedVariableDeclaration(identifier) {
3411
+ return Boolean(nearestScopedVariableDeclaration(identifier));
3412
+ }
3413
+ function namedValueDeclarationMatches(node, name) {
3414
+ if (ts9.isFunctionDeclaration(node) || ts9.isClassDeclaration(node) || ts9.isEnumDeclaration(node)) return node.name?.text === name;
3415
+ return ts9.isModuleDeclaration(node) && ts9.isIdentifier(node.name) && node.name.text === name;
3416
+ }
3417
+ function declarationContainerContains(node, use) {
3418
+ const container = node.parent;
3419
+ return ts9.isSourceFile(container) || (ts9.isBlock(container) || ts9.isModuleBlock(container)) && nodeContains(container, use);
3420
+ }
3421
+ function selfNamedValueDeclarationMatches(node, identifier) {
3422
+ return (ts9.isFunctionExpression(node) || ts9.isClassExpression(node)) && node.name?.text === identifier.text && nodeContains(node, identifier);
3423
+ }
3424
+ function scopedNonVariableDeclarationMatches(node, identifier) {
3425
+ return namedValueDeclarationMatches(node, identifier.text) && declarationContainerContains(node, identifier) || selfNamedValueDeclarationMatches(node, identifier);
3426
+ }
3427
+ function nearestScopedNonVariableDeclaration(identifier) {
3428
+ let best;
3429
+ const visit = (node) => {
3430
+ if (scopedNonVariableDeclarationMatches(node, identifier) && (!best || bindingIsCloser(node, best, identifier))) best = node;
3431
+ ts9.forEachChild(node, visit);
3432
+ };
3433
+ visit(identifier.getSourceFile());
3434
+ return best;
3435
+ }
3436
+ function hasScopedNonVariableDeclaration(identifier) {
3437
+ return Boolean(nearestScopedNonVariableDeclaration(identifier));
3438
+ }
3439
+ function nonVariableBindingWins(identifier, selected) {
3440
+ const declaration = nearestScopedNonVariableDeclaration(identifier);
3441
+ return Boolean(declaration && (!selected || bindingIsCloser(declaration, selected, identifier)));
3442
+ }
3443
+ function importClauseBinds(clause, name) {
3444
+ if (!clause || clause.isTypeOnly) return false;
3445
+ if (clause.name?.text === name) return true;
3446
+ const bindings = clause.namedBindings;
3447
+ if (!bindings) return false;
3448
+ if (ts9.isNamespaceImport(bindings)) return bindings.name.text === name;
3449
+ return bindings.elements.some((element) => !element.isTypeOnly && element.name.text === name);
3450
+ }
3451
+ function hasValueImportBinding(identifier) {
3452
+ return identifier.getSourceFile().statements.some((statement) => {
3453
+ if (ts9.isImportDeclaration(statement))
3454
+ return importClauseBinds(statement.importClause, identifier.text);
3455
+ return ts9.isImportEqualsDeclaration(statement) && !statement.isTypeOnly && statement.name.text === identifier.text;
3456
+ });
3457
+ }
3458
+ function sourcePropertyName(element, localName) {
3459
+ const property = element.propertyName;
3460
+ if (!property) return localName;
3461
+ if (ts9.isIdentifier(property) || ts9.isStringLiteral(property) || ts9.isNumericLiteral(property)) return property.text;
3462
+ return void 0;
3463
+ }
3464
+ function resolveDestructuredBinding(identifier, use) {
3465
+ const source = use.getSourceFile();
3466
+ let best;
3467
+ const visit = (node) => {
3468
+ if ((ts9.isVariableDeclaration(node) || ts9.isParameter(node)) && isAccessibleDeclaration(node, use)) {
3469
+ const element = directBindingElement(node.name, identifier);
3470
+ const entityName = element ? sourcePropertyName(element, identifier.text) : void 0;
3471
+ if (entityName && (!best || node.name.getStart(source) > best.declaration.name.getStart(source))) {
3472
+ best = {
3473
+ declaration: node,
3474
+ initializer: node.initializer,
3475
+ entityName
3476
+ };
3477
+ }
3478
+ }
3479
+ ts9.forEachChild(node, visit);
3480
+ };
3481
+ visit(source);
3482
+ return best;
3483
+ }
3484
+ function isEntitiesBase(expr) {
3485
+ const value = unwrapQueryExpression2(expr);
3486
+ if (ts9.isPropertyAccessExpression(value)) return value.name.text === "entities";
3487
+ return ts9.isCallExpression(value) && ts9.isPropertyAccessExpression(value.expression) && value.expression.name.text === "entities";
3488
+ }
3489
+ function hasLexicalValueShadow(identifier, includeImports) {
3490
+ return hasScopedVariableDeclaration(identifier) || hasScopedNonVariableDeclaration(identifier) || includeImports && hasValueImportBinding(identifier);
3491
+ }
3492
+ function modelRequire(expr) {
3493
+ const value = unwrapQueryExpression2(expr);
3494
+ if (!ts9.isCallExpression(value) || !ts9.isIdentifier(value.expression) || value.expression.text !== "require" || value.arguments.length !== 1)
3495
+ return false;
3496
+ if (hasLexicalValueShadow(value.expression, true)) return false;
3497
+ const specifier = value.arguments[0];
3498
+ return Boolean(specifier && ts9.isStringLiteralLike(specifier) && cdsModelSpecifier.test(specifier.text));
3499
+ }
3500
+ function modelNamespaceImportName(statement) {
3501
+ if (!ts9.isImportDeclaration(statement) || !ts9.isStringLiteralLike(statement.moduleSpecifier) || !cdsModelSpecifier.test(statement.moduleSpecifier.text) || statement.importClause?.isTypeOnly) return void 0;
3502
+ const bindings = statement.importClause?.namedBindings;
3503
+ return bindings && ts9.isNamespaceImport(bindings) ? bindings.name.text : void 0;
3504
+ }
3505
+ function modelImportEqualsName(statement) {
3506
+ if (!ts9.isImportEqualsDeclaration(statement) || statement.isTypeOnly || !ts9.isExternalModuleReference(statement.moduleReference)) return void 0;
3507
+ const specifier = statement.moduleReference.expression;
3508
+ return specifier && ts9.isStringLiteralLike(specifier) && cdsModelSpecifier.test(specifier.text) ? statement.name.text : void 0;
3509
+ }
3510
+ function modelNamespaceNames(source) {
3511
+ const cached = modelNamespaceCache.get(source);
3512
+ if (cached) return cached;
3513
+ const names = /* @__PURE__ */ new Set();
3514
+ for (const statement of source.statements) {
3515
+ const name = modelNamespaceImportName(statement) ?? modelImportEqualsName(statement);
3516
+ if (name) names.add(name);
3517
+ }
3518
+ modelNamespaceCache.set(source, names);
3519
+ return names;
3520
+ }
3521
+ function destructuredEntitySource(initializer) {
3522
+ if (!initializer) return false;
3523
+ if (isEntitiesBase(initializer) || modelRequire(initializer)) return true;
3524
+ const value = unwrapQueryExpression2(initializer);
3525
+ return ts9.isIdentifier(value) && !hasLexicalValueShadow(value, false) && modelNamespaceNames(value.getSourceFile()).has(value.text);
3526
+ }
3527
+ function isAssignmentOperator(kind) {
3528
+ return kind >= ts9.SyntaxKind.FirstAssignment && kind <= ts9.SyntaxKind.LastAssignment;
3529
+ }
3530
+ function identifierIsReadWithinTarget(identifier, parent) {
3531
+ if (ts9.isPropertyAccessExpression(parent) && parent.name === identifier) return true;
3532
+ if (ts9.isElementAccessExpression(parent) && parent.argumentExpression && nodeContains(parent.argumentExpression, identifier)) return true;
3533
+ if (ts9.isPropertyAssignment(parent) && nodeContains(parent.name, identifier)) return true;
3534
+ return ts9.isComputedPropertyName(parent) && nodeContains(parent.expression, identifier);
3535
+ }
3536
+ function identifierIsUnaryWrite(identifier) {
3537
+ const direct = identifier.parent;
3538
+ if (!((ts9.isPrefixUnaryExpression(direct) || ts9.isPostfixUnaryExpression(direct)) && direct.operand === identifier)) return false;
3539
+ return direct.operator === ts9.SyntaxKind.PlusPlusToken || direct.operator === ts9.SyntaxKind.MinusMinusToken;
3540
+ }
3541
+ function identifierIsNestedWrite(identifier) {
3542
+ let current = identifier;
3543
+ while (current.parent) {
3544
+ const parent = current.parent;
3545
+ if (identifierIsReadWithinTarget(identifier, parent)) return false;
3546
+ if (ts9.isBinaryExpression(parent))
3547
+ return isAssignmentOperator(parent.operatorToken.kind) && nodeContains(parent.left, identifier);
3548
+ if (ts9.isForInStatement(parent) || ts9.isForOfStatement(parent))
3549
+ return nodeContains(parent.initializer, identifier);
3550
+ current = parent;
3551
+ }
3552
+ return false;
3553
+ }
3554
+ function identifierIsWrite(identifier) {
3555
+ return identifierIsUnaryWrite(identifier) || identifierIsNestedWrite(identifier);
3556
+ }
3557
+ function destructuredBindingWasWritten(binding, localName, use) {
3558
+ if (ts9.isParameter(binding.declaration)) return true;
3559
+ if ((binding.declaration.parent.flags & ts9.NodeFlags.Const) !== 0) return false;
3560
+ let written = false;
3561
+ const declarationEnd = binding.declaration.name.getEnd();
3562
+ const useStart = use.getStart();
3563
+ const visit = (node) => {
3564
+ if (written) return;
3565
+ if (ts9.isIdentifier(node) && node.text === localName && node.getStart() > declarationEnd && node.getStart() < useStart && identifierIsWrite(node) && resolveDestructuredBinding(node, node)?.declaration === binding.declaration)
3566
+ written = true;
3567
+ ts9.forEachChild(node, visit);
3568
+ };
3569
+ visit(use.getSourceFile());
3570
+ return written;
3571
+ }
3572
+ function destructuredBindingWins(destructured, simple, use) {
3573
+ return !simple.declaration || bindingIsCloser(destructured.declaration, simple.declaration, use);
3574
+ }
3575
+ function entityFromDestructuredBinding(binding, identifier) {
3576
+ if (destructuredBindingWasWritten(binding, identifier.text, identifier))
3577
+ return void 0;
3578
+ return destructuredEntitySource(binding.initializer) ? binding.entityName : void 0;
3579
+ }
3580
+ function entityFromSimpleBinding(binding, depth, seen) {
3581
+ if (!binding.declaration || !binding.immutable || !binding.initializer || seen.has(binding.declaration)) return void 0;
3582
+ seen.add(binding.declaration);
3583
+ return entityFromExpression(binding.initializer, depth + 1, seen);
3584
+ }
3585
+ function scopedBindingIsCurrent(identifier, declaration) {
3586
+ return nearestScopedVariableDeclaration(identifier) === declaration && !nonVariableBindingWins(identifier, declaration);
3587
+ }
3588
+ function unboundEntityName(identifier) {
3589
+ return hasScopedVariableDeclaration(identifier) || hasScopedNonVariableDeclaration(identifier) ? void 0 : identifier.text;
3590
+ }
3591
+ function entityFromIdentifier(expr, depth, seen) {
3592
+ const binding = resolveBinding2(expr, expr);
3593
+ const destructured = resolveDestructuredBinding(expr, expr);
3594
+ if (destructured && destructuredBindingWins(destructured, binding, expr)) {
3595
+ return scopedBindingIsCurrent(expr, destructured.declaration) ? entityFromDestructuredBinding(destructured, expr) : void 0;
3596
+ }
3597
+ if (!binding.declaration) return unboundEntityName(expr);
3598
+ if (!scopedBindingIsCurrent(expr, binding.declaration)) return void 0;
3599
+ return entityFromSimpleBinding(binding, depth, seen);
3600
+ }
3601
+ function literalEntity(expr) {
3602
+ if (ts9.isStringLiteral(expr) || ts9.isNoSubstitutionTemplateLiteral(expr))
3603
+ return expr.text;
3604
+ if (!ts9.isElementAccessExpression(expr) || !expr.argumentExpression)
3605
+ return void 0;
3606
+ return ts9.isStringLiteral(expr.argumentExpression) || ts9.isNoSubstitutionTemplateLiteral(expr.argumentExpression) ? expr.argumentExpression.text : void 0;
3607
+ }
3608
+ function propertyEntity(expr) {
3609
+ if (!ts9.isPropertyAccessExpression(expr)) return void 0;
3610
+ if (expr.expression.kind === ts9.SyntaxKind.ThisKeyword) return void 0;
3611
+ return isEntitiesBase(expr.expression) ? expr.name.text : void 0;
3612
+ }
3613
+ function entityFromExpression(expr, depth = 0, seen = /* @__PURE__ */ new Set()) {
3614
+ if (!expr || depth >= maxAliasDepth2) return void 0;
3615
+ const value = unwrapQueryExpression2(expr);
3616
+ const literal2 = literalEntity(value);
3617
+ if (literal2 !== void 0) return literal2;
3618
+ if (ts9.isIdentifier(value)) return entityFromIdentifier(value, depth, seen);
3619
+ return propertyEntity(value);
3620
+ }
3621
+ function queryAliasInitializer(identifier, initializers, seen) {
3622
+ const initializer = initializers.get(identifier.text);
3623
+ if (!initializer || seen.has(identifier.text)) return void 0;
3624
+ const binding = resolveBinding2(identifier, identifier);
3625
+ if (!binding.declaration || !binding.immutable || binding.initializer !== initializer || nearestScopedVariableDeclaration(identifier) !== binding.declaration || nonVariableBindingWins(identifier, binding.declaration)) return void 0;
3626
+ seen.add(identifier.text);
3627
+ return initializer;
3628
+ }
3629
+ function queryEntityFromCall(call, initializers, seenInitializers) {
3630
+ const name = expressionName2(call.expression);
3631
+ if (name === "cds.run")
3632
+ return queryEntityFromAst(call.arguments[0], initializers, seenInitializers);
3633
+ if (isCapQueryBuilderRootName(name))
3634
+ return entityFromExpression(call.arguments[0]);
3635
+ const receiver = ts9.isPropertyAccessExpression(call.expression) ? call.expression.expression : void 0;
3636
+ return receiver ? queryEntityFromAst(receiver, initializers, seenInitializers) : void 0;
3637
+ }
3638
+ function queryEntityFromAst(expr, initializers = /* @__PURE__ */ new Map(), seenInitializers = /* @__PURE__ */ new Set()) {
3639
+ const unwrapped = unwrapQueryExpression2(expr);
3640
+ if (ts9.isIdentifier(unwrapped)) {
3641
+ const initializer = queryAliasInitializer(
3642
+ unwrapped,
3643
+ initializers,
3644
+ seenInitializers
3645
+ );
3646
+ return initializer ? queryEntityFromAst(initializer, initializers, seenInitializers) : void 0;
3647
+ }
3648
+ return ts9.isCallExpression(unwrapped) ? queryEntityFromCall(unwrapped, initializers, seenInitializers) : void 0;
3649
+ }
3650
+
3651
+ // src/parsers/outbound-call-parser.ts
3652
+ function lineOf4(text, idx) {
3653
+ return text.slice(0, idx).split("\n").length;
3654
+ }
3326
3655
  function queryBuilderEvidence(source, statement) {
3327
3656
  return {
3328
3657
  classifier: "cap_query_builder_direct",
@@ -3347,18 +3676,6 @@ function queryRunEvidence(source, argument) {
3347
3676
  } : {}
3348
3677
  };
3349
3678
  }
3350
- function extractQueryEntity(expr) {
3351
- const source = ts9.createSourceFile("query.ts", `const __query = (${expr});`, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
3352
- const initializers = variableInitializers(source);
3353
- let found;
3354
- const visit = (node) => {
3355
- if (found) return;
3356
- if (ts9.isParenthesizedExpression(node)) found = queryEntityFromAst(node.expression, initializers);
3357
- ts9.forEachChild(node, visit);
3358
- };
3359
- visit(source);
3360
- return found;
3361
- }
3362
3679
  function queryWarning(expr) {
3363
3680
  if (/^\s*[`'"]/.test(expr)) return "raw_sql_or_cql_expression";
3364
3681
  if (/^\s*\w+\s*$/.test(expr)) return "query_variable_without_static_initializer";
@@ -3368,7 +3685,7 @@ function parserEvidence(source, node, extra) {
3368
3685
  return { parser: "typescript_ast", startOffset: node.getStart(source), endOffset: node.getEnd(), ...extra };
3369
3686
  }
3370
3687
  function isStringLike(expr) {
3371
- return Boolean(expr && (ts9.isStringLiteral(expr) || ts9.isNoSubstitutionTemplateLiteral(expr)));
3688
+ return Boolean(expr && (ts10.isStringLiteral(expr) || ts10.isNoSubstitutionTemplateLiteral(expr)));
3372
3689
  }
3373
3690
  function literalText(expr) {
3374
3691
  if (isStringLike(expr)) return expr.text;
@@ -3376,86 +3693,35 @@ function literalText(expr) {
3376
3693
  }
3377
3694
  function objectPropertyText(object, key) {
3378
3695
  const prop = object.properties.find(
3379
- (property) => ts9.isPropertyAssignment(property) && nameOfProperty(property.name) === key || ts9.isShorthandPropertyAssignment(property) && property.name.text === key
3696
+ (property) => ts10.isPropertyAssignment(property) && nameOfProperty(property.name) === key || ts10.isShorthandPropertyAssignment(property) && property.name.text === key
3380
3697
  );
3381
3698
  if (!prop) return void 0;
3382
- return ts9.isShorthandPropertyAssignment(prop) ? prop.name.text : prop.initializer.getText();
3699
+ return ts10.isShorthandPropertyAssignment(prop) ? prop.name.text : prop.initializer.getText();
3383
3700
  }
3384
3701
  function objectPropertyIsShorthand(object, key) {
3385
- return object.properties.some((property) => ts9.isShorthandPropertyAssignment(property) && property.name.text === key);
3702
+ return object.properties.some((property) => ts10.isShorthandPropertyAssignment(property) && property.name.text === key);
3386
3703
  }
3387
3704
  function nameOfProperty(name) {
3388
- if (ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name)) return name.text;
3705
+ if (ts10.isIdentifier(name) || ts10.isStringLiteral(name) || ts10.isNumericLiteral(name)) return name.text;
3389
3706
  return void 0;
3390
3707
  }
3391
- var maxAliasDepth2 = 5;
3392
3708
  function safeRaw(expr) {
3393
- if (ts9.isStringLiteral(expr) || ts9.isNoSubstitutionTemplateLiteral(expr) || ts9.isIdentifier(expr) || ts9.isTemplateExpression(expr)) return expr.getText(expr.getSourceFile());
3709
+ if (ts10.isStringLiteral(expr) || ts10.isNoSubstitutionTemplateLiteral(expr) || ts10.isIdentifier(expr) || ts10.isTemplateExpression(expr)) return expr.getText(expr.getSourceFile());
3394
3710
  return void 0;
3395
3711
  }
3396
3712
  function placeholders2(expr) {
3397
3713
  return expr.templateSpans.map((span) => span.expression.getText(expr.getSourceFile()));
3398
3714
  }
3399
- function isFunctionLikeScope(node) {
3400
- return ts9.isFunctionLike(node) || ts9.isSourceFile(node);
3401
- }
3402
- function nodeContains(parent, child) {
3403
- const source = child.getSourceFile();
3404
- return child.getStart(source) >= parent.getStart(source) && child.getEnd() <= parent.getEnd();
3405
- }
3406
- function declarationScope2(node) {
3407
- if (ts9.isParameter(node)) return node.parent;
3408
- if (ts9.isCatchClause(node.parent) && node.parent.variableDeclaration === node) return node.parent;
3409
- const list = node.parent;
3410
- const blockScoped = (list.flags & (ts9.NodeFlags.Const | ts9.NodeFlags.Let)) !== 0;
3411
- let current = list.parent;
3412
- if (!blockScoped) {
3413
- while (current.parent && !isFunctionLikeScope(current)) current = current.parent;
3414
- return current;
3415
- }
3416
- while (current.parent && !ts9.isBlock(current) && !ts9.isSourceFile(current) && !ts9.isModuleBlock(current) && !ts9.isCaseBlock(current) && !isLoopInitializerScope(node, current) && !isFunctionLikeScope(current)) current = current.parent;
3417
- return current;
3418
- }
3419
- function isLoopInitializerScope(declaration, scope) {
3420
- const list = declaration.parent;
3421
- return ts9.isForStatement(scope) && scope.initializer === list || (ts9.isForInStatement(scope) || ts9.isForOfStatement(scope)) && scope.initializer === list;
3422
- }
3423
- function catchBindingScope(declaration) {
3424
- if (ts9.isParameter(declaration)) return void 0;
3425
- return ts9.isCatchClause(declaration.parent) && declaration.parent.variableDeclaration === declaration ? declaration.parent : void 0;
3426
- }
3427
- function isAccessibleDeclaration(declaration, use) {
3428
- const source = use.getSourceFile();
3429
- if (declaration.name.getStart(source) >= use.getStart(source)) return false;
3430
- const catchScope = catchBindingScope(declaration);
3431
- if (catchScope) return nodeContains(catchScope.block, use);
3432
- const scope = declarationScope2(declaration);
3433
- if (ts9.isForStatement(scope) || ts9.isForInStatement(scope) || ts9.isForOfStatement(scope)) return nodeContains(scope.statement, use);
3434
- return ts9.isSourceFile(scope) || nodeContains(scope, use);
3435
- }
3436
- function resolveBinding2(identifier, use) {
3437
- const source = use.getSourceFile();
3438
- let best;
3439
- const visit = (node) => {
3440
- if (ts9.isVariableDeclaration(node) && ts9.isIdentifier(node.name) && node.name.text === identifier.text && isAccessibleDeclaration(node, use)) best = node;
3441
- if (ts9.isParameter(node) && ts9.isIdentifier(node.name) && node.name.text === identifier.text && isAccessibleDeclaration(node, use)) best = node;
3442
- ts9.forEachChild(node, visit);
3443
- };
3444
- visit(source);
3445
- if (!best) return { immutable: false, evidence: ["binding_not_found"] };
3446
- const immutable = ts9.isVariableDeclaration(best) && (best.parent.flags & ts9.NodeFlags.Const) !== 0;
3447
- return { declaration: best, initializer: ts9.isVariableDeclaration(best) ? best.initializer : void 0, immutable, evidence: [immutable ? "lexical_const_binding_before_use" : "lexical_mutable_or_parameter_binding"] };
3448
- }
3449
3715
  function resolveExpression(expr, use, policy, depth = 0, seen = /* @__PURE__ */ new Set()) {
3450
3716
  if (!expr) return { status: "unknown", sourceKind: "dynamic_expression", placeholderKeys: [], evidence: ["expression_missing"] };
3451
- if (ts9.isStringLiteral(expr)) return { status: "static", sourceKind: "string_literal", value: expr.text, rawExpression: safeRaw(expr), placeholderKeys: [], evidence: ["string_literal"] };
3452
- if (ts9.isNoSubstitutionTemplateLiteral(expr)) return { status: "static", sourceKind: "no_substitution_template", value: expr.text, rawExpression: safeRaw(expr), placeholderKeys: [], evidence: ["no_substitution_template"] };
3453
- if (ts9.isTemplateExpression(expr)) {
3717
+ if (ts10.isStringLiteral(expr)) return { status: "static", sourceKind: "string_literal", value: expr.text, rawExpression: safeRaw(expr), placeholderKeys: [], evidence: ["string_literal"] };
3718
+ if (ts10.isNoSubstitutionTemplateLiteral(expr)) return { status: "static", sourceKind: "no_substitution_template", value: expr.text, rawExpression: safeRaw(expr), placeholderKeys: [], evidence: ["no_substitution_template"] };
3719
+ if (ts10.isTemplateExpression(expr)) {
3454
3720
  const keys = placeholders2(expr);
3455
3721
  if (policy === "operation_path") return { status: "dynamic", sourceKind: "template_with_substitutions", value: stripQuotes(expr.getText(expr.getSourceFile())), rawExpression: safeRaw(expr), placeholderKeys: keys, evidence: ["operation_path_template_placeholders_retained"] };
3456
3722
  return { status: "dynamic", sourceKind: "template_with_substitutions", placeholderKeys: keys, evidence: ["template_substitutions_not_static_external_target"] };
3457
3723
  }
3458
- if (ts9.isIdentifier(expr)) {
3724
+ if (ts10.isIdentifier(expr)) {
3459
3725
  if (depth >= maxAliasDepth2) return { status: "unknown", sourceKind: "const_alias", rawExpression: safeRaw(expr), placeholderKeys: [], evidence: ["alias_depth_exceeded"], constName: expr.text };
3460
3726
  const binding = resolveBinding2(expr, use);
3461
3727
  if (!binding.declaration || !binding.initializer || !binding.immutable) return { status: "dynamic", sourceKind: "dynamic_expression", rawExpression: safeRaw(expr), placeholderKeys: [], evidence: binding.evidence, constName: expr.text };
@@ -3464,12 +3730,12 @@ function resolveExpression(expr, use, policy, depth = 0, seen = /* @__PURE__ */
3464
3730
  const resolved3 = resolveExpression(binding.initializer, binding.declaration, policy, depth + 1, seen);
3465
3731
  return { ...resolved3, sourceKind: "const_alias", rawExpression: safeRaw(expr), constName: expr.text, evidence: [...binding.evidence, ...resolved3.evidence] };
3466
3732
  }
3467
- return { status: "dynamic", sourceKind: "dynamic_expression", rawExpression: safeRaw(expr), placeholderKeys: [], evidence: [`unsupported_${ts9.SyntaxKind[expr.kind] ?? "expression"}`] };
3733
+ return { status: "dynamic", sourceKind: "dynamic_expression", rawExpression: safeRaw(expr), placeholderKeys: [], evidence: [`unsupported_${ts10.SyntaxKind[expr.kind] ?? "expression"}`] };
3468
3734
  }
3469
3735
  function staticExpressionText(expr, initializers) {
3470
3736
  if (!expr) return void 0;
3471
3737
  if (isStringLike(expr)) return expr.text;
3472
- if (ts9.isIdentifier(expr) && initializers.has(expr.text)) return staticExpressionText(initializers.get(expr.text), initializers);
3738
+ if (ts10.isIdentifier(expr) && initializers.has(expr.text)) return staticExpressionText(initializers.get(expr.text), initializers);
3473
3739
  return void 0;
3474
3740
  }
3475
3741
  function operationPathFromStatic(text) {
@@ -3477,17 +3743,17 @@ function operationPathFromStatic(text) {
3477
3743
  }
3478
3744
  function destinationExpressionShape(expr) {
3479
3745
  if (!expr) return void 0;
3480
- if (ts9.isIdentifier(expr)) return "identifier";
3481
- if (ts9.isPropertyAccessExpression(expr) || ts9.isElementAccessExpression(expr)) return "property_read";
3482
- if (ts9.isCallExpression(expr)) return "function_call";
3483
- if (ts9.isConditionalExpression(expr)) return "conditional";
3484
- if (ts9.isBinaryExpression(expr)) return "binary_expression";
3485
- if (ts9.isTemplateExpression(expr)) return "template_expression";
3486
- return ts9.SyntaxKind[expr.kind] ?? "expression";
3746
+ if (ts10.isIdentifier(expr)) return "identifier";
3747
+ if (ts10.isPropertyAccessExpression(expr) || ts10.isElementAccessExpression(expr)) return "property_read";
3748
+ if (ts10.isCallExpression(expr)) return "function_call";
3749
+ if (ts10.isConditionalExpression(expr)) return "conditional";
3750
+ if (ts10.isBinaryExpression(expr)) return "binary_expression";
3751
+ if (ts10.isTemplateExpression(expr)) return "template_expression";
3752
+ return ts10.SyntaxKind[expr.kind] ?? "expression";
3487
3753
  }
3488
3754
  function staticConditionalCandidates(expr, initializers) {
3489
- const resolved3 = expr && ts9.isIdentifier(expr) && initializers.has(expr.text) ? initializers.get(expr.text) : expr;
3490
- if (!resolved3 || !ts9.isConditionalExpression(resolved3)) return void 0;
3755
+ const resolved3 = expr && ts10.isIdentifier(expr) && initializers.has(expr.text) ? initializers.get(expr.text) : expr;
3756
+ if (!resolved3 || !ts10.isConditionalExpression(resolved3)) return void 0;
3491
3757
  const left = staticExpressionText(resolved3.whenTrue, initializers);
3492
3758
  const right = staticExpressionText(resolved3.whenFalse, initializers);
3493
3759
  if (!left || !right) return void 0;
@@ -3495,8 +3761,8 @@ function staticConditionalCandidates(expr, initializers) {
3495
3761
  }
3496
3762
  function propertyInitializer(object, key) {
3497
3763
  for (const property of object.properties) {
3498
- if (ts9.isPropertyAssignment(property) && nameOfProperty(property.name) === key) return property.initializer;
3499
- if (ts9.isShorthandPropertyAssignment(property) && property.name.text === key) return property.name;
3764
+ if (ts10.isPropertyAssignment(property) && nameOfProperty(property.name) === key) return property.initializer;
3765
+ if (ts10.isShorthandPropertyAssignment(property) && property.name.text === key) return property.name;
3500
3766
  }
3501
3767
  return void 0;
3502
3768
  }
@@ -3557,7 +3823,7 @@ function externalHttpEvidence(node, source) {
3557
3823
  const exprText = expr.getText(source);
3558
3824
  if (exprText === "useOrFetchDestination") {
3559
3825
  const objectArg = node.arguments[0];
3560
- if (objectArg && ts9.isObjectLiteralExpression(objectArg)) {
3826
+ if (objectArg && ts10.isObjectLiteralExpression(objectArg)) {
3561
3827
  const destination = destinationTargetFromExpression(propertyInitializer(objectArg, "destinationName"), node);
3562
3828
  return { externalTarget: destination ?? { kind: "unknown", dynamic: false }, classifier: "sap_destination_lookup", sourceCallShape: "useOrFetchDestination" };
3563
3829
  }
@@ -3565,13 +3831,13 @@ function externalHttpEvidence(node, source) {
3565
3831
  if (exprText === "executeHttpRequest") {
3566
3832
  const destination = destinationTargetFromExpression(node.arguments[0], node);
3567
3833
  const config = node.arguments[1];
3568
- const method = config && ts9.isObjectLiteralExpression(config) ? httpMethodFromObject(config, node) : void 0;
3569
- const url = config && ts9.isObjectLiteralExpression(config) ? urlTargetFromExpression(propertyInitializer(config, "url"), node) : { kind: "unknown", dynamic: false };
3834
+ const method = config && ts10.isObjectLiteralExpression(config) ? httpMethodFromObject(config, node) : void 0;
3835
+ const url = config && ts10.isObjectLiteralExpression(config) ? urlTargetFromExpression(propertyInitializer(config, "url"), node) : { kind: "unknown", dynamic: false };
3570
3836
  return { method, externalTarget: destination ? { ...url, destination } : url, classifier: "sap_execute_http_request", sourceCallShape: "executeHttpRequest" };
3571
3837
  }
3572
3838
  if (exprText === "axios") {
3573
3839
  const config = node.arguments[0];
3574
- if (config && ts9.isObjectLiteralExpression(config)) {
3840
+ if (config && ts10.isObjectLiteralExpression(config)) {
3575
3841
  const method = httpMethodFromObject(config, node);
3576
3842
  return { method, externalTarget: urlTargetFromExpression(propertyInitializer(config, "url"), node), classifier: "axios_config_call", sourceCallShape: "axios(config)" };
3577
3843
  }
@@ -3579,10 +3845,10 @@ function externalHttpEvidence(node, source) {
3579
3845
  }
3580
3846
  if (exprText === "fetch") {
3581
3847
  const init = node.arguments[1];
3582
- const method = init && ts9.isObjectLiteralExpression(init) ? httpMethodFromObject(init, node) : void 0;
3848
+ const method = init && ts10.isObjectLiteralExpression(init) ? httpMethodFromObject(init, node) : void 0;
3583
3849
  return { method, externalTarget: urlTargetFromExpression(node.arguments[0], node), classifier: "fetch_call", sourceCallShape: "fetch" };
3584
3850
  }
3585
- if (ts9.isPropertyAccessExpression(expr) && ["get", "post", "put", "patch", "delete", "head"].includes(expr.name.text) && expr.expression.getText(source) === "axios") {
3851
+ if (ts10.isPropertyAccessExpression(expr) && ["get", "post", "put", "patch", "delete", "head"].includes(expr.name.text) && expr.expression.getText(source) === "axios") {
3586
3852
  return { method: expr.name.text.toUpperCase(), externalTarget: urlTargetFromExpression(node.arguments[0], node), classifier: "axios_member_call", sourceCallShape: `axios.${expr.name.text}` };
3587
3853
  }
3588
3854
  return void 0;
@@ -3590,27 +3856,27 @@ function externalHttpEvidence(node, source) {
3590
3856
  function collectServiceVariables(source) {
3591
3857
  const vars = /* @__PURE__ */ new Set(["cds", "messaging", "messageClient", "eventClient"]);
3592
3858
  const visit = (node) => {
3593
- if (ts9.isVariableDeclaration(node) && ts9.isIdentifier(node.name) && node.initializer) {
3859
+ if (ts10.isVariableDeclaration(node) && ts10.isIdentifier(node.name) && node.initializer) {
3594
3860
  const text = node.initializer.getText(source);
3595
3861
  if (/cds\.connect\.(to|messaging)\s*\(/.test(text)) vars.add(node.name.text);
3596
3862
  }
3597
- ts9.forEachChild(node, visit);
3863
+ ts10.forEachChild(node, visit);
3598
3864
  };
3599
3865
  visit(source);
3600
3866
  return vars;
3601
3867
  }
3602
3868
  function receiverName(expr) {
3603
- if (ts9.isIdentifier(expr)) return expr.text;
3604
- if (ts9.isPropertyAccessExpression(expr)) return expr.getText(sourceOf(expr));
3869
+ if (ts10.isIdentifier(expr)) return expr.text;
3870
+ if (ts10.isPropertyAccessExpression(expr)) return expr.getText(sourceOf(expr));
3605
3871
  return void 0;
3606
3872
  }
3607
3873
  function sourceOf(node) {
3608
3874
  return node.getSourceFile();
3609
3875
  }
3610
3876
  function rootReceiverName(expr) {
3611
- if (ts9.isIdentifier(expr)) return expr.text;
3612
- if (ts9.isPropertyAccessExpression(expr)) return rootReceiverName(expr.expression);
3613
- if (ts9.isCallExpression(expr)) return rootReceiverName(expr.expression);
3877
+ if (ts10.isIdentifier(expr)) return expr.text;
3878
+ if (ts10.isPropertyAccessExpression(expr)) return rootReceiverName(expr.expression);
3879
+ if (ts10.isCallExpression(expr)) return rootReceiverName(expr.expression);
3614
3880
  return void 0;
3615
3881
  }
3616
3882
  function isSupportedEventReceiver(receiver, rootReceiver, serviceVariables) {
@@ -3627,38 +3893,38 @@ function collectWrapperSpecs(source) {
3627
3893
  const serviceVariables = collectServiceVariables(source);
3628
3894
  const calledNames = /* @__PURE__ */ new Set();
3629
3895
  const collectCalls = (node) => {
3630
- if (ts9.isCallExpression(node) && ts9.isIdentifier(node.expression))
3896
+ if (ts10.isCallExpression(node) && ts10.isIdentifier(node.expression))
3631
3897
  calledNames.add(node.expression.text);
3632
- if (ts9.isCallExpression(node) && ts9.isCallExpression(node.expression) && ts9.isIdentifier(node.expression.expression))
3898
+ if (ts10.isCallExpression(node) && ts10.isCallExpression(node.expression) && ts10.isIdentifier(node.expression.expression))
3633
3899
  calledNames.add(node.expression.expression.text);
3634
- ts9.forEachChild(node, collectCalls);
3900
+ ts10.forEachChild(node, collectCalls);
3635
3901
  };
3636
3902
  collectCalls(source);
3637
3903
  const scanFunction = (name, fn) => {
3638
3904
  if (!calledNames.has(name) && !isExportedWrapper(fn)) return;
3639
- const params = fn.parameters.map((param) => ts9.isIdentifier(param.name) ? param.name.text : void 0);
3905
+ const params = fn.parameters.map((param) => ts10.isIdentifier(param.name) ? param.name.text : void 0);
3640
3906
  const sends = [];
3641
3907
  const visit = (node) => {
3642
- if (ts9.isCallExpression(node) && ts9.isPropertyAccessExpression(node.expression) && node.expression.name.text === "send" && ts9.isIdentifier(node.expression.expression)) {
3908
+ if (ts10.isCallExpression(node) && ts10.isPropertyAccessExpression(node.expression) && node.expression.name.text === "send" && ts10.isIdentifier(node.expression.expression)) {
3643
3909
  const objectArg = node.arguments[0];
3644
- if (objectArg && ts9.isObjectLiteralExpression(objectArg)) {
3910
+ if (objectArg && ts10.isObjectLiteralExpression(objectArg)) {
3645
3911
  const pathProp = propertyInitializer(objectArg, "path");
3646
3912
  const methodProp = propertyInitializer(objectArg, "method");
3647
- const pathName = pathProp && ts9.isIdentifier(pathProp) ? pathProp.text : void 0;
3648
- const methodName2 = methodProp && ts9.isIdentifier(methodProp) ? methodProp.text : void 0;
3913
+ const pathName = pathProp && ts10.isIdentifier(pathProp) ? pathProp.text : void 0;
3914
+ const methodName2 = methodProp && ts10.isIdentifier(methodProp) ? methodProp.text : void 0;
3649
3915
  const methodLiteral = resolveExpression(methodProp, node, "literal").value;
3650
3916
  if (pathName) sends.push({ client: node.expression.expression.text, path: pathName, method: methodName2, methodLiteral, start: node.getStart(source), end: node.getEnd() });
3651
3917
  }
3652
3918
  }
3653
- if (ts9.isCallExpression(node) && ts9.isIdentifier(node.expression) && specs.has(node.expression.text)) {
3919
+ if (ts10.isCallExpression(node) && ts10.isIdentifier(node.expression) && specs.has(node.expression.text)) {
3654
3920
  const nested = specs.get(node.expression.text);
3655
3921
  const pathArg = nested ? node.arguments[nested.pathIndex] : void 0;
3656
3922
  const clientArg = nested?.clientIndex === void 0 ? void 0 : node.arguments[nested.clientIndex];
3657
- const pathName = pathArg && ts9.isIdentifier(pathArg) ? pathArg.text : void 0;
3658
- const clientName = clientArg && ts9.isIdentifier(clientArg) ? clientArg.text : nested?.clientName;
3923
+ const pathName = pathArg && ts10.isIdentifier(pathArg) ? pathArg.text : void 0;
3924
+ const clientName = clientArg && ts10.isIdentifier(clientArg) ? clientArg.text : nested?.clientName;
3659
3925
  if (nested && pathName && clientName) sends.push({ client: clientName, path: pathName, method: nested.methodName, methodLiteral: nested.methodLiteral, nestedWrapperFunction: node.expression.text, start: node.getStart(source), end: node.getEnd() });
3660
3926
  }
3661
- ts9.forEachChild(node, visit);
3927
+ ts10.forEachChild(node, visit);
3662
3928
  };
3663
3929
  visit(fn);
3664
3930
  if (sends.length !== 1) return;
@@ -3670,17 +3936,17 @@ function collectWrapperSpecs(source) {
3670
3936
  if (pathIndex >= 0 && (clientIndex >= 0 || capturesKnownClient)) specs.set(name, { clientIndex: clientIndex >= 0 ? clientIndex : void 0, clientName: clientIndex >= 0 ? void 0 : found.client, pathIndex, methodIndex: methodIndex >= 0 ? methodIndex : void 0, methodName: found.method, methodLiteral: found.methodLiteral, nestedWrapperFunction: found.nestedWrapperFunction, definitionLine: lineOf4(source.text, fn.getStart(source)), internalStart: found.start, internalEnd: found.end });
3671
3937
  };
3672
3938
  const visitTop = (node) => {
3673
- if (ts9.isFunctionDeclaration(node) && node.name) scanFunction(node.name.text, node);
3674
- if (ts9.isVariableDeclaration(node) && ts9.isIdentifier(node.name) && node.initializer && (ts9.isArrowFunction(node.initializer) || ts9.isFunctionExpression(node.initializer))) scanFunction(node.name.text, node.initializer);
3675
- ts9.forEachChild(node, visitTop);
3939
+ if (ts10.isFunctionDeclaration(node) && node.name) scanFunction(node.name.text, node);
3940
+ if (ts10.isVariableDeclaration(node) && ts10.isIdentifier(node.name) && node.initializer && (ts10.isArrowFunction(node.initializer) || ts10.isFunctionExpression(node.initializer))) scanFunction(node.name.text, node.initializer);
3941
+ ts10.forEachChild(node, visitTop);
3676
3942
  };
3677
3943
  visitTop(source);
3678
3944
  return specs;
3679
3945
  }
3680
3946
  function isExportedWrapper(fn) {
3681
- const declaration = ts9.isFunctionDeclaration(fn) ? fn : ts9.isVariableDeclaration(fn.parent) ? fn.parent.parent.parent : void 0;
3682
- if (!declaration || !ts9.canHaveModifiers(declaration)) return false;
3683
- return ts9.getModifiers(declaration)?.some((modifier) => modifier.kind === ts9.SyntaxKind.ExportKeyword) ?? false;
3947
+ const declaration = ts10.isFunctionDeclaration(fn) ? fn : ts10.isVariableDeclaration(fn.parent) ? fn.parent.parent.parent : void 0;
3948
+ if (!declaration || !ts10.canHaveModifiers(declaration)) return false;
3949
+ return ts10.getModifiers(declaration)?.some((modifier) => modifier.kind === ts10.SyntaxKind.ExportKeyword) ?? false;
3684
3950
  }
3685
3951
  function classifyOutboundCallsInSource(source, filePath) {
3686
3952
  const calls = [];
@@ -3693,7 +3959,7 @@ function classifyOutboundCallsInSource(source, filePath) {
3693
3959
  calls.push({ node, fact: { ...fact, sourceFile, sourceLine: lineOf4(source.text, node.getStart(source)), confidence: fact.confidence ?? 0.8, evidence: parserEvidence(source, node, extra) } });
3694
3960
  };
3695
3961
  const visit = (node) => {
3696
- if (ts9.isCallExpression(node)) {
3962
+ if (ts10.isCallExpression(node)) {
3697
3963
  if (wrapperInternalRanges.some((range) => node.getStart(source) >= range.start && node.getEnd() <= range.end)) {
3698
3964
  return;
3699
3965
  }
@@ -3709,11 +3975,11 @@ function classifyOutboundCallsInSource(source, filePath) {
3709
3975
  const entity = queryEntityFromAst(directQuery.logicalCall, initializers);
3710
3976
  const payload = directQuery.logicalCall.getText(source);
3711
3977
  add(directQuery.logicalCall, { callType: "local_db_query", queryEntity: entity, payloadSummary: summarizeExpression(payload), confidence: entity ? 0.9 : 0.55, unresolvedReason: entity ? void 0 : queryWarning(payload) }, queryBuilderEvidence(source, directQuery));
3712
- } else if (ts9.isPropertyAccessExpression(expr) && expr.name.text === "send" && (ts9.isIdentifier(expr.expression) || ts9.isPropertyAccessExpression(expr.expression))) {
3978
+ } else if (ts10.isPropertyAccessExpression(expr) && expr.name.text === "send" && (ts10.isIdentifier(expr.expression) || ts10.isPropertyAccessExpression(expr.expression))) {
3713
3979
  const objectArg = node.arguments[0];
3714
- if (objectArg && ts9.isObjectLiteralExpression(objectArg)) {
3980
+ if (objectArg && ts10.isObjectLiteralExpression(objectArg)) {
3715
3981
  const receiver = receiverName(expr.expression);
3716
- const query = objectPropertyText(objectArg, "query");
3982
+ const queryExpression = propertyInitializer(objectArg, "query");
3717
3983
  const method = stripQuotes(resolveExpression(propertyInitializer(objectArg, "method"), node, "literal").value ?? objectPropertyText(objectArg, "method") ?? "POST");
3718
3984
  const pathExpr = propertyInitializer(objectArg, "path") ?? propertyInitializer(objectArg, "event");
3719
3985
  const pathAnalysis = analyzeOperationPath(pathExpr, node, method);
@@ -3724,8 +3990,9 @@ function classifyOutboundCallsInSource(source, filePath) {
3724
3990
  const entityCallTypes = { entity_mutation: "remote_entity_mutation", entity_delete: "remote_entity_delete", entity_media: "remote_entity_media", entity_candidate: "remote_entity_candidate" };
3725
3991
  const entityCallType = entityCallTypes[intent.kind];
3726
3992
  const isODataQueryRead = method.toUpperCase() === "GET" && ["entity_query", "entity_key_read", "entity_navigation_query"].includes(intent.kind);
3727
- const unresolvedReason = !query && pathExpr ? pathUnresolvedReason(pathAnalysis) : void 0;
3728
- add(node, { callType: query ? "remote_query" : entityCallType ?? (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 }, { receiver, classifier: "service_client_send_object", operationPathExpression: shorthandPath ? op : void 0, rawPathExpression: pathAnalysis.rawExpression, literalPathSource: literalPathSource(pathAnalysis), odataPathIntent: operationPathExpr ? intent : void 0, pathAnalysis, staticPathCandidates: legacyPathCandidates(pathAnalysis), parserWarning: unresolvedReason });
3993
+ const queryEntity = queryExpression ? queryEntityFromAst(queryExpression, initializers) : isODataQueryRead ? intent.entitySegment : void 0;
3994
+ const unresolvedReason = queryExpression ? queryEntity ? void 0 : queryWarning(queryExpression.getText(source)) : pathExpr ? pathUnresolvedReason(pathAnalysis) : void 0;
3995
+ add(node, { callType: queryExpression ? "remote_query" : entityCallType ?? (isODataQueryRead ? "remote_query" : "remote_action"), serviceVariableName: receiver, method, operationPathExpr, queryEntity, payloadSummary: summarizeExpression(objectArg.getText(source)), confidence: op || queryExpression ? 0.8 : 0.4, unresolvedReason }, { receiver, classifier: "service_client_send_object", operationPathExpression: shorthandPath ? op : void 0, rawPathExpression: pathAnalysis.rawExpression, literalPathSource: literalPathSource(pathAnalysis), odataPathIntent: operationPathExpr ? intent : void 0, pathAnalysis, staticPathCandidates: legacyPathCandidates(pathAnalysis), parserWarning: unresolvedReason });
3729
3996
  } else {
3730
3997
  const receiver = receiverName(expr.expression);
3731
3998
  const rootReceiver = rootReceiverName(expr.expression);
@@ -3744,14 +4011,14 @@ function classifyOutboundCallsInSource(source, filePath) {
3744
4011
  add(node, { callType: "remote_action", serviceVariableName: rootReceiver ?? receiver, operationPathExpr, payloadSummary: summarizeExpression(node.getText(source)), confidence: operationPathExpr ? 0.75 : 0.35, unresolvedReason: operationPathExpr ? void 0 : "unsupported_cap_send_signature" }, { receiver, rootReceiver, classifier: operationPathExpr ? "service_client_send_operation_event" : "service_client_send_unsupported_signature", rawOperationExpression: firstArg2.rawExpression, literalOperationSource: firstArg2.value ? firstArg2.sourceKind : void 0, parserWarning: operationPathExpr ? void 0 : "unsupported_cap_send_signature" });
3745
4012
  }
3746
4013
  }
3747
- } else if (ts9.isCallExpression(expr) && ts9.isIdentifier(expr.expression) && wrapperSpecs.has(expr.expression.text) || ts9.isIdentifier(expr) && wrapperSpecs.has(expr.text)) {
3748
- const wrapperName = ts9.isIdentifier(expr) ? expr.text : ts9.isCallExpression(expr) && ts9.isIdentifier(expr.expression) ? expr.expression.text : "";
3749
- const wrapperArgs = ts9.isIdentifier(expr) ? node.arguments : ts9.isCallExpression(expr) ? expr.arguments : node.arguments;
4014
+ } else if (ts10.isCallExpression(expr) && ts10.isIdentifier(expr.expression) && wrapperSpecs.has(expr.expression.text) || ts10.isIdentifier(expr) && wrapperSpecs.has(expr.text)) {
4015
+ const wrapperName = ts10.isIdentifier(expr) ? expr.text : ts10.isCallExpression(expr) && ts10.isIdentifier(expr.expression) ? expr.expression.text : "";
4016
+ const wrapperArgs = ts10.isIdentifier(expr) ? node.arguments : ts10.isCallExpression(expr) ? expr.arguments : node.arguments;
3750
4017
  const spec = wrapperSpecs.get(wrapperName);
3751
4018
  const clientArg = spec?.clientIndex === void 0 ? void 0 : wrapperArgs[spec.clientIndex];
3752
4019
  const pathArg = spec ? wrapperArgs[spec.pathIndex] : void 0;
3753
4020
  const methodArg = spec?.methodIndex === void 0 ? void 0 : wrapperArgs[spec.methodIndex];
3754
- const receiver = clientArg && ts9.isIdentifier(clientArg) ? clientArg.text : spec?.clientName;
4021
+ const receiver = clientArg && ts10.isIdentifier(clientArg) ? clientArg.text : spec?.clientName;
3755
4022
  const method = stripQuotes(resolveExpression(methodArg, node, "literal").value ?? spec?.methodLiteral ?? "POST");
3756
4023
  const pathAnalysis = analyzeOperationPath(pathArg, node, method);
3757
4024
  const operationPathExpr = operationPathExpression(pathAnalysis);
@@ -3762,7 +4029,7 @@ function classifyOutboundCallsInSource(source, filePath) {
3762
4029
  } else if (spec && receiver) {
3763
4030
  add(node, { callType: "remote_action", serviceVariableName: receiver, method, payloadSummary: summarizeExpression(node.getText(source)), confidence: 0.45, unresolvedReason }, { receiver, classifier: pathAnalysis.status === "ambiguous" ? "higher_order_wrapper_ambiguous_path" : "higher_order_wrapper_dynamic_path", wrapperFunction: wrapperName, wrapperDefinitionLine: spec.definitionLine, callerLine: lineOf4(source.text, node.getStart(source)), wrapperPathSourceKind: wrapperSourceKind(pathAnalysis.sourceKind), rawPathExpression: pathAnalysis.rawExpression, pathAnalysis, parserWarning: unresolvedReason });
3764
4031
  }
3765
- } else if (ts9.isPropertyAccessExpression(expr) && ["emit", "publish", "on"].includes(expr.name.text)) {
4032
+ } else if (ts10.isPropertyAccessExpression(expr) && ["emit", "publish", "on"].includes(expr.name.text)) {
3766
4033
  const receiver = receiverName(expr.expression);
3767
4034
  const rootReceiver = rootReceiverName(expr.expression);
3768
4035
  if (isSupportedEventReceiver(receiver, rootReceiver, serviceVariables)) {
@@ -3778,7 +4045,7 @@ function classifyOutboundCallsInSource(source, filePath) {
3778
4045
  }
3779
4046
  }
3780
4047
  }
3781
- ts9.forEachChild(node, visit);
4048
+ ts10.forEachChild(node, visit);
3782
4049
  };
3783
4050
  visit(source);
3784
4051
  return calls;
@@ -3792,12 +4059,12 @@ function containsSupportedOutboundCall(node) {
3792
4059
  async function parseOutboundCalls(repoPath, filePath, context) {
3793
4060
  const snapshot = context?.get(filePath);
3794
4061
  const text = snapshot?.text ?? await fs8.readFile(path11.join(repoPath, filePath), "utf8");
3795
- const source = snapshot?.sourceFile() ?? ts9.createSourceFile(
4062
+ const source = snapshot?.sourceFile() ?? ts10.createSourceFile(
3796
4063
  filePath,
3797
4064
  text,
3798
- ts9.ScriptTarget.Latest,
4065
+ ts10.ScriptTarget.Latest,
3799
4066
  true,
3800
- filePath.endsWith(".ts") ? ts9.ScriptKind.TS : ts9.ScriptKind.JS
4067
+ filePath.endsWith(".ts") ? ts10.ScriptKind.TS : ts10.ScriptKind.JS
3801
4068
  );
3802
4069
  const bindingNames = new Set((await parseServiceBindings(
3803
4070
  repoPath,
@@ -3813,21 +4080,21 @@ async function parseOutboundCalls(repoPath, filePath, context) {
3813
4080
  );
3814
4081
  return [...classifyOutboundCallsInSource(source, filePath).map((call) => call.fact), ...importedWrappers, ...parseLocalServiceCalls(text, filePath, source)];
3815
4082
  }
3816
- function parseLocalServiceCalls(text, filePath, source = ts9.createSourceFile(
4083
+ function parseLocalServiceCalls(text, filePath, source = ts10.createSourceFile(
3817
4084
  filePath,
3818
4085
  text,
3819
- ts9.ScriptTarget.Latest,
4086
+ ts10.ScriptTarget.Latest,
3820
4087
  true,
3821
- filePath.endsWith(".ts") ? ts9.ScriptKind.TS : ts9.ScriptKind.JS
4088
+ filePath.endsWith(".ts") ? ts10.ScriptKind.TS : ts10.ScriptKind.JS
3822
4089
  )) {
3823
4090
  const aliases = /* @__PURE__ */ new Map();
3824
4091
  const calls = [];
3825
4092
  const visit = (node) => {
3826
- if (ts9.isVariableDeclaration(node) && ts9.isIdentifier(node.name) && node.initializer) {
4093
+ if (ts10.isVariableDeclaration(node) && ts10.isIdentifier(node.name) && node.initializer) {
3827
4094
  const origin = serviceLookup(node.initializer, aliases);
3828
4095
  if (origin) aliases.set(node.name.text, { ...origin, chain: [...origin.chain, node.name.text] });
3829
4096
  }
3830
- if (ts9.isCallExpression(node)) {
4097
+ if (ts10.isCallExpression(node)) {
3831
4098
  const parsed = serviceOperationCall(node, aliases);
3832
4099
  if (parsed && parsed.operation !== "entities") calls.push({
3833
4100
  callType: "local_service_call",
@@ -3850,20 +4117,20 @@ function parseLocalServiceCalls(text, filePath, source = ts9.createSourceFile(
3850
4117
  })
3851
4118
  });
3852
4119
  }
3853
- ts9.forEachChild(node, visit);
4120
+ ts10.forEachChild(node, visit);
3854
4121
  };
3855
4122
  visit(source);
3856
4123
  return calls;
3857
4124
  }
3858
4125
  function serviceLookup(expr, aliases) {
3859
- if (ts9.isIdentifier(expr)) return aliases.get(expr.text);
3860
- if (ts9.isPropertyAccessExpression(expr) && expr.expression.getText() === "cds.services") return { service: expr.name.text, lookup: expr.getText(), chain: [expr.getText()] };
3861
- if (ts9.isElementAccessExpression(expr) && expr.expression.getText() === "cds.services" && ts9.isStringLiteral(expr.argumentExpression)) return { service: expr.argumentExpression.text, lookup: expr.getText(), chain: [expr.getText()] };
4126
+ if (ts10.isIdentifier(expr)) return aliases.get(expr.text);
4127
+ if (ts10.isPropertyAccessExpression(expr) && expr.expression.getText() === "cds.services") return { service: expr.name.text, lookup: expr.getText(), chain: [expr.getText()] };
4128
+ if (ts10.isElementAccessExpression(expr) && expr.expression.getText() === "cds.services" && ts10.isStringLiteral(expr.argumentExpression)) return { service: expr.argumentExpression.text, lookup: expr.getText(), chain: [expr.getText()] };
3862
4129
  return void 0;
3863
4130
  }
3864
4131
  function serviceOperationCall(node, aliases) {
3865
4132
  const expr = node.expression;
3866
- if (!ts9.isPropertyAccessExpression(expr)) return void 0;
4133
+ if (!ts10.isPropertyAccessExpression(expr)) return void 0;
3867
4134
  const origin = serviceLookup(expr.expression, aliases);
3868
4135
  if (!origin) return void 0;
3869
4136
  if (expr.name.text === "send") {
@@ -8692,4 +8959,4 @@ export {
8692
8959
  selectorRepoAmbiguousDiagnostic,
8693
8960
  trace
8694
8961
  };
8695
- //# sourceMappingURL=chunk-CRSSXWQ2.js.map
8962
+ //# sourceMappingURL=chunk-BGD7UYJN.js.map