@suss/adapter-typescript 0.11.0 → 0.12.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.d.cts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, Project, Symbol, Expression } from 'ts-morph';
2
- import { TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
2
+ import { PackDeclarations, TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
3
3
  import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
4
4
  import { Proof, Atom } from '@suss/datalog';
5
5
  import { ResolutionExplanation } from '@suss/resolution';
6
+ import { AstCapableOps } from '@suss/recognize/ast';
7
+ import { CallOps } from '@suss/recognize';
6
8
 
7
9
  /**
8
10
  * cache.ts: the on-disk extraction cache.
@@ -123,20 +125,30 @@ interface PackFunnel {
123
125
  /**
124
126
  * Bound summaries on the provider side of their boundary.
125
127
  *
126
- * Transitions say what a unit does with a request, which only a
127
- * provider can say. A consumer records what it reads back from the
128
- * response instead, and that goes on the summary's metadata. Measuring
129
- * a client pack against transitions would report every working one as
130
- * having extracted nothing.
128
+ * Kept apart from the count below because a provider that produced
129
+ * no transitions is a different problem from a client that produced
130
+ * none.
131
131
  */
132
132
  providerSummaries: number;
133
- /** Provider summaries with at least one transition. */
133
+ /**
134
+ * Summaries with at least one transition, of any role. A provider's
135
+ * transitions say what it does with a request and a client's say what
136
+ * it expects back, so a pack whose summaries have none has bound
137
+ * something and described nothing either way.
138
+ */
134
139
  summariesWithBehavior: number;
135
140
  /**
136
141
  * Where one of this pack's hooks threw. Every count above is a floor
137
142
  * while this is non-empty.
138
143
  */
139
144
  failures: PackFailure[];
145
+ /**
146
+ * What the pack wrote as data rather than as code, or null for a pack
147
+ * written as a hand-rolled walk. This is the one thing in the funnel
148
+ * that no run produces: it is the pack's own shape, and it is here so
149
+ * the migration onto the declared surface can be measured.
150
+ */
151
+ declarations: PackDeclarations | null;
140
152
  }
141
153
  interface ExtractionReport {
142
154
  /** Files in the tsconfig include set, or null when the caller supplied a Project. */
@@ -926,13 +938,14 @@ interface HealthCheck {
926
938
  /** The property being checked, as something either true or false. */
927
939
  name: string;
928
940
  /**
929
- * The heading printed when this check finds something.
941
+ * The short word this check reports under, kebab-case.
930
942
  *
931
- * `name` is written as an assertion, so printing it above the
932
- * violations would say "no pack collides with itself" and then list a
933
- * pack colliding with itself.
943
+ * It is the first column of every line the check prints, so a reader
944
+ * works out what it means once and recognises it after that. `name`
945
+ * is written as an assertion and would read backwards over a list of
946
+ * things failing it.
934
947
  */
935
- whenBroken: string;
948
+ code: string;
936
949
  /**
937
950
  * Who the finding is addressed to.
938
951
  *
@@ -946,6 +959,26 @@ interface HealthCheck {
946
959
  audience: "run" | "pack";
947
960
  violations: HealthViolation[];
948
961
  }
962
+ /**
963
+ * What one pack paid for what it matches.
964
+ *
965
+ * Expressiveness is bought link by link, and #542 asks for the price to
966
+ * be printed. A pack with every link written as data runs on any
967
+ * adapter with the executor ops. A link written as a function runs only
968
+ * where its own language does, and one that reads the syntax tree is
969
+ * the floor. All three are allowed, and this says which is which.
970
+ */
971
+ interface PackGradient {
972
+ pack: string;
973
+ /** Links written as data, across every declaration. */
974
+ dataLinks: number;
975
+ /** Links written as a function, as "declaration.question". */
976
+ functionLinks: string[];
977
+ /** Links whose function reads the adapter's own syntax tree. */
978
+ astLinks: string[];
979
+ /** Declarations shipped without a line of code to run against them. */
980
+ withoutExample: string[];
981
+ }
949
982
  /**
950
983
  * Run every health check over one extraction report and return what
951
984
  * fired, grouped by which check caught it.
@@ -973,6 +1006,77 @@ declare function formatPackHealth(checks: ReadonlyArray<HealthCheck>, audiences:
973
1006
  */
974
1007
  declare function parseConditionExpression(expr: Expression, depth?: number): Predicate | null;
975
1008
 
1009
+ /**
1010
+ * What this adapter can tell a declared pack about a call.
1011
+ *
1012
+ * Every question here was already worked out somewhere in this adapter,
1013
+ * once per pack that needed it. Collecting them behind the one
1014
+ * interface `@suss/recognize` declares is what lets a pack stop being a
1015
+ * walk over ts-morph and start being data.
1016
+ *
1017
+ * Two of the receiver origins are implemented. The migration plan for
1018
+ * #542 lists four more, and each one adds an entry to `ORIGIN` beside
1019
+ * the union member it matches.
1020
+ */
1021
+
1022
+ /** One-hop lookup from a written name to the value it was bound to. */
1023
+ type Resolve = (value: Node) => Node | null;
1024
+ /** What a declared pack can ask about one TypeScript call. */
1025
+ declare function callOpsFor(call: CallExpression, resolveWrittenValue?: Resolve): AstCapableOps;
1026
+
1027
+ /**
1028
+ * Context handed to TypeScript-adapter recognizers. Recognizers in
1029
+ * `@suss/framework-prisma` (and other packs) receive this and use
1030
+ * the type-checker / source-file primitives to decide whether the
1031
+ * call site matches their semantics. `extractArgs` reuses the same
1032
+ * `EffectArg` builder the adapter uses for `invocation` effects, so
1033
+ * recognizers don't have to re-implement literal/object/identifier
1034
+ * shape extraction.
1035
+ */
1036
+ interface TsInvocationRecognizerContext {
1037
+ /** The call expression itself (also passed as the first arg). */
1038
+ call: CallExpression;
1039
+ /** Source file the call lives in. Useful for import resolution. */
1040
+ sourceFile: SourceFile;
1041
+ /**
1042
+ * Convert the call's arguments to `EffectArg[]` using the same
1043
+ * literal / object / identifier extraction the adapter applies to
1044
+ * `invocation` effects. Recognizers call this when they want
1045
+ * field-level shape (e.g. Prisma's `select: { id: true }`).
1046
+ */
1047
+ extractArgs(): EffectArg[];
1048
+ /**
1049
+ * Whether `identifier` was introduced by an import of
1050
+ * `expectedModule`. Recognizers use this to tell a library's export
1051
+ * apart from a local class that happens to share its name.
1052
+ *
1053
+ * Named, default, and namespace imports all match. So does an import
1054
+ * through a project-local barrel that re-exports the module: the
1055
+ * aliased symbol is still in the package that declared it.
1056
+ */
1057
+ isImportedFrom(identifier: Node, expectedModule: string): boolean;
1058
+ /**
1059
+ * The expression `value` is written as, followed through const
1060
+ * bindings, imports, and re-export barrels. A recognizer asks this
1061
+ * before claiming the source does not name something:
1062
+ *
1063
+ * const url = "https://sqs/.../orders";
1064
+ * client.send(new SendMessageCommand({ QueueUrl: url }));
1065
+ *
1066
+ * Resolving `url` gives back the string literal, and the recognizer's
1067
+ * own pattern match runs on that. Null when the value has no written
1068
+ * form (a parameter, a call result), which is exactly when null on the
1069
+ * binding is correct.
1070
+ */
1071
+ resolveWrittenValue(value: Node): Node | null;
1072
+ /**
1073
+ * What a declared pack asks about this call, in the vocabulary
1074
+ * `@suss/recognize` defines. A pack written as a chain of data links
1075
+ * reads only this; the members above are what a pack written as code
1076
+ * reaches for.
1077
+ */
1078
+ ops: CallOps;
1079
+ }
976
1080
  declare function isImportedFrom(identifier: Node, expectedModule: string): boolean;
977
1081
  /**
978
1082
  * Whether `expectedModule` declares the method a call goes to. A pack
@@ -1175,4 +1279,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
1175
1279
  version?: string;
1176
1280
  }>): string;
1177
1281
 
1178
- export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };
1282
+ export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type PackGradient, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, callOpsFor, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { SourceFile, Node, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, CallExpression, Project, Symbol, Expression } from 'ts-morph';
2
- import { TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
2
+ import { PackDeclarations, TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, LanguageAdapter, PatternPack, ExtractorOptions, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, EffectArg, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
3
3
  import { BehavioralSummary, MessageBusSemantics, DeployableUnit, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
4
4
  import { Proof, Atom } from '@suss/datalog';
5
5
  import { ResolutionExplanation } from '@suss/resolution';
6
+ import { AstCapableOps } from '@suss/recognize/ast';
7
+ import { CallOps } from '@suss/recognize';
6
8
 
7
9
  /**
8
10
  * cache.ts: the on-disk extraction cache.
@@ -123,20 +125,30 @@ interface PackFunnel {
123
125
  /**
124
126
  * Bound summaries on the provider side of their boundary.
125
127
  *
126
- * Transitions say what a unit does with a request, which only a
127
- * provider can say. A consumer records what it reads back from the
128
- * response instead, and that goes on the summary's metadata. Measuring
129
- * a client pack against transitions would report every working one as
130
- * having extracted nothing.
128
+ * Kept apart from the count below because a provider that produced
129
+ * no transitions is a different problem from a client that produced
130
+ * none.
131
131
  */
132
132
  providerSummaries: number;
133
- /** Provider summaries with at least one transition. */
133
+ /**
134
+ * Summaries with at least one transition, of any role. A provider's
135
+ * transitions say what it does with a request and a client's say what
136
+ * it expects back, so a pack whose summaries have none has bound
137
+ * something and described nothing either way.
138
+ */
134
139
  summariesWithBehavior: number;
135
140
  /**
136
141
  * Where one of this pack's hooks threw. Every count above is a floor
137
142
  * while this is non-empty.
138
143
  */
139
144
  failures: PackFailure[];
145
+ /**
146
+ * What the pack wrote as data rather than as code, or null for a pack
147
+ * written as a hand-rolled walk. This is the one thing in the funnel
148
+ * that no run produces: it is the pack's own shape, and it is here so
149
+ * the migration onto the declared surface can be measured.
150
+ */
151
+ declarations: PackDeclarations | null;
140
152
  }
141
153
  interface ExtractionReport {
142
154
  /** Files in the tsconfig include set, or null when the caller supplied a Project. */
@@ -926,13 +938,14 @@ interface HealthCheck {
926
938
  /** The property being checked, as something either true or false. */
927
939
  name: string;
928
940
  /**
929
- * The heading printed when this check finds something.
941
+ * The short word this check reports under, kebab-case.
930
942
  *
931
- * `name` is written as an assertion, so printing it above the
932
- * violations would say "no pack collides with itself" and then list a
933
- * pack colliding with itself.
943
+ * It is the first column of every line the check prints, so a reader
944
+ * works out what it means once and recognises it after that. `name`
945
+ * is written as an assertion and would read backwards over a list of
946
+ * things failing it.
934
947
  */
935
- whenBroken: string;
948
+ code: string;
936
949
  /**
937
950
  * Who the finding is addressed to.
938
951
  *
@@ -946,6 +959,26 @@ interface HealthCheck {
946
959
  audience: "run" | "pack";
947
960
  violations: HealthViolation[];
948
961
  }
962
+ /**
963
+ * What one pack paid for what it matches.
964
+ *
965
+ * Expressiveness is bought link by link, and #542 asks for the price to
966
+ * be printed. A pack with every link written as data runs on any
967
+ * adapter with the executor ops. A link written as a function runs only
968
+ * where its own language does, and one that reads the syntax tree is
969
+ * the floor. All three are allowed, and this says which is which.
970
+ */
971
+ interface PackGradient {
972
+ pack: string;
973
+ /** Links written as data, across every declaration. */
974
+ dataLinks: number;
975
+ /** Links written as a function, as "declaration.question". */
976
+ functionLinks: string[];
977
+ /** Links whose function reads the adapter's own syntax tree. */
978
+ astLinks: string[];
979
+ /** Declarations shipped without a line of code to run against them. */
980
+ withoutExample: string[];
981
+ }
949
982
  /**
950
983
  * Run every health check over one extraction report and return what
951
984
  * fired, grouped by which check caught it.
@@ -973,6 +1006,77 @@ declare function formatPackHealth(checks: ReadonlyArray<HealthCheck>, audiences:
973
1006
  */
974
1007
  declare function parseConditionExpression(expr: Expression, depth?: number): Predicate | null;
975
1008
 
1009
+ /**
1010
+ * What this adapter can tell a declared pack about a call.
1011
+ *
1012
+ * Every question here was already worked out somewhere in this adapter,
1013
+ * once per pack that needed it. Collecting them behind the one
1014
+ * interface `@suss/recognize` declares is what lets a pack stop being a
1015
+ * walk over ts-morph and start being data.
1016
+ *
1017
+ * Two of the receiver origins are implemented. The migration plan for
1018
+ * #542 lists four more, and each one adds an entry to `ORIGIN` beside
1019
+ * the union member it matches.
1020
+ */
1021
+
1022
+ /** One-hop lookup from a written name to the value it was bound to. */
1023
+ type Resolve = (value: Node) => Node | null;
1024
+ /** What a declared pack can ask about one TypeScript call. */
1025
+ declare function callOpsFor(call: CallExpression, resolveWrittenValue?: Resolve): AstCapableOps;
1026
+
1027
+ /**
1028
+ * Context handed to TypeScript-adapter recognizers. Recognizers in
1029
+ * `@suss/framework-prisma` (and other packs) receive this and use
1030
+ * the type-checker / source-file primitives to decide whether the
1031
+ * call site matches their semantics. `extractArgs` reuses the same
1032
+ * `EffectArg` builder the adapter uses for `invocation` effects, so
1033
+ * recognizers don't have to re-implement literal/object/identifier
1034
+ * shape extraction.
1035
+ */
1036
+ interface TsInvocationRecognizerContext {
1037
+ /** The call expression itself (also passed as the first arg). */
1038
+ call: CallExpression;
1039
+ /** Source file the call lives in. Useful for import resolution. */
1040
+ sourceFile: SourceFile;
1041
+ /**
1042
+ * Convert the call's arguments to `EffectArg[]` using the same
1043
+ * literal / object / identifier extraction the adapter applies to
1044
+ * `invocation` effects. Recognizers call this when they want
1045
+ * field-level shape (e.g. Prisma's `select: { id: true }`).
1046
+ */
1047
+ extractArgs(): EffectArg[];
1048
+ /**
1049
+ * Whether `identifier` was introduced by an import of
1050
+ * `expectedModule`. Recognizers use this to tell a library's export
1051
+ * apart from a local class that happens to share its name.
1052
+ *
1053
+ * Named, default, and namespace imports all match. So does an import
1054
+ * through a project-local barrel that re-exports the module: the
1055
+ * aliased symbol is still in the package that declared it.
1056
+ */
1057
+ isImportedFrom(identifier: Node, expectedModule: string): boolean;
1058
+ /**
1059
+ * The expression `value` is written as, followed through const
1060
+ * bindings, imports, and re-export barrels. A recognizer asks this
1061
+ * before claiming the source does not name something:
1062
+ *
1063
+ * const url = "https://sqs/.../orders";
1064
+ * client.send(new SendMessageCommand({ QueueUrl: url }));
1065
+ *
1066
+ * Resolving `url` gives back the string literal, and the recognizer's
1067
+ * own pattern match runs on that. Null when the value has no written
1068
+ * form (a parameter, a call result), which is exactly when null on the
1069
+ * binding is correct.
1070
+ */
1071
+ resolveWrittenValue(value: Node): Node | null;
1072
+ /**
1073
+ * What a declared pack asks about this call, in the vocabulary
1074
+ * `@suss/recognize` defines. A pack written as a chain of data links
1075
+ * reads only this; the members above are what a pack written as code
1076
+ * reaches for.
1077
+ */
1078
+ ops: CallOps;
1079
+ }
976
1080
  declare function isImportedFrom(identifier: Node, expectedModule: string): boolean;
977
1081
  /**
978
1082
  * Whether `expectedModule` declares the method a call goes to. A pack
@@ -1175,4 +1279,4 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
1175
1279
  version?: string;
1176
1280
  }>): string;
1177
1281
 
1178
- export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };
1282
+ export { ADAPTER_VERSION, type CacheDiagnostic, type CacheLookup, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DiscoveredUnit, type EmptyStage, type ExplainCallableOptions, type ExplainStats, type ExplainedResolution, type ExtractionReport, type FoundTerminal, type FunctionRoot, type HealthCheck, type HealthViolation, type PackFunnel, type PackGradient, type ReadNameOptions, ResolutionStore, type Timer, type TimingReport, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, type ValueLocation, type WhyExplained, WhySession, type WhySessionOptions, callOpsFor, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, computeContentHash, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, discoverUnits, evaluatePackHealth, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findNearestTsconfig, findTerminals, formatPackHealth, isImportedFrom, methodDeclaredIn, parseConditionExpression, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, workspaceRootFor };