@routepact/express 0.1.6 → 0.1.8
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 +59 -34
- package/dist/endpoint.utils.d.ts.map +1 -1
- package/dist/endpoint.utils.js +4 -1
- package/dist/endpoint.utils.js.map +1 -1
- package/dist/router.utils.d.ts.map +1 -1
- package/dist/router.utils.js +32 -11
- package/dist/router.utils.js.map +1 -1
- package/dist/types.d.ts +46 -23
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +4 -5
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +5 -21
- package/dist/validation.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install -D @types/express
|
|
|
13
13
|
|
|
14
14
|
### `defineEndpoint`
|
|
15
15
|
|
|
16
|
-
Wraps a handler with a pact
|
|
16
|
+
Wraps a handler with a pact. Instead of receiving the raw Express `req`/`res`, the handler receives a typed **context object** whose types are inferred directly from the pact's Zod schemas.
|
|
17
17
|
|
|
18
18
|
```ts
|
|
19
19
|
import { defineEndpoint } from "@routepact/express";
|
|
@@ -21,11 +21,9 @@ import { PostPacts } from "../shared/pacts/post.pact";
|
|
|
21
21
|
|
|
22
22
|
const createPost = defineEndpoint({
|
|
23
23
|
pact: PostPacts.create,
|
|
24
|
-
handler: async (
|
|
25
|
-
//
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const post = await db.posts.insert({ title, body });
|
|
24
|
+
handler: async ({ body, res }) => {
|
|
25
|
+
// body is typed as { title: string; body: string } (from pact.request)
|
|
26
|
+
const post = await db.posts.insert(body);
|
|
29
27
|
|
|
30
28
|
// res.json only accepts the shape defined by PostPacts.create.response
|
|
31
29
|
res.status(201).json(post);
|
|
@@ -33,23 +31,53 @@ const createPost = defineEndpoint({
|
|
|
33
31
|
});
|
|
34
32
|
```
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
**Returning a value** is a shorthand for `res.json(value)` — the framework calls it for you:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const createPost = defineEndpoint({
|
|
38
|
+
pact: PostPacts.create,
|
|
39
|
+
handler: async ({ body }) => {
|
|
40
|
+
return await db.posts.insert(body); // sent as res.json(post) automatically
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
#### Context properties
|
|
46
|
+
|
|
47
|
+
| Property | Type | Description |
|
|
48
|
+
| --------- | ------------------------- | -------------------------------------------------------------------------- |
|
|
49
|
+
| `body` | inferred from `request` | Parsed and validated request body. `null` if the pact has no request schema. |
|
|
50
|
+
| `params` | inferred from path string | Path parameters (e.g. `{ id: string }` for `/posts/:id`). |
|
|
51
|
+
| `queries` | inferred from `query` | Validated query parameters. `{}` if the pact has no query schema. |
|
|
52
|
+
| `req` | `Request` | Raw Express request — use for headers, cookies, IP, etc. |
|
|
53
|
+
| `res` | `TypedResponse<TBody>` | Express response with `json()` typed to the pact's response schema. |
|
|
54
|
+
| `next` | `NextFunction` | Express next function — use to forward errors to your error handler. |
|
|
37
55
|
|
|
38
56
|
```ts
|
|
39
57
|
const getPostById = defineEndpoint({
|
|
40
58
|
pact: PostPacts.getById, // path: "/posts/:id"
|
|
41
|
-
handler: (
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
// ...
|
|
59
|
+
handler: ({ params }) => {
|
|
60
|
+
// params is typed as { id: string }
|
|
61
|
+
return db.posts.findById(params.id);
|
|
45
62
|
},
|
|
46
63
|
});
|
|
47
64
|
|
|
48
65
|
const listPosts = defineEndpoint({
|
|
49
66
|
pact: PostPacts.list, // has query: z.object({ page: z.string().optional() })
|
|
50
|
-
handler: (
|
|
51
|
-
//
|
|
52
|
-
|
|
67
|
+
handler: ({ queries }) => {
|
|
68
|
+
// queries is typed as { page?: string }
|
|
69
|
+
return db.posts.list({ page: queries.page });
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For anything beyond body/params/queries — headers, cookies, IP address, etc. — use `ctx.req`:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const createPost = defineEndpoint({
|
|
78
|
+
pact: PostPacts.create,
|
|
79
|
+
handler: ({ body, req }) => {
|
|
80
|
+
const ip = req.ip;
|
|
53
81
|
// ...
|
|
54
82
|
},
|
|
55
83
|
});
|
|
@@ -136,14 +164,14 @@ const router = createRouter({
|
|
|
136
164
|
|
|
137
165
|
### Endpoint middleware (`createEndpointMiddleware`)
|
|
138
166
|
|
|
139
|
-
Type-safe middleware that
|
|
167
|
+
Type-safe middleware that adds properties directly to the handler context. The properties returned by the middleware are merged into the context type seen by the handler.
|
|
140
168
|
|
|
141
169
|
```ts
|
|
142
170
|
import { createEndpointMiddleware, defineEndpoint } from "@routepact/express";
|
|
143
171
|
import { PostPacts } from "../shared/pacts/post.pact";
|
|
144
172
|
import { getSessionFromRequest } from "./auth";
|
|
145
173
|
|
|
146
|
-
// Declare what this middleware adds to
|
|
174
|
+
// Declare what this middleware adds to the context
|
|
147
175
|
const withUser = createEndpointMiddleware(async (req) => {
|
|
148
176
|
const session = await getSessionFromRequest(req);
|
|
149
177
|
if (!session) throw new Error("Unauthorized");
|
|
@@ -153,13 +181,9 @@ const withUser = createEndpointMiddleware(async (req) => {
|
|
|
153
181
|
const createPost = defineEndpoint({
|
|
154
182
|
pact: PostPacts.create,
|
|
155
183
|
middlewares: [withUser] as const, // `as const` needed to preserve tuple type
|
|
156
|
-
handler: async (
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
...req.body.resource,
|
|
160
|
-
authorId: req.user.id,
|
|
161
|
-
});
|
|
162
|
-
res.status(201).json({ post });
|
|
184
|
+
handler: async ({ body, user }) => {
|
|
185
|
+
// user is typed as User — no casting needed
|
|
186
|
+
return db.posts.insert({ ...body, authorId: user.id });
|
|
163
187
|
},
|
|
164
188
|
});
|
|
165
189
|
```
|
|
@@ -170,8 +194,8 @@ Multiple middlewares are supported and their added types are merged:
|
|
|
170
194
|
const getPost = defineEndpoint({
|
|
171
195
|
pact: PostPacts.getById,
|
|
172
196
|
middlewares: [withUser, withRateLimit] as const,
|
|
173
|
-
handler: async (
|
|
174
|
-
//
|
|
197
|
+
handler: async ({ params, user, rateLimit }) => {
|
|
198
|
+
// context has both .user (from withUser) and .rateLimit (from withRateLimit)
|
|
175
199
|
},
|
|
176
200
|
});
|
|
177
201
|
```
|
|
@@ -187,7 +211,7 @@ import {
|
|
|
187
211
|
} from "@routepact/express";
|
|
188
212
|
import { z } from "zod";
|
|
189
213
|
|
|
190
|
-
// Validates req.body against the schema
|
|
214
|
+
// Validates req.body against the schema, result available as ctx.body
|
|
191
215
|
app.use(createRequestValidationMiddleware(z.object({ name: z.string() })));
|
|
192
216
|
|
|
193
217
|
// Validates res.json(...) before sending
|
|
@@ -205,7 +229,7 @@ When validation fails, the middleware calls `next(error)` with one of these:
|
|
|
205
229
|
| Error class | Status | When |
|
|
206
230
|
| ------------------------- | ------ | -------------------------------------------------- |
|
|
207
231
|
| `RequestValidationError` | 400 | `req.body` or `req.query` fails validation |
|
|
208
|
-
| `ResponseValidationError` | 500 | `res.json(
|
|
232
|
+
| `ResponseValidationError` | 500 | `res.json(...)` fails the response schema |
|
|
209
233
|
|
|
210
234
|
Both expose a `cause` property with the raw `ZodError`. Register an error handler in your Express app to format them:
|
|
211
235
|
|
|
@@ -242,14 +266,15 @@ app.use((err, req, res, next) => {
|
|
|
242
266
|
| `defineRouteGroup(group)` | Creates a typed route group |
|
|
243
267
|
| `createEndpointMiddleware(handler)` | Creates a type-augmenting middleware |
|
|
244
268
|
| `createRouter(config, options?)` | Builds a versioned Express router |
|
|
245
|
-
| `createRequestValidationMiddleware(schema)` | Validates `req.body
|
|
246
|
-
| `createResponseValidationMiddleware(
|
|
269
|
+
| `createRequestValidationMiddleware(schema)` | Validates `req.body` and stores result in handler context as `body` |
|
|
270
|
+
| `createResponseValidationMiddleware(schema?)` | Validates `res.json(...)` output before sending |
|
|
247
271
|
| `ValidationError` | Base class for all validation errors — has `status` and `cause: ZodError` |
|
|
248
|
-
| `RequestValidationError` | Extends `ValidationError` — thrown on bad request
|
|
249
|
-
| `ResponseValidationError` | Extends `ValidationError` — thrown on bad response body (
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
272
|
+
| `RequestValidationError` | Extends `ValidationError` — thrown on bad request body or query (400) |
|
|
273
|
+
| `ResponseValidationError` | Extends `ValidationError` — thrown on bad response body (500) |
|
|
274
|
+
| `PactHandlerContext<TPact, TMiddlewares>` | The typed context object passed to every handler |
|
|
275
|
+
| `TypedResponse<TBody>` | Express `Response` with `json()` narrowed to `TBody` |
|
|
276
|
+
| `PactServerResponse<TPact>` | `TypedResponse` specialised for a pact's response schema |
|
|
277
|
+
| `EndpointMiddleware<TAdds>` | A middleware that augments the handler context with `TAdds` |
|
|
253
278
|
| `RouteEndpoint<TPact, TMiddlewares>` | Full endpoint type including handler and middlewares |
|
|
254
279
|
| `RouteGroup` | A group of endpoints with optional shared middleware |
|
|
255
280
|
| `RouterConfig` | Config passed to `createRouter` |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.utils.d.ts","sourceRoot":"","sources":["../src/endpoint.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EACV,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,SAAS,YAAY,EAC1B,YAAY,SAAS,SAAS,kBAAkB,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAE/D,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,GACzC,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,CAEpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,MAAM,EAC3D,OAAO,EAAE,yBAAyB,CAAC,KAAK,CAAC,GACxC,kBAAkB,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"endpoint.utils.d.ts","sourceRoot":"","sources":["../src/endpoint.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EACV,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,KAAK,SAAS,YAAY,EAC1B,YAAY,SAAS,SAAS,kBAAkB,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAE/D,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,GACzC,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,CAEpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAE9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,SAAS,MAAM,EAC3D,OAAO,EAAE,yBAAyB,CAAC,KAAK,CAAC,GACxC,kBAAkB,CAAC,KAAK,CAAC,CAoB3B"}
|
package/dist/endpoint.utils.js
CHANGED
|
@@ -46,8 +46,11 @@ export function createEndpointMiddleware(handler) {
|
|
|
46
46
|
handler: async (req, res, next) => {
|
|
47
47
|
try {
|
|
48
48
|
const additions = await handler(req, res, next);
|
|
49
|
+
if (!req._routepact) {
|
|
50
|
+
req._routepact = {};
|
|
51
|
+
}
|
|
49
52
|
if (additions) {
|
|
50
|
-
Object.assign(req, additions);
|
|
53
|
+
Object.assign(req._routepact, additions);
|
|
51
54
|
}
|
|
52
55
|
next();
|
|
53
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.utils.js","sourceRoot":"","sources":["../src/endpoint.utils.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAI5B,MAA0C;IAE1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAyC;IAEzC,OAAO;QACL,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"endpoint.utils.js","sourceRoot":"","sources":["../src/endpoint.utils.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAI5B,MAA0C;IAE1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiB;IAChD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAyC;IAEzC,OAAO;QACL,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;YAChC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBAEhD,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;oBACpB,GAAG,CAAC,UAAU,GAAG,EAAE,CAAC;gBACtB,CAAC;gBAED,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAC3C,CAAC;gBACD,IAAI,EAAE,CAAC;YACT,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.utils.d.ts","sourceRoot":"","sources":["../src/router.utils.ts"],"names":[],"mappings":"AACA,OAAO,OAA6C,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"router.utils.d.ts","sourceRoot":"","sources":["../src/router.utils.ts"],"names":[],"mappings":"AACA,OAAO,OAA6C,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,EAKV,YAAY,EACZ,aAAa,EACd,MAAM,YAAY,CAAC;AAkLpB;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAyBhB"}
|
package/dist/router.utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { exhaustiveGuard } from "@routepact/core";
|
|
2
2
|
import express from "express";
|
|
3
|
-
import {
|
|
3
|
+
import { createQueryValidationMiddleware, createRequestValidationMiddleware, createResponseValidationMiddleware, } from "./validation.js";
|
|
4
4
|
function validateRouteConfig(config) {
|
|
5
5
|
if (!config.basePath || !config.basePath.startsWith("/")) {
|
|
6
6
|
throw new Error("Router configuration must have a basePath starting with '/'");
|
|
@@ -26,15 +26,11 @@ function buildMiddlewareChain(endpoint) {
|
|
|
26
26
|
middlewares.push(middleware);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
req.parsedParams = { ...req.params };
|
|
35
|
-
next();
|
|
36
|
-
});
|
|
37
|
-
}
|
|
29
|
+
middlewares.push((req, _res, next) => {
|
|
30
|
+
req._routepact ??= {};
|
|
31
|
+
req._routepact.params = { ...req.params };
|
|
32
|
+
next();
|
|
33
|
+
});
|
|
38
34
|
if (endpoint.pact?.query) {
|
|
39
35
|
middlewares.push(createQueryValidationMiddleware(endpoint.pact.query));
|
|
40
36
|
}
|
|
@@ -46,6 +42,31 @@ function buildMiddlewareChain(endpoint) {
|
|
|
46
42
|
}
|
|
47
43
|
return middlewares;
|
|
48
44
|
}
|
|
45
|
+
function wrapHandler(endpoint) {
|
|
46
|
+
return async (req, res, next) => {
|
|
47
|
+
try {
|
|
48
|
+
const { body, params, queries, ...additions } = req._routepact ?? {};
|
|
49
|
+
const ctx = {
|
|
50
|
+
...additions,
|
|
51
|
+
// body: prefer _routepact.body (schema-validated), fall back to raw req.body
|
|
52
|
+
body: "body" in (req._routepact ?? {}) ? body : req.body,
|
|
53
|
+
params: params ?? {},
|
|
54
|
+
queries: queries ?? {},
|
|
55
|
+
req,
|
|
56
|
+
res,
|
|
57
|
+
next,
|
|
58
|
+
};
|
|
59
|
+
// biome-ignore lint/suspicious/noExplicitAny: ctx type is built dynamically
|
|
60
|
+
const result = await endpoint.handler(ctx);
|
|
61
|
+
if (result !== undefined && !res.headersSent) {
|
|
62
|
+
res.json(result);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
next(error);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
49
70
|
function registerHttpMethod(router, path, method, middlewares, handler) {
|
|
50
71
|
switch (method) {
|
|
51
72
|
case "get":
|
|
@@ -81,7 +102,7 @@ function processEndpoint(endpoint, router, registeredRoutes, groupMiddlewares =
|
|
|
81
102
|
...buildMiddlewareChain(endpoint),
|
|
82
103
|
];
|
|
83
104
|
try {
|
|
84
|
-
registerHttpMethod(router, path, method, middlewareChain, endpoint
|
|
105
|
+
registerHttpMethod(router, path, method, middlewareChain, wrapHandler(endpoint));
|
|
85
106
|
}
|
|
86
107
|
catch (error) {
|
|
87
108
|
throw new Error(`Failed to register endpoint [${method.toUpperCase()}] ${path}`, { cause: error });
|
package/dist/router.utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.utils.js","sourceRoot":"","sources":["../src/router.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAmB,MAAM,iBAAiB,CAAC;AACnE,OAAO,OAA6C,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"router.utils.js","sourceRoot":"","sources":["../src/router.utils.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,41 +1,64 @@
|
|
|
1
1
|
import type { AnyRoutePact, ExpectedParams, HasParams } from "@routepact/core";
|
|
2
2
|
import type { NextFunction, Request, RequestHandler, Response } from "express";
|
|
3
3
|
import type z from "zod/v4";
|
|
4
|
-
export interface
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export interface RoutePactRequest extends Request {
|
|
5
|
+
/**
|
|
6
|
+
* Internal namespace used by routepact to pass typed data (body, params,
|
|
7
|
+
* queries, middleware additions) between middleware and the route handler
|
|
8
|
+
* without polluting the root Express request object.
|
|
9
|
+
*/
|
|
10
|
+
_routepact?: Record<string, unknown>;
|
|
8
11
|
}
|
|
9
|
-
|
|
10
|
-
parsedParams: Omit<ExpectedParams<TPact["path"]>, keyof TParams> & TParams;
|
|
11
|
-
} : HasParams<TPact["path"]> extends true ? {
|
|
12
|
-
parsedParams: ExpectedParams<TPact["path"]>;
|
|
13
|
-
} : {
|
|
14
|
-
parsedParams?: never;
|
|
15
|
-
};
|
|
16
|
-
type PactQueriesField<TPact extends AnyRoutePact> = TPact["query"] extends z.ZodType<infer TQuery> ? {
|
|
17
|
-
parsedQueries: TQuery;
|
|
18
|
-
} : {
|
|
19
|
-
parsedQueries?: never;
|
|
20
|
-
};
|
|
21
|
-
export type PactServerRequest<TPact extends AnyRoutePact> = Omit<AnyServerRequest<TPact["request"] extends z.ZodType<unknown> ? z.infer<TPact["request"]> : null>, "parsedParams" | "parsedQueries"> & PactParamsField<TPact> & PactQueriesField<TPact>;
|
|
22
|
-
export interface AnyServerResponse<TBody = unknown> extends Response {
|
|
12
|
+
export interface TypedResponse<TBody> extends Response {
|
|
23
13
|
json: (body: TBody) => this;
|
|
24
14
|
}
|
|
25
|
-
export type PactServerResponse<TPact extends AnyRoutePact> =
|
|
15
|
+
export type PactServerResponse<TPact extends AnyRoutePact> = TypedResponse<TPact extends {
|
|
26
16
|
response: z.ZodType<unknown>;
|
|
27
|
-
} ? z.infer<TPact["response"]> :
|
|
17
|
+
} ? z.infer<TPact["response"]> : unknown>;
|
|
18
|
+
export type EndpointMiddlewareRequestHandler = (req: RoutePactRequest, res: Response, next: NextFunction) => Promise<void> | void;
|
|
28
19
|
export interface EndpointMiddleware<TAdds extends object = object> {
|
|
29
20
|
_type: "endpoint";
|
|
30
21
|
_adds?: TAdds;
|
|
31
|
-
handler:
|
|
22
|
+
handler: EndpointMiddlewareRequestHandler;
|
|
32
23
|
}
|
|
33
24
|
export type MergeMiddlewares<T extends readonly EndpointMiddleware<object>[]> = T extends readonly [infer First, ...infer Rest] ? First extends EndpointMiddleware<infer Adds> ? Rest extends readonly EndpointMiddleware<object>[] ? Adds & MergeMiddlewares<Rest> : Adds : {} : {};
|
|
34
|
-
export type EndpointMiddlewareHandler<TAdds extends object> = (req:
|
|
25
|
+
export type EndpointMiddlewareHandler<TAdds extends object> = (req: RoutePactRequest, res: Response, next: NextFunction) => Promise<TAdds | undefined> | TAdds | undefined;
|
|
26
|
+
type PactBody<TPact extends AnyRoutePact> = TPact["request"] extends z.ZodType<unknown> ? z.infer<TPact["request"]> : null;
|
|
27
|
+
type PactParams<TPact extends AnyRoutePact> = HasParams<TPact["path"]> extends true ? ExpectedParams<TPact["path"]> : {};
|
|
28
|
+
type PactQueries<TPact extends AnyRoutePact> = TPact["query"] extends z.ZodType<infer TQuery> ? TQuery : {};
|
|
29
|
+
type PactResponseBody<TPact extends AnyRoutePact> = TPact["response"] extends z.ZodType<infer TResponse> ? TResponse : unknown;
|
|
30
|
+
/**
|
|
31
|
+
* The typed context passed to every route handler.
|
|
32
|
+
*
|
|
33
|
+
* - `body` — parsed & validated request body (null when no request schema)
|
|
34
|
+
* - `params` — path parameters extracted from the URL
|
|
35
|
+
* - `queries` — parsed & validated query parameters
|
|
36
|
+
* - `req` — raw Express Request (headers, cookies, etc.)
|
|
37
|
+
* - `res` — raw Express Response (status codes, redirects, etc.)
|
|
38
|
+
* - `next` — Express NextFunction (pass errors, call next middleware)
|
|
39
|
+
*
|
|
40
|
+
* Any endpoint-middleware additions are merged in at the type level.
|
|
41
|
+
*/
|
|
42
|
+
export type PactHandlerContext<TPact extends AnyRoutePact, TMiddlewares extends readonly EndpointMiddleware<object>[] = []> = {
|
|
43
|
+
body: PactBody<TPact>;
|
|
44
|
+
params: PactParams<TPact>;
|
|
45
|
+
queries: PactQueries<TPact>;
|
|
46
|
+
} & MergeMiddlewares<TMiddlewares> & {
|
|
47
|
+
req: Request;
|
|
48
|
+
res: PactServerResponse<TPact>;
|
|
49
|
+
next: NextFunction;
|
|
50
|
+
};
|
|
35
51
|
export type RouteEndpoint<TPact extends AnyRoutePact, TMiddlewares extends readonly EndpointMiddleware<object>[] = []> = {
|
|
36
52
|
pact: TPact;
|
|
37
53
|
middlewares?: TMiddlewares;
|
|
38
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Handle the request using a typed context.
|
|
56
|
+
*
|
|
57
|
+
* Return a value to send it as JSON (validated against the pact response
|
|
58
|
+
* schema if one is defined). Return `void` / `undefined` to manage the
|
|
59
|
+
* response yourself via `ctx.res`.
|
|
60
|
+
*/
|
|
61
|
+
handler: (ctx: PactHandlerContext<TPact, TMiddlewares>) => PactResponseBody<TPact> | void | Promise<PactResponseBody<TPact> | void>;
|
|
39
62
|
};
|
|
40
63
|
export type AnyRouteEndpoint = RouteEndpoint<AnyRoutePact, readonly EndpointMiddleware<object>[]>;
|
|
41
64
|
export interface RouteGroup {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { NextFunction, Request, Response } from "express";
|
|
2
2
|
import z from "zod/v4";
|
|
3
|
-
import type {
|
|
4
|
-
export declare function createRequestValidationMiddleware(schema: z.ZodType): (req:
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function createResponseValidationMiddleware(schema?: z.ZodType): (_req: Request, res: PactServerResponse<any>, next: NextFunction) => Promise<void>;
|
|
3
|
+
import type { RoutePactRequest } from "./types.js";
|
|
4
|
+
export declare function createRequestValidationMiddleware(schema: z.ZodType): (req: RoutePactRequest, _res: Response, next: NextFunction) => Promise<void>;
|
|
5
|
+
export declare function createQueryValidationMiddleware(schema: z.ZodType<Record<string, unknown>>): (req: RoutePactRequest, _res: Response, next: NextFunction) => Promise<void>;
|
|
6
|
+
export declare function createResponseValidationMiddleware(schema?: z.ZodType): (_req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
8
7
|
//# sourceMappingURL=validation.d.ts.map
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,CAAC,MAAM,QAAQ,CAAC;AAEvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,IAE/D,KAAK,gBAAgB,EACrB,MAAM,QAAQ,EACd,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAajB;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,IAGxC,KAAK,gBAAgB,EACrB,MAAM,QAAQ,EACd,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAajB;AAED,wBAAgB,kCAAkC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,IAEjE,MAAM,OAAO,EACb,KAAK,QAAQ,EACb,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAwBjB"}
|
package/dist/validation.js
CHANGED
|
@@ -3,23 +3,8 @@ import { RequestValidationError, ResponseValidationError } from "./errors.js";
|
|
|
3
3
|
export function createRequestValidationMiddleware(schema) {
|
|
4
4
|
return async (req, _res, next) => {
|
|
5
5
|
try {
|
|
6
|
-
req.
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
catch (error) {
|
|
10
|
-
if (error instanceof z.ZodError) {
|
|
11
|
-
next(new RequestValidationError(error));
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
next(error);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
export function createParamsValidationMiddleware(schema) {
|
|
20
|
-
return async (req, _res, next) => {
|
|
21
|
-
try {
|
|
22
|
-
req.parsedParams = { ...req.params, ...schema.parse(req.params) };
|
|
6
|
+
req._routepact ??= {};
|
|
7
|
+
req._routepact.body = schema.parse(req.body);
|
|
23
8
|
next();
|
|
24
9
|
}
|
|
25
10
|
catch (error) {
|
|
@@ -35,7 +20,8 @@ export function createParamsValidationMiddleware(schema) {
|
|
|
35
20
|
export function createQueryValidationMiddleware(schema) {
|
|
36
21
|
return async (req, _res, next) => {
|
|
37
22
|
try {
|
|
38
|
-
req.
|
|
23
|
+
req._routepact ??= {};
|
|
24
|
+
req._routepact.queries = schema.parse(req.query);
|
|
39
25
|
next();
|
|
40
26
|
}
|
|
41
27
|
catch (error) {
|
|
@@ -49,9 +35,7 @@ export function createQueryValidationMiddleware(schema) {
|
|
|
49
35
|
};
|
|
50
36
|
}
|
|
51
37
|
export function createResponseValidationMiddleware(schema) {
|
|
52
|
-
return async (_req,
|
|
53
|
-
// biome-ignore lint/suspicious/noExplicitAny: response type not known
|
|
54
|
-
res, next) => {
|
|
38
|
+
return async (_req, res, next) => {
|
|
55
39
|
const originalJson = res.json;
|
|
56
40
|
res.json = function (body) {
|
|
57
41
|
if (this.statusCode >= 400) {
|
package/dist/validation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG9E,MAAM,UAAU,iCAAiC,CAAC,MAAiB;IACjE,OAAO,KAAK,EACV,GAAqB,EACrB,IAAc,EACd,IAAkB,EACH,EAAE;QACjB,IAAI,CAAC;YACH,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAG9E,MAAM,UAAU,iCAAiC,CAAC,MAAiB;IACjE,OAAO,KAAK,EACV,GAAqB,EACrB,IAAc,EACd,IAAkB,EACH,EAAE;QACjB,IAAI,CAAC;YACH,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC;YACtB,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAChC,IAAI,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,MAA0C;IAE1C,OAAO,KAAK,EACV,GAAqB,EACrB,IAAc,EACd,IAAkB,EACH,EAAE;QACjB,IAAI,CAAC;YACH,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC;YACtB,GAAG,CAAC,UAAU,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAChC,IAAI,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,KAAK,CAAC,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kCAAkC,CAAC,MAAkB;IACnE,OAAO,KAAK,EACV,IAAa,EACb,GAAa,EACb,IAAkB,EACH,EAAE;QACjB,MAAM,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC;QAE9B,GAAG,CAAC,IAAI,GAAG,UAAU,IAAI;YACvB,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBAC3B,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBACrD,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;oBAChC,IAAI,CAAC,IAAI,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC3C,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,KAAK,CAAC,CAAC;gBACd,CAAC;gBAED,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@routepact/express",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Express adapter for type-safe route pacts — endpoint builders, request/response validation middleware, and router setup",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "gitlab:mr5k/routepact",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dev": "tsc -b --watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@routepact/core": "^0.1.
|
|
24
|
+
"@routepact/core": "^0.1.8"
|
|
25
25
|
},
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
@@ -43,4 +43,4 @@
|
|
|
43
43
|
"middleware"
|
|
44
44
|
],
|
|
45
45
|
"license": "MIT"
|
|
46
|
-
}
|
|
46
|
+
}
|