@orpc/server 2.0.0-beta.31 → 2.0.0-beta.33
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 +46 -30
- package/dist/adapters/aws-lambda/index.mjs +3 -3
- package/dist/adapters/crossws/index.mjs +3 -3
- package/dist/adapters/fastify/index.mjs +3 -3
- package/dist/adapters/fetch/index.mjs +3 -3
- package/dist/adapters/message-port/index.mjs +3 -3
- package/dist/adapters/node/index.mjs +3 -3
- package/dist/adapters/standard/index.mjs +3 -3
- package/dist/adapters/websocket/index.mjs +3 -3
- package/dist/extensions/callable.mjs +2 -2
- package/dist/index.mjs +5 -5
- package/dist/plugins/index.d.mts +37 -4
- package/dist/plugins/index.d.ts +37 -4
- package/dist/plugins/index.mjs +84 -15
- package/dist/shared/{server.CkButhNT.mjs → server.3Ex_8ISY.mjs} +3 -1
- package/dist/shared/{server.DpUGXBi2.mjs → server.7G43pSxo.mjs} +2 -2
- package/dist/shared/{server.eCTV8Vpp.mjs → server.Cqk3swxs.mjs} +1 -1
- package/dist/shared/{server.Dh77P3ii.mjs → server.S8BnCR3a.mjs} +1 -1
- package/package.json +12 -13
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<a href="https://codecov.io/gh/middleapi/orpc">
|
|
5
5
|
<img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg">
|
|
6
6
|
</a>
|
|
7
|
-
<a href="https://
|
|
7
|
+
<a href="https://www.npmjs.com/package/@orpc/server">
|
|
8
8
|
<img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Fserver?logo=npm" />
|
|
9
9
|
</a>
|
|
10
10
|
<a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
|
|
@@ -29,44 +29,54 @@ You can read the documentation [here](https://orpc.dev).
|
|
|
29
29
|
|
|
30
30
|
**Core**
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
| Package | Purpose | Docs |
|
|
33
|
+
| -------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
34
|
+
| [@orpc/contract](https://www.npmjs.com/package/@orpc/contract) | Define API contract as the single source of truth. | [Procedure Contract](https://orpc.dev/docs/contract/procedure), [Contract Router](https://orpc.dev/docs/contract/router), [Implementation](https://orpc.dev/docs/contract/implementation), [Generate from OpenAPI](https://orpc.dev/docs/contract/generate-from-openapi) |
|
|
35
|
+
| [@orpc/server](https://www.npmjs.com/package/@orpc/server) | Build APIs or implement contracts. | [Procedure](https://orpc.dev/docs/procedure), [Router](https://orpc.dev/docs/router), [Middleware](https://orpc.dev/docs/middleware), [Context](https://orpc.dev/docs/context), [RPC Handler](https://orpc.dev/docs/rpc/handler) |
|
|
36
|
+
| [@orpc/client](https://www.npmjs.com/package/@orpc/client) | Consume APIs with end-to-end type safety. | [Client-Side Clients](https://orpc.dev/docs/client/client-side), [Server-Side Clients](https://orpc.dev/docs/client/server-side), [RPC Link](https://orpc.dev/docs/rpc/link), [Error Handling](https://orpc.dev/docs/client/error-handling) |
|
|
37
|
+
| [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi) | Add OpenAPI compatibility to APIs. | [OpenAPI Handler](https://orpc.dev/docs/openapi/handler), [OpenAPI Link](https://orpc.dev/docs/openapi/link), [Specification](https://orpc.dev/docs/openapi/specification), [Scalar](https://orpc.dev/docs/openapi/scalar) |
|
|
36
38
|
|
|
37
39
|
**Schema validation**
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
| Package | Purpose | Docs |
|
|
42
|
+
| ------------------------------------------------------------ | ----------------------------------------------- | ----------------------------------------------------- |
|
|
43
|
+
| [@orpc/zod](https://www.npmjs.com/package/@orpc/zod) | Integrate with [Zod](https://zod.dev/). | [Zod](https://orpc.dev/docs/integrations/zod) |
|
|
44
|
+
| [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot) | Integrate with [Valibot](https://valibot.dev/). | [Valibot](https://orpc.dev/docs/integrations/valibot) |
|
|
45
|
+
| [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype) | Integrate with [ArkType](https://arktype.io/). | [ArkType](https://orpc.dev/docs/integrations/arktype) |
|
|
42
46
|
|
|
43
47
|
**Built-in features**
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
| Package | Purpose | Docs |
|
|
50
|
+
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
51
|
+
| [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher) | Pub/Sub with memory, Redis, and Upstash adapters. | [Publisher](https://orpc.dev/docs/helpers/publisher) |
|
|
52
|
+
| [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit) | Rate limiting with memory, Redis, and Upstash adapters. | [Rate Limit](https://orpc.dev/docs/helpers/ratelimit) |
|
|
53
|
+
| [@orpc/hibernation](https://www.npmjs.com/package/@orpc/hibernation) | Leverage Hibernation APIs like [Cloudflare's Hibernation WebSocket](https://developers.cloudflare.com/durable-objects/best-practices/websockets/#durable-objects-hibernation-websocket-api). | [Hibernation](https://orpc.dev/docs/integrations/hibernation) |
|
|
54
|
+
| [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema) | Smart coercion for OpenAPI requests. | [Smart Coercion](https://orpc.dev/docs/plugins/smart-coercion) |
|
|
49
55
|
|
|
50
56
|
**Framework & ecosystem integrations**
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
| Package | Purpose | Docs |
|
|
59
|
+
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
60
|
+
| [@orpc/next](https://www.npmjs.com/package/@orpc/next) | Integrate with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data). | [Next.js](https://orpc.dev/docs/integrations/next) |
|
|
61
|
+
| [@orpc/ai-sdk](https://www.npmjs.com/package/@orpc/ai-sdk) | Turn contracts and procedures into [AI SDK](https://ai-sdk.dev/) tools. | [AI SDK](https://orpc.dev/docs/integrations/ai-sdk) |
|
|
62
|
+
| [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query) | Integrate with [TanStack Query](https://tanstack.com/query/latest). | [TanStack Query](https://orpc.dev/docs/integrations/tanstack-query) |
|
|
63
|
+
| [@orpc/pinia-colada](https://www.npmjs.com/package/@orpc/pinia-colada) | Integrate with [Pinia Colada](https://pinia-colada.esm.dev/). | [Pinia Colada](https://orpc.dev/docs/integrations/pinia-colada) |
|
|
64
|
+
| [@orpc/swr](https://www.npmjs.com/package/@orpc/swr) | Integrate with [SWR](https://swr.vercel.app/). | [SWR](https://orpc.dev/docs/integrations/swr) |
|
|
65
|
+
| [@orpc/experimental-msw](https://www.npmjs.com/package/@orpc/experimental-msw) | Mock procedures with [Mock Service Worker](https://mswjs.io/). | [MSW](https://orpc.dev/docs/integrations/msw) |
|
|
66
|
+
| [@orpc/experimental-effect](https://www.npmjs.com/package/@orpc/experimental-effect) | Integrate with [Effect](https://effect.website/). | [Effect](https://orpc.dev/docs/integrations/effect) |
|
|
67
|
+
| [@orpc/nest](https://www.npmjs.com/package/@orpc/nest) | Implement your contract with [NestJS](https://nestjs.com/). | [NestJS](https://orpc.dev/docs/integrations/nest) |
|
|
68
|
+
| [@orpc/node](https://www.npmjs.com/package/@orpc/node) | [Node.js](https://nodejs.org/) plugins for static file serving and large uploads. | [Static File](https://orpc.dev/docs/plugins/static-file), [Tmp File Upload](https://orpc.dev/docs/plugins/tmp-file-upload), [Batch Response Compression](https://orpc.dev/docs/plugins/batch-response-compression) |
|
|
69
|
+
| [@orpc/bun](https://www.npmjs.com/package/@orpc/bun) | Adapters for [Bun's Redis](https://bun.sh/). | [Publisher](https://orpc.dev/docs/helpers/publisher), [Rate Limit](https://orpc.dev/docs/helpers/ratelimit) |
|
|
70
|
+
| [@orpc/cloudflare](https://www.npmjs.com/package/@orpc/cloudflare) | Adapters for [Cloudflare's RateLimit and Durable Objects](https://developers.cloudflare.com/workers/). | [Publisher](https://orpc.dev/docs/helpers/publisher), [Rate Limit](https://orpc.dev/docs/helpers/ratelimit) |
|
|
71
|
+
| [@orpc/trpc](https://www.npmjs.com/package/@orpc/trpc) | Reuse existing [tRPC](https://trpc.io/) routers within oRPC. | [tRPC](https://orpc.dev/docs/integrations/trpc) |
|
|
64
72
|
|
|
65
73
|
**Observability**
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
| Package | Purpose | Docs |
|
|
76
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
77
|
+
| [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry) | Integrate with [OpenTelemetry](https://opentelemetry.io/) for distributed tracing. | [OpenTelemetry](https://orpc.dev/docs/integrations/opentelemetry) |
|
|
78
|
+
| [@orpc/pino](https://www.npmjs.com/package/@orpc/pino) | Integrate with [Pino](https://getpino.io/) for logging. | [Pino](https://orpc.dev/docs/integrations/pino) |
|
|
79
|
+
| [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog) | Integrate with [Evlog](https://evlog.dev/) for logging. | [Evlog](https://orpc.dev/docs/integrations/evlog) |
|
|
70
80
|
|
|
71
81
|
## Sponsors
|
|
72
82
|
|
|
@@ -76,6 +86,9 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
76
86
|
<tr>
|
|
77
87
|
<td width="2000"><a href="https://screenshotone.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener" title="The screenshot API for developers"><img src="https://avatars.githubusercontent.com/u/97035603?v=4" width="64" align="left" hspace="12" alt="ScreenshotOne.com"/><b>ScreenshotOne.com</b></a><br /><sub>The screenshot API for developers</sub></td>
|
|
78
88
|
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td width="2000"><a href="https://yuzu.health/careers?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="We're hiring NYC based engineers"><img src="https://avatars.githubusercontent.com/u/102488956?v=4" width="64" align="left" hspace="12" alt="Yuzu"/><b>Yuzu</b></a><br /><sub>We're hiring NYC based engineers</sub></td>
|
|
91
|
+
</tr>
|
|
79
92
|
<tr>
|
|
80
93
|
<td width="2000"><a href="https://misskey.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Decentralized microblogging SNS born on Earth"><img src="https://github.com/MisskeyIO.png" width="64" align="left" hspace="12" alt="MisskeyHQ"/><b>MisskeyHQ</b></a><br /><sub>Decentralized microblogging SNS born on Earth</sub></td>
|
|
81
94
|
</tr>
|
|
@@ -113,6 +126,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
113
126
|
<td align="center"><a href="https://github.com/itigoore01?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&v=4" width="139" alt="shota"/><br />shota</a></td>
|
|
114
127
|
<td align="center"><a href="https://github.com/ellis-driscoll?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Ellis Driscoll"><img src="https://avatars.githubusercontent.com/u/70685966?u=c5f95bc33b5991d9744abe00052542e4a2ed3cb9&v=4" width="139" alt="Ellis Driscoll"/><br />Ellis Driscoll</a></td>
|
|
115
128
|
<td align="center"><a href="https://github.com/hoangbn?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Hoang Nguyen"><img src="https://avatars.githubusercontent.com/u/38968280?u=c90084c6de65c56facabab7ba13a72a49ddbc3e4&v=4" width="139" alt="Hoang Nguyen"/><br />Hoang Nguyen</a></td>
|
|
129
|
+
<td align="center"><a href="https://opencollective.com/guest-ac41de3b?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Orestis Ioannou"><img src="https://images.opencollective.com/guest-ac41de3b/avatar/460.png" width="139" alt="Orestis Ioannou"/><br />Orestis Ioannou</a></td>
|
|
116
130
|
</tr>
|
|
117
131
|
</table>
|
|
118
132
|
|
|
@@ -121,30 +135,32 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
121
135
|
<table>
|
|
122
136
|
<tr>
|
|
123
137
|
<td align="center"><a href="https://github.com/rhinodavid?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="David Walsh"><img src="https://avatars.githubusercontent.com/u/5778036?u=b5521f07d2f88c3db2a0dae62b5f2f8357214af0&v=4" width="119" alt="David Walsh"/><br />David Walsh</a></td>
|
|
138
|
+
<td align="center"><a href="https://github.com/IPv4Addr?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="IPv4Addr"><img src="https://avatars.githubusercontent.com/u/100147665?u=59996b72f69bb53063cb7e9ff8b8f898616cd94d&v=4" width="119" alt="IPv4Addr"/><br />IPv4Addr</a></td>
|
|
124
139
|
<td align="center"><a href="https://robbevaes.be/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Robbe Vaes"><img src="https://avatars.githubusercontent.com/u/44748019?u=e0232402c045ad4eac7cbd217f1f47e083103b89&v=4" width="119" alt="Robbe Vaes"/><br />Robbe Vaes</a></td>
|
|
125
140
|
<td align="center"><a href="https://github.com/aidansunbury?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Aidan Sunbury"><img src="https://avatars.githubusercontent.com/u/64103161?v=4" width="119" alt="Aidan Sunbury"/><br />Aidan Sunbury</a></td>
|
|
126
141
|
<td align="center"><a href="https://github.com/soonoo?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="soonoo"><img src="https://avatars.githubusercontent.com/u/5436405?u=5d0b4aa955c87e30e6bda7f0cccae5402da99528&v=4" width="119" alt="soonoo"/><br />soonoo</a></td>
|
|
127
142
|
<td align="center"><a href="https://kevinporten.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kevin Porten"><img src="https://avatars.githubusercontent.com/u/1839345?u=dc2263d5cfe0d927ce1a0be04a1d55dd6b55405c&v=4" width="119" alt="Kevin Porten"/><br />Kevin Porten</a></td>
|
|
128
143
|
<td align="center"><a href="https://github.com/pumpkinlink?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Denis"><img src="https://avatars.githubusercontent.com/u/11864620?u=5f47bbe6c65d0f6f5cf011021490238e4b0593d0&v=4" width="119" alt="Denis"/><br />Denis</a></td>
|
|
129
|
-
<td align="center"><a href="https://github.com/christopher-kapic?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
|
|
130
144
|
</tr>
|
|
131
145
|
<tr>
|
|
146
|
+
<td align="center"><a href="https://github.com/christopher-kapic?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
|
|
132
147
|
<td align="center"><a href="http://ballingt.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Tom Ballinger"><img src="https://avatars.githubusercontent.com/u/458879?u=4b045ac75d721b6ac2b42a74d7d37f61f0414031&v=4" width="119" alt="Tom Ballinger"/><br />Tom Ballinger</a></td>
|
|
133
148
|
<td align="center"><a href="https://lee-sam.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Sam"><img src="https://avatars.githubusercontent.com/u/102863520?u=3c89611f549d5070be232eb4532f690c8f2e7a65&v=4" width="119" alt="Sam"/><br />Sam</a></td>
|
|
134
149
|
<td align="center"><a href="https://github.com/Titoine?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Titoine"><img src="https://avatars.githubusercontent.com/u/3514286?u=1bb1e86b0c99c8a1121372e56d51a177eea12191&v=4" width="119" alt="Titoine"/><br />Titoine</a></td>
|
|
135
150
|
<td align="center"><a href="https://rigtch.fm/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&v=4" width="119" alt="Igor Makowski"/><br />Igor Makowski</a></td>
|
|
136
151
|
<td align="center"><a href="https://blog.cwang.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="hanayashiki"><img src="https://avatars.githubusercontent.com/u/26056783?u=06c3b9205a16fd41a871e82da1cc2a09306d53f5&v=4" width="119" alt="hanayashiki"/><br />hanayashiki</a></td>
|
|
137
152
|
<td align="center"><a href="https://dubinets.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Lev Dubinets"><img src="https://avatars.githubusercontent.com/u/3114081?u=f547f5d5012cab54851f1b1ad72d10e537f78fc2&v=4" width="119" alt="Lev Dubinets"/><br />Lev Dubinets</a></td>
|
|
138
|
-
<td align="center"><a href="https://bika.ai/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
|
|
139
153
|
</tr>
|
|
140
154
|
<tr>
|
|
155
|
+
<td align="center"><a href="https://kellychan.im/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
|
|
141
156
|
<td align="center"><a href="https://guyariely.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Guy Ariely"><img src="https://avatars.githubusercontent.com/u/42813496?u=edb6b7f563bf28e160a290832e7da57c0506f8ca&v=4" width="119" alt="Guy Ariely"/><br />Guy Ariely</a></td>
|
|
157
|
+
<td align="center"><a href="https://paulsenon.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="PaulSenon"><img src="https://avatars.githubusercontent.com/u/19531087?u=6385741eb91d200b8c513ec6045482e301767ca6&v=4" width="119" alt="PaulSenon"/><br />PaulSenon</a></td>
|
|
142
158
|
<td align="center"><a href="https://piscis.dev/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&v=4" width="119" alt="Alex"/><br />Alex</a></td>
|
|
143
159
|
<td align="center"><a href="https://opensource.gubanov.eu/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=c5f2daf7ebece498e85c83367bb37b4e10e2649d&v=4" width="119" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
|
|
144
160
|
</tr>
|
|
145
161
|
</table>
|
|
146
162
|
|
|
147
|
-
With thanks to [
|
|
163
|
+
With thanks to [36 past sponsors](https://htmlpreview.github.io/?https://github.com/middleapi/static/blob/main/sponsors.svg) who helped get oRPC here.
|
|
148
164
|
|
|
149
165
|
## References
|
|
150
166
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
2
2
|
import { toStandardLazyRequest, sendStandardResponse } from '@standardserver/aws-lambda';
|
|
3
3
|
import { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
|
|
4
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
4
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
5
5
|
import '@orpc/client';
|
|
6
6
|
import '@standardserver/core';
|
|
7
|
-
import '../../shared/server.
|
|
7
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
8
8
|
import '@orpc/contract';
|
|
9
|
-
import '../../shared/server.
|
|
9
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
10
10
|
|
|
11
11
|
class CompositeAwsLambdaHandlerPlugin {
|
|
12
12
|
name = "~composite/aws-lambda";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
2
2
|
import { ServerPeer, encodePeerMessage, decodePeerMessage, isClientPeerSendMessage } from '@standardserver/peer';
|
|
3
3
|
import { c as createStandardPeerRequestHandler } from '../../shared/server.CX4vUnDk.mjs';
|
|
4
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
4
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
5
5
|
import '@orpc/client';
|
|
6
6
|
import '@standardserver/core';
|
|
7
|
-
import '../../shared/server.
|
|
7
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
8
8
|
import '@orpc/contract';
|
|
9
|
-
import '../../shared/server.
|
|
9
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
10
10
|
|
|
11
11
|
class experimental_CrosswsHandler {
|
|
12
12
|
constructor(handler, options = {}) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
2
2
|
import { toStandardLazyRequest, sendStandardResponse } from '@standardserver/fastify';
|
|
3
3
|
import { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
|
|
4
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
4
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
5
5
|
import '@orpc/client';
|
|
6
6
|
import '@standardserver/core';
|
|
7
|
-
import '../../shared/server.
|
|
7
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
8
8
|
import '@orpc/contract';
|
|
9
|
-
import '../../shared/server.
|
|
9
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
10
10
|
|
|
11
11
|
class CompositeFastifyHandlerPlugin {
|
|
12
12
|
name = "~composite/fastify";
|
|
@@ -2,12 +2,12 @@ export { R as BodyLimitPlugin } from '../../shared/server.Cd4Z1hpV.mjs';
|
|
|
2
2
|
import { sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
3
3
|
import { toStandardLazyRequest, toFetchResponse } from '@standardserver/fetch';
|
|
4
4
|
import { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
|
|
5
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
5
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
6
6
|
import '@orpc/client';
|
|
7
7
|
import '@standardserver/core';
|
|
8
|
-
import '../../shared/server.
|
|
8
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
9
9
|
import '@orpc/contract';
|
|
10
|
-
import '../../shared/server.
|
|
10
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
11
11
|
|
|
12
12
|
class CompositeFetchHandlerPlugin {
|
|
13
13
|
name = "~composite/fetch";
|
|
@@ -2,12 +2,12 @@ import { onMessagePortMessage, onMessagePortClose, postMessagePortMessage } from
|
|
|
2
2
|
import { value, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
3
3
|
import { ServerPeer, encodePeerMessage, decodePeerMessage, isClientPeerSendMessage, isPeerMessage } from '@standardserver/peer';
|
|
4
4
|
import { c as createStandardPeerRequestHandler } from '../../shared/server.CX4vUnDk.mjs';
|
|
5
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
5
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
6
6
|
import '@orpc/client';
|
|
7
7
|
import '@standardserver/core';
|
|
8
|
-
import '../../shared/server.
|
|
8
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
9
9
|
import '@orpc/contract';
|
|
10
|
-
import '../../shared/server.
|
|
10
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
11
11
|
|
|
12
12
|
class MessagePortHandler {
|
|
13
13
|
constructor(handler, options = {}) {
|
|
@@ -2,13 +2,13 @@ export { R as BodyLimitPlugin } from '../../shared/server.Cd4Z1hpV.mjs';
|
|
|
2
2
|
import { sortPlugins, intercept, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
3
3
|
import { toStandardLazyRequest, sendStandardResponse } from '@standardserver/node';
|
|
4
4
|
import { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
|
|
5
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
5
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
6
6
|
import '@orpc/client';
|
|
7
7
|
import '@standardserver/core';
|
|
8
8
|
import '@standardserver/fetch';
|
|
9
|
-
import '../../shared/server.
|
|
9
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
10
10
|
import '@orpc/contract';
|
|
11
|
-
import '../../shared/server.
|
|
11
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
12
12
|
|
|
13
13
|
class CompositeNodeHttpHandlerPlugin {
|
|
14
14
|
name = "~composite/node-http";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, R as RPCHandlerCodec, a as RPCMatcher, b as RPC_DEFAULT_ALLOW_METHODS, S as StandardHandler } from '../../shared/server.
|
|
1
|
+
export { C as CompositeStandardHandlerPlugin, O as OtelHandlerPlugin, R as RPCHandlerCodec, a as RPCMatcher, b as RPC_DEFAULT_ALLOW_METHODS, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
2
2
|
export { r as resolveFriendlyStandardHandlerHandleOptions } from '../../shared/server.W91HSRkE.mjs';
|
|
3
3
|
import '@orpc/client';
|
|
4
4
|
import '@orpc/shared';
|
|
5
5
|
import '@standardserver/core';
|
|
6
|
-
import '../../shared/server.
|
|
6
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
7
7
|
import '@orpc/contract';
|
|
8
|
-
import '../../shared/server.
|
|
8
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { toStringOrBytes, resolveMaybeOptionalOptions, sequential, loadBytes } from '@orpc/shared';
|
|
2
2
|
import { ServerPeer, encodePeerMessage, decodePeerMessage, isClientPeerSendMessage } from '@standardserver/peer';
|
|
3
3
|
import { c as createStandardPeerRequestHandler } from '../../shared/server.CX4vUnDk.mjs';
|
|
4
|
-
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.
|
|
4
|
+
import { R as RPCHandlerCodec, S as StandardHandler } from '../../shared/server.7G43pSxo.mjs';
|
|
5
5
|
import '@orpc/client';
|
|
6
6
|
import '@standardserver/core';
|
|
7
|
-
import '../../shared/server.
|
|
7
|
+
import '../../shared/server.3Ex_8ISY.mjs';
|
|
8
8
|
import '@orpc/contract';
|
|
9
|
-
import '../../shared/server.
|
|
9
|
+
import '../../shared/server.S8BnCR3a.mjs';
|
|
10
10
|
|
|
11
11
|
class WebSocketHandler {
|
|
12
12
|
constructor(handler, options = {}) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createProcedureClient } from '../shared/server.
|
|
2
|
-
import { D as DecoratedProcedure } from '../shared/server.
|
|
1
|
+
import { c as createProcedureClient } from '../shared/server.3Ex_8ISY.mjs';
|
|
2
|
+
import { D as DecoratedProcedure } from '../shared/server.Cqk3swxs.mjs';
|
|
3
3
|
import '@orpc/client';
|
|
4
4
|
import '@orpc/contract';
|
|
5
5
|
import '@orpc/shared';
|
package/dist/index.mjs
CHANGED
|
@@ -2,11 +2,11 @@ import { mergeErrorMap, resolveMetaPlugins, getHiddenMetaPlugins, ProcedureContr
|
|
|
2
2
|
export { ValidationError, asyncIteratorObject, defineMeta, error, eventIterator, reconcileORPCError, type } from '@orpc/contract';
|
|
3
3
|
import { toArray, bindMethods, isTypescriptObject, resolveMaybeOptionalOptions } from '@orpc/shared';
|
|
4
4
|
export { AsyncIteratorClass, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, streamToAsyncIteratorObject, streamToAsyncIteratorObject as streamToEventIterator } from '@orpc/shared';
|
|
5
|
-
import { L as Lazy, P as Procedure, c as createProcedureClient } from './shared/server.
|
|
6
|
-
export { u as unlazy } from './shared/server.
|
|
7
|
-
import { D as DecoratedProcedure } from './shared/server.
|
|
8
|
-
import { b as augmentRouter, d as augmentImplementedRouter, e as withHiddenRouterContract, f as createGuardedProcedureLazy, g as getRouter } from './shared/server.
|
|
9
|
-
export { a as DEFAULT_ERROR_STATUS, D as DEFAULT_SUCCESS_STATUS, h as call, c as createContractProcedure, i as getHiddenRouterContract, u as unlazyRouter, j as walkProcedureContractsAsync, w as walkProcedureContractsSync } from './shared/server.
|
|
5
|
+
import { L as Lazy, P as Procedure, c as createProcedureClient } from './shared/server.3Ex_8ISY.mjs';
|
|
6
|
+
export { u as unlazy } from './shared/server.3Ex_8ISY.mjs';
|
|
7
|
+
import { D as DecoratedProcedure } from './shared/server.Cqk3swxs.mjs';
|
|
8
|
+
import { b as augmentRouter, d as augmentImplementedRouter, e as withHiddenRouterContract, f as createGuardedProcedureLazy, g as getRouter } from './shared/server.S8BnCR3a.mjs';
|
|
9
|
+
export { a as DEFAULT_ERROR_STATUS, D as DEFAULT_SUCCESS_STATUS, h as call, c as createContractProcedure, i as getHiddenRouterContract, u as unlazyRouter, j as walkProcedureContractsAsync, w as walkProcedureContractsSync } from './shared/server.S8BnCR3a.mjs';
|
|
10
10
|
import { RECURSIVE_CLIENT_UNWRAP_KEYS } from '@orpc/client';
|
|
11
11
|
export { COMMON_ERROR_STATUS_MAP, ORPCError, RPCJsonSerializer, RPCSerializer, cloneORPCError, isDefinedError, isInferableError, safe, toORPCError } from '@orpc/client';
|
|
12
12
|
export { ErrorEvent, getEventMeta, unwrapEvent, withEventMeta } from '@standardserver/core';
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -151,6 +151,8 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
151
151
|
* secure as unsafe ones such as `POST`. It rejects `GET` requests arriving as top-level
|
|
152
152
|
* navigations initiated cross-site or from outside the browser, the only context where
|
|
153
153
|
* another site can make a browser attach `SameSite=Lax` cookies to a safe-method request.
|
|
154
|
+
* Requests matching no procedure stay unmatched, so they can fall through to whatever
|
|
155
|
+
* serves the rest of the site.
|
|
154
156
|
*
|
|
155
157
|
* @remarks
|
|
156
158
|
* **Note**: Requests browsers send without `SameSite=Lax` cookies, such as cross-site `fetch`
|
|
@@ -162,8 +164,6 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
162
164
|
*/
|
|
163
165
|
declare class GetMethodCsrfProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
164
166
|
name: string;
|
|
165
|
-
/** Judge the real request, before batch splits it into client-authored sub-requests. */
|
|
166
|
-
after: string[];
|
|
167
167
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
168
168
|
private isAllowed;
|
|
169
169
|
}
|
|
@@ -204,6 +204,30 @@ declare class MethodOverrideHandlerPlugin<T extends Context> implements Standard
|
|
|
204
204
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Rejects requests whose decoded input contains prototype-polluting keys: an own
|
|
209
|
+
* `__proto__` key, or an own `constructor` key holding a `prototype` key. oRPC's own
|
|
210
|
+
* decoding never assigns through the prototype chain, so this plugin exists to stop such
|
|
211
|
+
* keys from reaching application code that merges, clones, or path-sets input with a
|
|
212
|
+
* library vulnerable to prototype pollution. An `AsyncIteratorObject` input is checked
|
|
213
|
+
* value by value as it arrives, and a polluting value fails that iteration instead.
|
|
214
|
+
*
|
|
215
|
+
* @see {@link https://orpc.dev/docs/plugins/prototype-pollution-protection | Prototype Pollution Protection Plugin}
|
|
216
|
+
*/
|
|
217
|
+
declare class PrototypePollutionProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
218
|
+
name: string;
|
|
219
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
220
|
+
private rejectPollutingInput;
|
|
221
|
+
/**
|
|
222
|
+
* Walks the containers the built-in codecs can produce: arrays, maps, sets, and plain
|
|
223
|
+
* objects, including null-prototype ones. Other objects, such as files and dates, carry
|
|
224
|
+
* no attacker-authored keys and are left alone. The walk is iterative, so input nested
|
|
225
|
+
* deeper than the call stack allows still gets the intended verdict instead of a
|
|
226
|
+
* `RangeError`.
|
|
227
|
+
*/
|
|
228
|
+
private containsPollutingKey;
|
|
229
|
+
}
|
|
230
|
+
|
|
207
231
|
/**
|
|
208
232
|
* Decompresses incoming request bodies based on the Content-Encoding header,
|
|
209
233
|
* supporting gzip, deflate, and deflate-raw.
|
|
@@ -241,7 +265,7 @@ declare class RequestHeadersHandlerPlugin<T extends RequestHeadersHandlerPluginC
|
|
|
241
265
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
242
266
|
}
|
|
243
267
|
|
|
244
|
-
interface ResponseCompressionHandlerPluginOptions<
|
|
268
|
+
interface ResponseCompressionHandlerPluginOptions<T extends Context> {
|
|
245
269
|
/**
|
|
246
270
|
* The compression schemes to use for response compression.
|
|
247
271
|
* Schemes are prioritized by their order in this array and
|
|
@@ -258,6 +282,14 @@ interface ResponseCompressionHandlerPluginOptions<_T extends Context> {
|
|
|
258
282
|
* @default 1024 (1KB)
|
|
259
283
|
*/
|
|
260
284
|
threshold?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Determines whether a response with the given Content-Type should be compressed.
|
|
287
|
+
* Only consulted for binary transfers (streams, files, and file form-data parts).
|
|
288
|
+
* Also receives the routing interceptor options for per-request decisions.
|
|
289
|
+
*
|
|
290
|
+
* @default isCompressibleContentType (covers common text-based formats)
|
|
291
|
+
*/
|
|
292
|
+
isCompressibleContentType?: (contentType: string | null | undefined, options: StandardHandlerRoutingInterceptorOptions<T>) => boolean;
|
|
261
293
|
}
|
|
262
294
|
/**
|
|
263
295
|
* Compresses response bodies based on the client's Accept-Encoding header.
|
|
@@ -274,6 +306,7 @@ declare class ResponseCompressionHandlerPlugin<T extends Context> implements Sta
|
|
|
274
306
|
after: string[];
|
|
275
307
|
private readonly encodings;
|
|
276
308
|
private readonly threshold;
|
|
309
|
+
private readonly isCompressibleContentType;
|
|
277
310
|
constructor(options?: ResponseCompressionHandlerPluginOptions<T>);
|
|
278
311
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
279
312
|
}
|
|
@@ -371,5 +404,5 @@ declare class TimeoutHandlerPlugin<T extends Context> implements StandardHandler
|
|
|
371
404
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
372
405
|
}
|
|
373
406
|
|
|
374
|
-
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
407
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, PrototypePollutionProtectionHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
375
408
|
export type { BatchHandlerPluginOptions, CORSHandlerPluginOptions, MethodOverrideHandlerPluginOptions, RequestHeadersHandlerPluginContext, RequestHeadersHandlerPluginContext as RequestHeadersPluginContext, ResponseCompressionHandlerPluginOptions, ResponseHeadersHandlerPluginContext, ResponseHeadersHandlerPluginContext as ResponseHeadersPluginContext, RethrowHandlerPluginOptions, TimeoutHandlerPluginOptions };
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -151,6 +151,8 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
151
151
|
* secure as unsafe ones such as `POST`. It rejects `GET` requests arriving as top-level
|
|
152
152
|
* navigations initiated cross-site or from outside the browser, the only context where
|
|
153
153
|
* another site can make a browser attach `SameSite=Lax` cookies to a safe-method request.
|
|
154
|
+
* Requests matching no procedure stay unmatched, so they can fall through to whatever
|
|
155
|
+
* serves the rest of the site.
|
|
154
156
|
*
|
|
155
157
|
* @remarks
|
|
156
158
|
* **Note**: Requests browsers send without `SameSite=Lax` cookies, such as cross-site `fetch`
|
|
@@ -162,8 +164,6 @@ declare class CORSHandlerPlugin<T extends Context> implements StandardHandlerPlu
|
|
|
162
164
|
*/
|
|
163
165
|
declare class GetMethodCsrfProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
164
166
|
name: string;
|
|
165
|
-
/** Judge the real request, before batch splits it into client-authored sub-requests. */
|
|
166
|
-
after: string[];
|
|
167
167
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
168
168
|
private isAllowed;
|
|
169
169
|
}
|
|
@@ -204,6 +204,30 @@ declare class MethodOverrideHandlerPlugin<T extends Context> implements Standard
|
|
|
204
204
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Rejects requests whose decoded input contains prototype-polluting keys: an own
|
|
209
|
+
* `__proto__` key, or an own `constructor` key holding a `prototype` key. oRPC's own
|
|
210
|
+
* decoding never assigns through the prototype chain, so this plugin exists to stop such
|
|
211
|
+
* keys from reaching application code that merges, clones, or path-sets input with a
|
|
212
|
+
* library vulnerable to prototype pollution. An `AsyncIteratorObject` input is checked
|
|
213
|
+
* value by value as it arrives, and a polluting value fails that iteration instead.
|
|
214
|
+
*
|
|
215
|
+
* @see {@link https://orpc.dev/docs/plugins/prototype-pollution-protection | Prototype Pollution Protection Plugin}
|
|
216
|
+
*/
|
|
217
|
+
declare class PrototypePollutionProtectionHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
218
|
+
name: string;
|
|
219
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
220
|
+
private rejectPollutingInput;
|
|
221
|
+
/**
|
|
222
|
+
* Walks the containers the built-in codecs can produce: arrays, maps, sets, and plain
|
|
223
|
+
* objects, including null-prototype ones. Other objects, such as files and dates, carry
|
|
224
|
+
* no attacker-authored keys and are left alone. The walk is iterative, so input nested
|
|
225
|
+
* deeper than the call stack allows still gets the intended verdict instead of a
|
|
226
|
+
* `RangeError`.
|
|
227
|
+
*/
|
|
228
|
+
private containsPollutingKey;
|
|
229
|
+
}
|
|
230
|
+
|
|
207
231
|
/**
|
|
208
232
|
* Decompresses incoming request bodies based on the Content-Encoding header,
|
|
209
233
|
* supporting gzip, deflate, and deflate-raw.
|
|
@@ -241,7 +265,7 @@ declare class RequestHeadersHandlerPlugin<T extends RequestHeadersHandlerPluginC
|
|
|
241
265
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
242
266
|
}
|
|
243
267
|
|
|
244
|
-
interface ResponseCompressionHandlerPluginOptions<
|
|
268
|
+
interface ResponseCompressionHandlerPluginOptions<T extends Context> {
|
|
245
269
|
/**
|
|
246
270
|
* The compression schemes to use for response compression.
|
|
247
271
|
* Schemes are prioritized by their order in this array and
|
|
@@ -258,6 +282,14 @@ interface ResponseCompressionHandlerPluginOptions<_T extends Context> {
|
|
|
258
282
|
* @default 1024 (1KB)
|
|
259
283
|
*/
|
|
260
284
|
threshold?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Determines whether a response with the given Content-Type should be compressed.
|
|
287
|
+
* Only consulted for binary transfers (streams, files, and file form-data parts).
|
|
288
|
+
* Also receives the routing interceptor options for per-request decisions.
|
|
289
|
+
*
|
|
290
|
+
* @default isCompressibleContentType (covers common text-based formats)
|
|
291
|
+
*/
|
|
292
|
+
isCompressibleContentType?: (contentType: string | null | undefined, options: StandardHandlerRoutingInterceptorOptions<T>) => boolean;
|
|
261
293
|
}
|
|
262
294
|
/**
|
|
263
295
|
* Compresses response bodies based on the client's Accept-Encoding header.
|
|
@@ -274,6 +306,7 @@ declare class ResponseCompressionHandlerPlugin<T extends Context> implements Sta
|
|
|
274
306
|
after: string[];
|
|
275
307
|
private readonly encodings;
|
|
276
308
|
private readonly threshold;
|
|
309
|
+
private readonly isCompressibleContentType;
|
|
277
310
|
constructor(options?: ResponseCompressionHandlerPluginOptions<T>);
|
|
278
311
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
279
312
|
}
|
|
@@ -371,5 +404,5 @@ declare class TimeoutHandlerPlugin<T extends Context> implements StandardHandler
|
|
|
371
404
|
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
372
405
|
}
|
|
373
406
|
|
|
374
|
-
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
407
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, PrototypePollutionProtectionHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
375
408
|
export type { BatchHandlerPluginOptions, CORSHandlerPluginOptions, MethodOverrideHandlerPluginOptions, RequestHeadersHandlerPluginContext, RequestHeadersHandlerPluginContext as RequestHeadersPluginContext, ResponseCompressionHandlerPluginOptions, ResponseHeadersHandlerPluginContext, ResponseHeadersHandlerPluginContext as ResponseHeadersPluginContext, RethrowHandlerPluginOptions, TimeoutHandlerPluginOptions };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { toArray, value,
|
|
1
|
+
import { toArray, value, isPlainObject, isTypescriptObject, isAsyncIteratorObject, override, wrapAsyncIterator, isCompressibleContentType, isNoTransformCacheControl, parseAcceptEncodingQualities, varyByAcceptEncoding, stringifyJSON, anyAbortSignal, wrapReadableStream, AbortError } from '@orpc/shared';
|
|
2
2
|
import { flattenStandardHeader, parseStandardUrl, generateContentDisposition, mergeStandardHeaders } from '@standardserver/core';
|
|
3
3
|
import { isClientPeerSendMessage, ServerPeer, encodePeerMessage } from '@standardserver/peer';
|
|
4
|
+
import { ORPCError } from '@orpc/client';
|
|
4
5
|
import { toFetchHeaders, toStandardBody, toStandardHeaders } from '@standardserver/fetch';
|
|
5
6
|
export { R as RequestLimitHandlerPlugin } from '../shared/server.Cd4Z1hpV.mjs';
|
|
6
|
-
import '@orpc/client';
|
|
7
7
|
|
|
8
8
|
const BATCH_CONTENT_TYPE = "application/vnd.orpc.batch";
|
|
9
9
|
class BatchHandlerPlugin {
|
|
@@ -299,21 +299,16 @@ class CORSHandlerPlugin {
|
|
|
299
299
|
|
|
300
300
|
class GetMethodCsrfProtectionHandlerPlugin {
|
|
301
301
|
name = "~get-method-csrf-protection";
|
|
302
|
-
/** Judge the real request, before batch splits it into client-authored sub-requests. */
|
|
303
|
-
after = ["~batch"];
|
|
304
302
|
init(options) {
|
|
305
|
-
const
|
|
303
|
+
const interceptor = (interceptorOptions) => {
|
|
306
304
|
if (this.isAllowed(interceptorOptions)) {
|
|
307
305
|
return interceptorOptions.next();
|
|
308
306
|
}
|
|
309
|
-
|
|
310
|
-
matched: true,
|
|
311
|
-
response: { status: 403, headers: {}, body: "Request blocked by CSRF protection." }
|
|
312
|
-
});
|
|
307
|
+
throw new ORPCError("FORBIDDEN", { message: "Request blocked by CSRF protection." });
|
|
313
308
|
};
|
|
314
309
|
return {
|
|
315
310
|
...options,
|
|
316
|
-
|
|
311
|
+
interceptors: [interceptor, ...toArray(options.interceptors)]
|
|
317
312
|
};
|
|
318
313
|
}
|
|
319
314
|
isAllowed({ request }) {
|
|
@@ -375,6 +370,78 @@ class MethodOverrideHandlerPlugin {
|
|
|
375
370
|
}
|
|
376
371
|
}
|
|
377
372
|
|
|
373
|
+
class PrototypePollutionProtectionHandlerPlugin {
|
|
374
|
+
name = "~prototype-pollution-protection";
|
|
375
|
+
init(options) {
|
|
376
|
+
const interceptor = (interceptorOptions) => {
|
|
377
|
+
const input = interceptorOptions.input;
|
|
378
|
+
if (isAsyncIteratorObject(input)) {
|
|
379
|
+
const guardedInput = override(input, wrapAsyncIterator(input, {
|
|
380
|
+
mapResult: (result) => {
|
|
381
|
+
this.rejectPollutingInput(result.value);
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
}));
|
|
385
|
+
return interceptorOptions.next({ ...interceptorOptions, input: guardedInput });
|
|
386
|
+
}
|
|
387
|
+
this.rejectPollutingInput(input);
|
|
388
|
+
return interceptorOptions.next();
|
|
389
|
+
};
|
|
390
|
+
return {
|
|
391
|
+
...options,
|
|
392
|
+
clientInterceptors: [interceptor, ...toArray(options.clientInterceptors)]
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
rejectPollutingInput(input) {
|
|
396
|
+
if (this.containsPollutingKey(input)) {
|
|
397
|
+
throw new ORPCError("BAD_REQUEST", { message: "Request blocked by prototype pollution protection." });
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Walks the containers the built-in codecs can produce: arrays, maps, sets, and plain
|
|
402
|
+
* objects, including null-prototype ones. Other objects, such as files and dates, carry
|
|
403
|
+
* no attacker-authored keys and are left alone. The walk is iterative, so input nested
|
|
404
|
+
* deeper than the call stack allows still gets the intended verdict instead of a
|
|
405
|
+
* `RangeError`.
|
|
406
|
+
*/
|
|
407
|
+
containsPollutingKey(root) {
|
|
408
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
409
|
+
const stack = [root];
|
|
410
|
+
while (stack.length !== 0) {
|
|
411
|
+
const value = stack.pop();
|
|
412
|
+
if (typeof value !== "object" || value === null || visited.has(value)) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
visited.add(value);
|
|
416
|
+
if (Array.isArray(value)) {
|
|
417
|
+
for (const item of value) {
|
|
418
|
+
stack.push(item);
|
|
419
|
+
}
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (value instanceof Map || value instanceof Set) {
|
|
423
|
+
for (const entry of value) {
|
|
424
|
+
stack.push(entry);
|
|
425
|
+
}
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (!isPlainObject(value)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (Object.hasOwn(value, "__proto__")) {
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
if (Object.hasOwn(value, "constructor") && isTypescriptObject(value.constructor) && Object.hasOwn(value.constructor, "prototype")) {
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
for (const key of Object.keys(value)) {
|
|
438
|
+
stack.push(value[key]);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
378
445
|
class RequestCompressionHandlerPlugin {
|
|
379
446
|
name = "~request-compression";
|
|
380
447
|
/**
|
|
@@ -470,9 +537,11 @@ class ResponseCompressionHandlerPlugin {
|
|
|
470
537
|
after = ["~batch", "~response-headers"];
|
|
471
538
|
encodings;
|
|
472
539
|
threshold;
|
|
540
|
+
isCompressibleContentType;
|
|
473
541
|
constructor(options = {}) {
|
|
474
542
|
this.encodings = options.encodings ?? ["gzip", "deflate"];
|
|
475
543
|
this.threshold = options.threshold ?? 1024;
|
|
544
|
+
this.isCompressibleContentType = options.isCompressibleContentType ?? isCompressibleContentType;
|
|
476
545
|
}
|
|
477
546
|
init(options) {
|
|
478
547
|
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
@@ -502,7 +571,7 @@ class ResponseCompressionHandlerPlugin {
|
|
|
502
571
|
const headers = response.headers;
|
|
503
572
|
if (body instanceof ReadableStream) {
|
|
504
573
|
const contentLength = Number(flattenStandardHeader(headers["content-length"]));
|
|
505
|
-
if ((!Number.isFinite(contentLength) || contentLength >= this.threshold) && isCompressibleContentType(flattenStandardHeader(headers["content-type"]))) {
|
|
574
|
+
if ((!Number.isFinite(contentLength) || contentLength >= this.threshold) && this.isCompressibleContentType(flattenStandardHeader(headers["content-type"]), interceptorOptions)) {
|
|
506
575
|
return {
|
|
507
576
|
...result,
|
|
508
577
|
response: {
|
|
@@ -519,7 +588,7 @@ class ResponseCompressionHandlerPlugin {
|
|
|
519
588
|
};
|
|
520
589
|
}
|
|
521
590
|
} else if (body instanceof Blob) {
|
|
522
|
-
if ((!Number.isFinite(body.size) || body.size >= this.threshold) && isCompressibleContentType(body.type)) {
|
|
591
|
+
if ((!Number.isFinite(body.size) || body.size >= this.threshold) && this.isCompressibleContentType(body.type, interceptorOptions)) {
|
|
523
592
|
const contentDisposition = headers["content-disposition"] ?? generateContentDisposition(
|
|
524
593
|
body instanceof File ? body.name : "blob"
|
|
525
594
|
);
|
|
@@ -547,13 +616,13 @@ class ResponseCompressionHandlerPlugin {
|
|
|
547
616
|
contentLength += PART_OVERHEAD + key.length;
|
|
548
617
|
if (value instanceof Blob) {
|
|
549
618
|
if (!Number.isFinite(value.size)) {
|
|
550
|
-
if (!isCompressibleContentType(value.type)) {
|
|
619
|
+
if (!this.isCompressibleContentType(value.type, interceptorOptions)) {
|
|
551
620
|
contentLength = -Infinity;
|
|
552
621
|
break;
|
|
553
622
|
}
|
|
554
623
|
contentLength = Infinity;
|
|
555
624
|
} else {
|
|
556
|
-
contentLength += isCompressibleContentType(value.type) ? value.size : -value.size;
|
|
625
|
+
contentLength += this.isCompressibleContentType(value.type, interceptorOptions) ? value.size : -value.size;
|
|
557
626
|
}
|
|
558
627
|
} else {
|
|
559
628
|
contentLength += value.length * AVG_BYTES_PER_CHAR;
|
|
@@ -766,4 +835,4 @@ class TimeoutHandlerPlugin {
|
|
|
766
835
|
}
|
|
767
836
|
}
|
|
768
837
|
|
|
769
|
-
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
838
|
+
export { BATCH_CONTENT_TYPE, BatchHandlerPlugin, CORSHandlerPlugin, CORSHandlerPlugin as CORSPlugin, GetMethodCsrfProtectionHandlerPlugin, MethodOverrideHandlerPlugin, PrototypePollutionProtectionHandlerPlugin, RequestCompressionHandlerPlugin, RequestHeadersHandlerPlugin, RequestHeadersHandlerPlugin as RequestHeadersPlugin, ResponseCompressionHandlerPlugin, ResponseHeadersHandlerPlugin, ResponseHeadersHandlerPlugin as ResponseHeadersPlugin, RethrowHandlerPlugin, TimeoutHandlerPlugin };
|
|
@@ -123,6 +123,7 @@ async function executeProcedureInternal(procedure, options) {
|
|
|
123
123
|
const orderedMiddlewares = procedure["~orpc"].orderedMiddlewares;
|
|
124
124
|
const next = async (midIndex, context, input) => {
|
|
125
125
|
let currentInput = input;
|
|
126
|
+
let middlewareInput = input;
|
|
126
127
|
const startInputIndex = midIndex === 0 ? 0 : orderedMiddlewares[midIndex - 1].inputSchemasLengthAtUse ?? 0;
|
|
127
128
|
const endInputIndex = midIndex === orderedMiddlewares.length ? inputSchemas.length : orderedMiddlewares[midIndex].inputSchemasLengthAtUse ?? 0;
|
|
128
129
|
if (!procedure["~orpc"].disableInputValidation) {
|
|
@@ -134,6 +135,7 @@ async function executeProcedureInternal(procedure, options) {
|
|
|
134
135
|
);
|
|
135
136
|
currentInput = i !== 0 ? mergeTwoLevels(currentInput, validated) : validated;
|
|
136
137
|
}
|
|
138
|
+
middlewareInput = endInputIndex > 0 && endInputIndex < inputSchemas.length ? mergeTwoLevels(options.input, currentInput) : currentInput;
|
|
137
139
|
}
|
|
138
140
|
let currentOutput;
|
|
139
141
|
let currentContext = context;
|
|
@@ -156,7 +158,7 @@ async function executeProcedureInternal(procedure, options) {
|
|
|
156
158
|
},
|
|
157
159
|
lastEventId: options.lastEventId
|
|
158
160
|
},
|
|
159
|
-
|
|
161
|
+
middlewareInput,
|
|
160
162
|
middlewareDone
|
|
161
163
|
);
|
|
162
164
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ORPCError, toORPCError, RPCSerializer, COMMON_ERROR_STATUS_MAP } from '@orpc/client';
|
|
2
2
|
import { sortPlugins, getOpenTelemetryConfig, runWithSpan, toArray, matchesHttpPathPrefix, intercept, ORPC_NAME, isAsyncIteratorObject, override, traceAsyncIterator, recordSpanError, pathToHttpPath, normalizeHttpPath, value, parseEmptyableJSON, getOwn } from '@orpc/shared';
|
|
3
3
|
import { flattenStandardHeader, parseStandardUrl } from '@standardserver/core';
|
|
4
|
-
import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.
|
|
5
|
-
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.
|
|
4
|
+
import { c as createProcedureClient, u as unlazy, P as Procedure } from './server.3Ex_8ISY.mjs';
|
|
5
|
+
import { w as walkProcedureContractsSync, g as getRouter, c as createContractProcedure, D as DEFAULT_SUCCESS_STATUS, a as DEFAULT_ERROR_STATUS } from './server.S8BnCR3a.mjs';
|
|
6
6
|
|
|
7
7
|
class CompositeStandardHandlerPlugin {
|
|
8
8
|
name = "~composite";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveMetaPlugins, mergeErrorMap, getHiddenMetaPlugins } from '@orpc/contract';
|
|
2
|
-
import { P as Procedure } from './server.
|
|
2
|
+
import { P as Procedure } from './server.3Ex_8ISY.mjs';
|
|
3
3
|
|
|
4
4
|
class DecoratedProcedure extends Procedure {
|
|
5
5
|
meta(...plugins) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.
|
|
1
|
+
import { c as createProcedureClient, P as Procedure, L as Lazy, u as unlazy } from './server.3Ex_8ISY.mjs';
|
|
2
2
|
import { resolveMetaPlugins, mergeErrorMap, ProcedureContract } from '@orpc/contract';
|
|
3
3
|
import { omit, isTypescriptObject } from '@orpc/shared';
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.33",
|
|
5
5
|
"description": "Build typesafe APIs with oRPC: RPC and OpenAPI support, middleware, and adapters for Node.js, Bun, Deno, Fetch, Fastify, WebSocket, AWS Lambda, and more",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": [
|
|
@@ -117,25 +117,24 @@
|
|
|
117
117
|
}
|
|
118
118
|
},
|
|
119
119
|
"dependencies": {
|
|
120
|
-
"@
|
|
121
|
-
"@
|
|
122
|
-
"@
|
|
123
|
-
"@standardserver/
|
|
124
|
-
"@standardserver/
|
|
125
|
-
"@standardserver/
|
|
126
|
-
"
|
|
127
|
-
"@
|
|
128
|
-
"@
|
|
129
|
-
"
|
|
120
|
+
"@orpc/client": "2.0.0-beta.33",
|
|
121
|
+
"@orpc/contract": "2.0.0-beta.33",
|
|
122
|
+
"@orpc/shared": "2.0.0-beta.33",
|
|
123
|
+
"@standardserver/aws-lambda": "^0.8.3",
|
|
124
|
+
"@standardserver/core": "^0.8.3",
|
|
125
|
+
"@standardserver/fastify": "^0.8.3",
|
|
126
|
+
"@standardserver/fetch": "^0.8.3",
|
|
127
|
+
"@standardserver/node": "^0.8.3",
|
|
128
|
+
"@standardserver/peer": "^0.8.3",
|
|
129
|
+
"cookie": "^2.0.1"
|
|
130
130
|
},
|
|
131
131
|
"devDependencies": {
|
|
132
132
|
"crossws": "^0.4.6",
|
|
133
133
|
"fastify": "^5.12.1",
|
|
134
134
|
"supertest": "^7.2.2",
|
|
135
|
-
"zod": "^4.4
|
|
135
|
+
"zod": "^4.5.4"
|
|
136
136
|
},
|
|
137
137
|
"scripts": {
|
|
138
|
-
"build": "unbuild",
|
|
139
138
|
"type:check": "tsc -b"
|
|
140
139
|
}
|
|
141
140
|
}
|