lambda-reactor 1.0.4 → 1.0.6
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/dispatch.d.ts +1 -1
- package/dispatch.js +3 -3
- package/dispatch.js.map +3 -3
- package/handler.d.ts +1 -1
- package/handler.js +5 -5
- package/handler.js.map +3 -3
- package/method.d.ts +2 -2
- package/method.js.map +2 -2
- package/middleware.d.ts +6 -1
- package/middleware.js.map +2 -2
- package/package.json +1 -1
- package/route-handler.d.ts +2 -2
- package/router-class.d.ts +1 -1
- package/router-class.js +3 -3
- package/router-class.js.map +3 -3
- package/router.d.ts +1 -2
- package/router.js +3 -4
- package/router.js.map +3 -3
package/dispatch.d.ts
CHANGED
package/dispatch.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/dispatch.ts
|
|
2
|
-
import { logError } from "#src/logger";
|
|
3
|
-
import { Response } from "#src/response";
|
|
4
2
|
import { z } from "zod";
|
|
3
|
+
import { logError } from "./logger";
|
|
5
4
|
import { applyMiddlewares } from "./middleware";
|
|
5
|
+
import { Response } from "./response";
|
|
6
6
|
async function dispatch(route, event, context) {
|
|
7
7
|
let body;
|
|
8
8
|
try {
|
|
@@ -52,4 +52,4 @@ export {
|
|
|
52
52
|
dispatch
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
//# debugId=
|
|
55
|
+
//# debugId=424524B343A9873E64756E2164756E21
|
package/dispatch.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/dispatch.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {
|
|
5
|
+
"import type {APIGatewayProxyEvent, Context} from \"aws-lambda\"\nimport {z} from \"zod\"\n\nimport {logError} from \"./logger\"\nimport {RouteHandler} from \"./method\"\nimport {applyMiddlewares} from \"./middleware\"\nimport {Response} from \"./response\"\n\n/**\n * Executes a single {@link RouteHandler} for an incoming Lambda proxy event.\n *\n * Processing order:\n * 1. Parse `event.body` as JSON when possible.\n * 2. Validate the body against `route.bodySchema` (Zod); return `400` on\n * failure.\n * 3. Invoke `route.callback` with the validated body, event, and context.\n * 4. If the callback returns a {@link Response}, optionally validate its body\n * against `route.outputSchema`; return `500` on failure.\n * 5. If the callback returns a plain value, wrap it in a `200 JSON` response,\n * optionally validating against `route.outputSchema`.\n * 6. Apply all middlewares left-to-right before returning.\n *\n * @param route - The route handler to execute.\n * @param event - Raw API Gateway proxy event.\n * @param context - Lambda execution context.\n */\nexport async function dispatch(\n route: RouteHandler,\n event: APIGatewayProxyEvent,\n context: Context,\n) {\n let body\n try {\n body = event.body ? JSON.parse(event.body) : undefined\n } catch (error) {\n if (error instanceof Error) {\n return Response.text(400, error.message).toAPIGatewayProxyResult()\n }\n throw error\n }\n if (route.bodySchema) {\n const parsed = route.bodySchema.safeParse(body)\n if (!parsed.success) {\n return Response.text(\n 400,\n z.prettifyError(parsed.error),\n ).toAPIGatewayProxyResult()\n }\n body = parsed.data\n }\n if (!route.callback) {\n const err = new Error(\"Route has no handler defined\")\n logError(err)\n return Response.text(500, err.message).toAPIGatewayProxyResult()\n }\n const cb = route.callback as (props: {\n body: unknown\n event: APIGatewayProxyEvent\n context: Context\n }) => Promise<unknown>\n const result = await cb({body, event, context})\n if (result instanceof Response) {\n if (route.outputSchema) {\n const parsed = route.outputSchema.safeParse(result.body)\n if (!parsed.success) {\n logError(parsed.error)\n return Response.text(\n 500,\n z.prettifyError(parsed.error),\n ).toAPIGatewayProxyResult()\n }\n result.body = parsed.data\n }\n return applyMiddlewares(result.toAPIGatewayProxyResult(), route)\n }\n if (route.outputSchema) {\n const parsed = route.outputSchema.safeParse(result)\n if (!parsed.success) {\n logError(parsed.error)\n return Response.text(\n 500,\n z.prettifyError(parsed.error),\n ).toAPIGatewayProxyResult()\n }\n return applyMiddlewares(\n Response.json(200, parsed.data).toAPIGatewayProxyResult(),\n route,\n )\n }\n return applyMiddlewares(Response.json(200, result).toAPIGatewayProxyResult(), route)\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AACA;AAEA;AAEA;AACA;AAoBA,eAAsB,QAAQ,CAC1B,OACA,OACA,SACF;AAAA,EACE,IAAI;AAAA,EACJ,IAAI;AAAA,IACA,OAAO,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI,IAAI;AAAA,IAC/C,OAAO,OAAO;AAAA,IACZ,IAAI,iBAAiB,OAAO;AAAA,MACxB,OAAO,SAAS,KAAK,KAAK,MAAM,OAAO,EAAE,wBAAwB;AAAA,IACrE;AAAA,IACA,MAAM;AAAA;AAAA,EAEV,IAAI,MAAM,YAAY;AAAA,IAClB,MAAM,SAAS,MAAM,WAAW,UAAU,IAAI;AAAA,IAC9C,IAAI,CAAC,OAAO,SAAS;AAAA,MACjB,OAAO,SAAS,KACZ,KACA,EAAE,cAAc,OAAO,KAAK,CAChC,EAAE,wBAAwB;AAAA,IAC9B;AAAA,IACA,OAAO,OAAO;AAAA,EAClB;AAAA,EACA,IAAI,CAAC,MAAM,UAAU;AAAA,IACjB,MAAM,MAAM,IAAI,MAAM,8BAA8B;AAAA,IACpD,SAAS,GAAG;AAAA,IACZ,OAAO,SAAS,KAAK,KAAK,IAAI,OAAO,EAAE,wBAAwB;AAAA,EACnE;AAAA,EACA,MAAM,KAAK,MAAM;AAAA,EAKjB,MAAM,SAAS,MAAM,GAAG,EAAC,MAAM,OAAO,QAAO,CAAC;AAAA,EAC9C,IAAI,kBAAkB,UAAU;AAAA,IAC5B,IAAI,MAAM,cAAc;AAAA,MACpB,MAAM,SAAS,MAAM,aAAa,UAAU,OAAO,IAAI;AAAA,MACvD,IAAI,CAAC,OAAO,SAAS;AAAA,QACjB,SAAS,OAAO,KAAK;AAAA,QACrB,OAAO,SAAS,KACZ,KACA,EAAE,cAAc,OAAO,KAAK,CAChC,EAAE,wBAAwB;AAAA,MAC9B;AAAA,MACA,OAAO,OAAO,OAAO;AAAA,IACzB;AAAA,IACA,OAAO,iBAAiB,OAAO,wBAAwB,GAAG,KAAK;AAAA,EACnE;AAAA,EACA,IAAI,MAAM,cAAc;AAAA,IACpB,MAAM,SAAS,MAAM,aAAa,UAAU,MAAM;AAAA,IAClD,IAAI,CAAC,OAAO,SAAS;AAAA,MACjB,SAAS,OAAO,KAAK;AAAA,MACrB,OAAO,SAAS,KACZ,KACA,EAAE,cAAc,OAAO,KAAK,CAChC,EAAE,wBAAwB;AAAA,IAC9B;AAAA,IACA,OAAO,iBACH,SAAS,KAAK,KAAK,OAAO,IAAI,EAAE,wBAAwB,GACxD,KACJ;AAAA,EACJ;AAAA,EACA,OAAO,iBAAiB,SAAS,KAAK,KAAK,MAAM,EAAE,wBAAwB,GAAG,KAAK;AAAA;",
|
|
8
|
+
"debugId": "424524B343A9873E64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/handler.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RouteHandler } from "#src/method";
|
|
2
1
|
import type { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from "aws-lambda";
|
|
2
|
+
import { RouteHandler } from "./method";
|
|
3
3
|
/**
|
|
4
4
|
* Creates an AWS Lambda handler function from a map of HTTP-method names to
|
|
5
5
|
* {@link RouteHandler} instances.
|
package/handler.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/handler.ts
|
|
2
|
-
import { dispatch } from "#src/dispatch";
|
|
3
|
-
import { isProduction } from "#src/env";
|
|
4
|
-
import { formatError, logError } from "#src/logger";
|
|
5
|
-
import { Response } from "#src/response";
|
|
6
2
|
import { install } from "source-map-support";
|
|
3
|
+
import { dispatch } from "./dispatch";
|
|
4
|
+
import { isProduction } from "./env";
|
|
5
|
+
import { formatError, logError } from "./logger";
|
|
6
|
+
import { Response } from "./response";
|
|
7
7
|
install();
|
|
8
8
|
function createHandler(routes) {
|
|
9
9
|
return async (event, context) => {
|
|
@@ -26,4 +26,4 @@ export {
|
|
|
26
26
|
createHandler
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
//# debugId=
|
|
29
|
+
//# debugId=B901BA23F81EC95F64756E2164756E21
|
package/handler.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/handler.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {
|
|
5
|
+
"import type {APIGatewayProxyEvent, APIGatewayProxyResult, Context} from \"aws-lambda\"\nimport {install} from \"source-map-support\"\n\nimport {dispatch} from \"./dispatch\"\nimport {isProduction} from \"./env\"\nimport {formatError, logError} from \"./logger\"\nimport {RouteHandler} from \"./method\"\nimport {Response} from \"./response\"\n\ninstall()\n\n/**\n * Creates an AWS Lambda handler function from a map of HTTP-method names to\n * {@link RouteHandler} instances.\n *\n * The returned handler:\n * - Returns `405 Method Not Allowed` (with an `Allow` header) for any HTTP\n * method not present in `routes`.\n * - Delegates matching requests to {@link dispatch}.\n * - Catches any `Error` thrown by `dispatch`, logs it, and returns\n * `500 Internal Server Error`. In non-production environments the error\n * message and stack trace are included in the response body.\n * - Re-throws non-`Error` throwables so they propagate to the Lambda runtime.\n *\n * @param routes - Map of upper-case HTTP method names (e.g. `\"GET\"`, `\"POST\"`)\n * to their corresponding {@link RouteHandler}.\n *\n * @example\n * ```ts\n * export const handler = createHandler({\n * GET: method().handle(async () => Response.json(200, {ok: true})),\n * })\n * ```\n */\nexport function createHandler<T extends Record<string, RouteHandler>>(routes: T) {\n return async (\n event: APIGatewayProxyEvent,\n context: Context,\n ): Promise<APIGatewayProxyResult> => {\n const route = routes[event.httpMethod as keyof T]\n if (!route) {\n return Response.text(405, \"Method Not Allowed\")\n .header(\"Allow\", Object.keys(routes).join(\", \"))\n .toAPIGatewayProxyResult()\n }\n try {\n return await dispatch(route, event, context)\n } catch (error) {\n if (error instanceof Error) {\n logError(error)\n return Response.text(\n 500,\n isProduction() ? \"Internal Server Error\" : formatError(error),\n ).toAPIGatewayProxyResult()\n }\n throw error\n }\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AACA;AAEA;AACA;AACA;AAEA;AAEA,QAAQ;AAyBD,SAAS,aAAqD,CAAC,QAAW;AAAA,EAC7E,OAAO,OACH,OACA,YACiC;AAAA,IACjC,MAAM,QAAQ,OAAO,MAAM;AAAA,IAC3B,IAAI,CAAC,OAAO;AAAA,MACR,OAAO,SAAS,KAAK,KAAK,oBAAoB,EACzC,OAAO,SAAS,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC,EAC9C,wBAAwB;AAAA,IACjC;AAAA,IACA,IAAI;AAAA,MACA,OAAO,MAAM,SAAS,OAAO,OAAO,OAAO;AAAA,MAC7C,OAAO,OAAO;AAAA,MACZ,IAAI,iBAAiB,OAAO;AAAA,QACxB,SAAS,KAAK;AAAA,QACd,OAAO,SAAS,KACZ,KACA,aAAa,IAAI,0BAA0B,YAAY,KAAK,CAChE,EAAE,wBAAwB;AAAA,MAC9B;AAAA,MACA,MAAM;AAAA;AAAA;AAAA;",
|
|
8
|
+
"debugId": "B901BA23F81EC95F64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/method.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type Middleware } from "#src/middleware";
|
|
2
|
-
import { EndpointCallback, RouteHandler } from "#src/route-handler";
|
|
3
1
|
import type { ZodType } from "zod";
|
|
2
|
+
import { type Middleware } from "./middleware";
|
|
3
|
+
import { EndpointCallback, RouteHandler } from "./route-handler";
|
|
4
4
|
export type { EndpointCallback, RouteHandler };
|
|
5
5
|
/**
|
|
6
6
|
* Fluent, immutable builder for a single HTTP-method handler.
|
package/method.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/method.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import
|
|
5
|
+
"import type {ZodType} from \"zod\"\n\nimport {type Middleware} from \"./middleware\"\nimport {EndpointCallback, RouteHandler} from \"./route-handler\"\n\nexport type {EndpointCallback, RouteHandler}\n\n/**\n * Fluent, immutable builder for a single HTTP-method handler.\n *\n * Every method returns a new `Method` instance, leaving the original\n * unchanged. Build a method with the following chain:\n *\n * ```ts\n * method().use(cors()).input(schema).output(schema).handle(async ({body}) => …)\n * ```\n *\n * @typeParam TInput - Shape of the validated request body.\n * @typeParam TOutput - Return type of the handler callback.\n */\nexport class Method<TInput = unknown, TOutput = unknown> {\n middlewares: Middleware[] = []\n bodySchema?: ZodType<TInput>\n outputSchema?: ZodType<TOutput>\n callback?: EndpointCallback<TInput, TOutput>\n\n /**\n * Appends a middleware to the chain. Middlewares are applied\n * left-to-right after the callback resolves.\n *\n * @param middleware - The {@link Middleware} to append.\n */\n use(middleware: Middleware): Method<TInput, TOutput> {\n const r = new Method<TInput, TOutput>()\n r.middlewares = [...this.middlewares, middleware]\n if (this.bodySchema) r.bodySchema = this.bodySchema\n if (this.outputSchema) r.outputSchema = this.outputSchema\n if (this.callback) r.callback = this.callback\n return r\n }\n\n /**\n * Attaches a Zod schema used to validate (and narrow) the request body.\n * When validation fails, `dispatch` returns a `400` response automatically.\n *\n * @param bodySchema - Zod schema for the request body.\n */\n input<U>(bodySchema: ZodType<U>): Method<U, TOutput> {\n const r = new Method<U, TOutput>()\n r.middlewares = this.middlewares\n r.bodySchema = bodySchema\n if (this.outputSchema) r.outputSchema = this.outputSchema as ZodType<TOutput>\n if (this.callback)\n r.callback = this.callback as unknown as EndpointCallback<U, TOutput>\n return r\n }\n\n /**\n * Attaches a Zod schema that describes the expected response shape.\n * Currently stored for documentation / code-generation purposes.\n *\n * @param schema - Zod schema for the response body.\n */\n output<U>(schema: ZodType<U>): Method<TInput, U> {\n const r = new Method<TInput, U>()\n r.middlewares = this.middlewares\n if (this.bodySchema) r.bodySchema = this.bodySchema\n r.outputSchema = schema\n if (this.callback)\n r.callback = this.callback as unknown as EndpointCallback<TInput, U>\n return r\n }\n\n /**\n * Registers the async handler callback for this method.\n *\n * @param callback - Function that receives the validated body, the raw\n * Lambda event, and the Lambda context, and returns the response.\n */\n handle(callback: EndpointCallback<TInput, TOutput>): Method<TInput, TOutput> {\n const r = new Method<TInput, TOutput>()\n r.middlewares = this.middlewares\n if (this.bodySchema) r.bodySchema = this.bodySchema\n if (this.outputSchema) r.outputSchema = this.outputSchema\n r.callback = callback\n return r\n }\n}\n\n/** Creates a new, empty {@link Method} builder. */\nexport function method(): Method {\n return new Method()\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
7
|
+
"mappings": ";AAoBO,MAAM,OAA4C;AAAA,EACrD,cAA4B,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EAQA,GAAG,CAAC,YAAiD;AAAA,IACjD,MAAM,IAAI,IAAI;AAAA,IACd,EAAE,cAAc,CAAC,GAAG,KAAK,aAAa,UAAU;AAAA,IAChD,IAAI,KAAK;AAAA,MAAY,EAAE,aAAa,KAAK;AAAA,IACzC,IAAI,KAAK;AAAA,MAAc,EAAE,eAAe,KAAK;AAAA,IAC7C,IAAI,KAAK;AAAA,MAAU,EAAE,WAAW,KAAK;AAAA,IACrC,OAAO;AAAA;AAAA,EASX,KAAQ,CAAC,YAA4C;AAAA,IACjD,MAAM,IAAI,IAAI;AAAA,IACd,EAAE,cAAc,KAAK;AAAA,IACrB,EAAE,aAAa;AAAA,IACf,IAAI,KAAK;AAAA,MAAc,EAAE,eAAe,KAAK;AAAA,IAC7C,IAAI,KAAK;AAAA,MACL,EAAE,WAAW,KAAK;AAAA,IACtB,OAAO;AAAA;AAAA,EASX,MAAS,CAAC,QAAuC;AAAA,IAC7C,MAAM,IAAI,IAAI;AAAA,IACd,EAAE,cAAc,KAAK;AAAA,IACrB,IAAI,KAAK;AAAA,MAAY,EAAE,aAAa,KAAK;AAAA,IACzC,EAAE,eAAe;AAAA,IACjB,IAAI,KAAK;AAAA,MACL,EAAE,WAAW,KAAK;AAAA,IACtB,OAAO;AAAA;AAAA,EASX,MAAM,CAAC,UAAsE;AAAA,IACzE,MAAM,IAAI,IAAI;AAAA,IACd,EAAE,cAAc,KAAK;AAAA,IACrB,IAAI,KAAK;AAAA,MAAY,EAAE,aAAa,KAAK;AAAA,IACzC,IAAI,KAAK;AAAA,MAAc,EAAE,eAAe,KAAK;AAAA,IAC7C,EAAE,WAAW;AAAA,IACb,OAAO;AAAA;AAEf;AAGO,SAAS,MAAM,GAAW;AAAA,EAC7B,OAAO,IAAI;AAAA;",
|
|
8
8
|
"debugId": "5EADB1A7B72CB4BE64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/middleware.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { RouteHandler } from "./route-handler";
|
|
|
6
6
|
* by {@link dispatch}.
|
|
7
7
|
*/
|
|
8
8
|
export type Middleware = (result: APIGatewayProxyResult) => APIGatewayProxyResult;
|
|
9
|
+
/**
|
|
10
|
+
* Unprefixed CORS header names accepted by {@link cors}.
|
|
11
|
+
* Each key is prefixed with `"Access-Control-"` in the response.
|
|
12
|
+
*/
|
|
13
|
+
export type CorsHeaders = Partial<Record<"Allow-Origin" | "Allow-Methods" | "Allow-Headers" | "Allow-Credentials" | "Expose-Headers" | "Max-Age" | "Request-Headers" | "Request-Method", string>>;
|
|
9
14
|
/**
|
|
10
15
|
* Creates a middleware that injects CORS response headers.
|
|
11
16
|
*
|
|
@@ -16,7 +21,7 @@ export type Middleware = (result: APIGatewayProxyResult) => APIGatewayProxyResul
|
|
|
16
21
|
* @param headers - Map of unprefixed CORS header names to their values.
|
|
17
22
|
* Defaults to an empty object (no CORS headers added).
|
|
18
23
|
*/
|
|
19
|
-
export declare function cors(headers?:
|
|
24
|
+
export declare function cors(headers?: CorsHeaders): Middleware;
|
|
20
25
|
/**
|
|
21
26
|
* Folds all middlewares registered on `route` over `result`, applying them
|
|
22
27
|
* left-to-right, and returns the final {@link APIGatewayProxyResult}.
|
package/middleware.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/middleware.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type {APIGatewayProxyResult} from \"aws-lambda\"\n\nimport {RouteHandler} from \"./route-handler\"\n\n/**\n * A pure function that receives an {@link APIGatewayProxyResult} and returns\n * a (possibly modified) copy of it. Middlewares are composed left-to-right\n * by {@link dispatch}.\n */\nexport type Middleware = (result: APIGatewayProxyResult) => APIGatewayProxyResult\n\n/**\n * Creates a middleware that injects CORS response headers.\n *\n * Each key in `headers` is prefixed with `\"Access-Control-\"` before being\n * merged into the response, so passing `{\"Allow-Origin\": \"*\"}` produces the\n * `Access-Control-Allow-Origin: *` header.\n *\n * @param headers - Map of unprefixed CORS header names to their values.\n * Defaults to an empty object (no CORS headers added).\n */\nexport function cors(headers:
|
|
5
|
+
"import type {APIGatewayProxyResult} from \"aws-lambda\"\n\nimport {RouteHandler} from \"./route-handler\"\n\n/**\n * A pure function that receives an {@link APIGatewayProxyResult} and returns\n * a (possibly modified) copy of it. Middlewares are composed left-to-right\n * by {@link dispatch}.\n */\nexport type Middleware = (result: APIGatewayProxyResult) => APIGatewayProxyResult\n\n/**\n * Unprefixed CORS header names accepted by {@link cors}.\n * Each key is prefixed with `\"Access-Control-\"` in the response.\n */\nexport type CorsHeaders = Partial<\n Record<\n | \"Allow-Origin\"\n | \"Allow-Methods\"\n | \"Allow-Headers\"\n | \"Allow-Credentials\"\n | \"Expose-Headers\"\n | \"Max-Age\"\n | \"Request-Headers\"\n | \"Request-Method\",\n string\n >\n>\n\n/**\n * Creates a middleware that injects CORS response headers.\n *\n * Each key in `headers` is prefixed with `\"Access-Control-\"` before being\n * merged into the response, so passing `{\"Allow-Origin\": \"*\"}` produces the\n * `Access-Control-Allow-Origin: *` header.\n *\n * @param headers - Map of unprefixed CORS header names to their values.\n * Defaults to an empty object (no CORS headers added).\n */\nexport function cors(headers: CorsHeaders = {}): Middleware {\n return (result) => {\n const corsHeaders: Record<string, string> = {}\n for (const [key, value] of Object.entries(headers)) {\n corsHeaders[`Access-Control-${key}`] = value\n }\n return {...result, headers: {...result.headers, ...corsHeaders}}\n }\n}\n\n/**\n * Folds all middlewares registered on `route` over `result`, applying them\n * left-to-right, and returns the final {@link APIGatewayProxyResult}.\n */\nexport function applyMiddlewares(\n result: APIGatewayProxyResult,\n route: RouteHandler,\n): APIGatewayProxyResult {\n return route.middlewares.reduce((r, middleware) => middleware(r), result)\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
7
|
+
"mappings": ";AAuCO,SAAS,IAAI,CAAC,UAAuB,CAAC,GAAe;AAAA,EACxD,OAAO,CAAC,WAAW;AAAA,IACf,MAAM,cAAsC,CAAC;AAAA,IAC7C,YAAY,KAAK,UAAU,OAAO,QAAQ,OAAO,GAAG;AAAA,MAChD,YAAY,kBAAkB,SAAS;AAAA,IAC3C;AAAA,IACA,OAAO,KAAI,QAAQ,SAAS,KAAI,OAAO,YAAY,YAAW,EAAC;AAAA;AAAA;AAQhE,SAAS,gBAAgB,CAC5B,QACA,OACqB;AAAA,EACrB,OAAO,MAAM,YAAY,OAAO,CAAC,GAAG,eAAe,WAAW,CAAC,GAAG,MAAM;AAAA;",
|
|
8
8
|
"debugId": "235C7399F968D7AF64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/package.json
CHANGED
package/route-handler.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type Middleware } from "#src/middleware";
|
|
2
|
-
import { Response } from "#src/response";
|
|
3
1
|
import type { APIGatewayProxyEvent, Context } from "aws-lambda";
|
|
4
2
|
import type { ZodType } from "zod";
|
|
3
|
+
import { type Middleware } from "./middleware";
|
|
4
|
+
import { Response } from "./response";
|
|
5
5
|
/**
|
|
6
6
|
* The user-supplied handler function for a single HTTP method on a route.
|
|
7
7
|
*
|
package/router-class.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type FunctionFactory } from "#src/build-handlers";
|
|
2
1
|
import { type CorsOptions, IRestApi } from "aws-cdk-lib/aws-apigateway";
|
|
3
2
|
import { IFunction } from "aws-cdk-lib/aws-lambda";
|
|
3
|
+
import { type FunctionFactory } from "./build-handlers";
|
|
4
4
|
/**
|
|
5
5
|
* Immutable CDK router that maps route paths to Lambda-backed API Gateway
|
|
6
6
|
* resources.
|
package/router-class.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/router-class.ts
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
|
-
import { buildHandlers } from "#src/build-handlers";
|
|
5
|
-
import { getMethods } from "#src/router";
|
|
6
4
|
import { LambdaIntegration } from "aws-cdk-lib/aws-apigateway";
|
|
5
|
+
import { buildHandlers } from "./build-handlers";
|
|
6
|
+
import { getMethods } from "./router";
|
|
7
7
|
|
|
8
8
|
class Router {
|
|
9
9
|
srcDir;
|
|
@@ -43,4 +43,4 @@ export {
|
|
|
43
43
|
Router
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
//# debugId=
|
|
46
|
+
//# debugId=18C5AB48A82CE8B464756E2164756E21
|
package/router-class.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/router-class.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {readFileSync} from \"fs\"\nimport {join} from \"path\"\n\nimport {
|
|
5
|
+
"import {readFileSync} from \"fs\"\nimport {join} from \"path\"\n\nimport {type CorsOptions, IRestApi, LambdaIntegration} from \"aws-cdk-lib/aws-apigateway\"\nimport {IFunction} from \"aws-cdk-lib/aws-lambda\"\n\nimport {buildHandlers, type FunctionFactory} from \"./build-handlers\"\nimport {getMethods} from \"./router\"\n\n/**\n * Immutable CDK router that maps route paths to Lambda-backed API Gateway\n * resources.\n *\n * ```ts\n * const api = router()\n * .cors({allowOrigins: [\"*\"]})\n * .route(\"/users\")\n * .route(\"/items\")\n * .defineRestApi(restApi, factory)\n * ```\n *\n * @typeParam TPaths - Union of all route path strings registered so far.\n */\nexport class Router<TPaths extends string = never> {\n srcDir: string\n corsOptions?: CorsOptions\n paths: TPaths[] = []\n\n constructor(srcDir: string) {\n this.srcDir = srcDir\n }\n\n /**\n * Returns a new `Router` with CORS preflight options applied to every\n * resource added via {@link Router.route}.\n *\n * @param options - CDK `CorsOptions` passed to `addCorsPreflight`.\n */\n cors(options: CorsOptions): Router<TPaths> {\n const r = new Router<TPaths>(this.srcDir)\n r.corsOptions = options\n r.paths = this.paths\n return r\n }\n\n /**\n * Registers a new route path and returns a new `Router` with the path\n * added to its path union.\n *\n * @param path - Route path string (e.g. `\"/users\"`). Must correspond to a\n * handler file at `<srcDir>/<path>.ts`.\n */\n route<TPath extends string>(path: TPath): Router<TPaths | TPath> {\n const r = new Router<TPaths | TPath>(this.srcDir)\n if (this.corsOptions) r.corsOptions = this.corsOptions\n r.paths = [...this.paths, path as unknown as TPaths | TPath]\n return r\n }\n\n /**\n * Wires all registered routes into the given API Gateway REST API.\n *\n * For each route path the method:\n * 1. Creates (or reuses) nested API Gateway resources for each path segment.\n * 2. Optionally calls `addCorsPreflight` when CORS options are configured.\n * 3. Reads the handler source file and extracts HTTP method names via\n * {@link getMethods}.\n * 4. Adds an `addMethod` entry backed by a `LambdaIntegration` for each\n * discovered method.\n *\n * @param api - The CDK `IRestApi` to attach resources and methods to.\n * @param factory - {@link FunctionFactory} used to build Lambda functions.\n * @returns A record mapping each route path to its {@link IFunction}.\n */\n defineRestApi<TApi extends IRestApi>(\n api: TApi,\n factory: FunctionFactory,\n ): Record<TPaths, IFunction> {\n const handlers = buildHandlers(this.paths, factory)\n for (const path of this.paths) {\n const resource = path\n .split(\"/\")\n .filter(Boolean)\n .reduce(\n (r, part) => r.getResource(part) ?? r.addResource(part),\n api.root,\n )\n if (this.corsOptions) resource.addCorsPreflight(this.corsOptions)\n const src = readFileSync(\n join(process.cwd(), this.srcDir, `${path}.ts`),\n \"utf-8\",\n )\n for (const method of getMethods(src)) {\n resource.addMethod(method, new LambdaIntegration(handlers[path]!))\n }\n }\n return handlers\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;AACA;AAEA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AACA;AAEA;AAGA;AACA;AAAA;AAgBO,MAAM,OAAsC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA,QAAkB,CAAC;AAAA,EAEnB,WAAW,CAAC,QAAgB;AAAA,IACxB,KAAK,SAAS;AAAA;AAAA,EASlB,IAAI,CAAC,SAAsC;AAAA,IACvC,MAAM,IAAI,IAAI,OAAe,KAAK,MAAM;AAAA,IACxC,EAAE,cAAc;AAAA,IAChB,EAAE,QAAQ,KAAK;AAAA,IACf,OAAO;AAAA;AAAA,EAUX,KAA2B,CAAC,MAAqC;AAAA,IAC7D,MAAM,IAAI,IAAI,OAAuB,KAAK,MAAM;AAAA,IAChD,IAAI,KAAK;AAAA,MAAa,EAAE,cAAc,KAAK;AAAA,IAC3C,EAAE,QAAQ,CAAC,GAAG,KAAK,OAAO,IAAiC;AAAA,IAC3D,OAAO;AAAA;AAAA,EAkBX,aAAoC,CAChC,KACA,SACyB;AAAA,IACzB,MAAM,WAAW,cAAc,KAAK,OAAO,OAAO;AAAA,IAClD,WAAW,QAAQ,KAAK,OAAO;AAAA,MAC3B,MAAM,WAAW,KACZ,MAAM,GAAG,EACT,OAAO,OAAO,EACd,OACG,CAAC,GAAG,SAAS,EAAE,YAAY,IAAI,KAAK,EAAE,YAAY,IAAI,GACtD,IAAI,IACR;AAAA,MACJ,IAAI,KAAK;AAAA,QAAa,SAAS,iBAAiB,KAAK,WAAW;AAAA,MAChE,MAAM,MAAM,aACR,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ,GAAG,SAAS,GAC7C,OACJ;AAAA,MACA,WAAW,UAAU,WAAW,GAAG,GAAG;AAAA,QAClC,SAAS,UAAU,QAAQ,IAAI,kBAAkB,SAAS,KAAM,CAAC;AAAA,MACrE;AAAA,IACJ;AAAA,IACA,OAAO;AAAA;AAEf;",
|
|
8
|
+
"debugId": "18C5AB48A82CE8B464756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/router.d.ts
CHANGED
package/router.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/router.ts
|
|
2
|
-
import { Router } from "
|
|
2
|
+
import { Router } from "./router-class";
|
|
3
3
|
function getMethods(src) {
|
|
4
4
|
const match = src.match(/createHandler\(\{([^}]*)\}\)/);
|
|
5
5
|
if (!match || !match[1])
|
|
@@ -11,8 +11,7 @@ function router(srcDir = "src") {
|
|
|
11
11
|
}
|
|
12
12
|
export {
|
|
13
13
|
router,
|
|
14
|
-
getMethods
|
|
15
|
-
Router
|
|
14
|
+
getMethods
|
|
16
15
|
};
|
|
17
16
|
|
|
18
|
-
//# debugId=
|
|
17
|
+
//# debugId=CE3E23240E3736EA64756E2164756E21
|
package/router.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/router.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {Router} from \"
|
|
5
|
+
"import {Router} from \"./router-class\"\n\n/**\n * Extracts the HTTP method names declared inside a `createHandler({…})` call\n * by statically scanning the source text of a handler file.\n *\n * @param src - Raw TypeScript source of a handler module.\n * @returns Array of upper-case HTTP method names (e.g. `[\"GET\", \"POST\"]`),\n * or an empty array when no `createHandler` call is found.\n */\nexport function getMethods(src: string): string[] {\n const match = src.match(/createHandler\\(\\{([^}]*)\\}\\)/)\n if (!match || !match[1]) return []\n return match[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n}\n\n/**\n * Creates a new, empty {@link Router} builder.\n *\n * @param srcDir - Directory (relative to `cwd`) where handler `.ts` files\n * live. Defaults to `\"src\"`.\n */\nexport function router(srcDir: string = \"src\"): Router {\n return new Router(srcDir)\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AAUO,SAAS,UAAU,CAAC,KAAuB;AAAA,EAC9C,MAAM,QAAQ,IAAI,MAAM,8BAA8B;AAAA,EACtD,IAAI,CAAC,SAAS,CAAC,MAAM;AAAA,IAAI,OAAO,CAAC;AAAA,EACjC,OAAO,MAAM,GACR,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA;AAShB,SAAS,MAAM,CAAC,SAAiB,OAAe;AAAA,EACnD,OAAO,IAAI,OAAO,MAAM;AAAA;",
|
|
8
|
+
"debugId": "CE3E23240E3736EA64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|