@suss/packs 0.33.0 → 0.34.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/README.md +10 -11
- package/dist/activerecord.d.ts +7 -0
- package/dist/activerecord.js +34 -4
- package/dist/apollo-client.js +26 -39
- package/dist/apollo.js +12 -20
- package/dist/aws-dynamodb.js +4 -4
- package/dist/aws-eventbridge.js +3 -3
- package/dist/aws-lambda.js +31 -54
- package/dist/aws-s3.js +1 -1
- package/dist/aws-secrets-manager.js +1 -1
- package/dist/aws-sns.js +2 -2
- package/dist/aws-sqs.js +20 -11
- package/dist/aws-ssm.js +1 -1
- package/dist/axios.js +13 -27
- package/dist/bigquery-python.js +3 -3
- package/dist/bigquery.js +1 -1
- package/dist/{chunk-NYWZHQBJ.js → chunk-GK4BILHB.js} +8 -9
- package/dist/cloudflare-workers.js +26 -35
- package/dist/drizzle.js +15 -20
- package/dist/express.js +3 -6
- package/dist/fabrication.d.ts +1 -0
- package/dist/fabrication.js +36 -0
- package/dist/factory-bot.d.ts +1 -0
- package/dist/factory-bot.js +36 -0
- package/dist/faraday.js +4 -5
- package/dist/fastapi.js +21 -5
- package/dist/fastify.js +10 -14
- package/dist/fetch.js +3 -4
- package/dist/flask-restx.js +19 -12
- package/dist/gcs.js +1 -1
- package/dist/graphql-ruby.js +20 -16
- package/dist/hono.js +17 -27
- package/dist/httpx.js +3 -5
- package/dist/minitest.d.ts +1 -0
- package/dist/minitest.js +59 -0
- package/dist/mongoose.js +7 -7
- package/dist/nestjs-graphql.js +14 -25
- package/dist/nestjs-microservices.js +9 -10
- package/dist/nestjs-rest.js +42 -22
- package/dist/net-http.js +5 -6
- package/dist/nextjs.js +16 -17
- package/dist/node.js +144 -28
- package/dist/package-exports.js +1 -1
- package/dist/pg.js +3 -2
- package/dist/prisma.js +281 -48
- package/dist/pytest.d.ts +1 -0
- package/dist/pytest.js +81 -0
- package/dist/rails.js +46 -27
- package/dist/react-query.js +1 -1
- package/dist/react-router.js +21 -48
- package/dist/react.js +14 -5
- package/dist/redis.js +1 -1
- package/dist/requests.js +4 -5
- package/dist/rspec.d.ts +1 -0
- package/dist/rspec.js +135 -0
- package/dist/sqlalchemy.js +1 -1
- package/dist/sqlmodel.js +7 -8
- package/dist/ts-rest.js +6 -8
- package/dist/typeorm.d.ts +1 -0
- package/dist/typeorm.js +291 -0
- package/dist/vitest.d.ts +1 -0
- package/dist/vitest.js +64 -0
- package/package.json +47 -11
package/dist/aws-sqs.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
// ../framework/aws-sqs/dist/index.js
|
|
2
2
|
import { Node as N } from "ts-morph";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
climbSyntax,
|
|
6
|
+
readConfiguredCall,
|
|
7
|
+
receiverTypesOf
|
|
8
|
+
} from "@suss/adapter-typescript";
|
|
5
9
|
import { messageBusBinding } from "@suss/behavioral-ir";
|
|
6
10
|
import { configuredCallOption } from "@suss/extractor";
|
|
7
11
|
import { constructedFrom, messageSends, pack } from "@suss/recognize";
|
|
@@ -35,7 +39,7 @@ function sendDeclarations() {
|
|
|
35
39
|
wire: "aws_sqs",
|
|
36
40
|
client: constructedFrom(SQS),
|
|
37
41
|
messages: { each: "in", property: "Entries" },
|
|
38
|
-
//
|
|
42
|
+
// The queue is on the command input, once, beside the list of messages.
|
|
39
43
|
channel: [{ property: ["QueueUrl"], on: "theInput" }],
|
|
40
44
|
body: "MessageBody"
|
|
41
45
|
}).methods(INSIDE_THE_COMMAND(["SendMessageBatchCommand"])).example(
|
|
@@ -72,16 +76,15 @@ function messageReceiveRecognizer(call, ctx) {
|
|
|
72
76
|
if (!N.isIdentifier(recordExpr)) {
|
|
73
77
|
return null;
|
|
74
78
|
}
|
|
75
|
-
if (!isSqsRecordIdentifier(recordExpr)) {
|
|
79
|
+
if (!isSqsRecordIdentifier(recordExpr) && !isTypedSqsRecord(recordExpr)) {
|
|
76
80
|
return null;
|
|
77
81
|
}
|
|
78
82
|
const fields = extractDestructuredFields(callNode);
|
|
79
83
|
return [
|
|
80
84
|
{
|
|
81
85
|
type: "interaction",
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
// name it and the pairing pass joins by codeScope instead.
|
|
86
|
+
// The CloudFormation event source mapping sets the queue, so the
|
|
87
|
+
// pairing pass joins this effect to its consumer by code scope.
|
|
85
88
|
binding: messageBusBinding({
|
|
86
89
|
recognition: "@suss/framework-aws-sqs",
|
|
87
90
|
messageBus: "aws_sqs",
|
|
@@ -122,6 +125,12 @@ function isSqsRecordIdentifier(recordExpr) {
|
|
|
122
125
|
}
|
|
123
126
|
return false;
|
|
124
127
|
}
|
|
128
|
+
function isTypedSqsRecord(recordExpr) {
|
|
129
|
+
return receiverTypesOf(recordExpr).some((type) => isLambdaSqsRecord(type));
|
|
130
|
+
}
|
|
131
|
+
function isLambdaSqsRecord(type) {
|
|
132
|
+
return type.name === "SQSRecord" && type.declaredIn.some((filePath) => filePath.includes("/aws-lambda/"));
|
|
133
|
+
}
|
|
125
134
|
function extractDestructuredFields(call) {
|
|
126
135
|
const parent = climbSyntax(call).getParent();
|
|
127
136
|
if (parent === void 0 || !N.isVariableDeclaration(parent)) {
|
|
@@ -153,8 +162,8 @@ function extractDestructuredFields(call) {
|
|
|
153
162
|
}
|
|
154
163
|
var optionsSchema = z.object({
|
|
155
164
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
165
|
+
* Each dispatcher adds a recognizer, and the pack also reads files
|
|
166
|
+
* that import the dispatcher's module.
|
|
158
167
|
*/
|
|
159
168
|
producers: z.array(configuredCallOption).optional()
|
|
160
169
|
}).strict();
|
|
@@ -191,8 +200,8 @@ function sqsFramework(options = {}) {
|
|
|
191
200
|
languages: ["typescript", "javascript"],
|
|
192
201
|
recognizedAs: "@suss/framework-aws-sqs",
|
|
193
202
|
protocol: "sqs",
|
|
194
|
-
//
|
|
195
|
-
//
|
|
203
|
+
// A handler file imports `SQSEvent` from aws-lambda and often never
|
|
204
|
+
// imports the SQS client.
|
|
196
205
|
requiresImport: ["aws-lambda", ...producers.map((p) => p.module)],
|
|
197
206
|
recognizers: [
|
|
198
207
|
messageReceiveRecognizer,
|
|
@@ -204,7 +213,7 @@ var declares = {
|
|
|
204
213
|
kind: "effects",
|
|
205
214
|
package: "@suss/framework-aws-sqs",
|
|
206
215
|
dependencies: [{ ecosystem: "npm", name: "@aws-sdk/client-sqs" }],
|
|
207
|
-
reads: "AWS SDK v3 SQS producer calls
|
|
216
|
+
reads: "AWS SDK v3 SQS producer calls. Each one becomes a message-send interaction."
|
|
208
217
|
};
|
|
209
218
|
var index_default = sqsFramework;
|
|
210
219
|
export {
|
package/dist/aws-ssm.js
CHANGED
|
@@ -29,7 +29,7 @@ var declares = {
|
|
|
29
29
|
kind: "effects",
|
|
30
30
|
package: "@suss/framework-aws-ssm",
|
|
31
31
|
dependencies: [{ ecosystem: "npm", name: "@aws-sdk/client-ssm" }],
|
|
32
|
-
reads: "AWS SSM Parameter Store calls
|
|
32
|
+
reads: "AWS SSM Parameter Store calls. Each one becomes a storage-access interaction on the parameter."
|
|
33
33
|
};
|
|
34
34
|
var index_default = ssmFramework;
|
|
35
35
|
export {
|
package/dist/axios.js
CHANGED
|
@@ -17,23 +17,18 @@ var clientFactory = z.object({
|
|
|
17
17
|
}).strict();
|
|
18
18
|
var optionsSchema = z.object({
|
|
19
19
|
/**
|
|
20
|
-
* Project functions
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* axios.create() result is, wherever the call it delegates to
|
|
24
|
-
* lives.
|
|
20
|
+
* Project functions that build axios instances, in addition to
|
|
21
|
+
* axios.create. Calling one of these gives a client instance, the
|
|
22
|
+
* same as an axios.create() result.
|
|
25
23
|
*/
|
|
26
24
|
factories: z.array(clientFactory).optional()
|
|
27
25
|
}).strict();
|
|
28
26
|
function discoveryForVerb(verb, factories) {
|
|
29
27
|
const patterns = [
|
|
30
28
|
{
|
|
31
|
-
// Matches
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
// The factoryMethods entry tells the adapter that variables initialized
|
|
35
|
-
// from axios.create(...) are also clients, wherever that call and
|
|
36
|
-
// this one turn out to live.
|
|
29
|
+
// Matches `axios.<verb>(path)` and `api.<verb>(path)`. factoryMethods
|
|
30
|
+
// makes a variable set from axios.create(...) a client too, even
|
|
31
|
+
// when it is created in another file.
|
|
37
32
|
kind: "client",
|
|
38
33
|
match: {
|
|
39
34
|
type: "clientCall",
|
|
@@ -64,18 +59,9 @@ function discoveryForVerb(verb, factories) {
|
|
|
64
59
|
method: { type: "literal", value: verb.toUpperCase() },
|
|
65
60
|
path: { type: "fromArgument", position: 0 }
|
|
66
61
|
},
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
// points at a location relative to wherever it's written, and the
|
|
71
|
-
// pre-filter only ever reads a file's own import text before
|
|
72
|
-
// anything is parsed, so it has no way to tell "./apiClient"
|
|
73
|
-
// and a consumer's "../apiClient" apart from string text alone.
|
|
74
|
-
// Narrowing on that string would exclude the consumer roughly
|
|
75
|
-
// as often as include it, so a path-shaped factory gives no
|
|
76
|
-
// gate at all and every file is walked; the discovery layer
|
|
77
|
-
// resolves the module correctly once it's reading a file's
|
|
78
|
-
// imports against a parsed project.
|
|
62
|
+
// Each importing file spells a relative path differently, so the
|
|
63
|
+
// import-text prefilter cannot match one and a path-shaped factory
|
|
64
|
+
// walks every file. The README has the details.
|
|
79
65
|
requiresImport: isPathShapedSpecifier(factory.module) ? [] : [factory.module]
|
|
80
66
|
});
|
|
81
67
|
}
|
|
@@ -153,13 +139,13 @@ function axiosPack(options = {}) {
|
|
|
153
139
|
params: []
|
|
154
140
|
},
|
|
155
141
|
responseSemantics: [
|
|
156
|
-
// axios
|
|
142
|
+
// axios puts the parsed response body on `.data`.
|
|
157
143
|
{ name: "data", access: "property", semantics: { type: "body" } },
|
|
158
144
|
{ name: "status", access: "property", semantics: { type: "statusCode" } },
|
|
159
145
|
{ name: "headers", access: "property", semantics: { type: "headers" } }
|
|
160
146
|
],
|
|
161
|
-
//
|
|
162
|
-
//
|
|
147
|
+
// axios rejects on a non-2xx status, so every failure reaches the
|
|
148
|
+
// caller's catch block instead of coming back as a response.
|
|
163
149
|
failureDelivery: "exception"
|
|
164
150
|
};
|
|
165
151
|
}
|
|
@@ -167,7 +153,7 @@ var declares = {
|
|
|
167
153
|
kind: "client",
|
|
168
154
|
package: "@suss/client-axios",
|
|
169
155
|
dependencies: [{ ecosystem: "npm", name: "axios" }],
|
|
170
|
-
reads: "axios call sites
|
|
156
|
+
reads: "axios call sites, including calls on a client that `axios.create` made."
|
|
171
157
|
};
|
|
172
158
|
var index_default = axiosPack;
|
|
173
159
|
export {
|
package/dist/bigquery-python.js
CHANGED
|
@@ -88,8 +88,8 @@ function bigqueryClients() {
|
|
|
88
88
|
clientTypes: ["BigQueryHook"],
|
|
89
89
|
statements: HOOK_STATEMENTS,
|
|
90
90
|
tables: HOOK_TABLES,
|
|
91
|
-
// The hook documents `get_client` as
|
|
92
|
-
//
|
|
91
|
+
// The hook documents `get_client` as returning the client library's
|
|
92
|
+
// own `Client`, so a chain off it is read the same way.
|
|
93
93
|
handsBack: [
|
|
94
94
|
{ method: "get_client", module: CLIENT_MODULE, name: "Client" }
|
|
95
95
|
],
|
|
@@ -113,7 +113,7 @@ var declares = {
|
|
|
113
113
|
{ ecosystem: "pypi", name: "google-cloud-bigquery" },
|
|
114
114
|
{ ecosystem: "pypi", name: "apache-airflow-providers-google" }
|
|
115
115
|
],
|
|
116
|
-
reads: "BigQuery calls (Python)
|
|
116
|
+
reads: "BigQuery calls (Python). The statement a client or an Airflow hook is handed is read for the tables it touches. Calls such as `get_table` and `insert_rows` take a table name instead of SQL, and that name is read too."
|
|
117
117
|
};
|
|
118
118
|
var index_default = bigqueryFramework;
|
|
119
119
|
export {
|
package/dist/bigquery.js
CHANGED
|
@@ -45,7 +45,7 @@ var declares = {
|
|
|
45
45
|
kind: "effects",
|
|
46
46
|
package: "@suss/framework-bigquery",
|
|
47
47
|
dependencies: [{ ecosystem: "npm", name: "@google-cloud/bigquery" }],
|
|
48
|
-
reads: "BigQuery queries and table calls
|
|
48
|
+
reads: "BigQuery queries and table calls. Each one becomes a storage-access interaction scoped to its dataset."
|
|
49
49
|
};
|
|
50
50
|
var index_default = bigqueryFramework;
|
|
51
51
|
export {
|
|
@@ -3,9 +3,8 @@ import { z } from "zod";
|
|
|
3
3
|
import { storageSystemOption } from "@suss/extractor";
|
|
4
4
|
var optionsSchema = z.object({
|
|
5
5
|
/**
|
|
6
|
-
* Which database is behind the
|
|
7
|
-
*
|
|
8
|
-
* rather than something the library settles.
|
|
6
|
+
* Which database is behind the engine. SQLAlchemy works with several,
|
|
7
|
+
* and the connection URL picks one, so the project has to set this.
|
|
9
8
|
*/
|
|
10
9
|
storageSystem: storageSystemOption
|
|
11
10
|
}).strict();
|
|
@@ -26,8 +25,8 @@ function sqlalchemyStorage(options) {
|
|
|
26
25
|
"bulk_insert_mappings",
|
|
27
26
|
"bulk_update_mappings"
|
|
28
27
|
],
|
|
29
|
-
//
|
|
30
|
-
//
|
|
28
|
+
// `execute` and the scalar calls run a statement whose own chain is
|
|
29
|
+
// read already, and the rest only manage the session.
|
|
31
30
|
recordsNothing: [
|
|
32
31
|
"execute",
|
|
33
32
|
"scalars",
|
|
@@ -46,9 +45,9 @@ function sqlalchemyStorage(options) {
|
|
|
46
45
|
module: "sqlalchemy",
|
|
47
46
|
queryTypes: ["Select", "Update", "Delete", "Insert"],
|
|
48
47
|
writes: ["update", "delete", "insert", "commit"],
|
|
49
|
-
// 2.0
|
|
50
|
-
// constructor
|
|
51
|
-
//
|
|
48
|
+
// A 2.0 statement such as `select(User.id).where(...)` calls an
|
|
49
|
+
// imported constructor directly, so there is no project method in
|
|
50
|
+
// the chain whose return type the adapter could read.
|
|
52
51
|
queryFunctions: ["select", "insert", "update", "delete"],
|
|
53
52
|
valueMethods: ["values"],
|
|
54
53
|
storageSystem: options.storageSystem
|
|
@@ -129,7 +128,7 @@ var declares = {
|
|
|
129
128
|
kind: "effects",
|
|
130
129
|
package: "@suss/framework-sqlalchemy",
|
|
131
130
|
dependencies: [{ ecosystem: "pypi", name: "sqlalchemy" }],
|
|
132
|
-
reads: `SQLAlchemy calls (Python)
|
|
131
|
+
reads: `SQLAlchemy calls (Python). The pack declares which types a query returns and which methods write. The adapter matches a call chain by following a project's own base class to the method behind the call, and reads that method's declared return type.`,
|
|
133
132
|
configuration: {
|
|
134
133
|
file: "suss.sqlalchemy.json",
|
|
135
134
|
example: { storageSystem: "postgresql" },
|
|
@@ -15,7 +15,11 @@ import {
|
|
|
15
15
|
} from "@suss/adapter-typescript";
|
|
16
16
|
import { runtimeConfigBinding } from "@suss/behavioral-ir";
|
|
17
17
|
import { Node as N3 } from "ts-morph";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
readName as readName2,
|
|
20
|
+
receiverTypesOf,
|
|
21
|
+
stringValueOf
|
|
22
|
+
} from "@suss/adapter-typescript";
|
|
19
23
|
import { storageBinding } from "@suss/behavioral-ir";
|
|
20
24
|
import { readSqlAccess } from "@suss/sql";
|
|
21
25
|
var TRIGGERS = {
|
|
@@ -163,11 +167,10 @@ function listenerAt(node) {
|
|
|
163
167
|
var ENV_PARAMETER_POSITION = 1;
|
|
164
168
|
var readName = (name) => `env.${name}`;
|
|
165
169
|
function envBindingRecognizer(options = {}) {
|
|
166
|
-
const instanceName = options.scriptName ?? "<unknown>";
|
|
167
170
|
return (access, ctx) => {
|
|
168
171
|
const { resolution } = ctx;
|
|
169
172
|
const read = envReadAt(access, resolution);
|
|
170
|
-
return read === null ? null : [configReadEffect(read,
|
|
173
|
+
return read === null ? null : [configReadEffect(read, options.scriptName)];
|
|
171
174
|
};
|
|
172
175
|
}
|
|
173
176
|
function envReadAt(node, resolution) {
|
|
@@ -222,7 +225,7 @@ function configReadEffect(read, instanceName) {
|
|
|
222
225
|
binding: runtimeConfigBinding({
|
|
223
226
|
recognition: "@suss/framework-cloudflare-workers",
|
|
224
227
|
deploymentTarget: "worker",
|
|
225
|
-
instanceName
|
|
228
|
+
...instanceName === void 0 ? {} : { instanceName }
|
|
226
229
|
}),
|
|
227
230
|
callee: readName(read.name),
|
|
228
231
|
interaction: {
|
|
@@ -297,10 +300,7 @@ function storeBindingRecognizer(call, ctx) {
|
|
|
297
300
|
if (binding === null) {
|
|
298
301
|
return null;
|
|
299
302
|
}
|
|
300
|
-
const store =
|
|
301
|
-
if (store === void 0) {
|
|
302
|
-
return null;
|
|
303
|
-
}
|
|
303
|
+
const { store } = binding;
|
|
304
304
|
const method = callee.getName();
|
|
305
305
|
const access = store.read(method, callNode, reading);
|
|
306
306
|
if (access === null) {
|
|
@@ -320,8 +320,8 @@ function storeBindingRecognizer(call, ctx) {
|
|
|
320
320
|
interaction: {
|
|
321
321
|
class: "storage-access",
|
|
322
322
|
kind: access.kind,
|
|
323
|
-
// KV and R2
|
|
324
|
-
// database level, so
|
|
323
|
+
// KV and R2 values are opaque, and a D1 statement is read at the
|
|
324
|
+
// database level, so a call never records a field.
|
|
325
325
|
fields: [],
|
|
326
326
|
operation: method,
|
|
327
327
|
...access.selector !== void 0 ? { selector: [access.selector] } : {}
|
|
@@ -344,11 +344,16 @@ function boundReceiver(subject, reading) {
|
|
|
344
344
|
if (!N3.isIdentifier(env) || !isTriggerEnvArgument(env, reading.resolution)) {
|
|
345
345
|
return null;
|
|
346
346
|
}
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
347
|
+
const store = storeTypedOn(receiver);
|
|
348
|
+
return store === null ? null : { name: receiver.getName(), store };
|
|
349
|
+
}
|
|
350
|
+
function storeTypedOn(receiver) {
|
|
351
|
+
for (const type of receiverTypesOf(receiver)) {
|
|
352
|
+
if (Object.hasOwn(STORES, type.name)) {
|
|
353
|
+
return STORES[type.name];
|
|
354
|
+
}
|
|
350
355
|
}
|
|
351
|
-
return
|
|
356
|
+
return null;
|
|
352
357
|
}
|
|
353
358
|
function declaredInitializer(identifier) {
|
|
354
359
|
for (const declaration of identifier.getSymbol()?.getDeclarations() ?? []) {
|
|
@@ -358,25 +363,11 @@ function declaredInitializer(identifier) {
|
|
|
358
363
|
}
|
|
359
364
|
return null;
|
|
360
365
|
}
|
|
361
|
-
function declaredTypeName(receiver) {
|
|
362
|
-
const declarations = receiver.getNameNode().getSymbol()?.getDeclarations() ?? [];
|
|
363
|
-
for (const declaration of declarations) {
|
|
364
|
-
if (!N3.isPropertySignature(declaration)) {
|
|
365
|
-
continue;
|
|
366
|
-
}
|
|
367
|
-
const typeNode = declaration.getTypeNode();
|
|
368
|
-
if (typeNode !== void 0) {
|
|
369
|
-
return typeNode.getText();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
366
|
var optionsSchema = z.object({
|
|
375
367
|
/**
|
|
376
|
-
* The name
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
* directory. Left out, the directory decides.
|
|
368
|
+
* The Worker's `name` from `wrangler.toml`. When it is set, every unit
|
|
369
|
+
* records it as its deployable, so a runtime-config provider pairs
|
|
370
|
+
* with the Worker by name. Without it, units pair by directory.
|
|
380
371
|
*/
|
|
381
372
|
scriptName: z.string().optional()
|
|
382
373
|
}).strict();
|
|
@@ -385,14 +376,14 @@ function cloudflareWorkersFramework(options = {}) {
|
|
|
385
376
|
name: "cloudflare-workers",
|
|
386
377
|
protocol: "http",
|
|
387
378
|
languages: ["typescript", "javascript"],
|
|
388
|
-
//
|
|
389
|
-
//
|
|
379
|
+
// A Worker registers nothing in code, so the pattern list stays empty
|
|
380
|
+
// and the callback reads the exported object.
|
|
390
381
|
discovery: [],
|
|
391
382
|
discoverUnits: cloudflareWorkersDiscovery(options),
|
|
392
383
|
terminals: [
|
|
393
384
|
{
|
|
394
|
-
// new Response(body, { status })
|
|
395
|
-
//
|
|
385
|
+
// new Response(body, { status }). A Worker returns a Response for
|
|
386
|
+
// JSON, a redirect, a stream and plain text alike.
|
|
396
387
|
kind: "response",
|
|
397
388
|
match: { type: "functionCall", functionName: "Response" },
|
|
398
389
|
extraction: {
|
package/dist/drizzle.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
propertiesOf,
|
|
8
8
|
propertyNameOf,
|
|
9
9
|
propertyOf,
|
|
10
|
+
receiverTypesOf,
|
|
10
11
|
stringValueOf,
|
|
11
12
|
writtenNodeOf
|
|
12
13
|
} from "@suss/adapter-typescript";
|
|
@@ -25,12 +26,12 @@ var DRIZZLE_PACKAGE = "drizzle-orm";
|
|
|
25
26
|
var CHAIN_WALK_LIMIT = 12;
|
|
26
27
|
var optionsSchema = z.object({
|
|
27
28
|
/**
|
|
28
|
-
*
|
|
29
|
-
* `storageSystem` on provider summaries
|
|
30
|
-
*
|
|
29
|
+
* The storage system the calls target, `"postgresql"` when unset. It
|
|
30
|
+
* has to match the `storageSystem` on provider summaries, or the
|
|
31
|
+
* calls do not pair.
|
|
31
32
|
*/
|
|
32
33
|
storageSystem: storageSystemOption.optional(),
|
|
33
|
-
/** Scope
|
|
34
|
+
/** Scope for the storage binding, `"default"` when unset. */
|
|
34
35
|
scope: scopeOption.optional()
|
|
35
36
|
}).strict();
|
|
36
37
|
function rawStatements(opts) {
|
|
@@ -159,7 +160,7 @@ function recognizeQueryApi(call, receiver, operation, resolution) {
|
|
|
159
160
|
if (!isDrizzleReceiver(queryAccess.getExpression())) {
|
|
160
161
|
return null;
|
|
161
162
|
}
|
|
162
|
-
const table = resolveTableName(receiver, resolution)
|
|
163
|
+
const table = resolveTableName(receiver, resolution);
|
|
163
164
|
const optionsArg = call.getArguments()[0];
|
|
164
165
|
const options = optionsArg === void 0 ? null : objectLiteralOf(optionsArg, resolution);
|
|
165
166
|
const fields = [];
|
|
@@ -200,17 +201,12 @@ function collectChainCalls(anchor) {
|
|
|
200
201
|
return chain;
|
|
201
202
|
}
|
|
202
203
|
function isDrizzleReceiver(node) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (decl.getSourceFile().getFilePath().includes("/drizzle-orm/")) {
|
|
210
|
-
return true;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return false;
|
|
204
|
+
return receiverTypesOf(node).some((type) => declaredByDrizzle(type));
|
|
205
|
+
}
|
|
206
|
+
function declaredByDrizzle(type) {
|
|
207
|
+
return type.declaredIn.some(
|
|
208
|
+
(filePath) => filePath.includes(`/${DRIZZLE_PACKAGE}/`)
|
|
209
|
+
);
|
|
214
210
|
}
|
|
215
211
|
function resolveTableName(tableExpr, resolution) {
|
|
216
212
|
const written = writtenNodeOf(tableExpr, resolution);
|
|
@@ -293,9 +289,8 @@ function drizzleFramework(options = {}) {
|
|
|
293
289
|
discovery: [],
|
|
294
290
|
terminals: [],
|
|
295
291
|
inputMapping: { type: "positionalParams", params: [] },
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
// them can't type-check as Drizzle receivers anyway.
|
|
292
|
+
// A file with no `drizzle-orm` import, subpaths included, has no
|
|
293
|
+
// value whose type Drizzle declares.
|
|
299
294
|
requiresImport: ["drizzle-orm"],
|
|
300
295
|
invocationRecognizers: [makeRecognizer(options)],
|
|
301
296
|
// A statement can be written as a tagged template, which the
|
|
@@ -308,7 +303,7 @@ var declares = {
|
|
|
308
303
|
kind: "effects",
|
|
309
304
|
package: "@suss/framework-drizzle",
|
|
310
305
|
dependencies: [{ ecosystem: "npm", name: "drizzle-orm" }],
|
|
311
|
-
reads: "Drizzle ORM query-builder and relational-query calls
|
|
306
|
+
reads: "Drizzle ORM query-builder and relational-query calls. Each one becomes a storage-access interaction on the SQL table it touches."
|
|
312
307
|
};
|
|
313
308
|
var index_default = drizzleFramework;
|
|
314
309
|
export {
|
package/dist/express.js
CHANGED
|
@@ -43,12 +43,9 @@ function expressFramework(_options = {}) {
|
|
|
43
43
|
name: "express",
|
|
44
44
|
protocol: "http",
|
|
45
45
|
languages: ["typescript", "javascript"],
|
|
46
|
-
//
|
|
47
|
-
// `
|
|
48
|
-
//
|
|
49
|
-
// Either can also be mounted onto another with `app.use(prefix,
|
|
50
|
-
// router)`, so a route declared on the mounted router summarizes
|
|
51
|
-
// with the mount's prefix composed in.
|
|
46
|
+
// Routes go on `Router()` or on `express()`, and either can be mounted
|
|
47
|
+
// with `app.use(prefix, router)`. A route on a mounted router is
|
|
48
|
+
// summarized with the mount's prefix in front of its path.
|
|
52
49
|
discovery: [
|
|
53
50
|
...httpRouteDiscovery({
|
|
54
51
|
importModule: "express",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { declares, default, optionsSchema } from '@suss/framework-fabrication';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// ../framework/fabrication/dist/index.js
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var optionsSchema = z.object({}).strict();
|
|
4
|
+
var LIBRARY = "Fabricate";
|
|
5
|
+
function fabricationFramework(_options = {}) {
|
|
6
|
+
return {
|
|
7
|
+
name: "fabrication",
|
|
8
|
+
protocol: "in-process",
|
|
9
|
+
discovery: [],
|
|
10
|
+
factories: [
|
|
11
|
+
{
|
|
12
|
+
definitionMethods: ["Fabricator"],
|
|
13
|
+
classKeywords: ["class_name"],
|
|
14
|
+
parentKeywords: ["from"],
|
|
15
|
+
nestedDefinitionsInherit: false,
|
|
16
|
+
builders: [
|
|
17
|
+
{ method: "Fabricate" },
|
|
18
|
+
{ method: "build", receiver: LIBRARY },
|
|
19
|
+
{ method: "create", receiver: LIBRARY }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var declares = {
|
|
26
|
+
kind: "framework",
|
|
27
|
+
package: "@suss/framework-fabrication",
|
|
28
|
+
dependencies: [],
|
|
29
|
+
reads: "Fabrication builds in tests (Ruby), typed by the class each fabricator builds, so a test's calls on them are followed."
|
|
30
|
+
};
|
|
31
|
+
var index_default = fabricationFramework;
|
|
32
|
+
export {
|
|
33
|
+
declares,
|
|
34
|
+
index_default as default,
|
|
35
|
+
optionsSchema
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { declares, default, optionsSchema } from '@suss/framework-factory-bot';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// ../framework/factory-bot/dist/index.js
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var optionsSchema = z.object({}).strict();
|
|
4
|
+
var BUILDS = ["create", "build", "build_stubbed"];
|
|
5
|
+
var LIBRARY = "FactoryBot";
|
|
6
|
+
function factoryBotFramework(_options = {}) {
|
|
7
|
+
return {
|
|
8
|
+
name: "factory-bot",
|
|
9
|
+
protocol: "in-process",
|
|
10
|
+
discovery: [],
|
|
11
|
+
factories: [
|
|
12
|
+
{
|
|
13
|
+
definitionMethods: ["factory"],
|
|
14
|
+
classKeywords: ["class"],
|
|
15
|
+
parentKeywords: ["parent"],
|
|
16
|
+
nestedDefinitionsInherit: true,
|
|
17
|
+
builders: [
|
|
18
|
+
...BUILDS.map((method) => ({ method })),
|
|
19
|
+
...BUILDS.map((method) => ({ method, receiver: LIBRARY }))
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var declares = {
|
|
26
|
+
kind: "framework",
|
|
27
|
+
package: "@suss/framework-factory-bot",
|
|
28
|
+
dependencies: [],
|
|
29
|
+
reads: "factory_bot builds in tests (Ruby), typed by the class each factory builds, so a test's calls on them are followed."
|
|
30
|
+
};
|
|
31
|
+
var index_default = factoryBotFramework;
|
|
32
|
+
export {
|
|
33
|
+
declares,
|
|
34
|
+
index_default as default,
|
|
35
|
+
optionsSchema
|
|
36
|
+
};
|
package/dist/faraday.js
CHANGED
|
@@ -17,14 +17,13 @@ function faradayClient() {
|
|
|
17
17
|
{
|
|
18
18
|
constantName: "Faraday",
|
|
19
19
|
verbMethodNames: VERB_METHODS,
|
|
20
|
-
// Every one of them takes the URL first.
|
|
21
20
|
url: { position: 0 },
|
|
22
21
|
receiverBuilders: ["new"],
|
|
23
|
-
// `Faraday.new(url: "
|
|
24
|
-
//
|
|
22
|
+
// Calls on a connection from `Faraday.new(url: ".../v1")` get the
|
|
23
|
+
// path of that URL in front of their own.
|
|
25
24
|
builderUrlKeyword: "url",
|
|
26
|
-
//
|
|
27
|
-
//
|
|
25
|
+
// A caller's condition on one of these members shows which
|
|
26
|
+
// statuses it handles.
|
|
28
27
|
response: {
|
|
29
28
|
statusCode: ["status"],
|
|
30
29
|
success: ["success?"],
|
package/dist/fastapi.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
var optionsSchema = z.object({
|
|
4
4
|
/**
|
|
5
|
-
* Modules
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* configures the pack rather than hardcoded here.
|
|
5
|
+
* Modules that re-export FastAPI's constructors, on top of `fastapi`
|
|
6
|
+
* itself. A dependency stub fills this in; a project's config file
|
|
7
|
+
* may not set it.
|
|
9
8
|
*/
|
|
10
9
|
wrapperModules: z.array(z.string()).optional()
|
|
11
10
|
}).strict();
|
|
@@ -18,10 +17,25 @@ var VERB_ATTRIBUTE_NAMES = {
|
|
|
18
17
|
head: "HEAD",
|
|
19
18
|
options: "OPTIONS"
|
|
20
19
|
};
|
|
20
|
+
var PARAMETER_SOURCES = {
|
|
21
|
+
Header: { role: "headers", underscoresAs: "-" },
|
|
22
|
+
Query: { role: "queryParams" },
|
|
23
|
+
Path: { role: "pathParams" },
|
|
24
|
+
Body: { role: "requestBody" },
|
|
25
|
+
Form: { role: "requestBody" },
|
|
26
|
+
Cookie: { role: "cookies" }
|
|
27
|
+
};
|
|
28
|
+
var REQUEST_SPELLING = {
|
|
29
|
+
headers: { path: ["headers"], saysWhichField: true },
|
|
30
|
+
query: { path: ["queryParams"], saysWhichField: true },
|
|
31
|
+
params: { path: ["pathParams"], saysWhichField: true },
|
|
32
|
+
body: { path: ["requestBody"], saysWhichField: true }
|
|
33
|
+
};
|
|
21
34
|
function fastapiFramework(options = {}) {
|
|
22
35
|
return {
|
|
23
36
|
name: "fastapi",
|
|
24
37
|
protocol: "http",
|
|
38
|
+
requestSpelling: REQUEST_SPELLING,
|
|
25
39
|
...options.wrapperModules !== void 0 ? { projectModules: options.wrapperModules } : {},
|
|
26
40
|
discovery: [
|
|
27
41
|
{
|
|
@@ -33,6 +47,8 @@ function fastapiFramework(options = {}) {
|
|
|
33
47
|
// FastAPI resolves both of these itself and calls the handler with
|
|
34
48
|
// the result, so a parameter defaulted to one is never sent.
|
|
35
49
|
injectedParameterCallees: ["Depends", "Security"],
|
|
50
|
+
parameterSources: PARAMETER_SOURCES,
|
|
51
|
+
parameterAliasKeyword: "alias",
|
|
36
52
|
// FastAPI returns 200 for a route that declares no status.
|
|
37
53
|
defaultStatusCode: 200,
|
|
38
54
|
responseModelKeyword: "response_model",
|
|
@@ -106,7 +122,7 @@ var declares = {
|
|
|
106
122
|
kind: "framework",
|
|
107
123
|
package: "@suss/framework-fastapi",
|
|
108
124
|
dependencies: [{ ecosystem: "pypi", name: "fastapi" }],
|
|
109
|
-
reads: `FastAPI routes (Python)
|
|
125
|
+
reads: `FastAPI routes (Python). The verb comes from the decorator's attribute name, \`APIRouter\` prefixes are composed one \`include_router\` hop deep, and \`response_model\` and \`status_code\` are taken as the declared contract.`
|
|
110
126
|
};
|
|
111
127
|
var index_default = fastapiFramework;
|
|
112
128
|
export {
|