@suss/packs 0.11.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.
Files changed (63) hide show
  1. package/LICENSE +205 -0
  2. package/README.md +29 -0
  3. package/dist/activerecord.d.ts +30 -0
  4. package/dist/activerecord.js +45 -0
  5. package/dist/apollo-client.d.ts +1 -0
  6. package/dist/apollo-client.js +137 -0
  7. package/dist/apollo.d.ts +1 -0
  8. package/dist/apollo.js +90 -0
  9. package/dist/aws-dynamodb.d.ts +1 -0
  10. package/dist/aws-dynamodb.js +386 -0
  11. package/dist/aws-eventbridge.d.ts +1 -0
  12. package/dist/aws-eventbridge.js +240 -0
  13. package/dist/aws-lambda.d.ts +1 -0
  14. package/dist/aws-lambda.js +382 -0
  15. package/dist/aws-s3.d.ts +1 -0
  16. package/dist/aws-s3.js +120 -0
  17. package/dist/aws-sqs.d.ts +1 -0
  18. package/dist/aws-sqs.js +296 -0
  19. package/dist/axios.d.ts +1 -0
  20. package/dist/axios.js +107 -0
  21. package/dist/cloudflare-workers.d.ts +1 -0
  22. package/dist/cloudflare-workers.js +562 -0
  23. package/dist/drizzle.d.ts +1 -0
  24. package/dist/drizzle.js +383 -0
  25. package/dist/express.d.ts +1 -0
  26. package/dist/express.js +124 -0
  27. package/dist/fastapi.d.ts +1 -0
  28. package/dist/fastapi.js +42 -0
  29. package/dist/fastify.d.ts +1 -0
  30. package/dist/fastify.js +116 -0
  31. package/dist/fetch.d.ts +1 -0
  32. package/dist/fetch.js +64 -0
  33. package/dist/flask-restx.d.ts +1 -0
  34. package/dist/flask-restx.js +59 -0
  35. package/dist/gcs.d.ts +1 -0
  36. package/dist/gcs.js +134 -0
  37. package/dist/graphql-ruby.d.ts +1 -0
  38. package/dist/graphql-ruby.js +84 -0
  39. package/dist/hono.d.ts +1 -0
  40. package/dist/hono.js +184 -0
  41. package/dist/mongoose.d.ts +1 -0
  42. package/dist/mongoose.js +379 -0
  43. package/dist/nestjs-graphql.d.ts +1 -0
  44. package/dist/nestjs-graphql.js +77 -0
  45. package/dist/nestjs-rest.d.ts +1 -0
  46. package/dist/nestjs-rest.js +89 -0
  47. package/dist/nextjs.d.ts +1 -0
  48. package/dist/nextjs.js +154 -0
  49. package/dist/node.d.ts +1 -0
  50. package/dist/node.js +667 -0
  51. package/dist/prisma.d.ts +1 -0
  52. package/dist/prisma.js +448 -0
  53. package/dist/react-router.d.ts +1 -0
  54. package/dist/react-router.js +197 -0
  55. package/dist/react.d.ts +1 -0
  56. package/dist/react.js +221 -0
  57. package/dist/redis.d.ts +1 -0
  58. package/dist/redis.js +93 -0
  59. package/dist/sqlalchemy.d.ts +1 -0
  60. package/dist/sqlalchemy.js +48 -0
  61. package/dist/ts-rest.d.ts +1 -0
  62. package/dist/ts-rest.js +89 -0
  63. package/package.json +208 -0
package/dist/prisma.js ADDED
@@ -0,0 +1,448 @@
1
+ // ../framework/prisma/dist/index.js
2
+ import {
3
+ Node as N
4
+ } from "ts-morph";
5
+ import { storageBinding } from "@suss/behavioral-ir";
6
+ import { readSqlAccess, sqlFromParts } from "@suss/sql";
7
+ var RAW_METHODS = /* @__PURE__ */ new Set([
8
+ "$queryRaw",
9
+ "$executeRaw",
10
+ "$queryRawUnsafe",
11
+ "$executeRawUnsafe"
12
+ ]);
13
+ var PRISMA_READ_METHODS = /* @__PURE__ */ new Set([
14
+ "findUnique",
15
+ "findFirst",
16
+ "findMany",
17
+ "count",
18
+ "aggregate",
19
+ "groupBy"
20
+ ]);
21
+ var WRITE_PAYLOAD_KEYS = ["data", "create", "update"];
22
+ var PRISMA_WRITE_METHODS = /* @__PURE__ */ new Set([
23
+ "create",
24
+ "update",
25
+ "delete",
26
+ "upsert",
27
+ "createMany",
28
+ "updateMany",
29
+ "deleteMany"
30
+ ]);
31
+ function makeRecognizer(opts) {
32
+ const storageSystem = opts.storageSystem ?? "postgresql";
33
+ const scope = opts.scope ?? "default";
34
+ return (call, ctx) => recognizePrismaCall(call, ctx, storageSystem, scope);
35
+ }
36
+ function recognizePrismaCall(call, ctx, storageSystem, scope) {
37
+ const callNode = call;
38
+ const recognizerCtx = ctx;
39
+ const calleeExpr = callNode.getExpression();
40
+ if (!N.isPropertyAccessExpression(calleeExpr)) {
41
+ return null;
42
+ }
43
+ const delegateExpr = calleeExpr.getExpression();
44
+ if (!N.isPropertyAccessExpression(delegateExpr)) {
45
+ return null;
46
+ }
47
+ const method = calleeExpr.getName();
48
+ const isRead = PRISMA_READ_METHODS.has(method);
49
+ const isWrite = PRISMA_WRITE_METHODS.has(method);
50
+ if (!isRead && !isWrite) {
51
+ return null;
52
+ }
53
+ const receiverExpr = delegateExpr.getExpression();
54
+ if (!isPrismaClientReceiver(receiverExpr)) {
55
+ return null;
56
+ }
57
+ const delegateName = delegateExpr.getName();
58
+ const tableName = capitalizeFirst(delegateName);
59
+ if (tableName === null) {
60
+ return null;
61
+ }
62
+ const kind = isRead ? "read" : "write";
63
+ const argsShape = recognizerCtx.extractArgs();
64
+ const optionsArg = readObjectArg(argsShape[0]);
65
+ const fields = extractFields(optionsArg, kind);
66
+ const selector = extractSelector(optionsArg);
67
+ const binding = storageBinding({
68
+ recognition: "@suss/framework-prisma",
69
+ storageSystem,
70
+ scope,
71
+ container: tableName
72
+ });
73
+ const callee = callNode.getExpression().getText();
74
+ return [
75
+ {
76
+ type: "interaction",
77
+ binding,
78
+ callee,
79
+ interaction: {
80
+ class: "storage-access",
81
+ kind,
82
+ fields,
83
+ ...selector !== null ? { selector } : {},
84
+ operation: method
85
+ }
86
+ },
87
+ ...nestedReads(optionsArg).map(
88
+ (nested) => ({
89
+ type: "interaction",
90
+ binding,
91
+ callee,
92
+ interaction: {
93
+ class: "storage-access",
94
+ kind: "read",
95
+ fields: nested.fields,
96
+ relationPath: nested.relationPath,
97
+ operation: method
98
+ }
99
+ })
100
+ ),
101
+ ...nestedWrites(optionsArg).map(
102
+ (nested) => ({
103
+ type: "interaction",
104
+ binding,
105
+ callee,
106
+ interaction: {
107
+ class: "storage-access",
108
+ kind: "write",
109
+ fields: nested.fields,
110
+ relationPath: nested.relationPath,
111
+ ...nested.relationKey === true ? { relationKey: true } : {},
112
+ // What reaches the other model is the nested operation, so
113
+ // that is what the effect records. The outer method belongs
114
+ // to the model in the binding.
115
+ operation: nested.operation
116
+ }
117
+ })
118
+ )
119
+ ];
120
+ }
121
+ function nestedReads(optionsArg) {
122
+ if (optionsArg === null) {
123
+ return [];
124
+ }
125
+ const found = [];
126
+ collectRelations(optionsArg, [], found);
127
+ return found;
128
+ }
129
+ function collectRelations(shape, path, found) {
130
+ const select = readObjectArg(shape.fields.select);
131
+ if (select !== null) {
132
+ for (const [name, value] of Object.entries(select.fields)) {
133
+ const nested = readObjectArg(value);
134
+ if (nested === null) {
135
+ continue;
136
+ }
137
+ recordRelation(name, nested, path, found);
138
+ }
139
+ }
140
+ const include = readObjectArg(shape.fields.include);
141
+ if (include === null) {
142
+ return;
143
+ }
144
+ for (const [name, value] of Object.entries(include.fields)) {
145
+ const nested = readObjectArg(value);
146
+ if (nested === null) {
147
+ found.push({ relationPath: [...path, name], fields: ["*"] });
148
+ continue;
149
+ }
150
+ recordRelation(name, nested, path, found);
151
+ }
152
+ }
153
+ function recordRelation(name, nested, path, found) {
154
+ const relationPath = [...path, name];
155
+ found.push({ relationPath, fields: extractFields(nested, "read") });
156
+ collectRelations(nested, relationPath, found);
157
+ }
158
+ var rowIsPayload = (payload) => {
159
+ const read = objectsIn(payload);
160
+ return { fields: fieldsOfRows(read), rows: read.rows };
161
+ };
162
+ function rowsUnder(...keys) {
163
+ return (payload) => {
164
+ const outer = objectsIn(payload);
165
+ const rows = [];
166
+ let written = outer.written && outer.rows.length > 0;
167
+ for (const entry of outer.rows) {
168
+ for (const key of keys) {
169
+ const inner = objectsIn(entry.fields[key]);
170
+ rows.push(...inner.rows);
171
+ written = written && inner.written;
172
+ }
173
+ }
174
+ return { fields: fieldsOfRows({ rows, written }), rows };
175
+ };
176
+ }
177
+ var updateRow = (payload) => {
178
+ const outer = objectsIn(payload);
179
+ const statesData = outer.rows.some((row) => "data" in row.fields);
180
+ return statesData ? rowsUnder("data")(payload) : rowIsPayload(payload);
181
+ };
182
+ var wholeRow = () => ({ fields: ["*"], rows: [] });
183
+ var NESTED_OPERATIONS = /* @__PURE__ */ new Map([
184
+ ["create", { rows: rowIsPayload }],
185
+ ["createMany", { rows: rowsUnder("data") }],
186
+ ["connectOrCreate", { rows: rowsUnder("create"), movesJoin: true }],
187
+ ["update", { rows: updateRow }],
188
+ ["updateMany", { rows: rowsUnder("data") }],
189
+ ["upsert", { rows: rowsUnder("create", "update") }],
190
+ ["delete", { rows: wholeRow }],
191
+ ["deleteMany", { rows: wholeRow }],
192
+ ["connect", { movesJoin: true }],
193
+ ["disconnect", { movesJoin: true }],
194
+ ["set", { movesJoin: true }]
195
+ ]);
196
+ function nestedWrites(optionsArg) {
197
+ if (optionsArg === null) {
198
+ return [];
199
+ }
200
+ const found = [];
201
+ for (const key of WRITE_PAYLOAD_KEYS) {
202
+ for (const row of objectsIn(optionsArg.fields[key]).rows) {
203
+ collectNestedWrites(row, [], found);
204
+ }
205
+ }
206
+ return found;
207
+ }
208
+ function collectNestedWrites(row, path, found) {
209
+ for (const [field, value] of Object.entries(row.fields)) {
210
+ const nested = readObjectArg(value);
211
+ if (nested === null) {
212
+ continue;
213
+ }
214
+ const relationPath = [...path, field];
215
+ for (const [operation, payload] of Object.entries(nested.fields)) {
216
+ const does = NESTED_OPERATIONS.get(operation);
217
+ if (does === void 0) {
218
+ continue;
219
+ }
220
+ if (does.rows !== void 0) {
221
+ const written = does.rows(payload);
222
+ found.push({ relationPath, fields: written.fields, operation });
223
+ for (const deeper of written.rows) {
224
+ collectNestedWrites(deeper, relationPath, found);
225
+ }
226
+ }
227
+ if (does.movesJoin === true) {
228
+ found.push({ relationPath, fields: [], operation, relationKey: true });
229
+ }
230
+ }
231
+ }
232
+ }
233
+ function objectsIn(arg) {
234
+ const object = readObjectArg(arg);
235
+ if (object !== null) {
236
+ return { rows: [object], written: true };
237
+ }
238
+ if (arg === null || arg === void 0 || typeof arg !== "object" || arg.kind !== "array") {
239
+ return { rows: [], written: false };
240
+ }
241
+ const rows = [];
242
+ let written = true;
243
+ for (const item of arg.items) {
244
+ const row = readObjectArg(item);
245
+ if (row === null) {
246
+ written = false;
247
+ continue;
248
+ }
249
+ rows.push(row);
250
+ }
251
+ return { rows, written };
252
+ }
253
+ function fieldsOfRows(read) {
254
+ if (!read.written) {
255
+ return ["*"];
256
+ }
257
+ const out = /* @__PURE__ */ new Set();
258
+ for (const row of read.rows) {
259
+ for (const key of Object.keys(row.fields)) {
260
+ out.add(key);
261
+ }
262
+ }
263
+ return out.size === 0 ? ["*"] : [...out];
264
+ }
265
+ function isPrismaClientReceiver(node) {
266
+ const type = node.getType();
267
+ if (type === null || typeof type !== "object") {
268
+ return false;
269
+ }
270
+ const symbol = type.getSymbol?.();
271
+ if (symbol === null || symbol === void 0) {
272
+ return false;
273
+ }
274
+ const decls = symbol.getDeclarations?.() ?? [];
275
+ for (const decl of decls) {
276
+ const declSourceFile = decl.getSourceFile();
277
+ const filePath = declSourceFile.getFilePath();
278
+ if (filePath.includes("/@prisma/client/") || filePath.includes("/.prisma/client/")) {
279
+ return true;
280
+ }
281
+ }
282
+ return false;
283
+ }
284
+ function capitalizeFirst(name) {
285
+ if (name.length === 0) {
286
+ return null;
287
+ }
288
+ return name[0].toUpperCase() + name.slice(1);
289
+ }
290
+ function readObjectArg(arg) {
291
+ if (arg === null || arg === void 0) {
292
+ return null;
293
+ }
294
+ if (typeof arg !== "object") {
295
+ return null;
296
+ }
297
+ if (arg.kind !== "object") {
298
+ return null;
299
+ }
300
+ return arg;
301
+ }
302
+ function extractFields(optionsArg, kind) {
303
+ if (optionsArg === null) {
304
+ return ["*"];
305
+ }
306
+ if (kind === "read") {
307
+ const select = readObjectArg(optionsArg.fields.select);
308
+ const include = readObjectArg(optionsArg.fields.include);
309
+ if (select === null) {
310
+ return ["*"];
311
+ }
312
+ const out = /* @__PURE__ */ new Set();
313
+ for (const k of Object.keys(select.fields)) {
314
+ out.add(k);
315
+ }
316
+ if (include !== null) {
317
+ for (const k of Object.keys(include.fields)) {
318
+ out.add(k);
319
+ }
320
+ }
321
+ return [...out];
322
+ }
323
+ const stated = /* @__PURE__ */ new Map();
324
+ for (const propName of WRITE_PAYLOAD_KEYS) {
325
+ const prop = readObjectArg(optionsArg.fields[propName]);
326
+ if (prop === null) {
327
+ continue;
328
+ }
329
+ for (const [name, value] of Object.entries(prop.fields)) {
330
+ stated.set(name, value);
331
+ }
332
+ }
333
+ if (stated.size === 0) {
334
+ return ["*"];
335
+ }
336
+ const columns = [];
337
+ for (const [name, value] of stated) {
338
+ if (statesNestedOperations(value)) {
339
+ continue;
340
+ }
341
+ columns.push(name);
342
+ }
343
+ return columns;
344
+ }
345
+ function statesNestedOperations(value) {
346
+ const nested = readObjectArg(value);
347
+ if (nested === null) {
348
+ return false;
349
+ }
350
+ return Object.keys(nested.fields).some((key) => NESTED_OPERATIONS.has(key));
351
+ }
352
+ function extractSelector(optionsArg) {
353
+ if (optionsArg === null) {
354
+ return null;
355
+ }
356
+ const where = readObjectArg(optionsArg.fields.where);
357
+ if (where === null) {
358
+ return null;
359
+ }
360
+ const keys = Object.keys(where.fields);
361
+ return keys.length > 0 ? keys : null;
362
+ }
363
+ function makeRawRecognizer(opts) {
364
+ const storageSystem = opts.storageSystem ?? "postgresql";
365
+ const scope = opts.scope ?? "default";
366
+ return ((node) => {
367
+ const statement = rawStatementAt(node);
368
+ if (statement === null) {
369
+ return null;
370
+ }
371
+ const accesses = readSqlAccess(statement.sql, { dialect: storageSystem });
372
+ if (accesses.length === 0) {
373
+ return null;
374
+ }
375
+ return accesses.map((access) => ({
376
+ type: "interaction",
377
+ binding: storageBinding({
378
+ recognition: "@suss/framework-prisma",
379
+ storageSystem,
380
+ scope,
381
+ container: access.table
382
+ }),
383
+ callee: statement.callee,
384
+ interaction: {
385
+ class: "storage-access",
386
+ kind: access.kind,
387
+ fields: access.fields,
388
+ ...access.selector.length > 0 ? { selector: access.selector } : {},
389
+ operation: statement.method
390
+ }
391
+ }));
392
+ });
393
+ }
394
+ function rawStatementAt(node) {
395
+ const tag = N.isTaggedTemplateExpression(node) ? node.getTag() : N.isCallExpression(node) ? node.getExpression() : null;
396
+ if (tag === null || !N.isPropertyAccessExpression(tag)) {
397
+ return null;
398
+ }
399
+ const method = tag.getName();
400
+ if (!RAW_METHODS.has(method)) {
401
+ return null;
402
+ }
403
+ if (!isPrismaClientReceiver(tag.getExpression())) {
404
+ return null;
405
+ }
406
+ const sql = N.isTaggedTemplateExpression(node) ? templateSql(node.getTemplate()) : N.isCallExpression(node) ? literalSql(node.getArguments()[0]) : null;
407
+ return sql === null ? null : { sql, method, callee: tag.getText() };
408
+ }
409
+ function templateSql(template) {
410
+ if (N.isNoSubstitutionTemplateLiteral(template)) {
411
+ return template.getLiteralValue();
412
+ }
413
+ if (!N.isTemplateExpression(template)) {
414
+ return null;
415
+ }
416
+ return sqlFromParts([
417
+ template.getHead().getLiteralText(),
418
+ ...template.getTemplateSpans().map((span) => span.getLiteral().getLiteralText())
419
+ ]);
420
+ }
421
+ function literalSql(argument) {
422
+ if (argument === void 0) {
423
+ return null;
424
+ }
425
+ if (N.isStringLiteral(argument) || N.isNoSubstitutionTemplateLiteral(argument)) {
426
+ return argument.getLiteralValue();
427
+ }
428
+ return N.isTemplateExpression(argument) ? templateSql(argument) : null;
429
+ }
430
+ function prismaFramework(options = {}) {
431
+ return {
432
+ name: "prisma",
433
+ protocol: "in-process",
434
+ languages: ["typescript", "javascript"],
435
+ discovery: [],
436
+ terminals: [],
437
+ inputMapping: { type: "positionalParams", params: [] },
438
+ // Skip files that don't import from @prisma/client: the
439
+ // recognizer's type-resolution check would reject them anyway.
440
+ requiresImport: ["@prisma/client"],
441
+ invocationRecognizers: [makeRecognizer(options)],
442
+ accessRecognizers: [makeRawRecognizer(options)]
443
+ };
444
+ }
445
+ var index_default = prismaFramework;
446
+ export {
447
+ index_default as default
448
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@suss/framework-react-router';
@@ -0,0 +1,197 @@
1
+ // ../framework/react-router/dist/index.js
2
+ var RESPONSE_MODULES = [
3
+ "react-router",
4
+ "react-router-dom",
5
+ "@remix-run/node",
6
+ "@remix-run/cloudflare",
7
+ "@remix-run/deno",
8
+ "@remix-run/server-runtime"
9
+ ];
10
+ var HTTP_ERRORS_CODES = {
11
+ BadRequest: 400,
12
+ Unauthorized: 401,
13
+ PaymentRequired: 402,
14
+ Forbidden: 403,
15
+ NotFound: 404,
16
+ MethodNotAllowed: 405,
17
+ NotAcceptable: 406,
18
+ RequestTimeout: 408,
19
+ Conflict: 409,
20
+ Gone: 410,
21
+ PayloadTooLarge: 413,
22
+ UnsupportedMediaType: 415,
23
+ ImATeapot: 418,
24
+ UnprocessableEntity: 422,
25
+ TooManyRequests: 429,
26
+ InternalServerError: 500,
27
+ NotImplemented: 501,
28
+ BadGateway: 502,
29
+ ServiceUnavailable: 503,
30
+ GatewayTimeout: 504
31
+ };
32
+ var ROUTER_MODULES = ["react-router", "react-router-dom"];
33
+ var JSX_ROUTES = {
34
+ type: "jsxElementRoute",
35
+ importModule: ROUTER_MODULES,
36
+ routeElement: "Route",
37
+ pathAttribute: "path",
38
+ elementAttribute: "element",
39
+ indexAttribute: "index",
40
+ childrenAttribute: "children",
41
+ routeObjectFactories: ["createBrowserRouter"],
42
+ elementsFactories: ["createRoutesFromElements"],
43
+ method: "GET"
44
+ };
45
+ function reactRouterFramework(options = {}) {
46
+ return {
47
+ name: "react-router",
48
+ protocol: "http",
49
+ languages: ["typescript", "javascript"],
50
+ discovery: [
51
+ {
52
+ kind: "loader",
53
+ match: { type: "namedExport", names: ["loader"] },
54
+ // No route derived from the filename. React Router only
55
+ // reads routes that way when the project opted in by
56
+ // importing @react-router/fs-routes, and the pack language
57
+ // has no way to say "only when that import is there". A
58
+ // loader whose route came out of a guess pairs with whatever
59
+ // consumer matches the guess, which is worse than pairing
60
+ // with nothing.
61
+ // Empty gate: route files often re-export `loader` /
62
+ // `action` from non-router-importing modules
63
+ // (server-side data functions, shared util re-exports).
64
+ // A heuristic gate would miss those. The dispatch only
65
+ // looks at named exports, so paying for the walk on
66
+ // every file is fine.
67
+ requiresImport: []
68
+ },
69
+ {
70
+ kind: "action",
71
+ match: { type: "namedExport", names: ["action"] },
72
+ // No route derived from the filename. React Router only
73
+ // reads routes that way when the project opted in by
74
+ // importing @react-router/fs-routes, and the pack language
75
+ // has no way to say "only when that import is there". A
76
+ // loader whose route came out of a guess pairs with whatever
77
+ // consumer matches the guess, which is worse than pairing
78
+ // with nothing.
79
+ requiresImport: []
80
+ },
81
+ {
82
+ kind: "component",
83
+ match: { type: "namedExport", names: ["default"] },
84
+ requiresImport: []
85
+ },
86
+ {
87
+ // The route tree the app declares in its own JSX, which is how
88
+ // most React Router apps say what serves which URL. Gated on
89
+ // the router import, since the whole pattern is written with
90
+ // names that come out of it.
91
+ kind: "component",
92
+ match: JSX_ROUTES,
93
+ requiresImport: ROUTER_MODULES
94
+ }
95
+ ],
96
+ terminals: [
97
+ {
98
+ // json(data, init?), for example `return json({ user })`
99
+ kind: "response",
100
+ match: {
101
+ type: "functionCall",
102
+ functionName: "json",
103
+ // These names come from the router, so a same-named helper
104
+ // the project wrote is a different function, with its own
105
+ // argument order, and must not match.
106
+ requiresImport: RESPONSE_MODULES
107
+ },
108
+ extraction: {
109
+ body: { from: "argument", position: 0 },
110
+ defaultStatusCode: 200
111
+ }
112
+ },
113
+ {
114
+ // data(value, init?), React Router v7's replacement for json()
115
+ kind: "response",
116
+ match: {
117
+ type: "functionCall",
118
+ functionName: "data",
119
+ // These names come from the router, so a same-named helper
120
+ // the project wrote is a different function, with its own
121
+ // argument order, and must not match.
122
+ requiresImport: RESPONSE_MODULES
123
+ },
124
+ extraction: {
125
+ body: { from: "argument", position: 0 },
126
+ defaultStatusCode: 200
127
+ }
128
+ },
129
+ {
130
+ // redirect(url, status?), for example `return redirect("/login")`
131
+ kind: "response",
132
+ match: {
133
+ type: "functionCall",
134
+ functionName: "redirect",
135
+ // These names come from the router, so a same-named helper
136
+ // the project wrote is a different function, with its own
137
+ // argument order, and must not match.
138
+ requiresImport: RESPONSE_MODULES
139
+ },
140
+ extraction: {
141
+ statusCode: { from: "argument", position: 1 },
142
+ defaultStatusCode: 302
143
+ }
144
+ },
145
+ {
146
+ // What a routed component renders. The route says which
147
+ // URL reaches this component, and the JSX it returns is what
148
+ // that URL renders, so the pack reads both rather than
149
+ // reporting the route and nothing behind it.
150
+ kind: "render",
151
+ match: { type: "jsxReturn" },
152
+ extraction: {}
153
+ },
154
+ {
155
+ // Loaders return data directly
156
+ kind: "return",
157
+ match: { type: "returnShape" },
158
+ extraction: {
159
+ body: { from: "argument", position: 0 }
160
+ }
161
+ },
162
+ // A project's error helper puts the status in the class name of its
163
+ // argument, so resolve through `argumentConstructor` rather
164
+ // than taking the argument's raw source text as a status value.
165
+ ...(options.errorHelpers ?? []).map((helper) => ({
166
+ kind: "throw",
167
+ match: {
168
+ type: "throwExpression",
169
+ constructorPattern: helper
170
+ },
171
+ extraction: {
172
+ statusCode: {
173
+ from: "argumentConstructor",
174
+ position: 0,
175
+ codes: HTTP_ERRORS_CODES
176
+ },
177
+ body: { from: "argument", position: 1 }
178
+ },
179
+ // The router turns the thrown error's status into the wire response.
180
+ producesResponse: true
181
+ }))
182
+ ],
183
+ inputMapping: {
184
+ type: "singleObjectParam",
185
+ paramPosition: 0,
186
+ knownProperties: {
187
+ request: "request",
188
+ params: "pathParams",
189
+ context: "context"
190
+ }
191
+ }
192
+ };
193
+ }
194
+ var index_default = reactRouterFramework;
195
+ export {
196
+ index_default as default
197
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@suss/framework-react';