@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
@@ -0,0 +1,379 @@
1
+ // ../framework/mongoose/dist/index.js
2
+ import {
3
+ Node as N
4
+ } from "ts-morph";
5
+ import { methodDeclaredIn } from "@suss/adapter-typescript";
6
+ import { storageBinding } from "@suss/behavioral-ir";
7
+ var RECOGNITION = "@suss/framework-mongoose";
8
+ var STORAGE_SYSTEM = "mongodb";
9
+ var METHODS = {
10
+ find: { kind: "read", filterArg: 0, projectionArg: 1 },
11
+ findOne: { kind: "read", filterArg: 0, projectionArg: 1 },
12
+ findById: { kind: "read", idArg: 0, projectionArg: 1 },
13
+ countDocuments: { kind: "read", filterArg: 0 },
14
+ exists: { kind: "read", filterArg: 0 },
15
+ distinct: { kind: "read", fieldArg: 0, filterArg: 1 },
16
+ create: { kind: "write", payloadArg: 0 },
17
+ insertMany: { kind: "write", payloadArg: 0 },
18
+ updateOne: { kind: "write", filterArg: 0, updateArg: 1 },
19
+ updateMany: { kind: "write", filterArg: 0, updateArg: 1 },
20
+ replaceOne: { kind: "write", filterArg: 0, payloadArg: 1 },
21
+ deleteOne: { kind: "write", filterArg: 0 },
22
+ deleteMany: { kind: "write", filterArg: 0 },
23
+ findOneAndUpdate: { kind: "write", filterArg: 0, updateArg: 1 },
24
+ findByIdAndUpdate: { kind: "write", idArg: 0, updateArg: 1 },
25
+ findOneAndDelete: { kind: "write", filterArg: 0 },
26
+ findByIdAndDelete: { kind: "write", idArg: 0 },
27
+ findOneAndReplace: { kind: "write", filterArg: 0, payloadArg: 1 }
28
+ };
29
+ function defaultCollectionName(modelName) {
30
+ const lower = modelName.toLowerCase();
31
+ if (/[^aeiou]y$/.test(lower)) {
32
+ return `${lower.slice(0, -1)}ies`;
33
+ }
34
+ if (/(s|x|z|ch|sh)$/.test(lower)) {
35
+ return `${lower}es`;
36
+ }
37
+ return `${lower}s`;
38
+ }
39
+ function resolveModelIdentity(node, resolve) {
40
+ if (N.isCallExpression(node)) {
41
+ return modelIdentityFromModelCall(node, resolve);
42
+ }
43
+ if (!N.isIdentifier(node)) {
44
+ return null;
45
+ }
46
+ const symbol = node.getSymbol();
47
+ if (symbol === void 0) {
48
+ return null;
49
+ }
50
+ for (const decl of symbol.getDeclarations()) {
51
+ const identity = modelIdentityFromDeclaration(decl, resolve);
52
+ if (identity !== null) {
53
+ return identity;
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+ function modelIdentityFromDeclaration(decl, resolve) {
59
+ if (N.isImportSpecifier(decl)) {
60
+ const symbol = decl.getNameNode().getSymbol();
61
+ for (const target of symbol?.getAliasedSymbol()?.getDeclarations() ?? []) {
62
+ const identity = modelIdentityFromDeclaration(target, resolve);
63
+ if (identity !== null) {
64
+ return identity;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ if (!N.isVariableDeclaration(decl)) {
70
+ return null;
71
+ }
72
+ const init = decl.getInitializer();
73
+ if (init === void 0 || !N.isCallExpression(init)) {
74
+ return null;
75
+ }
76
+ return modelIdentityFromModelCall(init, resolve);
77
+ }
78
+ function modelIdentityFromModelCall(call, resolve) {
79
+ const callee = call.getExpression();
80
+ if (!isModelFactoryCall(callee, resolve)) {
81
+ return null;
82
+ }
83
+ const args = call.getArguments();
84
+ const modelName = literalString(args[0]);
85
+ if (modelName === null) {
86
+ return null;
87
+ }
88
+ const explicitCollection = literalString(args[2]);
89
+ const schemaCollection = explicitCollection === null ? collectionFromSchemaArg(args[1]) : null;
90
+ const collection = explicitCollection ?? schemaCollection ?? defaultCollectionName(modelName);
91
+ return { modelName, collection };
92
+ }
93
+ function isModelFactoryCall(callee, resolve) {
94
+ if (N.isPropertyAccessExpression(callee)) {
95
+ return callee.getName() === "model" && methodDeclaredIn(callee, "mongoose", resolve);
96
+ }
97
+ return N.isIdentifier(callee) && isImportedAs(callee, "mongoose", "model");
98
+ }
99
+ function isImportedAs(identifier, module, exportName) {
100
+ const symbol = identifier.getSymbol();
101
+ if (symbol === void 0) {
102
+ return false;
103
+ }
104
+ for (const decl of symbol.getDeclarations()) {
105
+ if (N.isImportSpecifier(decl) && decl.getName() === exportName && decl.getImportDeclaration().getModuleSpecifierValue() === module) {
106
+ return true;
107
+ }
108
+ }
109
+ return false;
110
+ }
111
+ function collectionFromSchemaArg(schemaArg) {
112
+ if (schemaArg === void 0) {
113
+ return null;
114
+ }
115
+ const ctor = schemaConstructorOf(schemaArg);
116
+ const optionsArg = ctor?.getArguments()[1];
117
+ if (optionsArg === void 0 || !N.isObjectLiteralExpression(optionsArg)) {
118
+ return null;
119
+ }
120
+ for (const prop of optionsArg.getProperties()) {
121
+ if (N.isPropertyAssignment(prop) && prop.getName() === "collection") {
122
+ return literalString(prop.getInitializer());
123
+ }
124
+ }
125
+ return null;
126
+ }
127
+ function schemaConstructorOf(node) {
128
+ if (N.isNewExpression(node)) {
129
+ return node;
130
+ }
131
+ if (!N.isIdentifier(node)) {
132
+ return null;
133
+ }
134
+ const symbol = node.getSymbol();
135
+ for (const decl of symbol?.getDeclarations() ?? []) {
136
+ if (!N.isVariableDeclaration(decl)) {
137
+ continue;
138
+ }
139
+ const init = decl.getInitializer();
140
+ if (init !== void 0 && N.isNewExpression(init)) {
141
+ return init;
142
+ }
143
+ }
144
+ return null;
145
+ }
146
+ function resolveDocumentModelIdentity(node, resolve) {
147
+ if (N.isNewExpression(node)) {
148
+ return resolveModelIdentity(node.getExpression(), resolve);
149
+ }
150
+ if (N.isAwaitExpression(node) || N.isParenthesizedExpression(node)) {
151
+ return resolveDocumentModelIdentity(node.getExpression(), resolve);
152
+ }
153
+ if (N.isCallExpression(node)) {
154
+ const callee = node.getExpression();
155
+ if (!N.isPropertyAccessExpression(callee) || !(callee.getName() in METHODS)) {
156
+ return null;
157
+ }
158
+ return resolveModelIdentity(callee.getExpression(), resolve);
159
+ }
160
+ if (!N.isIdentifier(node)) {
161
+ return null;
162
+ }
163
+ const symbol = node.getSymbol();
164
+ for (const decl of symbol?.getDeclarations() ?? []) {
165
+ if (!N.isVariableDeclaration(decl)) {
166
+ continue;
167
+ }
168
+ const init = decl.getInitializer();
169
+ const identity = init === void 0 ? null : resolveDocumentModelIdentity(init, resolve);
170
+ if (identity !== null) {
171
+ return identity;
172
+ }
173
+ }
174
+ return null;
175
+ }
176
+ function literalString(node) {
177
+ if (node === void 0) {
178
+ return null;
179
+ }
180
+ return N.isStringLiteral(node) || N.isNoSubstitutionTemplateLiteral(node) ? node.getLiteralValue() : null;
181
+ }
182
+ function readObjectArg(arg) {
183
+ if (arg === null || arg === void 0 || typeof arg !== "object") {
184
+ return null;
185
+ }
186
+ return arg.kind === "object" ? arg : null;
187
+ }
188
+ function isTruthyLiteral(value) {
189
+ if (value === null || typeof value !== "object") {
190
+ return false;
191
+ }
192
+ if (value.kind === "number") {
193
+ return value.value !== 0;
194
+ }
195
+ return value.kind === "boolean" && value.value;
196
+ }
197
+ function projectionFromString(text) {
198
+ const included = text.trim().split(/\s+/).filter((term) => term.length > 0 && !term.startsWith("-")).map((term) => term.replace(/^\+/, ""));
199
+ return included.length > 0 ? included : ["*"];
200
+ }
201
+ function projectionFields(arg) {
202
+ if (arg !== null && typeof arg === "object" && arg.kind === "string") {
203
+ return projectionFromString(arg.value);
204
+ }
205
+ const object = readObjectArg(arg);
206
+ if (object === null) {
207
+ return ["*"];
208
+ }
209
+ const included = Object.entries(object.fields).filter(([, value]) => isTruthyLiteral(value)).map(([key]) => key);
210
+ return included.length > 0 ? included : ["*"];
211
+ }
212
+ function updateFields(arg) {
213
+ const object = readObjectArg(arg);
214
+ if (object === null) {
215
+ return ["*"];
216
+ }
217
+ const fields = /* @__PURE__ */ new Set();
218
+ for (const [key, value] of Object.entries(object.fields)) {
219
+ if (!key.startsWith("$")) {
220
+ fields.add(key);
221
+ continue;
222
+ }
223
+ const operand = readObjectArg(value);
224
+ for (const inner of Object.keys(operand?.fields ?? {})) {
225
+ fields.add(inner);
226
+ }
227
+ }
228
+ return fields.size > 0 ? [...fields] : ["*"];
229
+ }
230
+ function payloadFields(arg) {
231
+ const object = readObjectArg(arg);
232
+ if (object !== null) {
233
+ const keys = Object.keys(object.fields);
234
+ return keys.length > 0 ? keys : ["*"];
235
+ }
236
+ if (arg === null || arg === void 0 || typeof arg !== "object" || arg.kind !== "array") {
237
+ return ["*"];
238
+ }
239
+ const union = /* @__PURE__ */ new Set();
240
+ for (const item of arg.items) {
241
+ const row = readObjectArg(item);
242
+ if (row === null) {
243
+ return ["*"];
244
+ }
245
+ for (const key of Object.keys(row.fields)) {
246
+ union.add(key);
247
+ }
248
+ }
249
+ return union.size > 0 ? [...union] : ["*"];
250
+ }
251
+ function distinctField(arg) {
252
+ return arg !== null && typeof arg === "object" && arg.kind === "string" ? [arg.value] : [];
253
+ }
254
+ function fieldsOf(spec, args) {
255
+ if (spec.projectionArg !== void 0) {
256
+ return projectionFields(args[spec.projectionArg]);
257
+ }
258
+ if (spec.updateArg !== void 0) {
259
+ return updateFields(args[spec.updateArg]);
260
+ }
261
+ if (spec.payloadArg !== void 0) {
262
+ return payloadFields(args[spec.payloadArg]);
263
+ }
264
+ if (spec.fieldArg !== void 0) {
265
+ return distinctField(args[spec.fieldArg]);
266
+ }
267
+ return spec.kind === "write" ? ["*"] : [];
268
+ }
269
+ function selectorOf(spec, args) {
270
+ if (spec.idArg !== void 0) {
271
+ return args[spec.idArg] !== void 0 ? ["_id"] : null;
272
+ }
273
+ if (spec.filterArg === void 0) {
274
+ return null;
275
+ }
276
+ const object = readObjectArg(args[spec.filterArg]);
277
+ if (object === null) {
278
+ return null;
279
+ }
280
+ const keys = Object.keys(object.fields);
281
+ return keys.length > 0 ? keys : null;
282
+ }
283
+ function buildAccess(opts) {
284
+ return {
285
+ type: "interaction",
286
+ binding: storageBinding({
287
+ recognition: RECOGNITION,
288
+ storageSystem: STORAGE_SYSTEM,
289
+ scope: opts.scope,
290
+ container: opts.collection
291
+ }),
292
+ callee: opts.calleeText,
293
+ interaction: {
294
+ class: "storage-access",
295
+ kind: opts.kind,
296
+ fields: opts.fields,
297
+ ...opts.selector !== null ? { selector: opts.selector } : {},
298
+ operation: opts.operation
299
+ }
300
+ };
301
+ }
302
+ function makeStaticRecognizer(scope) {
303
+ return (call, ctx) => {
304
+ const callNode = call;
305
+ const recognizerCtx = ctx;
306
+ const resolve = recognizerCtx.resolveWrittenValue ?? (() => null);
307
+ const callee = callNode.getExpression();
308
+ if (!N.isPropertyAccessExpression(callee)) {
309
+ return null;
310
+ }
311
+ const method = callee.getName();
312
+ const spec = METHODS[method];
313
+ if (spec === void 0 || !methodDeclaredIn(callee, "mongoose", resolve)) {
314
+ return null;
315
+ }
316
+ const identity = resolveModelIdentity(callee.getExpression(), resolve);
317
+ const args = recognizerCtx.extractArgs?.() ?? [];
318
+ return [
319
+ buildAccess({
320
+ scope,
321
+ collection: identity?.collection ?? null,
322
+ calleeText: callee.getText(),
323
+ operation: method,
324
+ kind: spec.kind,
325
+ fields: fieldsOf(spec, args),
326
+ selector: selectorOf(spec, args)
327
+ })
328
+ ];
329
+ };
330
+ }
331
+ function makeSaveRecognizer(scope) {
332
+ return (call, ctx) => {
333
+ const callNode = call;
334
+ const recognizerCtx = ctx;
335
+ const resolve = recognizerCtx.resolveWrittenValue ?? (() => null);
336
+ const callee = callNode.getExpression();
337
+ if (!N.isPropertyAccessExpression(callee) || callee.getName() !== "save") {
338
+ return null;
339
+ }
340
+ if (!methodDeclaredIn(callee, "mongoose", resolve)) {
341
+ return null;
342
+ }
343
+ const identity = resolveDocumentModelIdentity(
344
+ callee.getExpression(),
345
+ resolve
346
+ );
347
+ return [
348
+ buildAccess({
349
+ scope,
350
+ collection: identity?.collection ?? null,
351
+ calleeText: callee.getText(),
352
+ operation: "save",
353
+ kind: "write",
354
+ fields: ["*"],
355
+ selector: null
356
+ })
357
+ ];
358
+ };
359
+ }
360
+ function mongooseFramework(options = {}) {
361
+ const scope = options.scope ?? "default";
362
+ return {
363
+ name: "mongoose",
364
+ protocol: "in-process",
365
+ languages: ["typescript", "javascript"],
366
+ discovery: [],
367
+ terminals: [],
368
+ inputMapping: { type: "positionalParams", params: [] },
369
+ requiresImport: ["mongoose"],
370
+ invocationRecognizers: [
371
+ makeStaticRecognizer(scope),
372
+ makeSaveRecognizer(scope)
373
+ ]
374
+ };
375
+ }
376
+ var index_default = mongooseFramework;
377
+ export {
378
+ index_default as default
379
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@suss/framework-nestjs-graphql';
@@ -0,0 +1,77 @@
1
+ // ../framework/nestjs-graphql/dist/index.js
2
+ function nestjsGraphqlFramework(options = {}) {
3
+ return {
4
+ name: "nestjs-graphql",
5
+ languages: ["typescript"],
6
+ // Apollo Server runs underneath via `GraphQLModule.forRoot({...
7
+ // ApolloDriver })`; the wire transport stays HTTP regardless of
8
+ // whether the resolver was discovered via decorator or via an
9
+ // object-literal resolver map.
10
+ protocol: "http",
11
+ discovery: [
12
+ {
13
+ kind: "resolver",
14
+ match: {
15
+ type: "decoratedMethod",
16
+ importModule: "@nestjs/graphql",
17
+ // First match wins, so the framework's own decorator is
18
+ // tried before any wrapper a project names.
19
+ classDecorators: ["Resolver", ...options.classDecorators ?? []],
20
+ methodDecorators: [
21
+ "Query",
22
+ "Mutation",
23
+ "ResolveField",
24
+ "Subscription"
25
+ ],
26
+ // The three that settle their own type, each named after the
27
+ // type it puts its field on. `ResolveField` is deliberately
28
+ // absent: it is the one that needs the class decorator.
29
+ methodDecoratorTypeMap: {
30
+ Query: "Query",
31
+ Mutation: "Mutation",
32
+ Subscription: "Subscription"
33
+ }
34
+ },
35
+ requiresImport: ["@nestjs/graphql"]
36
+ }
37
+ ],
38
+ terminals: [
39
+ // Resolvers return a value; errors propagate as thrown
40
+ // exceptions (NestJS / Apollo map them to `errors[]` on the
41
+ // outgoing response). No framework-specific response-call
42
+ // shape: return + throw cover the observable behaviour.
43
+ {
44
+ kind: "return",
45
+ match: { type: "returnStatement" },
46
+ extraction: {}
47
+ },
48
+ {
49
+ kind: "throw",
50
+ match: { type: "throwExpression" },
51
+ extraction: {}
52
+ },
53
+ {
54
+ // Resolver methods can fall through and return `undefined` when the
55
+ // field is optional and the parent object already has the value. Keep a
56
+ // default transition so the unit does not come out with no transitions
57
+ // at all.
58
+ kind: "return",
59
+ match: { type: "functionFallthrough" },
60
+ extraction: {}
61
+ }
62
+ ],
63
+ inputMapping: {
64
+ type: "decoratedParams",
65
+ decoratorRoleMap: {
66
+ Args: "args",
67
+ Parent: "parent",
68
+ Context: "context",
69
+ Info: "info"
70
+ }
71
+ }
72
+ };
73
+ }
74
+ var index_default = nestjsGraphqlFramework;
75
+ export {
76
+ index_default as default
77
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@suss/framework-nestjs-rest';
@@ -0,0 +1,89 @@
1
+ // ../framework/nestjs-rest/dist/index.js
2
+ function nestjsRestFramework(options = {}) {
3
+ return {
4
+ name: "nestjs-rest",
5
+ languages: ["typescript"],
6
+ protocol: "http",
7
+ discovery: [
8
+ {
9
+ kind: "handler",
10
+ match: {
11
+ type: "decoratedRoute",
12
+ importModule: "@nestjs/common",
13
+ // First match wins, so the framework's own decorator is
14
+ // tried before any wrapper a project names.
15
+ classDecorators: ["Controller", ...options.classDecorators ?? []],
16
+ methodDecoratorRouteMap: {
17
+ Get: "GET",
18
+ Post: "POST",
19
+ Put: "PUT",
20
+ Delete: "DELETE",
21
+ Patch: "PATCH",
22
+ Options: "OPTIONS",
23
+ Head: "HEAD",
24
+ All: "*"
25
+ }
26
+ },
27
+ requiresImport: ["@nestjs/common"]
28
+ }
29
+ ],
30
+ terminals: [
31
+ // NestJS controllers serialise the returned value as the
32
+ // response body and pick a 200 default unless the method
33
+ // declares `@HttpCode(N)` (deferred: that decorator is
34
+ // metadata-only). Match bare returns and treat object literals
35
+ // / identifiers / awaited calls as 200 responses.
36
+ {
37
+ kind: "response",
38
+ match: { type: "returnStatement", excludeCallReturns: false },
39
+ extraction: {
40
+ defaultStatusCode: 200
41
+ }
42
+ },
43
+ {
44
+ // `throw new HttpException(msg, status)` / `throw new
45
+ // BadRequestException()` etc. NestJS maps these to HTTP
46
+ // responses; v0 records the exception type so downstream
47
+ // contract-checking can pair it with the wire status that
48
+ // the framework would emit.
49
+ kind: "throw",
50
+ match: { type: "throwExpression" },
51
+ extraction: {}
52
+ },
53
+ {
54
+ // Many controllers fall through (return undefined) when the
55
+ // operation is fire-and-forget (`@HttpCode(204)` for
56
+ // delete-style). Keep a default transition so
57
+ // `transitions: []` isn't the surface shape.
58
+ kind: "response",
59
+ match: { type: "functionFallthrough" },
60
+ extraction: {
61
+ defaultStatusCode: 200
62
+ }
63
+ }
64
+ ],
65
+ inputMapping: {
66
+ type: "decoratedParams",
67
+ decoratorRoleMap: {
68
+ Body: "requestBody",
69
+ Param: "pathParams",
70
+ Query: "queryParams",
71
+ Headers: "headers",
72
+ Req: "request",
73
+ Request: "request",
74
+ Res: "response",
75
+ Response: "response",
76
+ Next: "next",
77
+ Session: "session",
78
+ Ip: "ip",
79
+ HostParam: "host",
80
+ UploadedFile: "file",
81
+ UploadedFiles: "files"
82
+ }
83
+ }
84
+ };
85
+ }
86
+ var index_default = nestjsRestFramework;
87
+ export {
88
+ index_default as default
89
+ };
@@ -0,0 +1 @@
1
+ export { default } from '@suss/framework-nextjs';
package/dist/nextjs.js ADDED
@@ -0,0 +1,154 @@
1
+ // ../framework/nextjs/dist/index.js
2
+ var ROUTE_METHODS = [
3
+ "GET",
4
+ "POST",
5
+ "PUT",
6
+ "PATCH",
7
+ "DELETE",
8
+ "HEAD",
9
+ "OPTIONS"
10
+ ];
11
+ var APP_ROUTES = {
12
+ type: "fromFilename",
13
+ root: "app",
14
+ dropBasenames: ["route", "page"],
15
+ dynamic: "brackets",
16
+ dropParenthesized: true
17
+ };
18
+ var PAGES_ROUTES = {
19
+ type: "fromFilename",
20
+ root: "pages",
21
+ dropBasenames: ["index"],
22
+ dynamic: "brackets"
23
+ };
24
+ var NEXT_SERVER = ["next/server"];
25
+ function nextjsFramework() {
26
+ return {
27
+ name: "nextjs",
28
+ protocol: "http",
29
+ languages: ["typescript", "javascript"],
30
+ discovery: [
31
+ {
32
+ kind: "handler",
33
+ match: {
34
+ type: "fileConvention",
35
+ filePattern: "**/app/**/route.{ts,tsx,js,jsx,mts,mjs}",
36
+ exportNames: ROUTE_METHODS
37
+ },
38
+ bindingExtraction: {
39
+ method: { type: "fromExportName" },
40
+ path: APP_ROUTES
41
+ }
42
+ },
43
+ {
44
+ kind: "handler",
45
+ match: {
46
+ type: "fileConvention",
47
+ filePattern: "**/pages/api/**/*.{ts,tsx,js,jsx,mts,mjs}",
48
+ exportNames: ["default"]
49
+ },
50
+ bindingExtraction: {
51
+ // One export serves every method, which is what the wildcard says.
52
+ // Pairing matches it against whichever method a consumer used.
53
+ method: { type: "literal", value: "*" },
54
+ path: PAGES_ROUTES
55
+ }
56
+ }
57
+ ],
58
+ terminals: [
59
+ {
60
+ // NextResponse.json(body, { status })
61
+ kind: "response",
62
+ match: {
63
+ type: "functionCall",
64
+ functionName: "NextResponse.json",
65
+ requiresImport: NEXT_SERVER
66
+ },
67
+ extraction: {
68
+ body: { from: "argument", position: 0 },
69
+ statusCode: { from: "argumentProperty", position: 1, name: "status" },
70
+ defaultStatusCode: 200
71
+ }
72
+ },
73
+ {
74
+ // Response.json(body, { status }), the platform's own, which a
75
+ // handler can return without importing anything.
76
+ kind: "response",
77
+ match: { type: "functionCall", functionName: "Response.json" },
78
+ extraction: {
79
+ body: { from: "argument", position: 0 },
80
+ statusCode: { from: "argumentProperty", position: 1, name: "status" },
81
+ defaultStatusCode: 200
82
+ }
83
+ },
84
+ {
85
+ // new Response(body, { status }), which a handler returns for
86
+ // anything that is not JSON: a redirect, a stream, plain text.
87
+ kind: "response",
88
+ match: { type: "functionCall", functionName: "Response" },
89
+ extraction: {
90
+ body: { from: "argument", position: 0 },
91
+ statusCode: { from: "argumentProperty", position: 1, name: "status" },
92
+ defaultStatusCode: 200
93
+ }
94
+ },
95
+ {
96
+ // NextResponse.redirect(url) sends a 307 unless the caller says
97
+ // otherwise, and the alternative is written as an init object
98
+ // this pack does not read yet.
99
+ kind: "response",
100
+ match: {
101
+ type: "functionCall",
102
+ functionName: "NextResponse.redirect",
103
+ requiresImport: NEXT_SERVER
104
+ },
105
+ extraction: { defaultStatusCode: 307 }
106
+ },
107
+ {
108
+ // A pages handler writes to the response it was handed, the
109
+ // same shape Express uses.
110
+ kind: "response",
111
+ match: {
112
+ type: "parameterMethodCall",
113
+ parameterPosition: 1,
114
+ methodChain: ["status", "json"]
115
+ },
116
+ extraction: {
117
+ statusCode: { from: "argument", position: 0 },
118
+ body: { from: "argument", position: 0 }
119
+ }
120
+ },
121
+ {
122
+ kind: "response",
123
+ match: {
124
+ type: "parameterMethodCall",
125
+ parameterPosition: 1,
126
+ methodChain: ["json"]
127
+ },
128
+ extraction: {
129
+ body: { from: "argument", position: 0 },
130
+ defaultStatusCode: 200
131
+ }
132
+ },
133
+ {
134
+ kind: "throw",
135
+ match: { type: "throwExpression" },
136
+ extraction: {}
137
+ }
138
+ ],
139
+ // A route handler takes the request first. The app directory hands
140
+ // it a context object holding the route parameters; a pages handler
141
+ // takes the response object there instead.
142
+ inputMapping: {
143
+ type: "positionalParams",
144
+ params: [
145
+ { position: 0, role: "request" },
146
+ { position: 1, role: "context" }
147
+ ]
148
+ }
149
+ };
150
+ }
151
+ var index_default = nextjsFramework;
152
+ export {
153
+ index_default as default
154
+ };