@suss/adapter-typescript 0.22.3 → 0.23.0

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/dist/index.js CHANGED
@@ -3716,6 +3716,18 @@ var ResolutionStore = class {
3716
3716
  const target = factKeyOf(value);
3717
3717
  return this.askAbout(target, "wanted", () => this.lookupObject(target));
3718
3718
  }
3719
+ /**
3720
+ * The function a call returns: `app.use(requireCaller(config))`
3721
+ * registers what the factory gives back. A separate question from
3722
+ * `resolveCallable`, which keeps a call unresolved on purpose so an
3723
+ * unwrapping answer wins; this one is asked only after that has
3724
+ * declined. Two returned functions give null, like every other
3725
+ * single-answer question here.
3726
+ */
3727
+ resolveReturnedCallable(call) {
3728
+ const target = factKeyOf(call);
3729
+ return this.askAbout(target, "wanted", () => this.lookupReturned(target));
3730
+ }
3719
3731
  /**
3720
3732
  * For a value that is neither a function nor an object, such as a
3721
3733
  * GraphQL document kept in a constant in another file.
@@ -4159,6 +4171,21 @@ var ResolutionStore = class {
4159
4171
  }
4160
4172
  return [...candidates][0];
4161
4173
  }
4174
+ lookupReturned(call) {
4175
+ this.derive();
4176
+ const candidates = /* @__PURE__ */ new Set();
4177
+ for (const target of this.answersFor("wantedGivesBack", nodeId(call))) {
4178
+ const node = this.table.byId.get(target);
4179
+ if (node === void 0 || !isFunctionRoot(node)) {
4180
+ continue;
4181
+ }
4182
+ candidates.add(node);
4183
+ }
4184
+ if (candidates.size !== 1) {
4185
+ return null;
4186
+ }
4187
+ return [...candidates][0];
4188
+ }
4162
4189
  /**
4163
4190
  * Two candidates give null, since ambiguity is nothing. The value
4164
4191
  * itself is never a result either, or an identifier whose chain went
@@ -5286,7 +5313,27 @@ function functionValueOf(value, resolution) {
5286
5313
  return null;
5287
5314
  }
5288
5315
  const resolved = resolution.resolveCallable(written);
5289
- return resolved === null ? null : toFunctionRoot(resolved);
5316
+ if (resolved !== null) {
5317
+ return toFunctionRoot(resolved);
5318
+ }
5319
+ if (!Node17.isCallExpression(written)) {
5320
+ return null;
5321
+ }
5322
+ const returned = resolution.resolveReturnedCallable(written);
5323
+ return returned === null ? null : toFunctionRoot(returned);
5324
+ }
5325
+ function propertyNameOf(property) {
5326
+ if (Node17.isPropertyAssignment(property) || Node17.isShorthandPropertyAssignment(property) || Node17.isMethodDeclaration(property)) {
5327
+ return property.getName();
5328
+ }
5329
+ return null;
5330
+ }
5331
+ function propertyFunctionOf(property, resolution) {
5332
+ if (Node17.isMethodDeclaration(property)) {
5333
+ return property;
5334
+ }
5335
+ const held = propertyValueOf(property);
5336
+ return held === null ? null : functionValueOf(held, resolution);
5290
5337
  }
5291
5338
  function objectLiteralOf(value, resolution) {
5292
5339
  return literalValueOf(
@@ -8760,7 +8807,7 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
8760
8807
  }
8761
8808
  const schemaSdl = extractTypeDefsSdl(config, store);
8762
8809
  for (const typeProp of propertiesOf(resolversObj, store)) {
8763
- const typeName = resolverPropertyName(typeProp);
8810
+ const typeName = propertyNameOf(typeProp);
8764
8811
  if (typeName === null || excludeTypes.has(typeName)) {
8765
8812
  continue;
8766
8813
  }
@@ -8769,11 +8816,11 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
8769
8816
  continue;
8770
8817
  }
8771
8818
  for (const fieldProp of propertiesOf(typeObj, store)) {
8772
- const fieldName = resolverPropertyName(fieldProp);
8819
+ const fieldName = propertyNameOf(fieldProp);
8773
8820
  if (fieldName === null) {
8774
8821
  continue;
8775
8822
  }
8776
- const fn = resolverPropertyFunction(fieldProp, store);
8823
+ const fn = propertyFunctionOf(fieldProp, store);
8777
8824
  if (fn === null) {
8778
8825
  continue;
8779
8826
  }
@@ -8837,22 +8884,6 @@ function writtenSdl(expr) {
8837
8884
  }
8838
8885
  return null;
8839
8886
  }
8840
- function resolverPropertyName(prop) {
8841
- if (Node36.isPropertyAssignment(prop) || Node36.isMethodDeclaration(prop)) {
8842
- return prop.getName();
8843
- }
8844
- if (Node36.isShorthandPropertyAssignment(prop)) {
8845
- return prop.getName();
8846
- }
8847
- return null;
8848
- }
8849
- function resolverPropertyFunction(prop, resolution) {
8850
- if (Node36.isMethodDeclaration(prop)) {
8851
- return prop;
8852
- }
8853
- const held = propertyValueOf(prop);
8854
- return held === null ? null : functionValueOf(held, resolution);
8855
- }
8856
8887
 
8857
8888
  // src/discovery/index.ts
8858
8889
  function runPattern(sourceFile, pattern, resolution, mountPrefixes, expandedElsewhere) {
@@ -10249,6 +10280,7 @@ import {
10249
10280
 
10250
10281
  // src/shapes/typeShapes.ts
10251
10282
  import { createHash } from "crypto";
10283
+ import { TypeFormatFlags } from "ts-morph";
10252
10284
 
10253
10285
  // src/shapes/definitions.ts
10254
10286
  var current = null;
@@ -10410,7 +10442,7 @@ function typeToShape(type, ctx) {
10410
10442
  if (type.isEnum() || type.isEnumLiteral()) {
10411
10443
  return enumToShape(type, ctx);
10412
10444
  }
10413
- const text = type.getText(ctx.enclosing);
10445
+ const text = printedTypeName(type, ctx);
10414
10446
  if (text && text.length > 0 && text !== "__type") {
10415
10447
  return { type: "ref", name: text };
10416
10448
  }
@@ -10458,8 +10490,7 @@ function intersectionToShape(type, ctx) {
10458
10490
  if (nonRecords.length === 1 && records.length === 0) {
10459
10491
  return nonRecords[0];
10460
10492
  }
10461
- const text = type.getText(ctx.enclosing);
10462
- return { type: "ref", name: text };
10493
+ return { type: "ref", name: printedTypeName(type, ctx) };
10463
10494
  }
10464
10495
  function objectToShape(type, ctx) {
10465
10496
  const key = typeKey(type, ctx.enclosing);
@@ -10519,7 +10550,7 @@ function opaqueNamedRef(type, ctx) {
10519
10550
  if (!OPAQUE_NAMED_TYPES.has(name)) {
10520
10551
  return null;
10521
10552
  }
10522
- const text = type.getText(ctx.enclosing);
10553
+ const text = printedTypeName(type, ctx);
10523
10554
  return { type: "ref", name: text && text.length > 0 ? text : name };
10524
10555
  }
10525
10556
  function outsideProjectRef(type, ctx) {
@@ -10600,6 +10631,12 @@ function refFromType(type, ctx) {
10600
10631
  }
10601
10632
  return { type: "ref", name: withoutImportQualifiers(type.getText()) };
10602
10633
  }
10634
+ var PRINTED_NAME_FLAGS = TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.NoTruncation | TypeFormatFlags.WriteTypeArgumentsOfSignature;
10635
+ function printedTypeName(type, ctx) {
10636
+ return withoutImportQualifiers(
10637
+ type.getText(ctx.enclosing, PRINTED_NAME_FLAGS)
10638
+ );
10639
+ }
10603
10640
  var IMPORT_QUALIFIER = /import\("[^"]*"\)\./g;
10604
10641
  var withoutImportQualifiers = (text) => text.replace(IMPORT_QUALIFIER, "");
10605
10642
  function declaringFileOf(symbol) {
@@ -12265,7 +12302,7 @@ function countUnmatchedReturns(func, terminals, barriers = NO_BARRIERS) {
12265
12302
  });
12266
12303
  return unmatched;
12267
12304
  }
12268
- function extractRawBranches(func, terminalPatterns, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf, resolveCallee2) {
12305
+ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf, resolveCallee2, collectCallAccounting = false) {
12269
12306
  const terminals = findTerminals(
12270
12307
  func,
12271
12308
  terminalPatterns,
@@ -12353,8 +12390,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
12353
12390
  seenBranches.add(key);
12354
12391
  return true;
12355
12392
  });
12393
+ const terminalNodes = new Set(terminals.map(({ node }) => node));
12356
12394
  if (invocations.length > 0) {
12357
- const terminalNodes = new Set(terminals.map(({ node }) => node));
12358
12395
  const sideEffects = invocations.filter(
12359
12396
  (i) => !writesTerminal(i.node, terminalNodes)
12360
12397
  );
@@ -12370,7 +12407,39 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
12370
12407
  branch.extraEffects = [...branch.extraEffects ?? [], ...extra];
12371
12408
  }
12372
12409
  }
12373
- return { branches: distinctBranches, terminals };
12410
+ return {
12411
+ branches: distinctBranches,
12412
+ terminals,
12413
+ ...collectCallAccounting ? {
12414
+ callAccounting: invocations.map(
12415
+ (site) => accountFor(site, terminalNodes, distinctBranches)
12416
+ )
12417
+ } : {}
12418
+ };
12419
+ }
12420
+ function accountFor(site, terminalNodes, branches) {
12421
+ const { node, line } = site;
12422
+ const callee = node.getExpression().getText();
12423
+ if (writesTerminal(node, terminalNodes)) {
12424
+ return { node, callee, line, outcome: "terminal" };
12425
+ }
12426
+ const call = {
12427
+ line,
12428
+ alwaysRuns: site.alwaysRuns,
12429
+ preconditions: preconditionsOf(site.effect)
12430
+ };
12431
+ if (branches.some((branch) => firesOn(call, branch))) {
12432
+ return { node, callee, line, outcome: "invocation" };
12433
+ }
12434
+ const reachable = branches.some(
12435
+ (branch) => site.alwaysRuns || runsBefore(line, branch.terminal.location.end)
12436
+ );
12437
+ return {
12438
+ node,
12439
+ callee,
12440
+ line,
12441
+ outcome: reachable ? "unrecorded" : "unreachable"
12442
+ };
12374
12443
  }
12375
12444
 
12376
12445
  // src/bootstrap/sourceFileLookup.ts
@@ -12585,7 +12654,7 @@ function unwrapContractInit(init) {
12585
12654
  }
12586
12655
  return null;
12587
12656
  }
12588
- function extractEndpointContract(endpointNode, pattern, framework) {
12657
+ function extractEndpointContract(endpointNode, pattern, framework, resolution) {
12589
12658
  if (!Node54.isObjectLiteralExpression(endpointNode)) {
12590
12659
  return null;
12591
12660
  }
@@ -12610,9 +12679,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
12610
12679
  }
12611
12680
  }
12612
12681
  if (propName === pattern.responseExtraction.property) {
12613
- const val = prop.getInitializer();
12614
- if (val !== void 0 && Node54.isObjectLiteralExpression(val)) {
12615
- for (const respProp of val.getProperties()) {
12682
+ const written = prop.getInitializer();
12683
+ const val = written === void 0 ? null : objectLiteralOf(written, resolution);
12684
+ if (val !== null) {
12685
+ for (const respProp of propertiesOf(val, resolution)) {
12616
12686
  if (!Node54.isPropertyAssignment(respProp)) {
12617
12687
  continue;
12618
12688
  }
@@ -12651,7 +12721,12 @@ function readContract(unit, pattern, framework, resolution) {
12651
12721
  if (endpointNode === null) {
12652
12722
  return null;
12653
12723
  }
12654
- return extractEndpointContract(endpointNode, pattern, framework);
12724
+ return extractEndpointContract(
12725
+ endpointNode,
12726
+ pattern,
12727
+ framework,
12728
+ resolution
12729
+ );
12655
12730
  }
12656
12731
  const routerInfo = findRouterCall(unit);
12657
12732
  if (routerInfo === null) {
@@ -12672,7 +12747,12 @@ function readContract(unit, pattern, framework, resolution) {
12672
12747
  if (endpointInit === void 0) {
12673
12748
  continue;
12674
12749
  }
12675
- return extractEndpointContract(endpointInit, pattern, framework);
12750
+ return extractEndpointContract(
12751
+ endpointInit,
12752
+ pattern,
12753
+ framework,
12754
+ resolution
12755
+ );
12676
12756
  }
12677
12757
  return null;
12678
12758
  }
@@ -12749,7 +12829,12 @@ function readContractForClientCall(callExpression, methodName, pattern, framewor
12749
12829
  if (endpointInit === void 0) {
12750
12830
  continue;
12751
12831
  }
12752
- return extractEndpointContract(endpointInit, pattern, framework);
12832
+ return extractEndpointContract(
12833
+ endpointInit,
12834
+ pattern,
12835
+ framework,
12836
+ resolution
12837
+ );
12753
12838
  }
12754
12839
  return null;
12755
12840
  }
@@ -13509,7 +13594,11 @@ function recordEdge(edgesByChild, candidate) {
13509
13594
  // src/discovery/wrapperIndex.ts
13510
13595
  import { Node as Node58 } from "ts-morph";
13511
13596
  import { joinMountedPath as joinMountedPath3 } from "@suss/resolution";
13512
- var NO_WRAPPERS = { wrappersFor: () => [], unitsIn: () => [] };
13597
+ var NO_WRAPPERS = {
13598
+ wrappersFor: () => [],
13599
+ unfollowedFor: () => [],
13600
+ unitsIn: () => []
13601
+ };
13513
13602
  var ANONYMOUS = "<anon>";
13514
13603
  function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13515
13604
  const workByPack = /* @__PURE__ */ new Map();
@@ -13535,21 +13624,32 @@ function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13535
13624
  }
13536
13625
  }
13537
13626
  const bySubject = /* @__PURE__ */ new Map();
13627
+ const unfollowedBySubject = /* @__PURE__ */ new Map();
13538
13628
  const unitsByFile = /* @__PURE__ */ new Map();
13629
+ const stopsSeen = /* @__PURE__ */ new Set();
13539
13630
  let found = false;
13540
13631
  for (const [packName, work] of workByPack) {
13541
13632
  const candidates = [];
13542
13633
  for (const { sourceFile, pattern, match, wraps } of work) {
13543
- candidates.push(
13544
- ...discoverWrapperRegistrations(
13545
- sourceFile,
13546
- pattern,
13547
- match,
13548
- wraps,
13549
- resolution,
13550
- mountPrefixes
13551
- )
13634
+ const scan = discoverWrapperRegistrations(
13635
+ sourceFile,
13636
+ pattern,
13637
+ match,
13638
+ wraps,
13639
+ resolution,
13640
+ mountPrefixes
13552
13641
  );
13642
+ candidates.push(...scan.candidates);
13643
+ for (const { subjectId, callId, stop } of scan.unresolved) {
13644
+ if (stopsSeen.has(callId)) {
13645
+ continue;
13646
+ }
13647
+ stopsSeen.add(callId);
13648
+ found = true;
13649
+ const stops = unfollowedBySubject.get(subjectId) ?? [];
13650
+ stops.push(stop);
13651
+ unfollowedBySubject.set(subjectId, stops);
13652
+ }
13553
13653
  }
13554
13654
  for (const candidate of mostSpecific(candidates)) {
13555
13655
  found = true;
@@ -13567,6 +13667,7 @@ function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13567
13667
  }
13568
13668
  return {
13569
13669
  wrappersFor: (subjectId) => bySubject.get(subjectId) ?? [],
13670
+ unfollowedFor: (subjectId) => unfollowedBySubject.get(subjectId) ?? [],
13570
13671
  unitsIn: (file, pack) => unitsByFile.get(unitKey(file, pack)) ?? []
13571
13672
  };
13572
13673
  }
@@ -13600,10 +13701,20 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13600
13701
  match.importName,
13601
13702
  resolution
13602
13703
  );
13704
+ if ("constructorOption" in wraps) {
13705
+ return discoverConstructorOptions(
13706
+ sourceFile,
13707
+ pattern,
13708
+ wraps,
13709
+ subjects,
13710
+ resolution
13711
+ );
13712
+ }
13603
13713
  if (subjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution)) {
13604
- return [];
13714
+ return { candidates: [], unresolved: [] };
13605
13715
  }
13606
13716
  const candidates = [];
13717
+ const unresolved = [];
13607
13718
  sourceFile.forEachDescendant((node) => {
13608
13719
  if (!Node58.isCallExpression(node)) {
13609
13720
  return;
@@ -13626,8 +13737,13 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13626
13737
  if (targetArg === void 0) {
13627
13738
  return;
13628
13739
  }
13740
+ const subjectId = nodeId(subjectNode);
13629
13741
  const target = functionValueOf(targetArg, resolution);
13630
13742
  if (target === null) {
13743
+ const stop = factoryStopOf(targetArg);
13744
+ if (stop !== null) {
13745
+ unresolved.push({ subjectId, callId: nodeId(node), stop });
13746
+ }
13631
13747
  return;
13632
13748
  }
13633
13749
  if (wraps.arity !== void 0 && target.getParameters().length !== wraps.arity) {
@@ -13637,29 +13753,136 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13637
13753
  if (scope === null) {
13638
13754
  return;
13639
13755
  }
13640
- const subjectId = nodeId(subjectNode);
13641
13756
  const mountedScope = scope === void 0 ? void 0 : mountedAt(subjectId, mountPrefixes, scope);
13642
- const named2 = functionNameOrAnon(target) !== ANONYMOUS;
13643
- candidates.push({
13644
- subjectId,
13645
- callId: nodeId(node),
13646
- targetId: nodeId(target),
13647
- byArity: wraps.arity !== void 0,
13648
- target,
13649
- pattern,
13650
- registeredIn: sourceFile.getFilePath(),
13651
- named: named2,
13652
- reference: {
13653
- file: target.getSourceFile().getFilePath(),
13654
- // A function written out at the registration call has no name
13655
- // of its own, so it goes by the method that registered it.
13656
- name: named2 ? functionNameOrAnon(target) : wraps.method,
13657
- ...wraps.throwParam === void 0 ? {} : { onThrow: true },
13658
- ...mountedScope === void 0 ? {} : { scope: mountedScope }
13659
- }
13660
- });
13757
+ candidates.push(
13758
+ candidateOf(
13759
+ {
13760
+ subjectId,
13761
+ callId: nodeId(node),
13762
+ target,
13763
+ label: labelFor(targetArg, wraps),
13764
+ byArity: wraps.arity !== void 0,
13765
+ onThrow: wraps.throwParam !== void 0,
13766
+ scope: mountedScope
13767
+ },
13768
+ pattern,
13769
+ sourceFile
13770
+ )
13771
+ );
13661
13772
  });
13662
- return candidates;
13773
+ return { candidates, unresolved };
13774
+ }
13775
+ function discoverConstructorOptions(sourceFile, pattern, wraps, subjects, resolution) {
13776
+ const candidates = [];
13777
+ const unresolved = [];
13778
+ const seen = /* @__PURE__ */ new Set();
13779
+ for (const construction of subjects.values()) {
13780
+ const subjectId = nodeId(construction);
13781
+ if (seen.has(subjectId) || construction.getSourceFile() !== sourceFile) {
13782
+ continue;
13783
+ }
13784
+ seen.add(subjectId);
13785
+ const option = constructorOptionOf(construction, wraps, resolution);
13786
+ if (option === void 0) {
13787
+ continue;
13788
+ }
13789
+ const callId = nodeId(option);
13790
+ const written = propertyValueOf(option);
13791
+ const target = propertyFunctionOf(option, resolution);
13792
+ if (target === null) {
13793
+ const stop = written === null ? null : factoryStopOf(written);
13794
+ if (stop !== null) {
13795
+ unresolved.push({ subjectId, callId, stop });
13796
+ }
13797
+ continue;
13798
+ }
13799
+ candidates.push(
13800
+ candidateOf(
13801
+ {
13802
+ subjectId,
13803
+ callId,
13804
+ target,
13805
+ label: (written === null ? void 0 : factoryNameOf(written)) ?? wraps.constructorOption,
13806
+ byArity: false,
13807
+ onThrow: wraps.throwParam !== void 0,
13808
+ scope: void 0
13809
+ },
13810
+ pattern,
13811
+ sourceFile
13812
+ )
13813
+ );
13814
+ }
13815
+ return { candidates, unresolved };
13816
+ }
13817
+ function constructorOptionOf(construction, wraps, resolution) {
13818
+ if (!(Node58.isNewExpression(construction) || Node58.isCallExpression(construction))) {
13819
+ return void 0;
13820
+ }
13821
+ const optionsArg = construction.getArguments()[wraps.targetPosition];
13822
+ if (optionsArg === void 0) {
13823
+ return void 0;
13824
+ }
13825
+ const options = objectLiteralOf(optionsArg, resolution);
13826
+ if (options === null) {
13827
+ return void 0;
13828
+ }
13829
+ return propertiesOf(options, resolution).find(
13830
+ (property) => propertyNameOf(property) === wraps.constructorOption
13831
+ );
13832
+ }
13833
+ function candidateOf(registration, pattern, sourceFile) {
13834
+ const { target, label, onThrow, scope } = registration;
13835
+ const named2 = functionNameOrAnon(target) !== ANONYMOUS;
13836
+ return {
13837
+ subjectId: registration.subjectId,
13838
+ callId: registration.callId,
13839
+ targetId: nodeId(target),
13840
+ byArity: registration.byArity,
13841
+ target,
13842
+ pattern,
13843
+ registeredIn: sourceFile.getFilePath(),
13844
+ named: named2,
13845
+ reference: {
13846
+ file: target.getSourceFile().getFilePath(),
13847
+ name: named2 ? functionNameOrAnon(target) : label,
13848
+ ...onThrow ? { onThrow: true } : {},
13849
+ ...scope === void 0 ? {} : { scope }
13850
+ }
13851
+ };
13852
+ }
13853
+ function labelFor(targetArg, wraps) {
13854
+ return factoryNameOf(targetArg) ?? wraps.method;
13855
+ }
13856
+ function factoryNameOf(targetArg) {
13857
+ const written = factKeyOf(targetArg);
13858
+ if (!Node58.isCallExpression(written)) {
13859
+ return void 0;
13860
+ }
13861
+ const callee = written.getExpression();
13862
+ if (Node58.isIdentifier(callee)) {
13863
+ return callee.getText();
13864
+ }
13865
+ if (Node58.isPropertyAccessExpression(callee)) {
13866
+ return callee.getName();
13867
+ }
13868
+ return void 0;
13869
+ }
13870
+ function factoryStopOf(targetArg) {
13871
+ const written = factKeyOf(targetArg);
13872
+ if (!Node58.isCallExpression(written)) {
13873
+ return null;
13874
+ }
13875
+ const callee = factoryNameOf(targetArg);
13876
+ if (callee === void 0) {
13877
+ return null;
13878
+ }
13879
+ const reason = classifyStop(
13880
+ declarationsBehind(written.getExpression().getSymbol())
13881
+ );
13882
+ if (!worthRecording(reason)) {
13883
+ return null;
13884
+ }
13885
+ return { callee, reason: "unresolvedWrapper" };
13663
13886
  }
13664
13887
  function mountedAt(subjectId, mountPrefixes, scope) {
13665
13888
  const prefix = mountPrefixes?.prefixForId?.(subjectId) ?? "";
@@ -14034,22 +14257,23 @@ import { Node as Node60 } from "ts-morph";
14034
14257
  import { functionCallBinding, TargetPlacements } from "@suss/behavioral-ir";
14035
14258
  import { Database as Database3, evaluate as evaluate4, lit as lit4, rule as rule4, variable as variable2 } from "@suss/datalog";
14036
14259
  import { assembleSummary as assembleSummary2 } from "@suss/extractor";
14260
+ var GENERIC_TERMINALS = [
14261
+ { kind: "return", match: { type: "returnStatement" }, extraction: {} },
14262
+ { kind: "throw", match: { type: "throwExpression" }, extraction: {} },
14263
+ {
14264
+ // Implicit fall-through at the end of a function body: covers
14265
+ // void-returning orchestrators that never write `return`.
14266
+ kind: "return",
14267
+ match: { type: "functionFallthrough" },
14268
+ extraction: {}
14269
+ }
14270
+ ];
14037
14271
  var reachablePack = {
14038
14272
  name: "reachable",
14039
14273
  languages: ["typescript"],
14040
14274
  protocol: "in-process",
14041
14275
  discovery: [],
14042
- terminals: [
14043
- { kind: "return", match: { type: "returnStatement" }, extraction: {} },
14044
- { kind: "throw", match: { type: "throwExpression" }, extraction: {} },
14045
- {
14046
- // Implicit fall-through at the end of a function body: covers
14047
- // void-returning orchestrators that never write `return`.
14048
- kind: "return",
14049
- match: { type: "functionFallthrough" },
14050
- extraction: {}
14051
- }
14052
- ],
14276
+ terminals: GENERIC_TERMINALS,
14053
14277
  inputMapping: { type: "allPositional" }
14054
14278
  };
14055
14279
  function nodeKey(func) {
@@ -15854,10 +16078,10 @@ var FUNCTION_FALLTHROUGH_TERMINAL = {
15854
16078
  match: { type: "functionFallthrough" },
15855
16079
  extraction: {}
15856
16080
  };
15857
- function thrownValueAt(unit) {
15858
- return unit.pattern?.wraps?.throwParam;
16081
+ function frameworkValueAt(unit) {
16082
+ return unit.pattern?.wraps?.throwParam ?? unit.pattern?.wraps?.resultParam;
15859
16083
  }
15860
- function pastThrownValue(terminals, at) {
16084
+ function pastFrameworkValue(terminals, at) {
15861
16085
  if (at === void 0) {
15862
16086
  return terminals;
15863
16087
  }
@@ -15871,7 +16095,7 @@ function pastThrownValue(terminals, at) {
15871
16095
  } : pattern
15872
16096
  );
15873
16097
  }
15874
- function rolesPastThrownValue(mapping, at) {
16098
+ function rolesPastFrameworkValue(mapping, at) {
15875
16099
  if (at === void 0 || mapping.type !== "positionalParams") {
15876
16100
  return mapping;
15877
16101
  }
@@ -15897,7 +16121,7 @@ function continuationTerminal(unit) {
15897
16121
  }
15898
16122
  function terminalsFor(unit, pack) {
15899
16123
  const declared = [
15900
- ...unit.terminals ?? pastThrownValue(pack.terminals, thrownValueAt(unit)),
16124
+ ...unit.terminals ?? pastFrameworkValue(pack.terminals, frameworkValueAt(unit)),
15901
16125
  ...continuationTerminal(unit)
15902
16126
  ];
15903
16127
  if (unit.callSite === void 0) {
@@ -15915,7 +16139,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
15915
16139
  }
15916
16140
  const params = extractParameters(
15917
16141
  func,
15918
- unit.inputMapping ?? rolesPastThrownValue(pack.inputMapping, thrownValueAt(unit))
16142
+ unit.inputMapping ?? rolesPastFrameworkValue(pack.inputMapping, frameworkValueAt(unit))
15919
16143
  );
15920
16144
  const extracted = extractRawBranches(
15921
16145
  func,
@@ -16417,8 +16641,10 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
16417
16641
  }
16418
16642
  }
16419
16643
  const summary = assembleSummary3(raw, options);
16420
- if (unit.unfollowed !== void 0 && options?.gapHandling !== "silent") {
16421
- summary.gaps.push(unfollowedCallGap(unit.unfollowed));
16644
+ if (options?.gapHandling !== "silent") {
16645
+ for (const stop of unfollowedStopsOf(unit, wrappers)) {
16646
+ summary.gaps.push(unfollowedCallGap(stop));
16647
+ }
16422
16648
  }
16423
16649
  if (unit.metadata !== void 0 && Object.keys(unit.metadata).length > 0) {
16424
16650
  summary.metadata = {
@@ -16471,6 +16697,13 @@ function stampWrappers(raw, unit, wrappers) {
16471
16697
  recordFileDependency(wrapper.file);
16472
16698
  }
16473
16699
  }
16700
+ function unfollowedStopsOf(unit, wrappers) {
16701
+ const stops = unit.unfollowed === void 0 ? [] : [unit.unfollowed];
16702
+ if (wrappers === void 0 || unit.registrationSubjectId === void 0) {
16703
+ return stops;
16704
+ }
16705
+ return [...stops, ...wrappers.unfollowedFor(unit.registrationSubjectId)];
16706
+ }
16474
16707
  function emitLibraryEnvReadMarkers(summaries, project, frameworks) {
16475
16708
  for (const pack of frameworks) {
16476
16709
  for (const declared of pack.libraryEnvVars ?? []) {
@@ -17185,7 +17418,7 @@ function createTypeScriptAdapter(suppliedConfig) {
17185
17418
  });
17186
17419
  const composed = timer.time(
17187
17420
  "composeWrappers",
17188
- () => composeWrappers(enriched)
17421
+ () => composeWrappers(enriched, config.extractorOptions ?? {})
17189
17422
  );
17190
17423
  if (config.onTiming !== void 0) {
17191
17424
  config.onTiming(timer.report());
@@ -17809,6 +18042,8 @@ function stubEvidence(options) {
17809
18042
  }
17810
18043
  export {
17811
18044
  ADAPTER_VERSION,
18045
+ GENERIC_TERMINALS,
18046
+ NO_BARRIERS,
17812
18047
  ResolutionStore,
17813
18048
  TypeScriptWhySession,
17814
18049
  accessContextFor,
@@ -17829,6 +18064,7 @@ export {
17829
18064
  findNearestTsconfig,
17830
18065
  findTerminals,
17831
18066
  functionTargetOf,
18067
+ hasBody,
17832
18068
  importDeclarationsOf,
17833
18069
  importedNamesOf,
17834
18070
  importedRootsOf,
@@ -17844,6 +18080,7 @@ export {
17844
18080
  resolveAliasedSymbol,
17845
18081
  resolveSubject,
17846
18082
  rootIdentifier,
18083
+ startsItsOwnScope,
17847
18084
  stubEvidence,
17848
18085
  stubEvidenceIn,
17849
18086
  workspaceRootFor