@suss/extractor 0.14.0 → 0.15.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.cjs CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  makeTransitionId: () => makeTransitionId,
39
39
  mapReading: () => mapReading,
40
40
  paramToInput: () => paramToInput,
41
+ registrationHelperDiscovery: () => registrationHelperDiscovery,
41
42
  sharedGatingConditions: () => sharedGatingConditions,
42
43
  terminalToOutput: () => terminalToOutput,
43
44
  unreadableReading: () => unreadableReading,
@@ -132,7 +133,7 @@ function nested(value, depth) {
132
133
  // src/packHelpers.ts
133
134
  function httpRouteDiscovery(opts) {
134
135
  const kind = opts.kind ?? "handler";
135
- return opts.importNames.map((importName) => ({
136
+ const calls = opts.importNames.map((importName) => ({
136
137
  kind,
137
138
  match: {
138
139
  type: "registrationCall",
@@ -153,6 +154,44 @@ function httpRouteDiscovery(opts) {
153
154
  ...opts.mount !== void 0 ? { mount: opts.mount } : {},
154
155
  requiresImport: [opts.importModule]
155
156
  }));
157
+ if (opts.importNames.length === 0) {
158
+ return calls;
159
+ }
160
+ return [
161
+ ...calls,
162
+ // Routes registered in a loop over an array of specs, a shape
163
+ // registration-call discovery cannot see. The receiver comes from
164
+ // the same import declaration as the calls above, so a loop that
165
+ // never touches this library's routable is left alone.
166
+ {
167
+ kind,
168
+ match: {
169
+ type: "registrationLoop",
170
+ elementShape: LOOP_ELEMENT_SHAPE,
171
+ receiver: {
172
+ importModule: opts.importModule,
173
+ importNames: [...opts.importNames]
174
+ }
175
+ },
176
+ requiresImport: [opts.importModule]
177
+ }
178
+ ];
179
+ }
180
+ var LOOP_ELEMENT_SHAPE = {
181
+ methodKey: "method",
182
+ pathKey: "path",
183
+ handlerKey: "handler"
184
+ };
185
+ function registrationHelperDiscovery(helpers, kind = "handler") {
186
+ return helpers.map((helper) => ({
187
+ kind,
188
+ match: {
189
+ type: "registrationTemplate",
190
+ helperName: helper.helperName,
191
+ ...helper.importModule !== void 0 ? { importModule: helper.importModule } : {},
192
+ registrations: helper.registrations.map((one) => ({ ...one }))
193
+ }
194
+ }));
156
195
  }
157
196
  function unwrapJsonStringify(body) {
158
197
  if (body === null || typeof body !== "object") {
@@ -1126,6 +1165,7 @@ function paramToInput(param) {
1126
1165
  makeTransitionId,
1127
1166
  mapReading,
1128
1167
  paramToInput,
1168
+ registrationHelperDiscovery,
1129
1169
  sharedGatingConditions,
1130
1170
  terminalToOutput,
1131
1171
  unreadableReading,
package/dist/index.d.cts CHANGED
@@ -316,6 +316,18 @@ type DiscoveryMatch = {
316
316
  pathKey: string;
317
317
  handlerKey: string;
318
318
  };
319
+ /**
320
+ * The routable the loop registers on. When set, the loop's body
321
+ * must call a method on a variable constructed from one of these
322
+ * imports, the same resolution a registration call's subject
323
+ * gets. Without it, any loop over objects with the three keys
324
+ * above matches, and a file that imports the library can contain
325
+ * an unrelated one.
326
+ */
327
+ receiver?: {
328
+ importModule: string;
329
+ importNames: string[];
330
+ };
319
331
  } | {
320
332
  /**
321
333
  * Helper-call expansion: one function call at the user's site is
@@ -1589,6 +1601,35 @@ declare function httpRouteDiscovery(opts: {
1589
1601
  */
1590
1602
  mount?: DiscoveryPattern["mount"];
1591
1603
  }): DiscoveryPattern[];
1604
+ /**
1605
+ * One route a project helper registers when called, spelled with `{N}`
1606
+ * placeholders for the call's positional arguments.
1607
+ */
1608
+ interface RegistrationHelper {
1609
+ /** The helper's exported name, as the project's code imports it. */
1610
+ helperName: string;
1611
+ /** The module the helper is imported from, to tell two apart. */
1612
+ importModule?: string;
1613
+ registrations: Array<{
1614
+ method: string;
1615
+ pathTemplate: string;
1616
+ handlerArg: string;
1617
+ }>;
1618
+ }
1619
+ /**
1620
+ * Discovery patterns for a project's own registration helpers.
1621
+ *
1622
+ * A helper like `registerCrud(app, "users", handlers)` registers
1623
+ * routes the call-site never spells out, so registration-call
1624
+ * discovery cannot see them. The helper's name belongs to one project,
1625
+ * which is why this arrives through per-project pack config rather
1626
+ * than shipping inside any framework pack:
1627
+ *
1628
+ * suss extract -f express=config.json
1629
+ *
1630
+ * with `{ "registrationHelpers": [...] }` in the file.
1631
+ */
1632
+ declare function registrationHelperDiscovery(helpers: readonly RegistrationHelper[], kind?: string): DiscoveryPattern[];
1592
1633
  /**
1593
1634
  * The payload behind a `JSON.stringify(...)` call, or the argument
1594
1635
  * unchanged when it is anything else. A producer serializes its message
@@ -1775,11 +1816,7 @@ interface ConstructedFrom {
1775
1816
  */
1776
1817
  readonly named?: readonly string[];
1777
1818
  }
1778
- /**
1779
- * What a reader gives back for a name nothing in the source settles.
1780
- * `"nothing"` gives null, `"reference"` gives the value to go and ask
1781
- * about instead.
1782
- */
1819
+
1783
1820
  type UnsettledName = "nothing" | "reference";
1784
1821
  /**
1785
1822
  * One value a call states, as the questions a pack can ask about it.
@@ -1816,6 +1853,13 @@ interface ValueOps {
1816
1853
  items(): readonly ValueOps[];
1817
1854
  /** What one named property of this object states, or null for none. */
1818
1855
  property(name: string): ValueOps | null;
1856
+ /**
1857
+ * This value in the form an effect records an argument, or null when
1858
+ * the adapter cannot write one. A pack that wants a payload compared
1859
+ * across a boundary asks for this, since a body reduced to text
1860
+ * cannot be paired field by field.
1861
+ */
1862
+ asArg(): EffectArg | null;
1819
1863
  /**
1820
1864
  * The pieces of text the source wrote here, in order, with whatever
1821
1865
  * it interpolated between them left out. A string is one piece and a
@@ -2218,4 +2262,4 @@ declare function terminalToOutput(terminal: RawTerminal): Output;
2218
2262
  declare function effectToIR(effect: RawEffect): Effect;
2219
2263
  declare function paramToInput(param: RawParameter): Input;
2220
2264
 
2221
- export { type AccessRecognizer, type AstCapableOps, type BindingExtraction, type BodyContent, type CallOps, type CaseGroup, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type ExitKind, type ExtractorOptions, type FailureDelivery, IdMap, IdSet, type Identified, type InputMappingPattern, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, type OpsCarrier, type PackDeclarations, PathBudgetExceeded, type PatternPack, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type ResponsePropertyMapping, type ResponsePropertyMeaning, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, detectGaps, effectToIR, enumerateOrDegrade, enumerateStructuredPaths, firstWrittenReading, httpRouteDiscovery, makeTransitionId, mapReading, paramToInput, sharedGatingConditions, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, writtenReading };
2265
+ export { type AccessRecognizer, type AstCapableOps, type BindingExtraction, type BodyContent, type CallOps, type CaseGroup, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type ExitKind, type ExtractorOptions, type FailureDelivery, IdMap, IdSet, type Identified, type InputMappingPattern, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, type OpsCarrier, type PackDeclarations, PathBudgetExceeded, type PatternPack, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, detectGaps, effectToIR, enumerateOrDegrade, enumerateStructuredPaths, firstWrittenReading, httpRouteDiscovery, makeTransitionId, mapReading, paramToInput, registrationHelperDiscovery, sharedGatingConditions, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, writtenReading };
package/dist/index.d.ts CHANGED
@@ -316,6 +316,18 @@ type DiscoveryMatch = {
316
316
  pathKey: string;
317
317
  handlerKey: string;
318
318
  };
319
+ /**
320
+ * The routable the loop registers on. When set, the loop's body
321
+ * must call a method on a variable constructed from one of these
322
+ * imports, the same resolution a registration call's subject
323
+ * gets. Without it, any loop over objects with the three keys
324
+ * above matches, and a file that imports the library can contain
325
+ * an unrelated one.
326
+ */
327
+ receiver?: {
328
+ importModule: string;
329
+ importNames: string[];
330
+ };
319
331
  } | {
320
332
  /**
321
333
  * Helper-call expansion: one function call at the user's site is
@@ -1589,6 +1601,35 @@ declare function httpRouteDiscovery(opts: {
1589
1601
  */
1590
1602
  mount?: DiscoveryPattern["mount"];
1591
1603
  }): DiscoveryPattern[];
1604
+ /**
1605
+ * One route a project helper registers when called, spelled with `{N}`
1606
+ * placeholders for the call's positional arguments.
1607
+ */
1608
+ interface RegistrationHelper {
1609
+ /** The helper's exported name, as the project's code imports it. */
1610
+ helperName: string;
1611
+ /** The module the helper is imported from, to tell two apart. */
1612
+ importModule?: string;
1613
+ registrations: Array<{
1614
+ method: string;
1615
+ pathTemplate: string;
1616
+ handlerArg: string;
1617
+ }>;
1618
+ }
1619
+ /**
1620
+ * Discovery patterns for a project's own registration helpers.
1621
+ *
1622
+ * A helper like `registerCrud(app, "users", handlers)` registers
1623
+ * routes the call-site never spells out, so registration-call
1624
+ * discovery cannot see them. The helper's name belongs to one project,
1625
+ * which is why this arrives through per-project pack config rather
1626
+ * than shipping inside any framework pack:
1627
+ *
1628
+ * suss extract -f express=config.json
1629
+ *
1630
+ * with `{ "registrationHelpers": [...] }` in the file.
1631
+ */
1632
+ declare function registrationHelperDiscovery(helpers: readonly RegistrationHelper[], kind?: string): DiscoveryPattern[];
1592
1633
  /**
1593
1634
  * The payload behind a `JSON.stringify(...)` call, or the argument
1594
1635
  * unchanged when it is anything else. A producer serializes its message
@@ -1775,11 +1816,7 @@ interface ConstructedFrom {
1775
1816
  */
1776
1817
  readonly named?: readonly string[];
1777
1818
  }
1778
- /**
1779
- * What a reader gives back for a name nothing in the source settles.
1780
- * `"nothing"` gives null, `"reference"` gives the value to go and ask
1781
- * about instead.
1782
- */
1819
+
1783
1820
  type UnsettledName = "nothing" | "reference";
1784
1821
  /**
1785
1822
  * One value a call states, as the questions a pack can ask about it.
@@ -1816,6 +1853,13 @@ interface ValueOps {
1816
1853
  items(): readonly ValueOps[];
1817
1854
  /** What one named property of this object states, or null for none. */
1818
1855
  property(name: string): ValueOps | null;
1856
+ /**
1857
+ * This value in the form an effect records an argument, or null when
1858
+ * the adapter cannot write one. A pack that wants a payload compared
1859
+ * across a boundary asks for this, since a body reduced to text
1860
+ * cannot be paired field by field.
1861
+ */
1862
+ asArg(): EffectArg | null;
1819
1863
  /**
1820
1864
  * The pieces of text the source wrote here, in order, with whatever
1821
1865
  * it interpolated between them left out. A string is one piece and a
@@ -2218,4 +2262,4 @@ declare function terminalToOutput(terminal: RawTerminal): Output;
2218
2262
  declare function effectToIR(effect: RawEffect): Effect;
2219
2263
  declare function paramToInput(param: RawParameter): Input;
2220
2264
 
2221
- export { type AccessRecognizer, type AstCapableOps, type BindingExtraction, type BodyContent, type CallOps, type CaseGroup, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type ExitKind, type ExtractorOptions, type FailureDelivery, IdMap, IdSet, type Identified, type InputMappingPattern, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, type OpsCarrier, type PackDeclarations, PathBudgetExceeded, type PatternPack, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type ResponsePropertyMapping, type ResponsePropertyMeaning, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, detectGaps, effectToIR, enumerateOrDegrade, enumerateStructuredPaths, firstWrittenReading, httpRouteDiscovery, makeTransitionId, mapReading, paramToInput, sharedGatingConditions, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, writtenReading };
2265
+ export { type AccessRecognizer, type AstCapableOps, type BindingExtraction, type BodyContent, type CallOps, type CaseGroup, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type ExitKind, type ExtractorOptions, type FailureDelivery, IdMap, IdSet, type Identified, type InputMappingPattern, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, type OpsCarrier, type PackDeclarations, PathBudgetExceeded, type PatternPack, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, detectGaps, effectToIR, enumerateOrDegrade, enumerateStructuredPaths, firstWrittenReading, httpRouteDiscovery, makeTransitionId, mapReading, paramToInput, registrationHelperDiscovery, sharedGatingConditions, terminalToOutput, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, writtenReading };
package/dist/index.js CHANGED
@@ -90,7 +90,7 @@ function nested(value, depth) {
90
90
  // src/packHelpers.ts
91
91
  function httpRouteDiscovery(opts) {
92
92
  const kind = opts.kind ?? "handler";
93
- return opts.importNames.map((importName) => ({
93
+ const calls = opts.importNames.map((importName) => ({
94
94
  kind,
95
95
  match: {
96
96
  type: "registrationCall",
@@ -111,6 +111,44 @@ function httpRouteDiscovery(opts) {
111
111
  ...opts.mount !== void 0 ? { mount: opts.mount } : {},
112
112
  requiresImport: [opts.importModule]
113
113
  }));
114
+ if (opts.importNames.length === 0) {
115
+ return calls;
116
+ }
117
+ return [
118
+ ...calls,
119
+ // Routes registered in a loop over an array of specs, a shape
120
+ // registration-call discovery cannot see. The receiver comes from
121
+ // the same import declaration as the calls above, so a loop that
122
+ // never touches this library's routable is left alone.
123
+ {
124
+ kind,
125
+ match: {
126
+ type: "registrationLoop",
127
+ elementShape: LOOP_ELEMENT_SHAPE,
128
+ receiver: {
129
+ importModule: opts.importModule,
130
+ importNames: [...opts.importNames]
131
+ }
132
+ },
133
+ requiresImport: [opts.importModule]
134
+ }
135
+ ];
136
+ }
137
+ var LOOP_ELEMENT_SHAPE = {
138
+ methodKey: "method",
139
+ pathKey: "path",
140
+ handlerKey: "handler"
141
+ };
142
+ function registrationHelperDiscovery(helpers, kind = "handler") {
143
+ return helpers.map((helper) => ({
144
+ kind,
145
+ match: {
146
+ type: "registrationTemplate",
147
+ helperName: helper.helperName,
148
+ ...helper.importModule !== void 0 ? { importModule: helper.importModule } : {},
149
+ registrations: helper.registrations.map((one) => ({ ...one }))
150
+ }
151
+ }));
114
152
  }
115
153
  function unwrapJsonStringify(body) {
116
154
  if (body === null || typeof body !== "object") {
@@ -1083,6 +1121,7 @@ export {
1083
1121
  makeTransitionId,
1084
1122
  mapReading,
1085
1123
  paramToInput,
1124
+ registrationHelperDiscovery,
1086
1125
  sharedGatingConditions,
1087
1126
  terminalToOutput,
1088
1127
  unreadableReading,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/extractor",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "type": "module",
5
5
  "description": "Framework-agnostic extraction pipeline that turns raw extractions into suss behavioral summaries.",
6
6
  "keywords": [
@@ -45,7 +45,7 @@
45
45
  "typecheck": "tsc --noEmit"
46
46
  },
47
47
  "dependencies": {
48
- "@suss/behavioral-ir": "0.14.0"
48
+ "@suss/behavioral-ir": "0.15.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsup": "*",