@suss/adapter-ruby 0.21.0 → 0.21.1

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.
Files changed (3) hide show
  1. package/dist/index.cjs +105 -45
  2. package/dist/index.js +108 -48
  3. package/package.json +4 -4
package/dist/index.cjs CHANGED
@@ -15319,7 +15319,7 @@ function date4(params) {
15319
15319
  // ../../../node_modules/zod/v4/classic/external.js
15320
15320
  config(en_default());
15321
15321
 
15322
- // ../../ir-core/dist/chunk-QHFMZPEG.js
15322
+ // ../../ir-core/dist/chunk-PPQWK62O.js
15323
15323
  function gqlIdentityKey(typeName, fieldName) {
15324
15324
  return `gql:${typeName}.${fieldName}`;
15325
15325
  }
@@ -15605,6 +15605,42 @@ var metricSemantics = defineBoundarySemantics({
15605
15605
  }
15606
15606
  }
15607
15607
  });
15608
+ var HOLE_SPLIT = /(\{[^}]*\})/;
15609
+ function isHole(piece) {
15610
+ return piece.startsWith("{") && piece.endsWith("}");
15611
+ }
15612
+ function parseBoundaryName(name) {
15613
+ const parts = name.split(HOLE_SPLIT).filter((piece) => piece !== "").map(
15614
+ (piece) => isHole(piece) ? { type: "hole", label: piece.slice(1, -1) } : { type: "text", text: piece }
15615
+ );
15616
+ const only = parts.length === 1 ? parts[0] : void 0;
15617
+ if (only !== void 0 && only.type === "hole") {
15618
+ return { type: "reference", path: only.label.split(".") };
15619
+ }
15620
+ if (parts.some((part) => part.type === "hole")) {
15621
+ return { type: "pattern", parts };
15622
+ }
15623
+ return { type: "literal", value: name };
15624
+ }
15625
+ function patternHole(label) {
15626
+ return `{${label}}`;
15627
+ }
15628
+ function namesNothing(name) {
15629
+ return parseBoundaryName(name).type === "reference";
15630
+ }
15631
+ function referenceOf(name) {
15632
+ if (name.type !== "reference") {
15633
+ return null;
15634
+ }
15635
+ const root = name.path[0];
15636
+ if (root === void 0 || name.path.some((part) => part === "")) {
15637
+ return null;
15638
+ }
15639
+ return { root, fields: name.path.slice(1) };
15640
+ }
15641
+ function referenceFromName(name) {
15642
+ return referenceOf(parseBoundaryName(name));
15643
+ }
15608
15644
  var SCHEME_ORIGIN = /^[a-zA-Z][a-zA-Z\d+.-]*:\/\/[^/]*/;
15609
15645
  var PROTOCOL_RELATIVE_ORIGIN = /^\/\/[^/]*/;
15610
15646
  function pathAfterOrigin(text) {
@@ -15631,9 +15667,9 @@ var RestSemanticsSchema = external_exports.object({
15631
15667
  declaredResponses: external_exports.array(external_exports.number()).optional()
15632
15668
  });
15633
15669
  var OPENING_HOLE = /^\{([^{}]+)\}(.*)$/;
15634
- function variableOf(label) {
15635
- const parts = label.split(".");
15636
- return parts[parts.length - 1] ?? label;
15670
+ function baseUrlReference(semantics) {
15671
+ const label = OPENING_HOLE.exec(semantics.path ?? "")?.[1];
15672
+ return label === void 0 ? null : referenceFromName(patternHole(label));
15637
15673
  }
15638
15674
  function normalizePath(path4) {
15639
15675
  let normalized = path4.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
@@ -15767,22 +15803,20 @@ var restSemantics = defineBoundarySemantics({
15767
15803
  * route parameter, and `/orders/{id}` means every id rather than a
15768
15804
  * variable somebody set.
15769
15805
  */
15770
- groundName(semantics, deployedAs) {
15771
- if (semantics.path === null) {
15806
+ groundName(semantics, deployment) {
15807
+ const reference = baseUrlReference(semantics);
15808
+ if (reference === null) {
15772
15809
  return null;
15773
15810
  }
15774
- const opening = OPENING_HOLE.exec(semantics.path);
15775
- if (opening === null) {
15776
- return null;
15777
- }
15778
- const [, label, rest] = opening;
15779
- const base = deployedAs(variableOf(label));
15811
+ const base = deployment.setTo(reference);
15780
15812
  if (base === null) {
15781
15813
  return null;
15782
15814
  }
15815
+ const rest = OPENING_HOLE.exec(semantics.path ?? "")?.[2] ?? "";
15783
15816
  const grounded = pathAfterOrigin(`${base}${rest}`);
15784
15817
  return { ...semantics, path: grounded === "" ? "/" : grounded };
15785
15818
  },
15819
+ nameReference: baseUrlReference,
15786
15820
  ruleBoundary: {
15787
15821
  // "METHOD /path": one leading token, then an absolute path.
15788
15822
  claims(raw) {
@@ -15858,6 +15892,9 @@ var StorageSemanticsSchema = external_exports.object({
15858
15892
  */
15859
15893
  accessPath: external_exports.string().nullable()
15860
15894
  });
15895
+ function containerReference(semantics) {
15896
+ return semantics.container === null ? null : referenceFromName(semantics.container);
15897
+ }
15861
15898
  var storageSemantics = defineBoundarySemantics({
15862
15899
  name: "storage",
15863
15900
  schema: StorageSemanticsSchema,
@@ -15874,7 +15911,21 @@ var storageSemantics = defineBoundarySemantics({
15874
15911
  exchangesHttpResponses: false,
15875
15912
  reportsUnpairedItself: false,
15876
15913
  identityKey: () => null,
15877
- displayLabel: storageLabel
15914
+ displayLabel: storageLabel,
15915
+ /**
15916
+ * A container the source states as a variable is whatever the
15917
+ * deployment sets that variable to. `{SUBSCRIBERS_TABLE}` in the
15918
+ * code and `prod-subscribers-v1` in the manifest are one table.
15919
+ */
15920
+ groundName(semantics, deployment) {
15921
+ const reference = containerReference(semantics);
15922
+ if (reference === null) {
15923
+ return null;
15924
+ }
15925
+ const name = deployment.setTo(reference);
15926
+ return name === null ? null : { ...semantics, container: name };
15927
+ },
15928
+ nameReference: containerReference
15878
15929
  }
15879
15930
  });
15880
15931
  function storageLabel(semantics) {
@@ -15889,6 +15940,9 @@ var UnitInvocationSemanticsSchema = DeployableUnitSchema.extend({
15889
15940
  name: external_exports.literal("unit-invocation"),
15890
15941
  instanceName: DeployableUnitSchema.shape.instanceName.nullable()
15891
15942
  });
15943
+ function calleeReference(semantics) {
15944
+ return semantics.instanceName === null ? null : referenceFromName(semantics.instanceName);
15945
+ }
15892
15946
  var unitInvocationSemantics = defineBoundarySemantics({
15893
15947
  name: "unit-invocation",
15894
15948
  schema: UnitInvocationSemanticsSchema,
@@ -15911,8 +15965,13 @@ var unitInvocationSemantics = defineBoundarySemantics({
15911
15965
  * being reported as a problem here.
15912
15966
  */
15913
15967
  reportsUnpairedItself: false,
15968
+ /**
15969
+ * A callee the source states only as a variable is not a name for
15970
+ * anything until the deployment fills it in, so it keys as nothing
15971
+ * rather than as a bucket that would agree with itself alone.
15972
+ */
15914
15973
  identityKey(semantics) {
15915
- if (semantics.instanceName === null) {
15974
+ if (semantics.instanceName === null || namesNothing(semantics.instanceName)) {
15916
15975
  return null;
15917
15976
  }
15918
15977
  return unitIdentityKey(
@@ -15928,7 +15987,23 @@ var unitInvocationSemantics = defineBoundarySemantics({
15928
15987
  semantics.deploymentTarget,
15929
15988
  semantics.instanceName
15930
15989
  );
15931
- }
15990
+ },
15991
+ /**
15992
+ * A call that reads its callee's name out of the environment
15993
+ * reaches whichever resource the template wires that variable to.
15994
+ * The logical id is the answer rather than the deployed name,
15995
+ * because the invoked unit's own summary is keyed by the logical
15996
+ * id and neither side ever writes the other's string.
15997
+ */
15998
+ groundName(semantics, deployment) {
15999
+ const reference = calleeReference(semantics);
16000
+ if (reference === null) {
16001
+ return null;
16002
+ }
16003
+ const logicalId = deployment.pointsAt(reference);
16004
+ return logicalId === null ? null : { ...semantics, instanceName: logicalId };
16005
+ },
16006
+ nameReference: calleeReference
15932
16007
  }
15933
16008
  });
15934
16009
  var SemanticsSchema = external_exports.discriminatedUnion("name", [
@@ -16236,9 +16311,9 @@ var RESOLUTION_RULES = [
16236
16311
  [(0, import_datalog2.lit)("invokes", (0, import_datalog2.variable)("r"), (0, import_datalog2.variable)("f")), (0, import_datalog2.lit)("returnsValue", (0, import_datalog2.variable)("f"), (0, import_datalog2.variable)("ret"))],
16237
16312
  "call result"
16238
16313
  ),
16239
- // Where a walk gets to, and whether it ran a call on the way. A value
16240
- // step keeps whatever the rest of the walk was, and a result step
16241
- // makes the whole walk one that ran a call.
16314
+ // Where a walk gets to, and whether it ran a call on the way. The walk
16315
+ // so far comes first, so demand stays on the value asked about; the
16316
+ // README says what the other order cost.
16242
16317
  (0, import_datalog2.rule)(
16243
16318
  "reaches",
16244
16319
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind")],
@@ -16248,27 +16323,27 @@ var RESOLUTION_RULES = [
16248
16323
  "reaches",
16249
16324
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind")],
16250
16325
  [
16251
- (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), VALUE_STEP),
16252
- (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind"))
16326
+ (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), VALUE_STEP),
16327
+ (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), (0, import_datalog2.variable)("kind"))
16253
16328
  ]
16254
16329
  ),
16255
- // Two rules rather than one leaving the rest of the walk's kind free.
16256
- // A free kind is a second question about the same relation, and a
16330
+ // Two rules rather than one leaving the next step's kind free. A free
16331
+ // kind is a second question about the same relation, and a
16257
16332
  // demand-driven run then derives both to answer either.
16258
16333
  (0, import_datalog2.rule)(
16259
16334
  "reaches",
16260
16335
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), RESULT_STEP],
16261
16336
  [
16262
- (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
16263
- (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), VALUE_STEP)
16337
+ (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
16338
+ (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), VALUE_STEP)
16264
16339
  ]
16265
16340
  ),
16266
16341
  (0, import_datalog2.rule)(
16267
16342
  "reaches",
16268
16343
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"), RESULT_STEP],
16269
16344
  [
16270
- (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
16271
- (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), RESULT_STEP)
16345
+ (0, import_datalog2.lit)("reaches", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y"), RESULT_STEP),
16346
+ (0, import_datalog2.lit)("stepsTo", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"), RESULT_STEP)
16272
16347
  ]
16273
16348
  ),
16274
16349
  // What a value comes down to: the walk that never ran a call, stopped
@@ -16614,29 +16689,14 @@ var RESOLUTION_QUESTIONS = [
16614
16689
  // here demands reaches or callsInto. The chains are closures with
16615
16690
  // no depth bound: an alias run of any length resolves.
16616
16691
  (0, import_datalog2.rule)("callOriginChain", [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("x")], [(0, import_datalog2.lit)("wantedCallOrigin", (0, import_datalog2.variable)("x"))]),
16692
+ // The chain with at least one hop taken, which is what tells a
16693
+ // destructured binding apart from asking about a node directly. The
16694
+ // whole chain is the seed plus those hops.
16617
16695
  (0, import_datalog2.rule)(
16618
16696
  "callOriginChain",
16619
16697
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
16620
- [(0, import_datalog2.lit)("callOriginChain", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y")), (0, import_datalog2.lit)("binds", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"))]
16621
- ),
16622
- (0, import_datalog2.rule)(
16623
- "callOriginChain",
16624
- [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
16625
- [
16626
- (0, import_datalog2.lit)("callOriginChain", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y")),
16627
- (0, import_datalog2.lit)("endsHolding", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"))
16628
- ]
16629
- ),
16630
- (0, import_datalog2.rule)(
16631
- "callOriginChain",
16632
- [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
16633
- [
16634
- (0, import_datalog2.lit)("callOriginChain", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("y")),
16635
- (0, import_datalog2.lit)("fallbackBranch", (0, import_datalog2.variable)("y"), (0, import_datalog2.variable)("z"))
16636
- ]
16698
+ [(0, import_datalog2.lit)("callOriginChainStepped", (0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z"))]
16637
16699
  ),
16638
- // The chain with at least one hop taken, which is what tells a
16639
- // destructured binding apart from asking about a node directly.
16640
16700
  (0, import_datalog2.rule)(
16641
16701
  "callOriginChainStepped",
16642
16702
  [(0, import_datalog2.variable)("x"), (0, import_datalog2.variable)("z")],
package/dist/index.js CHANGED
@@ -401,7 +401,7 @@ function inheritedStatements(ancestry, blockConfigures) {
401
401
  }
402
402
 
403
403
  // src/discovery.ts
404
- import { dispatchByType, graphqlResolverBinding } from "@suss/behavioral-ir";
404
+ import { dispatchByType as dispatchByType2, graphqlResolverBinding } from "@suss/behavioral-ir";
405
405
  import { unreadableReading } from "@suss/extractor";
406
406
 
407
407
  // src/paths/effects.ts
@@ -15268,7 +15268,7 @@ function date4(params) {
15268
15268
  // ../../../node_modules/zod/v4/classic/external.js
15269
15269
  config(en_default());
15270
15270
 
15271
- // ../../ir-core/dist/chunk-QHFMZPEG.js
15271
+ // ../../ir-core/dist/chunk-PPQWK62O.js
15272
15272
  function gqlIdentityKey(typeName, fieldName) {
15273
15273
  return `gql:${typeName}.${fieldName}`;
15274
15274
  }
@@ -15554,6 +15554,42 @@ var metricSemantics = defineBoundarySemantics({
15554
15554
  }
15555
15555
  }
15556
15556
  });
15557
+ var HOLE_SPLIT = /(\{[^}]*\})/;
15558
+ function isHole(piece) {
15559
+ return piece.startsWith("{") && piece.endsWith("}");
15560
+ }
15561
+ function parseBoundaryName(name) {
15562
+ const parts = name.split(HOLE_SPLIT).filter((piece) => piece !== "").map(
15563
+ (piece) => isHole(piece) ? { type: "hole", label: piece.slice(1, -1) } : { type: "text", text: piece }
15564
+ );
15565
+ const only = parts.length === 1 ? parts[0] : void 0;
15566
+ if (only !== void 0 && only.type === "hole") {
15567
+ return { type: "reference", path: only.label.split(".") };
15568
+ }
15569
+ if (parts.some((part) => part.type === "hole")) {
15570
+ return { type: "pattern", parts };
15571
+ }
15572
+ return { type: "literal", value: name };
15573
+ }
15574
+ function patternHole(label) {
15575
+ return `{${label}}`;
15576
+ }
15577
+ function namesNothing(name) {
15578
+ return parseBoundaryName(name).type === "reference";
15579
+ }
15580
+ function referenceOf(name) {
15581
+ if (name.type !== "reference") {
15582
+ return null;
15583
+ }
15584
+ const root = name.path[0];
15585
+ if (root === void 0 || name.path.some((part) => part === "")) {
15586
+ return null;
15587
+ }
15588
+ return { root, fields: name.path.slice(1) };
15589
+ }
15590
+ function referenceFromName(name) {
15591
+ return referenceOf(parseBoundaryName(name));
15592
+ }
15557
15593
  var SCHEME_ORIGIN = /^[a-zA-Z][a-zA-Z\d+.-]*:\/\/[^/]*/;
15558
15594
  var PROTOCOL_RELATIVE_ORIGIN = /^\/\/[^/]*/;
15559
15595
  function pathAfterOrigin(text) {
@@ -15580,9 +15616,9 @@ var RestSemanticsSchema = external_exports.object({
15580
15616
  declaredResponses: external_exports.array(external_exports.number()).optional()
15581
15617
  });
15582
15618
  var OPENING_HOLE = /^\{([^{}]+)\}(.*)$/;
15583
- function variableOf(label) {
15584
- const parts = label.split(".");
15585
- return parts[parts.length - 1] ?? label;
15619
+ function baseUrlReference(semantics) {
15620
+ const label = OPENING_HOLE.exec(semantics.path ?? "")?.[1];
15621
+ return label === void 0 ? null : referenceFromName(patternHole(label));
15586
15622
  }
15587
15623
  function normalizePath(path4) {
15588
15624
  let normalized = path4.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
@@ -15716,22 +15752,20 @@ var restSemantics = defineBoundarySemantics({
15716
15752
  * route parameter, and `/orders/{id}` means every id rather than a
15717
15753
  * variable somebody set.
15718
15754
  */
15719
- groundName(semantics, deployedAs) {
15720
- if (semantics.path === null) {
15755
+ groundName(semantics, deployment) {
15756
+ const reference = baseUrlReference(semantics);
15757
+ if (reference === null) {
15721
15758
  return null;
15722
15759
  }
15723
- const opening = OPENING_HOLE.exec(semantics.path);
15724
- if (opening === null) {
15725
- return null;
15726
- }
15727
- const [, label, rest] = opening;
15728
- const base = deployedAs(variableOf(label));
15760
+ const base = deployment.setTo(reference);
15729
15761
  if (base === null) {
15730
15762
  return null;
15731
15763
  }
15764
+ const rest = OPENING_HOLE.exec(semantics.path ?? "")?.[2] ?? "";
15732
15765
  const grounded = pathAfterOrigin(`${base}${rest}`);
15733
15766
  return { ...semantics, path: grounded === "" ? "/" : grounded };
15734
15767
  },
15768
+ nameReference: baseUrlReference,
15735
15769
  ruleBoundary: {
15736
15770
  // "METHOD /path": one leading token, then an absolute path.
15737
15771
  claims(raw) {
@@ -15807,6 +15841,9 @@ var StorageSemanticsSchema = external_exports.object({
15807
15841
  */
15808
15842
  accessPath: external_exports.string().nullable()
15809
15843
  });
15844
+ function containerReference(semantics) {
15845
+ return semantics.container === null ? null : referenceFromName(semantics.container);
15846
+ }
15810
15847
  var storageSemantics = defineBoundarySemantics({
15811
15848
  name: "storage",
15812
15849
  schema: StorageSemanticsSchema,
@@ -15823,7 +15860,21 @@ var storageSemantics = defineBoundarySemantics({
15823
15860
  exchangesHttpResponses: false,
15824
15861
  reportsUnpairedItself: false,
15825
15862
  identityKey: () => null,
15826
- displayLabel: storageLabel
15863
+ displayLabel: storageLabel,
15864
+ /**
15865
+ * A container the source states as a variable is whatever the
15866
+ * deployment sets that variable to. `{SUBSCRIBERS_TABLE}` in the
15867
+ * code and `prod-subscribers-v1` in the manifest are one table.
15868
+ */
15869
+ groundName(semantics, deployment) {
15870
+ const reference = containerReference(semantics);
15871
+ if (reference === null) {
15872
+ return null;
15873
+ }
15874
+ const name = deployment.setTo(reference);
15875
+ return name === null ? null : { ...semantics, container: name };
15876
+ },
15877
+ nameReference: containerReference
15827
15878
  }
15828
15879
  });
15829
15880
  function storageLabel(semantics) {
@@ -15838,6 +15889,9 @@ var UnitInvocationSemanticsSchema = DeployableUnitSchema.extend({
15838
15889
  name: external_exports.literal("unit-invocation"),
15839
15890
  instanceName: DeployableUnitSchema.shape.instanceName.nullable()
15840
15891
  });
15892
+ function calleeReference(semantics) {
15893
+ return semantics.instanceName === null ? null : referenceFromName(semantics.instanceName);
15894
+ }
15841
15895
  var unitInvocationSemantics = defineBoundarySemantics({
15842
15896
  name: "unit-invocation",
15843
15897
  schema: UnitInvocationSemanticsSchema,
@@ -15860,8 +15914,13 @@ var unitInvocationSemantics = defineBoundarySemantics({
15860
15914
  * being reported as a problem here.
15861
15915
  */
15862
15916
  reportsUnpairedItself: false,
15917
+ /**
15918
+ * A callee the source states only as a variable is not a name for
15919
+ * anything until the deployment fills it in, so it keys as nothing
15920
+ * rather than as a bucket that would agree with itself alone.
15921
+ */
15863
15922
  identityKey(semantics) {
15864
- if (semantics.instanceName === null) {
15923
+ if (semantics.instanceName === null || namesNothing(semantics.instanceName)) {
15865
15924
  return null;
15866
15925
  }
15867
15926
  return unitIdentityKey(
@@ -15877,7 +15936,23 @@ var unitInvocationSemantics = defineBoundarySemantics({
15877
15936
  semantics.deploymentTarget,
15878
15937
  semantics.instanceName
15879
15938
  );
15880
- }
15939
+ },
15940
+ /**
15941
+ * A call that reads its callee's name out of the environment
15942
+ * reaches whichever resource the template wires that variable to.
15943
+ * The logical id is the answer rather than the deployed name,
15944
+ * because the invoked unit's own summary is keyed by the logical
15945
+ * id and neither side ever writes the other's string.
15946
+ */
15947
+ groundName(semantics, deployment) {
15948
+ const reference = calleeReference(semantics);
15949
+ if (reference === null) {
15950
+ return null;
15951
+ }
15952
+ const logicalId = deployment.pointsAt(reference);
15953
+ return logicalId === null ? null : { ...semantics, instanceName: logicalId };
15954
+ },
15955
+ nameReference: calleeReference
15881
15956
  }
15882
15957
  });
15883
15958
  var SemanticsSchema = external_exports.discriminatedUnion("name", [
@@ -16185,9 +16260,9 @@ var RESOLUTION_RULES = [
16185
16260
  [lit("invokes", v("r"), v("f")), lit("returnsValue", v("f"), v("ret"))],
16186
16261
  "call result"
16187
16262
  ),
16188
- // Where a walk gets to, and whether it ran a call on the way. A value
16189
- // step keeps whatever the rest of the walk was, and a result step
16190
- // makes the whole walk one that ran a call.
16263
+ // Where a walk gets to, and whether it ran a call on the way. The walk
16264
+ // so far comes first, so demand stays on the value asked about; the
16265
+ // README says what the other order cost.
16191
16266
  rule(
16192
16267
  "reaches",
16193
16268
  [v("x"), v("z"), v("kind")],
@@ -16197,27 +16272,27 @@ var RESOLUTION_RULES = [
16197
16272
  "reaches",
16198
16273
  [v("x"), v("z"), v("kind")],
16199
16274
  [
16200
- lit("stepsTo", v("x"), v("y"), VALUE_STEP),
16201
- lit("reaches", v("y"), v("z"), v("kind"))
16275
+ lit("reaches", v("x"), v("y"), VALUE_STEP),
16276
+ lit("stepsTo", v("y"), v("z"), v("kind"))
16202
16277
  ]
16203
16278
  ),
16204
- // Two rules rather than one leaving the rest of the walk's kind free.
16205
- // A free kind is a second question about the same relation, and a
16279
+ // Two rules rather than one leaving the next step's kind free. A free
16280
+ // kind is a second question about the same relation, and a
16206
16281
  // demand-driven run then derives both to answer either.
16207
16282
  rule(
16208
16283
  "reaches",
16209
16284
  [v("x"), v("z"), RESULT_STEP],
16210
16285
  [
16211
- lit("stepsTo", v("x"), v("y"), RESULT_STEP),
16212
- lit("reaches", v("y"), v("z"), VALUE_STEP)
16286
+ lit("reaches", v("x"), v("y"), RESULT_STEP),
16287
+ lit("stepsTo", v("y"), v("z"), VALUE_STEP)
16213
16288
  ]
16214
16289
  ),
16215
16290
  rule(
16216
16291
  "reaches",
16217
16292
  [v("x"), v("z"), RESULT_STEP],
16218
16293
  [
16219
- lit("stepsTo", v("x"), v("y"), RESULT_STEP),
16220
- lit("reaches", v("y"), v("z"), RESULT_STEP)
16294
+ lit("reaches", v("x"), v("y"), RESULT_STEP),
16295
+ lit("stepsTo", v("y"), v("z"), RESULT_STEP)
16221
16296
  ]
16222
16297
  ),
16223
16298
  // What a value comes down to: the walk that never ran a call, stopped
@@ -16563,29 +16638,14 @@ var RESOLUTION_QUESTIONS = [
16563
16638
  // here demands reaches or callsInto. The chains are closures with
16564
16639
  // no depth bound: an alias run of any length resolves.
16565
16640
  rule("callOriginChain", [v("x"), v("x")], [lit("wantedCallOrigin", v("x"))]),
16641
+ // The chain with at least one hop taken, which is what tells a
16642
+ // destructured binding apart from asking about a node directly. The
16643
+ // whole chain is the seed plus those hops.
16566
16644
  rule(
16567
16645
  "callOriginChain",
16568
16646
  [v("x"), v("z")],
16569
- [lit("callOriginChain", v("x"), v("y")), lit("binds", v("y"), v("z"))]
16570
- ),
16571
- rule(
16572
- "callOriginChain",
16573
- [v("x"), v("z")],
16574
- [
16575
- lit("callOriginChain", v("x"), v("y")),
16576
- lit("endsHolding", v("y"), v("z"))
16577
- ]
16578
- ),
16579
- rule(
16580
- "callOriginChain",
16581
- [v("x"), v("z")],
16582
- [
16583
- lit("callOriginChain", v("x"), v("y")),
16584
- lit("fallbackBranch", v("y"), v("z"))
16585
- ]
16647
+ [lit("callOriginChainStepped", v("x"), v("z"))]
16586
16648
  ),
16587
- // The chain with at least one hop taken, which is what tells a
16588
- // destructured binding apart from asking about a node directly.
16589
16649
  rule(
16590
16650
  "callOriginChainStepped",
16591
16651
  [v("x"), v("z")],
@@ -17057,7 +17117,7 @@ function unitsFor(pattern, pack, info, ownBlocks, fileBlocks, options) {
17057
17117
  const table = {
17058
17118
  graphqlObjectFields: (p) => graphqlObjectFieldUnits(p, pack, info, ownBlocks, fileBlocks, options)
17059
17119
  };
17060
- return dispatchByType(table, pattern);
17120
+ return dispatchByType2(table, pattern);
17061
17121
  }
17062
17122
  async function graphqlObjectFieldUnits(pattern, pack, info, ownBlocks, fileBlocks, options) {
17063
17123
  if (info.bodyNode === null || pattern.baseClassNames.includes(info.qualifiedName)) {
@@ -17168,7 +17228,7 @@ function bodyFromLookup(found, range, subject, nothingThere, storage) {
17168
17228
  ),
17169
17229
  none: () => nothingThere
17170
17230
  };
17171
- return dispatchByType(table, found);
17231
+ return dispatchByType2(table, found);
17172
17232
  }
17173
17233
  async function readFieldCall(stmt, scope, ctx, ancestry) {
17174
17234
  if (stmt.type !== "call" || field(stmt, "receiver") !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/adapter-ruby",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "type": "module",
5
5
  "description": "Ruby language adapter for suss, parsing source with tree-sitter (WASM), resolving constant nesting with a lexical binder, and emitting raw extractions for the suss pipeline.",
6
6
  "keywords": [
@@ -47,9 +47,9 @@
47
47
  "typecheck": "tsc --noEmit"
48
48
  },
49
49
  "dependencies": {
50
- "@suss/behavioral-ir": "0.21.0",
51
- "@suss/datalog": "0.21.0",
52
- "@suss/extractor": "0.21.0",
50
+ "@suss/behavioral-ir": "0.21.1",
51
+ "@suss/datalog": "0.21.1",
52
+ "@suss/extractor": "0.21.1",
53
53
  "web-tree-sitter": "^0.26.11"
54
54
  },
55
55
  "devDependencies": {