@contractspec/lib.contracts-runtime-server-rest 3.7.5 → 3.7.7
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 +54 -152
- package/dist/rest-elysia.d.ts +2 -2
- package/dist/rest-express.d.ts +2 -2
- package/dist/rest-next-app.d.ts +1 -1
- package/dist/rest-next-pages.d.ts +2 -2
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -1,166 +1,68 @@
|
|
|
1
1
|
# @contractspec/lib.contracts-runtime-server-rest
|
|
2
2
|
|
|
3
|
-
REST runtime adapters for
|
|
3
|
+
**REST server runtime adapters for ContractSpec contracts.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## What It Provides
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Layer**: lib.
|
|
8
|
+
- **Consumers**: bundles, all REST apps.
|
|
9
|
+
- Related ContractSpec packages include `@contractspec/lib.contracts-spec`, `@contractspec/lib.schema`, `@contractspec/tool.bun`, `@contractspec/tool.typescript`.
|
|
10
|
+
- Related ContractSpec packages include `@contractspec/lib.contracts-spec`, `@contractspec/lib.schema`, `@contractspec/tool.bun`, `@contractspec/tool.typescript`.
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
## Installation
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
`npm install @contractspec/lib.contracts-runtime-server-rest`
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
- Express adapter
|
|
15
|
-
- Elysia adapter
|
|
16
|
-
- Next.js App Router adapter
|
|
17
|
-
- Next.js Pages Router adapter
|
|
16
|
+
or
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
`bun add @contractspec/lib.contracts-runtime-server-rest`
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
## Usage
|
|
22
21
|
|
|
23
|
-
-
|
|
24
|
-
- Shared REST concerns (route derivation, input parsing, CORS, error mapping).
|
|
25
|
-
- Helper utilities reused by GraphQL runtime (`contracts-adapter-input`, `contracts-adapter-hydration`).
|
|
22
|
+
Import the root entrypoint from `@contractspec/lib.contracts-runtime-server-rest`, or choose a documented subpath when you only need one part of the package surface.
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
## Architecture
|
|
28
25
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
26
|
+
- `src/contracts-adapter-hydration.ts` is part of the package's public or composition surface.
|
|
27
|
+
- `src/contracts-adapter-input.ts` is part of the package's public or composition surface.
|
|
28
|
+
- `src/index.ts` is the root public barrel and package entrypoint.
|
|
29
|
+
- `src/rest-elysia.ts` is part of the package's public or composition surface.
|
|
30
|
+
- `src/rest-express.ts` is part of the package's public or composition surface.
|
|
31
|
+
- `src/rest-generic.ts` is part of the package's public or composition surface.
|
|
32
|
+
- `src/rest-next-app.ts` is part of the package's public or composition surface.
|
|
31
33
|
|
|
32
|
-
##
|
|
34
|
+
## Public Entry Points
|
|
35
|
+
|
|
36
|
+
- Export `.` resolves through `./src/index.ts`.
|
|
37
|
+
- Export `./contracts-adapter-hydration` resolves through `./src/contracts-adapter-hydration.ts`.
|
|
38
|
+
- Export `./contracts-adapter-input` resolves through `./src/contracts-adapter-input.ts`.
|
|
39
|
+
- Export `./rest-elysia` resolves through `./src/rest-elysia.ts`.
|
|
40
|
+
- Export `./rest-express` resolves through `./src/rest-express.ts`.
|
|
41
|
+
- Export `./rest-generic` resolves through `./src/rest-generic.ts`.
|
|
42
|
+
- Export `./rest-next-app` resolves through `./src/rest-next-app.ts`.
|
|
43
|
+
- Export `./rest-next-pages` resolves through `./src/rest-next-pages.ts`.
|
|
44
|
+
|
|
45
|
+
## Local Commands
|
|
46
|
+
|
|
47
|
+
- `bun run dev` — contractspec-bun-build dev
|
|
48
|
+
- `bun run build` — bun run prebuild && bun run build:bundle && bun run build:types
|
|
49
|
+
- `bun run lint` — bun run lint:fix
|
|
50
|
+
- `bun run lint:check` — biome check .
|
|
51
|
+
- `bun run lint:fix` — biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .
|
|
52
|
+
- `bun run typecheck` — tsc --noEmit
|
|
53
|
+
- `bun run publish:pkg` — bun publish --tolerate-republish --ignore-scripts --verbose
|
|
54
|
+
- `bun run publish:pkg:canary` — bun publish:pkg --tag canary
|
|
55
|
+
- `bun run clean` — rm -rf dist
|
|
56
|
+
- `bun run build:bundle` — contractspec-bun-build transpile
|
|
57
|
+
- `bun run build:types` — contractspec-bun-build types
|
|
58
|
+
- `bun run prebuild` — contractspec-bun-build prebuild
|
|
59
|
+
|
|
60
|
+
## Recent Updates
|
|
61
|
+
|
|
62
|
+
- Replace eslint+prettier by biomejs to optimize speed.
|
|
63
|
+
|
|
64
|
+
## Notes
|
|
33
65
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
bun add @contractspec/lib.contracts-runtime-server-rest @contractspec/lib.contracts-spec
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Install whichever peer framework you use (`express`, `elysia`, `next`).
|
|
41
|
-
|
|
42
|
-
## Export map
|
|
43
|
-
|
|
44
|
-
- Generic handler:
|
|
45
|
-
- `createFetchHandler`
|
|
46
|
-
- `RestOptions`
|
|
47
|
-
- Framework adapters:
|
|
48
|
-
- `expressRouter`
|
|
49
|
-
- `elysiaPlugin`
|
|
50
|
-
- `makeNextAppHandler`
|
|
51
|
-
- `makeNextPagesHandler`
|
|
52
|
-
- Shared adapter internals:
|
|
53
|
-
- `createInputTypeBuilder`
|
|
54
|
-
- `hydrateResourceIfNeeded`
|
|
55
|
-
- `parseReturns`
|
|
56
|
-
|
|
57
|
-
## Quick start (framework-agnostic)
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
import { createFetchHandler } from "@contractspec/lib.contracts-runtime-server-rest";
|
|
61
|
-
import type { HandlerCtx } from "@contractspec/lib.contracts-spec";
|
|
62
|
-
import type { OperationSpecRegistry } from "@contractspec/lib.contracts-spec/operations/registry";
|
|
63
|
-
|
|
64
|
-
declare const operations: OperationSpecRegistry;
|
|
65
|
-
|
|
66
|
-
const handler = createFetchHandler(
|
|
67
|
-
operations,
|
|
68
|
-
(request): HandlerCtx => ({
|
|
69
|
-
actor: "user",
|
|
70
|
-
channel: "web",
|
|
71
|
-
traceId: request.headers.get("x-trace-id") ?? undefined,
|
|
72
|
-
}),
|
|
73
|
-
{
|
|
74
|
-
basePath: "/api/contracts",
|
|
75
|
-
cors: true,
|
|
76
|
-
prettyJson: 2,
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const response = await handler(
|
|
81
|
-
new Request("https://example.com/api/contracts/workspace/get/v1.0.0")
|
|
82
|
-
);
|
|
83
|
-
console.log(response.status);
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Framework examples
|
|
87
|
-
|
|
88
|
-
### Express
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
import express from "express";
|
|
92
|
-
import { expressRouter } from "@contractspec/lib.contracts-runtime-server-rest/rest-express";
|
|
93
|
-
|
|
94
|
-
declare const operations: import("@contractspec/lib.contracts-spec/operations/registry").OperationSpecRegistry;
|
|
95
|
-
|
|
96
|
-
const app = express();
|
|
97
|
-
app.use(express.json());
|
|
98
|
-
|
|
99
|
-
app.use(
|
|
100
|
-
expressRouter(
|
|
101
|
-
express,
|
|
102
|
-
operations,
|
|
103
|
-
() => ({ actor: "user", channel: "web" }),
|
|
104
|
-
{ basePath: "/api/contracts", cors: true }
|
|
105
|
-
)
|
|
106
|
-
);
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Next.js App Router
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
import { makeNextAppHandler } from "@contractspec/lib.contracts-runtime-server-rest/rest-next-app";
|
|
113
|
-
|
|
114
|
-
declare const operations: import("@contractspec/lib.contracts-spec/operations/registry").OperationSpecRegistry;
|
|
115
|
-
|
|
116
|
-
const handler = makeNextAppHandler(
|
|
117
|
-
operations,
|
|
118
|
-
() => ({ actor: "user", channel: "web" }),
|
|
119
|
-
{ basePath: "/api/contracts" }
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
export const GET = handler;
|
|
123
|
-
export const POST = handler;
|
|
124
|
-
export const OPTIONS = handler;
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## Runtime behavior details
|
|
128
|
-
|
|
129
|
-
- Default method mapping:
|
|
130
|
-
- query -> `GET`
|
|
131
|
-
- command -> `POST`
|
|
132
|
-
- Default path mapping:
|
|
133
|
-
- `/<operation.key with dots replaced by slashes>/v<version>`
|
|
134
|
-
- GET input parsing:
|
|
135
|
-
- if `input` query param exists, parse it as JSON
|
|
136
|
-
- otherwise use query params as flat object
|
|
137
|
-
- POST input parsing:
|
|
138
|
-
- supports `application/json` and `application/x-www-form-urlencoded`
|
|
139
|
-
- Error mapping defaults:
|
|
140
|
-
- validation errors -> `400`
|
|
141
|
-
- `PolicyDenied*` errors -> `403`
|
|
142
|
-
- unknown errors -> `500`
|
|
143
|
-
- unsupported content type -> `415`
|
|
144
|
-
|
|
145
|
-
You can override error serialization using `RestOptions.onError`.
|
|
146
|
-
|
|
147
|
-
## AI assistant guidance
|
|
148
|
-
|
|
149
|
-
When generating code:
|
|
150
|
-
|
|
151
|
-
- Define operation specs first in `@contractspec/lib.contracts-spec`.
|
|
152
|
-
- Start with `createFetchHandler` for deterministic behavior, then choose framework wrappers.
|
|
153
|
-
- Keep `basePath` explicit to avoid route ambiguity in generated handlers.
|
|
154
|
-
|
|
155
|
-
When debugging:
|
|
156
|
-
|
|
157
|
-
- If a route is 404, verify operation key/version and derived path.
|
|
158
|
-
- If input parsing fails on GET, check whether caller sends `input=` JSON vs plain query params.
|
|
159
|
-
|
|
160
|
-
## Split migration from deprecated monolith
|
|
161
|
-
|
|
162
|
-
- `@contractspec/lib.contracts/server/rest-generic` -> `@contractspec/lib.contracts-runtime-server-rest/rest-generic`
|
|
163
|
-
- `@contractspec/lib.contracts/server/rest-express` -> `@contractspec/lib.contracts-runtime-server-rest/rest-express`
|
|
164
|
-
- `@contractspec/lib.contracts/server/rest-elysia` -> `@contractspec/lib.contracts-runtime-server-rest/rest-elysia`
|
|
165
|
-
- `@contractspec/lib.contracts/server/rest-next-app` -> `@contractspec/lib.contracts-runtime-server-rest/rest-next-app`
|
|
166
|
-
- `@contractspec/lib.contracts/server/rest-next-pages` -> `@contractspec/lib.contracts-runtime-server-rest/rest-next-pages`
|
|
66
|
+
- High blast radius — all REST APIs depend on this package.
|
|
67
|
+
- Framework adapters (Elysia, Express, Next.js) must stay independent of each other.
|
|
68
|
+
- Do not introduce cross-adapter coupling.
|
package/dist/rest-elysia.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Elysia } from 'elysia';
|
|
2
|
-
import { type RestOptions } from './rest-generic';
|
|
3
1
|
import type { OperationSpecRegistry } from '@contractspec/lib.contracts-spec/operations/registry';
|
|
4
2
|
import type { HandlerCtx } from '@contractspec/lib.contracts-spec/types';
|
|
3
|
+
import type { Elysia } from 'elysia';
|
|
4
|
+
import { type RestOptions } from './rest-generic';
|
|
5
5
|
export declare function elysiaPlugin(app: Elysia, reg: OperationSpecRegistry, ctxFactory: (c: {
|
|
6
6
|
request: Request;
|
|
7
7
|
store: unknown;
|
package/dist/rest-express.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Request as ExpressReq, Router } from 'express';
|
|
2
|
-
import { type RestOptions } from './rest-generic';
|
|
3
1
|
import type { OperationSpecRegistry } from '@contractspec/lib.contracts-spec/operations/registry';
|
|
4
2
|
import type { HandlerCtx } from '@contractspec/lib.contracts-spec/types';
|
|
3
|
+
import type { Request as ExpressReq, Router } from 'express';
|
|
4
|
+
import { type RestOptions } from './rest-generic';
|
|
5
5
|
export declare function expressRouter(express: {
|
|
6
6
|
Router: () => Router;
|
|
7
7
|
}, reg: OperationSpecRegistry, ctxFactory: (req: ExpressReq) => HandlerCtx, options?: RestOptions): Router;
|
package/dist/rest-next-app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RestOptions } from './rest-generic';
|
|
2
1
|
import type { OperationSpecRegistry } from '@contractspec/lib.contracts-spec/operations/registry';
|
|
3
2
|
import type { HandlerCtx } from '@contractspec/lib.contracts-spec/types';
|
|
3
|
+
import { type RestOptions } from './rest-generic';
|
|
4
4
|
export declare function makeNextAppHandler(reg: OperationSpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): (req: Request) => Promise<Response>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
-
import { type RestOptions } from './rest-generic';
|
|
3
1
|
import type { OperationSpecRegistry } from '@contractspec/lib.contracts-spec/operations/registry';
|
|
4
2
|
import type { HandlerCtx } from '@contractspec/lib.contracts-spec/types';
|
|
3
|
+
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
4
|
+
import { type RestOptions } from './rest-generic';
|
|
5
5
|
export declare function makeNextPagesHandler(reg: OperationSpecRegistry, ctxFactory: (req: NextApiRequest) => HandlerCtx, options?: RestOptions): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/lib.contracts-runtime-server-rest",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.7",
|
|
4
4
|
"description": "REST server runtime adapters for ContractSpec contracts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"publish:pkg:canary": "bun publish:pkg --tag canary",
|
|
10
10
|
"clean": "rm -rf dist",
|
|
11
11
|
"lint": "bun run lint:fix",
|
|
12
|
-
"lint:fix": "
|
|
13
|
-
"lint:check": "
|
|
12
|
+
"lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
|
|
13
|
+
"lint:check": "biome check .",
|
|
14
14
|
"build": "bun run prebuild && bun run build:bundle && bun run build:types",
|
|
15
15
|
"build:bundle": "contractspec-bun-build transpile",
|
|
16
16
|
"build:types": "contractspec-bun-build types",
|
|
@@ -24,19 +24,19 @@
|
|
|
24
24
|
"directory": "packages/libs/contract-runtime-server-rest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@contractspec/lib.contracts-spec": "
|
|
28
|
-
"@contractspec/lib.schema": "3.7.
|
|
27
|
+
"@contractspec/lib.contracts-spec": "4.0.0",
|
|
28
|
+
"@contractspec/lib.schema": "3.7.6"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@pothos/core": "^4.9.1",
|
|
32
|
-
"elysia": "^1.4.
|
|
32
|
+
"elysia": "^1.4.28",
|
|
33
33
|
"express": "^5.2.1",
|
|
34
|
-
"next": "16.
|
|
34
|
+
"next": "16.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@contractspec/tool.typescript": "3.7.
|
|
37
|
+
"@contractspec/tool.typescript": "3.7.6",
|
|
38
38
|
"typescript": "^5.9.3",
|
|
39
|
-
"@contractspec/tool.bun": "3.7.
|
|
39
|
+
"@contractspec/tool.bun": "3.7.6"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"dist",
|