@routepact/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +163 -0
- package/dist/api.d.ts +10 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +2 -0
- package/dist/api.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +14 -0
- package/dist/utils.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# @routepact/core
|
|
2
|
+
|
|
3
|
+
Shared types and utilities for defining type-safe route pacts. This package is the contract between your server and client — import it in shared code that both sides depend on.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @routepact/core zod
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Defining a route spec
|
|
12
|
+
|
|
13
|
+
A `RoutePact` describes a single endpoint: its path, HTTP method, and optional Zod schemas for request body, response body, and response metadata.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import type { RoutePact } from "@routepact/core";
|
|
18
|
+
|
|
19
|
+
export const PostPacts = {
|
|
20
|
+
list: {
|
|
21
|
+
method: "get",
|
|
22
|
+
path: "/posts",
|
|
23
|
+
validation: {
|
|
24
|
+
response: z.object({ id: z.string(), title: z.string() }).array(),
|
|
25
|
+
meta: z.object({ total: z.number(), page: z.number() }),
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
getById: {
|
|
29
|
+
method: "get",
|
|
30
|
+
path: "/posts/:id",
|
|
31
|
+
validation: {
|
|
32
|
+
response: z.object({
|
|
33
|
+
id: z.string(),
|
|
34
|
+
title: z.string(),
|
|
35
|
+
body: z.string(),
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
create: {
|
|
40
|
+
method: "post",
|
|
41
|
+
path: "/posts",
|
|
42
|
+
validation: {
|
|
43
|
+
request: z.object({ title: z.string(), body: z.string() }),
|
|
44
|
+
response: z.object({
|
|
45
|
+
id: z.string(),
|
|
46
|
+
title: z.string(),
|
|
47
|
+
body: z.string(),
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
update: {
|
|
52
|
+
method: "patch",
|
|
53
|
+
path: "/posts/:id",
|
|
54
|
+
validation: {
|
|
55
|
+
request: z.object({
|
|
56
|
+
title: z.string().optional(),
|
|
57
|
+
body: z.string().optional(),
|
|
58
|
+
}),
|
|
59
|
+
response: z.object({
|
|
60
|
+
id: z.string(),
|
|
61
|
+
title: z.string(),
|
|
62
|
+
body: z.string(),
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
delete: {
|
|
67
|
+
method: "delete",
|
|
68
|
+
path: "/posts/:id",
|
|
69
|
+
validation: {},
|
|
70
|
+
},
|
|
71
|
+
} satisfies Record<string, RoutePact>;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Using `satisfies Record<string, RoutePact>` lets TypeScript keep the literal types (exact path strings, exact method literals) while still validating the shape.
|
|
75
|
+
|
|
76
|
+
## Validation rules
|
|
77
|
+
|
|
78
|
+
| Field | Required | Description |
|
|
79
|
+
| --------------------- | ------------------------------- | -------------------------------------------- |
|
|
80
|
+
| `validation.request` | Only for `post`, `patch`, `put` | Zod schema for `req.body.resource` |
|
|
81
|
+
| `validation.response` | Optional | Zod schema for `res.json({ resource: ... })` |
|
|
82
|
+
| `validation.meta` | Optional | Zod schema for `res.json({ meta: ... })` |
|
|
83
|
+
|
|
84
|
+
## Path parameters
|
|
85
|
+
|
|
86
|
+
Parameters in the path are extracted as a type-safe object. If a path contains `:id`, the `params` option is required and typed as `{ id: string }`.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// TypeScript requires params when the path has parameters
|
|
90
|
+
await request(PostPacts.getById, { params: { id: "abc" } });
|
|
91
|
+
|
|
92
|
+
// TypeScript forbids params when there are none
|
|
93
|
+
await request(PostPacts.list);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## API response shape
|
|
97
|
+
|
|
98
|
+
All endpoints follow the same envelope:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
// Response body sent from the server
|
|
102
|
+
interface ApiResponse<TResource, TMeta> {
|
|
103
|
+
resource: TResource;
|
|
104
|
+
meta?: TMeta;
|
|
105
|
+
message?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Request body sent to the server
|
|
109
|
+
interface ApiRequest<TResource> {
|
|
110
|
+
resource: TResource;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Utilities
|
|
115
|
+
|
|
116
|
+
### `buildEndpoint(spec, options)`
|
|
117
|
+
|
|
118
|
+
Interpolates path params and appends a query string.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { buildEndpoint } from "@routepact/core";
|
|
122
|
+
|
|
123
|
+
buildEndpoint(PostPacts.getById, { params: { id: "42" } });
|
|
124
|
+
// → "/posts/42"
|
|
125
|
+
|
|
126
|
+
buildEndpoint(PostPacts.list, { queries: { page: "2", limit: "10" } });
|
|
127
|
+
// → "/posts?page=2&limit=10"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `exhaustiveGuard(value)`
|
|
131
|
+
|
|
132
|
+
A compile-time exhaustiveness check for `switch` statements. Throws at runtime if an unhandled branch is reached.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { exhaustiveGuard, type HttpMethod } from "@routepact/core";
|
|
136
|
+
|
|
137
|
+
function handle(method: HttpMethod) {
|
|
138
|
+
switch (method) {
|
|
139
|
+
case "get":
|
|
140
|
+
return "GET";
|
|
141
|
+
case "post":
|
|
142
|
+
return "POST";
|
|
143
|
+
// ... etc
|
|
144
|
+
default:
|
|
145
|
+
exhaustiveGuard(method); // TypeScript errors if a case is missing
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Type reference
|
|
151
|
+
|
|
152
|
+
| Type | Description |
|
|
153
|
+
| ----------------------------- | ----------------------------------------------------------------- |
|
|
154
|
+
| `RoutePact` | Base type for a single endpoint definition |
|
|
155
|
+
| `RouteValidation` | The `validation` field of a spec |
|
|
156
|
+
| `HttpMethod` | `"get" \| "post" \| "patch" \| "put" \| "delete"` |
|
|
157
|
+
| `RouteOptions<TPact>` | Inferred options (params, payload, queries) for a spec |
|
|
158
|
+
| `RouteOptionsRequired<TPact>` | `true` if options are required (has params or request schema) |
|
|
159
|
+
| `RequestResult<TPact>` | Inferred return type when calling a spec from the client |
|
|
160
|
+
| `ExtractParams<TPath>` | Extracts parameter names from a path string |
|
|
161
|
+
| `ExpectedParams<TPath>` | Maps extracted param names to `string` values |
|
|
162
|
+
| `ApiRequest<T>` | `{ resource: T }` — request body envelope |
|
|
163
|
+
| `ApiResponse<T, M>` | `{ resource: T; meta?: M; message?: string }` — response envelope |
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ApiResponse<TResource, TMeta = undefined> {
|
|
2
|
+
resource: TResource;
|
|
3
|
+
meta?: TMeta;
|
|
4
|
+
message?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ApiRequest<TResource> {
|
|
7
|
+
resource: TResource;
|
|
8
|
+
}
|
|
9
|
+
export type QueryParam = Record<string, string | number | boolean | undefined>;
|
|
10
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS;IACvD,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU,CAAC,SAAS;IACnC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC"}
|
package/dist/api.js
ADDED
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type z from "zod/v4";
|
|
2
|
+
import type { ApiResponse } from "./api.js";
|
|
3
|
+
export type HttpMethod = "get" | "post" | "patch" | "put" | "delete";
|
|
4
|
+
export type RouteValidation = {
|
|
5
|
+
response?: z.ZodType<unknown>;
|
|
6
|
+
request?: z.ZodType<unknown>;
|
|
7
|
+
meta?: z.ZodType<unknown>;
|
|
8
|
+
};
|
|
9
|
+
export type RoutePact = {
|
|
10
|
+
path: string;
|
|
11
|
+
method: HttpMethod;
|
|
12
|
+
validation: RouteValidation;
|
|
13
|
+
};
|
|
14
|
+
export type ExtractParams<T extends string> = T extends `${string}/:${infer Param}/${infer Rest}` ? Param | ExtractParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? Param : never;
|
|
15
|
+
export type ExpectedParams<T extends string> = {
|
|
16
|
+
[Key in ExtractParams<T>]: string;
|
|
17
|
+
};
|
|
18
|
+
type ParamsOption<TPath extends string> = [ExtractParams<TPath>] extends [never] ? {
|
|
19
|
+
params?: never;
|
|
20
|
+
} : {
|
|
21
|
+
params: ExpectedParams<TPath>;
|
|
22
|
+
};
|
|
23
|
+
type PayloadOption<TPact extends RoutePact> = TPact["method"] extends "post" | "patch" | "put" ? TPact["validation"]["request"] extends z.ZodType<unknown> ? {
|
|
24
|
+
payload: z.infer<TPact["validation"]["request"]>;
|
|
25
|
+
} : {
|
|
26
|
+
payload?: never;
|
|
27
|
+
} : {
|
|
28
|
+
payload?: never;
|
|
29
|
+
};
|
|
30
|
+
export type RouteOptions<TPact extends RoutePact> = ParamsOption<TPact["path"]> & PayloadOption<TPact> & {
|
|
31
|
+
queries?: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
export type RouteOptionsRequired<TPact extends RoutePact> = TPact["validation"]["request"] extends z.ZodType<unknown> ? true : [ExtractParams<TPact["path"]>] extends [never] ? false : true;
|
|
34
|
+
export type RequestResult<TPact extends RoutePact> = ApiResponse<TPact["validation"] extends {
|
|
35
|
+
response: z.ZodType<unknown>;
|
|
36
|
+
} ? z.infer<TPact["validation"]["response"]> : undefined, TPact["validation"] extends {
|
|
37
|
+
response: z.ZodType<unknown>;
|
|
38
|
+
meta: z.ZodType<unknown>;
|
|
39
|
+
} ? z.infer<TPact["validation"]["meta"]> : undefined>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RouteOptions, RoutePact } from "./types.js";
|
|
2
|
+
export declare function exhaustiveGuard(_value: never): never;
|
|
3
|
+
export declare function buildEndpoint<TPact extends RoutePact>(pact: TPact, options?: RouteOptions<TPact>): string;
|
|
4
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE1E,wBAAgB,eAAe,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAIpD;AAED,wBAAgB,aAAa,CAAC,KAAK,SAAS,SAAS,EACnD,IAAI,EAAE,KAAK,EACX,OAAO,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,GAC5B,MAAM,CAUR"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function exhaustiveGuard(_value) {
|
|
2
|
+
throw new Error(`Reached forbidden guard function with unexpected value: ${JSON.stringify(_value)}`);
|
|
3
|
+
}
|
|
4
|
+
export function buildEndpoint(pact, options) {
|
|
5
|
+
const replacedEndpoint = pact.path.replace(/:(\w+)/g, (match, key) => {
|
|
6
|
+
if (options?.params && key in options.params) {
|
|
7
|
+
return options.params[key];
|
|
8
|
+
}
|
|
9
|
+
return match;
|
|
10
|
+
});
|
|
11
|
+
const queryString = new URLSearchParams(options?.queries).toString();
|
|
12
|
+
return queryString ? `${replacedEndpoint}?${queryString}` : replacedEndpoint;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAa;IAC3C,MAAM,IAAI,KAAK,CACb,2DAA2D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CACpF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,IAAW,EACX,OAA6B;IAE7B,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACnE,IAAI,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC7C,OAAO,OAAO,CAAC,MAAM,CAAC,GAA0C,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrE,OAAO,WAAW,CAAC,CAAC,CAAC,GAAG,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC;AAC/E,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@routepact/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Type-safe route spec definitions shared between server and client",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -b",
|
|
20
|
+
"dev": "tsc -b --watch"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"zod": ">=4.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"zod": "4.1.7"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"routes",
|
|
33
|
+
"typesafe",
|
|
34
|
+
"zod",
|
|
35
|
+
"spec"
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT"
|
|
38
|
+
}
|