@orpc/tanstack-query 2.0.0-beta.2 → 2.0.0-beta.20

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 CHANGED
@@ -7,6 +7,9 @@
7
7
  <a href="https://www.npmjs.com/package/@orpc/tanstack-query">
8
8
  <img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Ftanstack-query?logo=npm" />
9
9
  </a>
10
+ <a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
11
+ <img alt="CodSpeed" src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" />
12
+ </a>
10
13
  <a href="https://github.com/middleapi/orpc/blob/main/LICENSE">
11
14
  <img alt="MIT License" src="https://img.shields.io/github/license/middleapi/orpc?logo=open-source-initiative" />
12
15
  </a>
@@ -26,10 +29,10 @@ You can read the documentation [here](https://orpc.dev).
26
29
 
27
30
  **Core**
28
31
 
29
- - [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Define type-safe contracts for your API.
30
- - [@orpc/server](https://www.npmjs.com/package/@orpc/server): Implement your API or contract on the server.
31
- - [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API from the client with full type safety.
32
- - [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Bring OpenAPI compatibility to your APIs.
32
+ - [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Define API contract as the single source of truth.
33
+ - [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build APIs or implement contracts.
34
+ - [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume APIs with end-to-end type safety.
35
+ - [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Add OpenAPI compatibility to APIs.
33
36
 
34
37
  **Schema validation**
35
38
 
@@ -37,23 +40,30 @@ You can read the documentation [here](https://orpc.dev).
37
40
  - [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): Integrate with [Valibot](https://valibot.dev/).
38
41
  - [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): Integrate with [ArkType](https://arktype.io/).
39
42
 
43
+ **Built-in features**
44
+
45
+ - [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher): Pub/Sub with memory, Redis, and Upstash adapters.
46
+ - [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit): Rate limiting with memory, Redis, and Upstash adapters.
47
+ - [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema): Smart coercion for OpenAPI requests.
48
+
40
49
  **Framework & ecosystem integrations**
41
50
 
42
- - [@orpc/next](https://www.npmjs.com/package/@orpc/react): Use oRPC with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data).
51
+ - [@orpc/next](https://www.npmjs.com/package/@orpc/next): Integrate with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data).
52
+ - [@orpc/ai-sdk](https://www.npmjs.com/package/@orpc/ai-sdk): Turn contracts and procedures into [AI SDK](https://ai-sdk.dev/) tools.
43
53
  - [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): Integrate with [TanStack Query](https://tanstack.com/query/latest).
54
+ - [@orpc/pinia-colada](https://www.npmjs.com/package/@orpc/pinia-colada): Integrate with [Pinia Colada](https://pinia-colada.esm.dev/).
55
+ - [@orpc/swr](https://www.npmjs.com/package/@orpc/swr): Integrate with [SWR](https://swr.vercel.app/).
44
56
  - [@orpc/experimental-effect](https://www.npmjs.com/package/@orpc/experimental-effect): Integrate with [Effect](https://effect.website/).
45
-
46
- **Built-in features**
47
-
48
- - [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher): Pub/Sub.
49
- - [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit): Rate limiting.
50
- - [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema): Smart coercion for OpenAPI requests.
57
+ - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Implement your contract with [NestJS](https://nestjs.com/).
58
+ - [@orpc/bun](https://www.npmjs.com/package/@orpc/bun): Adapters for [Bun's Redis](https://bun.sh/).
59
+ - [@orpc/cloudflare](https://www.npmjs.com/package/@orpc/cloudflare): Adapters for [Cloudflare's RateLimit and Durable Objects](https://developers.cloudflare.com/workers/).
60
+ - [@orpc/trpc](https://www.npmjs.com/package/@orpc/trpc): Reuse existing [tRPC](https://trpc.io/) routers within oRPC.
51
61
 
52
62
  **Observability**
53
63
 
54
- - [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry): Instrument your API with [OpenTelemetry](https://opentelemetry.io/).
55
- - [@orpc/pino](https://www.npmjs.com/package/@orpc/pino): Log with [Pino](https://getpino.io/).
56
- - [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog): Log with [Evlog](https://evlog.dev/).
64
+ - [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry): Integrate with [OpenTelemetry](https://opentelemetry.io/) for distributed tracing.
65
+ - [@orpc/pino](https://www.npmjs.com/package/@orpc/pino): Integrate with [Pino](https://getpino.io/) for logging.
66
+ - [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog): Integrate with [Evlog](https://evlog.dev/) for logging.
57
67
 
58
68
  ## Sponsors
59
69
 
@@ -99,12 +109,10 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
99
109
  <td align="center"><a href="https://github.com/valerii15298?ref=orpc" target="_blank" rel="noopener" title="Valerii Petryniak"><img src="https://avatars.githubusercontent.com/u/44531564?u=88ac74d9bacd20401518441907acad21063cd397&amp;v=4" width="139" alt="Valerii Petryniak"/><br />Valerii Petryniak</a></td>
100
110
  <td align="center"><a href="https://github.com/letstri?ref=orpc" target="_blank" rel="noopener" title="Valerii Strilets"><img src="https://avatars.githubusercontent.com/u/13253748?u=c7b10399ccc8f8081e24db94ec32cd9858e86ac3&amp;v=4" width="139" alt="Valerii Strilets"/><br />Valerii Strilets</a></td>
101
111
  <td align="center"><a href="https://github.com/K-Mistele?ref=orpc" target="_blank" rel="noopener" title="Kyle Mistele"><img src="https://avatars.githubusercontent.com/u/18430555?u=3afebeb81de666e35aaac3ed46f14159d7603ffb&amp;v=4" width="139" alt="Kyle Mistele"/><br />Kyle Mistele</a></td>
102
- <td align="center"><a href="https://github.com/andrewpeters9?ref=orpc" target="_blank" rel="noopener" title="Andrew Peters"><img src="https://avatars.githubusercontent.com/u/36251325?v=4" width="139" alt="Andrew Peters"/><br />Andrew Peters</a></td>
103
112
  <td align="center"><a href="https://github.com/R44VC0RP?ref=orpc" target="_blank" rel="noopener" title="Ryan Vogel"><img src="https://avatars.githubusercontent.com/u/89211796?u=1857347b9787d8d8a7ea5bfc333f96be92d5a683&amp;v=4" width="139" alt="Ryan Vogel"/><br />Ryan Vogel</a></td>
113
+ <td align="center"><a href="https://github.com/christ12938?ref=orpc" target="_blank" rel="noopener" title="christ12938"><img src="https://avatars.githubusercontent.com/u/25758598?v=4" width="139" alt="christ12938"/><br />christ12938</a></td>
104
114
  </tr>
105
115
  <tr>
106
- <td align="center"><a href="https://github.com/christ12938?ref=orpc" target="_blank" rel="noopener" title="christ12938"><img src="https://avatars.githubusercontent.com/u/25758598?v=4" width="139" alt="christ12938"/><br />christ12938</a></td>
107
- <td align="center"><a href="https://github.com/peter-adam-dy?ref=orpc" target="_blank" rel="noopener" title="Peter Adam"><img src="https://avatars.githubusercontent.com/u/132129459?u=4f3dbbb3b443990b56acb7d6a5d11ed2c555f6db&amp;v=4" width="139" alt="Peter Adam"/><br />Peter Adam</a></td>
108
116
  <td align="center"><a href="https://github.com/Ryanjso?ref=orpc" target="_blank" rel="noopener" title="Ryan Soderberg"><img src="https://avatars.githubusercontent.com/u/39172778?u=5ed913c31d57e7221b75784abcad48c7ebddde27&amp;v=4" width="139" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td>
109
117
  <td align="center"><a href="https://github.com/itigoore01?ref=orpc" target="_blank" rel="noopener" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&amp;v=4" width="139" alt="shota"/><br />shota</a></td>
110
118
  </tr>
@@ -115,25 +123,25 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
115
123
  <table>
116
124
  <tr>
117
125
  <td align="center"><a href="https://github.com/rhinodavid?ref=orpc" target="_blank" rel="noopener" title="David Walsh"><img src="https://avatars.githubusercontent.com/u/5778036?u=b5521f07d2f88c3db2a0dae62b5f2f8357214af0&amp;v=4" width="119" alt="David Walsh"/><br />David Walsh</a></td>
126
+ <td align="center"><a href="https://github.com/Nic13Gamer?ref=orpc" target="_blank" rel="noopener" title="Nicholas"><img src="https://avatars.githubusercontent.com/u/54724556?u=56a7ab430ce7a80d648ab6eba051d454a818ed0b&amp;v=4" width="119" alt="Nicholas"/><br />Nicholas</a></td>
118
127
  <td align="center"><a href="https://github.com/Robbe95?ref=orpc" target="_blank" rel="noopener" title="Robbe Vaes"><img src="https://avatars.githubusercontent.com/u/44748019?u=e0232402c045ad4eac7cbd217f1f47e083103b89&amp;v=4" width="119" alt="Robbe Vaes"/><br />Robbe Vaes</a></td>
119
128
  <td align="center"><a href="https://github.com/aidansunbury?ref=orpc" target="_blank" rel="noopener" title="Aidan Sunbury"><img src="https://avatars.githubusercontent.com/u/64103161?v=4" width="119" alt="Aidan Sunbury"/><br />Aidan Sunbury</a></td>
120
129
  <td align="center"><a href="https://github.com/soonoo?ref=orpc" target="_blank" rel="noopener" title="soonoo"><img src="https://avatars.githubusercontent.com/u/5436405?u=5d0b4aa955c87e30e6bda7f0cccae5402da99528&amp;v=4" width="119" alt="soonoo"/><br />soonoo</a></td>
121
130
  <td align="center"><a href="https://github.com/kporten?ref=orpc" target="_blank" rel="noopener" title="Kevin Porten"><img src="https://avatars.githubusercontent.com/u/1839345?u=dc2263d5cfe0d927ce1a0be04a1d55dd6b55405c&amp;v=4" width="119" alt="Kevin Porten"/><br />Kevin Porten</a></td>
122
131
  <td align="center"><a href="https://github.com/pumpkinlink?ref=orpc" target="_blank" rel="noopener" title="Denis"><img src="https://avatars.githubusercontent.com/u/11864620?u=5f47bbe6c65d0f6f5cf011021490238e4b0593d0&amp;v=4" width="119" alt="Denis"/><br />Denis</a></td>
123
- <td align="center"><a href="https://github.com/christopher-kapic?ref=orpc" target="_blank" rel="noopener" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&amp;v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
124
132
  </tr>
125
133
  <tr>
134
+ <td align="center"><a href="https://github.com/christopher-kapic?ref=orpc" target="_blank" rel="noopener" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&amp;v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td>
126
135
  <td align="center"><a href="https://github.com/thomasballinger?ref=orpc" target="_blank" rel="noopener" title="Tom Ballinger"><img src="https://avatars.githubusercontent.com/u/458879?u=4b045ac75d721b6ac2b42a74d7d37f61f0414031&amp;v=4" width="119" alt="Tom Ballinger"/><br />Tom Ballinger</a></td>
127
136
  <td align="center"><a href="https://github.com/SSam0419?ref=orpc" target="_blank" rel="noopener" title="Sam"><img src="https://avatars.githubusercontent.com/u/102863520?u=3c89611f549d5070be232eb4532f690c8f2e7a65&amp;v=4" width="119" alt="Sam"/><br />Sam</a></td>
128
137
  <td align="center"><a href="https://github.com/Titoine?ref=orpc" target="_blank" rel="noopener" title="Titoine"><img src="https://avatars.githubusercontent.com/u/3514286?u=1bb1e86b0c99c8a1121372e56d51a177eea12191&amp;v=4" width="119" alt="Titoine"/><br />Titoine</a></td>
129
138
  <td align="center"><a href="https://github.com/Mnigos?ref=orpc" target="_blank" rel="noopener" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&amp;v=4" width="119" alt="Igor Makowski"/><br />Igor Makowski</a></td>
130
139
  <td align="center"><a href="https://github.com/hanayashiki?ref=orpc" target="_blank" rel="noopener" title="hanayashiki"><img src="https://avatars.githubusercontent.com/u/26056783?u=06c3b9205a16fd41a871e82da1cc2a09306d53f5&amp;v=4" width="119" alt="hanayashiki"/><br />hanayashiki</a></td>
131
140
  <td align="center"><a href="https://github.com/ldub?ref=orpc" target="_blank" rel="noopener" title="Lev Dubinets"><img src="https://avatars.githubusercontent.com/u/3114081?u=f547f5d5012cab54851f1b1ad72d10e537f78fc2&amp;v=4" width="119" alt="Lev Dubinets"/><br />Lev Dubinets</a></td>
132
- <td align="center"><a href="https://github.com/mr-kelly?ref=orpc" target="_blank" rel="noopener" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&amp;v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
133
141
  </tr>
134
142
  <tr>
143
+ <td align="center"><a href="https://github.com/mr-kelly?ref=orpc" target="_blank" rel="noopener" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&amp;v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
135
144
  <td align="center"><a href="https://github.com/piscis?ref=orpc" target="_blank" rel="noopener" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&amp;v=4" width="119" alt="Alex"/><br />Alex</a></td>
136
- <td align="center"><a href="https://github.com/nattstack?ref=orpc" target="_blank" rel="noopener" title="nattstack"><img src="https://avatars.githubusercontent.com/u/31426677?u=fa9dbb8b3e66eb0ea3c88db5dc07f31c8c5418fe&amp;v=4" width="119" alt="nattstack"/><br />nattstack</a></td>
137
145
  <td align="center"><a href="https://github.com/finom?ref=orpc" target="_blank" rel="noopener" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=29e91400dbd4a9c217048a8f59562c4f740498e6&amp;v=4" width="119" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
138
146
  </tr>
139
147
  </table>
@@ -150,7 +158,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
150
158
  <a href="https://github.com/theoludwig?ref=orpc" target="_blank" rel="noopener" title="Théo LUDWIG"><img src="https://avatars.githubusercontent.com/u/25207499?u=a6a9653725a2f574c07893748806668e0598cdbe&amp;v=4" width="32" height="32" alt="Théo LUDWIG" /></a>
151
159
  <a href="https://github.com/abhay-ramesh?ref=orpc" target="_blank" rel="noopener" title="Abhay Ramesh"><img src="https://avatars.githubusercontent.com/u/66196314?u=c5c2b0327b26606c2efcfaf17046ab18c3d25c57&amp;v=4" width="32" height="32" alt="Abhay Ramesh" /></a>
152
160
  <a href="https://github.com/shr-ink?ref=orpc" target="_blank" rel="noopener" title="shr.ink oü"><img src="https://avatars.githubusercontent.com/u/139700438?v=4" width="32" height="32" alt="shr.ink oü" /></a>
153
- <a href="https://github.com/johngerome?ref=orpc" target="_blank" rel="noopener" title="0x4e32"><img src="https://avatars.githubusercontent.com/u/2002000?u=24e8dd943cfc862aa284d858a023532c75071ade&amp;v=4" width="32" height="32" alt="0x4e32" /></a>
161
+ <a href="https://github.com/johngerome?ref=orpc" target="_blank" rel="noopener" title="0x4e32"><img src="https://avatars.githubusercontent.com/u/2002000?u=505e54608466ab53754f702973687b04c6424c1f&amp;v=4" width="32" height="32" alt="0x4e32" /></a>
154
162
  <a href="https://github.com/yzuyr?ref=orpc" target="_blank" rel="noopener" title="Ryuz"><img src="https://avatars.githubusercontent.com/u/196539378?u=d38374588d219b6748b16406982f6559411466d4&amp;v=4" width="32" height="32" alt="Ryuz" /></a>
155
163
  <a href="https://github.com/happyboy2022?ref=orpc" target="_blank" rel="noopener" title="happyboy"><img src="https://avatars.githubusercontent.com/u/103669586?u=65b49c4b893ed3703909fbb3a7a22313f3f9c121&amp;v=4" width="32" height="32" alt="happyboy" /></a>
156
164
  <a href="https://github.com/YiCChi?ref=orpc" target="_blank" rel="noopener" title="yicchi"><img src="https://avatars.githubusercontent.com/u/86967274?u=6c2756f09fe15dd94d572f560e979cd157982852&amp;v=4" width="32" height="32" alt="yicchi" /></a>
@@ -164,7 +172,9 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
164
172
  <a href="https://github.com/nelsonlaidev?ref=orpc" target="_blank" rel="noopener" title="Nelson Lai"><img src="https://avatars.githubusercontent.com/u/75498339?u=2fc0e0b95dd184c5ffb744df977cb15a18b60672&amp;v=4" width="32" height="32" alt="Nelson Lai" /></a>
165
173
  <a href="https://github.com/nguyenlc1993?ref=orpc" target="_blank" rel="noopener" title="Lê Cao Nguyên"><img src="https://avatars.githubusercontent.com/u/13871971?u=83c8b69d9e35b589c4e1f066cc113b1d9461386f&amp;v=4" width="32" height="32" alt="Lê Cao Nguyên" /></a>
166
174
  <a href="https://github.com/wobsoriano?ref=orpc" target="_blank" rel="noopener" title="Robert Soriano"><img src="https://avatars.githubusercontent.com/u/13049130?u=6d72104182e7c9ed25934815313fb69107332111&amp;v=4" width="32" height="32" alt="Robert Soriano" /></a>
175
+ <a href="https://github.com/andrewpeters9?ref=orpc" target="_blank" rel="noopener" title="Andrew Peters"><img src="https://avatars.githubusercontent.com/u/36251325?v=4" width="32" height="32" alt="Andrew Peters" /></a>
167
176
  <a href="https://github.com/SKostyukovich?ref=orpc" target="_blank" rel="noopener" title="SKostyukovich"><img src="https://avatars.githubusercontent.com/u/10700067?v=4" width="32" height="32" alt="SKostyukovich" /></a>
177
+ <a href="https://github.com/peter-adam-dy?ref=orpc" target="_blank" rel="noopener" title="Peter Adam"><img src="https://avatars.githubusercontent.com/u/132129459?u=4f3dbbb3b443990b56acb7d6a5d11ed2c555f6db&amp;v=4" width="32" height="32" alt="Peter Adam" /></a>
168
178
  <a href="https://github.com/FabworksHQ?ref=orpc" target="_blank" rel="noopener" title="Fabworks"><img src="https://avatars.githubusercontent.com/u/160179500?v=4" width="32" height="32" alt="Fabworks" /></a>
169
179
  <a href="https://github.com/NovakAnton?ref=orpc" target="_blank" rel="noopener" title="Novak Antonijevic"><img src="https://avatars.githubusercontent.com/u/157126729?u=ae49fa22292d55c0434ff0ca008206155b18663b&amp;v=4" width="32" height="32" alt="Novak Antonijevic" /></a>
170
180
  <a href="https://github.com/laduniestu?ref=orpc" target="_blank" rel="noopener" title="Laduni Estu Syalwa"><img src="https://avatars.githubusercontent.com/u/44757637?u=a2fc1ea8f7d827a96721176f79d30592d1c48059&amp;v=4" width="32" height="32" alt="Laduni Estu Syalwa" /></a>
@@ -172,6 +182,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
172
182
  <a href="https://github.com/illarionvk?ref=orpc" target="_blank" rel="noopener" title="Illarion Koperski"><img src="https://avatars.githubusercontent.com/u/5012724?u=7cfa13652f7ac5fb3c56d880e3eb3fbe40c3ea34&amp;v=4" width="32" height="32" alt="Illarion Koperski" /></a>
173
183
  <a href="https://github.com/steelbrain?ref=orpc" target="_blank" rel="noopener" title="Anees Iqbal"><img src="https://avatars.githubusercontent.com/u/4278113?u=22b80b5399eed68ac76cd58b02961b0481f1db11&amp;v=4" width="32" height="32" alt="Anees Iqbal" /></a>
174
184
  <a href="https://github.com/Scrumplex?ref=orpc" target="_blank" rel="noopener" title="Sefa Eyeoglu"><img src="https://avatars.githubusercontent.com/u/11587657?u=ab503582165c0bbff0cca47ce31c9450bb1553c9&amp;v=4" width="32" height="32" alt="Sefa Eyeoglu" /></a>
185
+ <a href="https://github.com/nattstack?ref=orpc" target="_blank" rel="noopener" title="natt"><img src="https://avatars.githubusercontent.com/u/31426677?u=fa9dbb8b3e66eb0ea3c88db5dc07f31c8c5418fe&amp;v=4" width="32" height="32" alt="natt" /></a>
175
186
  <a href="https://github.com/ChromeGG?ref=orpc" target="_blank" rel="noopener" title="Adam Tkaczyk"><img src="https://avatars.githubusercontent.com/u/39050595?u=a58ca6042a6950e94e6e92442db76ef584279bc0&amp;v=4" width="32" height="32" alt="Adam Tkaczyk" /></a>
176
187
  <a href="https://github.com/plancraft?ref=orpc" target="_blank" rel="noopener" title="plancraft"><img src="https://avatars.githubusercontent.com/u/46482287?v=4" width="32" height="32" alt="plancraft" /></a>
177
188
  </p>
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { ClientContext, Client, AnyNestedClient, InferClientContext, InferClientError, ThrowableError } from '@orpc/client';
2
- import { AnySchema, ErrorMap, ProcedureContract, InferSchemaInput, InferSchemaOutput, ORPCErrorFromErrorMap, RouterContractClient, RouterContract, ContractCaller } from '@orpc/contract';
3
- import { JsonifiedValue, JsonifiedClientError, JsonifiedClient } from '@orpc/openapi';
4
- import { Promisable, PartialDeep, Interceptor, PromiseWithError, MaybeOptionalOptions, OrderablePlugin, Public } from '@orpc/shared';
1
+ import { ClientContext, Client, AnyNestedClient, InferClientContext, InferClientError } from '@orpc/client';
2
+ import { RouterContract, RouterContractClient, ContractClientFactory, AnySchema, ErrorMap, MetaPlugin, Meta, InferSchemaInput, InferSchemaOutput, ORPCErrorFromErrorMap } from '@orpc/contract';
3
+ import { JsonifiedClient } from '@orpc/openapi';
4
+ import { Promisable, PartialDeep, Interceptor, PromiseWithError, MaybeOptionalOptions, OrderablePlugin, Public, ThrowableError } from '@orpc/shared';
5
5
  import { QueryKey, QueryFunctionContext, QueryFunction, SkipToken, QueryObserverOptions, InfiniteQueryObserverOptions, MutationObserverOptions, DataTag, InfiniteData, MutationFunctionContext } from '@tanstack/query-core';
6
6
 
7
7
  interface SerializableStreamedQueryOptions {
@@ -33,12 +33,6 @@ declare function serializableStreamedQuery<TQueryFnData = unknown, TQueryKey ext
33
33
  type InferStreamedQueryOutput<TOutput> = TOutput extends AsyncIterable<infer U> ? U[] : never;
34
34
  type InferLiveQueryOutput<TOutput> = TOutput extends AsyncIterable<infer U> ? U : never;
35
35
  type OperationType = 'query' | 'streamed' | 'live' | 'infinite' | 'mutation';
36
- type OperationKeyOptions<TType extends OperationType, TInput> = {
37
- type?: TType;
38
- input?: TType extends 'mutation' ? never : PartialDeep<TInput>;
39
- fnOptions?: TType extends 'streamed' ? SerializableStreamedQueryOptions : never;
40
- };
41
- type OperationKey<TType extends OperationType, TInput> = [path: string[], options: OperationKeyOptions<TType, TInput>];
42
36
  declare const OPERATION_CONTEXT_SYMBOL: unique symbol;
43
37
  interface OperationContext {
44
38
  [OPERATION_CONTEXT_SYMBOL]?: {
@@ -108,6 +102,31 @@ type MutationOptionsIn<TClientContext extends ClientContext, TInput, TOutput, TE
108
102
  }) & MutationOptionsOut<TInput, TOutput, TError, TMutationContext>;
109
103
  type MutationOptionsOut<TInput, TOutput, TError, TMutationContext> = MutationObserverOptions<TOutput, TError, TInput, TMutationContext>;
110
104
 
105
+ interface OperationKeyPrefixOptions {
106
+ /**
107
+ * Prepended as the first element of the key when present.
108
+ * Use this to avoid key conflicts when multiple router utils share the same client.
109
+ */
110
+ prefix?: string;
111
+ }
112
+ type OperationKeyOptions<TType extends OperationType, TInput> = OperationKeyPrefixOptions & {
113
+ type?: TType;
114
+ input?: TType extends 'mutation' ? never : PartialDeep<TInput>;
115
+ fnOptions?: TType extends 'streamed' ? SerializableStreamedQueryOptions : never;
116
+ };
117
+ type OperationKey<TType extends OperationType, TInput> = [path: string[], options: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>] | [prefix: string, path: string[], options: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>];
118
+ declare function generateOperationKey<TType extends OperationType, TInput>(path: string[], options?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
119
+
120
+ declare class SharedUtils<TInput> {
121
+ protected readonly path: string[];
122
+ protected readonly options: OperationKeyPrefixOptions;
123
+ constructor(path: string[], options: OperationKeyPrefixOptions);
124
+ /**
125
+ * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
126
+ */
127
+ key<TType extends OperationType>(options?: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>): OperationKey<TType, TInput>;
128
+ }
129
+
111
130
  interface ProcedureUtilsQueryInterceptorOptions<TClientContext extends ClientContext, TInput> {
112
131
  path: string[];
113
132
  context: TClientContext & OperationContext;
@@ -135,7 +154,7 @@ type ProcedureUtilsMutationInterceptor<TClientContext extends ClientContext, TIn
135
154
  * or a function that receives per-call options and returns overridden this.options.
136
155
  */
137
156
  type ProcedureUtilsModifier<T extends object> = Partial<T> | ((options: T) => T);
138
- interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError> {
157
+ interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError> extends OperationKeyPrefixOptions {
139
158
  /**
140
159
  * Key options modifier for .queryKey and .queryOptions
141
160
  * Can be partial options or a function that receives per-call options and returns override this.options.
@@ -207,9 +226,17 @@ interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TO
207
226
  */
208
227
  mutationOptions?: ProcedureUtilsModifier<MutationOptionsIn<TClientContext, TInput, TOutput, TError, unknown>>;
209
228
  }
210
- declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutput, TError> {
211
- private readonly path;
212
- private readonly options;
229
+ declare function isProcedureUtilsOptions(value: unknown): value is ProcedureUtilsOptions<any, any, any, any>;
230
+ /**
231
+ * Merge two procedure utils options where `override` takes priority.
232
+ * A key explicitly set to `undefined` in `override` resets the base value.
233
+ * When both sides define a key: interceptors are concatenated (base ones run first),
234
+ * modifiers are spread-merged when both are plain objects and composed (base applied
235
+ * first) otherwise, with plain objects applied as regular spread merges.
236
+ */
237
+ declare function mergeProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError>(base: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>, override: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>): ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>;
238
+ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutput, TError> extends SharedUtils<TInput> {
239
+ protected readonly options: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>;
213
240
  /**
214
241
  * Calling corresponding procedure client
215
242
  */
@@ -228,7 +255,7 @@ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutp
228
255
  */
229
256
  streamedKey(...rest: MaybeOptionalOptions<StreamedKeyOptions<TInput>>): DataTag<QueryKey, InferStreamedQueryOutput<TOutput>, TError>;
230
257
  /**
231
- * Configure queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
258
+ * Configure queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
232
259
  * This is built on [TanStack Query streamedQuery](https://tanstack.com/query/latest/docs/reference/streamedQuery)
233
260
  * and works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
234
261
  */
@@ -238,7 +265,7 @@ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutp
238
265
  */
239
266
  liveKey(...rest: MaybeOptionalOptions<QueryKeyOptions<TInput>>): DataTag<QueryKey, InferLiveQueryOutput<TOutput>, TError>;
240
267
  /**
241
- * Configure live queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
268
+ * Configure live queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
242
269
  * Unlike `.streamedOptions` which accumulates chunks, live queries replace the entire result with each new chunk received.
243
270
  * Works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
244
271
  */
@@ -296,25 +323,25 @@ interface RouterUtilsPlugin<T extends AnyNestedClient> extends OrderablePlugin {
296
323
  */
297
324
  initProcedureOptions?(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
298
325
  }
299
-
300
- declare class SharedRouterUtils<TInput> {
301
- private readonly path;
302
- constructor(path: string[]);
303
- /**
304
- * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
305
- */
306
- key<TType extends OperationType>(options?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
326
+ declare class CompositeRouterUtilsPlugin<T extends AnyNestedClient> implements RouterUtilsPlugin<T> {
327
+ protected readonly plugins: RouterUtilsPlugin<T>[];
328
+ readonly name = "~composite";
329
+ constructor(plugins?: RouterUtilsPlugin<T>[]);
330
+ init(options: RouterUtilsOptions<T>): RouterUtilsOptions<T>;
331
+ initProcedureOptions(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
307
332
  }
308
- type RouterUtils<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Public<ProcedureUtils<UClientContext, UInput, UOutput, UError>> & Public<SharedRouterUtils<UInput>> : {
333
+
334
+ type RouterUtils<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Public<ProcedureUtils<UClientContext, UInput, UOutput, UError>> : {
309
335
  [K in keyof T]: T[K] extends AnyNestedClient ? RouterUtils<T[K]> : never;
310
- } & Public<SharedRouterUtils<unknown>>;
336
+ } & Public<SharedUtils<unknown>>;
311
337
  type RouterUtilsScoped<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? ProcedureUtilsOptions<UClientContext, UInput, UOutput, UError> : {
312
338
  [K in keyof T]?: T[K] extends AnyNestedClient ? RouterUtilsScoped<T[K]> : never;
313
339
  };
314
- interface RouterUtilsOptions<T extends AnyNestedClient> {
340
+ interface RouterUtilsOptions<T extends AnyNestedClient> extends OperationKeyPrefixOptions {
315
341
  /**
316
- * Base path for all query keys. Use this to avoid conflicts when mounting
317
- * multiple router utils instances.
342
+ * Base path for all query keys.
343
+ *
344
+ * @internal
318
345
  */
319
346
  path?: string[] | undefined;
320
347
  /**
@@ -356,19 +383,54 @@ interface RouterUtilsOptions<T extends AnyNestedClient> {
356
383
  declare function createRouterUtils<T extends AnyNestedClient>(client: T, options?: NoInfer<RouterUtilsOptions<T>>): RouterUtils<T>;
357
384
 
358
385
  interface ContractUtilsFactory<TClientContext extends ClientContext> {
359
- <TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(procedure: ProcedureContract<TInputSchema, TOutputSchema, TErrorMap>): Public<SharedRouterUtils<InferSchemaInput<TInputSchema>>> & Public<ProcedureUtils<TClientContext, InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>>;
386
+ <T extends RouterContract>(contract: T): RouterUtils<RouterContractClient<T, TClientContext>>;
360
387
  }
361
- interface ContractUtilsFactoryOptions<TClientContext extends ClientContext> extends RouterUtilsOptions<RouterContractClient<RouterContract, TClientContext>> {
388
+ interface ContractUtilsFactoryOptions<TClientContext extends ClientContext> extends Omit<RouterUtilsOptions<RouterContractClient<RouterContract, TClientContext>>, 'path'> {
362
389
  }
363
- declare function createContractUtilsFactory<TClientContext extends ClientContext>(caller: ContractCaller<TClientContext>, options: ContractUtilsFactoryOptions<TClientContext>): ContractUtilsFactory<TClientContext>;
390
+ declare function createContractUtilsFactory<TClientContext extends ClientContext>(clientFactory: ContractClientFactory<TClientContext>, options: ContractUtilsFactoryOptions<TClientContext>): ContractUtilsFactory<TClientContext>;
364
391
  interface ContractJsonifiedUtilsFactory<TClientContext extends ClientContext> {
365
- <TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(procedure: ProcedureContract<TInputSchema, TOutputSchema, TErrorMap>): SharedRouterUtils<InferSchemaInput<TInputSchema>> & ProcedureUtils<TClientContext, InferSchemaInput<TInputSchema>, JsonifiedValue<InferSchemaOutput<TOutputSchema>>, JsonifiedClientError<ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>>;
392
+ <T extends RouterContract>(contract: T): RouterUtils<JsonifiedClient<RouterContractClient<T, TClientContext>>>;
366
393
  }
367
- interface ContractJsonifiedUtilsFactoryOptions<TClientContext extends ClientContext> extends RouterUtilsOptions<JsonifiedClient<RouterContractClient<RouterContract, TClientContext>>> {
394
+ interface ContractJsonifiedUtilsFactoryOptions<TClientContext extends ClientContext> extends Omit<RouterUtilsOptions<JsonifiedClient<RouterContractClient<RouterContract, TClientContext>>>, 'path'> {
368
395
  }
369
- declare function createContractJsonifiedUtilsFactory<TClientContext extends ClientContext>(caller: ContractCaller<TClientContext>, options: ContractJsonifiedUtilsFactoryOptions<TClientContext>): ContractJsonifiedUtilsFactory<TClientContext>;
396
+ declare function createContractJsonifiedUtilsFactory<TClientContext extends ClientContext>(clientFactory: ContractClientFactory<TClientContext>, options: ContractJsonifiedUtilsFactoryOptions<TClientContext>): ContractJsonifiedUtilsFactory<TClientContext>;
370
397
 
371
- declare function generateOperationKey<TType extends OperationType, TInput>(path: string[], state?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
398
+ type TanstackQueryMetaOptions<TClientContext extends ClientContext, TInput, TOutput, TError> = Omit<ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>, 'prefix'>;
399
+ interface TanstackQueryMetaPlugin<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> extends MetaPlugin<TInputSchema, TOutputSchema, TErrorMap> {
400
+ name: '~tanstack-query';
401
+ }
402
+ /**
403
+ * Define base TanStack Query options and interceptors on a procedure contract.
404
+ * Applied multiple times, later options are spread-merged with higher priority
405
+ * while interceptors are concatenated. A key explicitly set to `undefined`
406
+ * resets the value from earlier applications instead of merging.
407
+ *
408
+ * Apply them to router utils with {@link ContractOptionsUtilsPlugin}.
409
+ *
410
+ * @see {@link https://orpc.dev/docs/integrations/tanstack-query#contract-options-plugin TanStack Query Contract Options Plugin Docs}
411
+ */
412
+ declare function tanstackQuery<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(options: TanstackQueryMetaOptions<ClientContext, InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>): TanstackQueryMetaPlugin<TInputSchema, TOutputSchema, TErrorMap>;
413
+ declare function getTanstackQueryMeta(procedureOrLazy: {
414
+ '~orpc': {
415
+ meta: Meta;
416
+ };
417
+ }): TanstackQueryMetaOptions<ClientContext, unknown, unknown, ThrowableError> | undefined;
418
+ /**
419
+ * Router utils plugin that applies base options defined via {@link tanstackQuery}
420
+ * on the given router contract. Meta options act as the base layer: options defined
421
+ * on the utils override them, and utils interceptors run after meta interceptors.
422
+ *
423
+ * The contract shape must match the client the utils are created from,
424
+ * so pass the root router contract when utils paths start from the root.
425
+ *
426
+ * @see {@link https://orpc.dev/docs/integrations/tanstack-query#contract-options-plugin TanStack Query Contract Options Plugin Docs}
427
+ */
428
+ declare class ContractOptionsUtilsPlugin<T extends AnyNestedClient = AnyNestedClient> implements RouterUtilsPlugin<T> {
429
+ private readonly contract;
430
+ readonly name = "~contract-options";
431
+ constructor(contract: RouterContract);
432
+ initProcedureOptions(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
433
+ }
372
434
 
373
- export { OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedRouterUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, serializableStreamedQuery };
374
- export type { ContractJsonifiedUtilsFactory, ContractJsonifiedUtilsFactoryOptions, ContractUtilsFactory, ContractUtilsFactoryOptions, InferLiveQueryOutput, InferStreamedQueryOutput, InfiniteKeyOptions, InfiniteOptionsIn, InfiniteOptionsOut, MutationKeyOptions, MutationOptionsIn, MutationOptionsOut, OperationContext, OperationKey, OperationKeyOptions, OperationType, ProcedureUtilsInfiniteInterceptor, ProcedureUtilsInfiniteInterceptorOptions, ProcedureUtilsLiveInterceptor, ProcedureUtilsLiveInterceptorOptions, ProcedureUtilsModifier, ProcedureUtilsMutationInterceptor, ProcedureUtilsMutationInterceptorOptions, ProcedureUtilsOptions, ProcedureUtilsQueryInterceptor, ProcedureUtilsQueryInterceptorOptions, ProcedureUtilsStreamedInterceptor, ProcedureUtilsStreamedInterceptorOptions, QueryKeyOptions, QueryOptionsIn, QueryOptionsOut, RouterUtils, RouterUtilsOptions, RouterUtilsScoped, SerializableStreamedQueryOptions, StreamedKeyOptions, StreamedOptionsIn, StreamedOptionsOut, OperationContext as TanstackQueryOperationContext };
435
+ export { CompositeRouterUtilsPlugin, ContractOptionsUtilsPlugin, OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, getTanstackQueryMeta, isProcedureUtilsOptions, mergeProcedureUtilsOptions, serializableStreamedQuery, tanstackQuery };
436
+ export type { ContractJsonifiedUtilsFactory, ContractJsonifiedUtilsFactoryOptions, ContractUtilsFactory, ContractUtilsFactoryOptions, InferLiveQueryOutput, InferStreamedQueryOutput, InfiniteKeyOptions, InfiniteOptionsIn, InfiniteOptionsOut, MutationKeyOptions, MutationOptionsIn, MutationOptionsOut, OperationContext, OperationKey, OperationKeyOptions, OperationKeyPrefixOptions, OperationType, ProcedureUtilsInfiniteInterceptor, ProcedureUtilsInfiniteInterceptorOptions, ProcedureUtilsLiveInterceptor, ProcedureUtilsLiveInterceptorOptions, ProcedureUtilsModifier, ProcedureUtilsMutationInterceptor, ProcedureUtilsMutationInterceptorOptions, ProcedureUtilsOptions, ProcedureUtilsQueryInterceptor, ProcedureUtilsQueryInterceptorOptions, ProcedureUtilsStreamedInterceptor, ProcedureUtilsStreamedInterceptorOptions, QueryKeyOptions, QueryOptionsIn, QueryOptionsOut, RouterUtils, RouterUtilsOptions, RouterUtilsPlugin, RouterUtilsScoped, SerializableStreamedQueryOptions, StreamedKeyOptions, StreamedOptionsIn, StreamedOptionsOut, TanstackQueryMetaOptions, TanstackQueryMetaPlugin, OperationContext as TanstackQueryOperationContext };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { ClientContext, Client, AnyNestedClient, InferClientContext, InferClientError, ThrowableError } from '@orpc/client';
2
- import { AnySchema, ErrorMap, ProcedureContract, InferSchemaInput, InferSchemaOutput, ORPCErrorFromErrorMap, RouterContractClient, RouterContract, ContractCaller } from '@orpc/contract';
3
- import { JsonifiedValue, JsonifiedClientError, JsonifiedClient } from '@orpc/openapi';
4
- import { Promisable, PartialDeep, Interceptor, PromiseWithError, MaybeOptionalOptions, OrderablePlugin, Public } from '@orpc/shared';
1
+ import { ClientContext, Client, AnyNestedClient, InferClientContext, InferClientError } from '@orpc/client';
2
+ import { RouterContract, RouterContractClient, ContractClientFactory, AnySchema, ErrorMap, MetaPlugin, Meta, InferSchemaInput, InferSchemaOutput, ORPCErrorFromErrorMap } from '@orpc/contract';
3
+ import { JsonifiedClient } from '@orpc/openapi';
4
+ import { Promisable, PartialDeep, Interceptor, PromiseWithError, MaybeOptionalOptions, OrderablePlugin, Public, ThrowableError } from '@orpc/shared';
5
5
  import { QueryKey, QueryFunctionContext, QueryFunction, SkipToken, QueryObserverOptions, InfiniteQueryObserverOptions, MutationObserverOptions, DataTag, InfiniteData, MutationFunctionContext } from '@tanstack/query-core';
6
6
 
7
7
  interface SerializableStreamedQueryOptions {
@@ -33,12 +33,6 @@ declare function serializableStreamedQuery<TQueryFnData = unknown, TQueryKey ext
33
33
  type InferStreamedQueryOutput<TOutput> = TOutput extends AsyncIterable<infer U> ? U[] : never;
34
34
  type InferLiveQueryOutput<TOutput> = TOutput extends AsyncIterable<infer U> ? U : never;
35
35
  type OperationType = 'query' | 'streamed' | 'live' | 'infinite' | 'mutation';
36
- type OperationKeyOptions<TType extends OperationType, TInput> = {
37
- type?: TType;
38
- input?: TType extends 'mutation' ? never : PartialDeep<TInput>;
39
- fnOptions?: TType extends 'streamed' ? SerializableStreamedQueryOptions : never;
40
- };
41
- type OperationKey<TType extends OperationType, TInput> = [path: string[], options: OperationKeyOptions<TType, TInput>];
42
36
  declare const OPERATION_CONTEXT_SYMBOL: unique symbol;
43
37
  interface OperationContext {
44
38
  [OPERATION_CONTEXT_SYMBOL]?: {
@@ -108,6 +102,31 @@ type MutationOptionsIn<TClientContext extends ClientContext, TInput, TOutput, TE
108
102
  }) & MutationOptionsOut<TInput, TOutput, TError, TMutationContext>;
109
103
  type MutationOptionsOut<TInput, TOutput, TError, TMutationContext> = MutationObserverOptions<TOutput, TError, TInput, TMutationContext>;
110
104
 
105
+ interface OperationKeyPrefixOptions {
106
+ /**
107
+ * Prepended as the first element of the key when present.
108
+ * Use this to avoid key conflicts when multiple router utils share the same client.
109
+ */
110
+ prefix?: string;
111
+ }
112
+ type OperationKeyOptions<TType extends OperationType, TInput> = OperationKeyPrefixOptions & {
113
+ type?: TType;
114
+ input?: TType extends 'mutation' ? never : PartialDeep<TInput>;
115
+ fnOptions?: TType extends 'streamed' ? SerializableStreamedQueryOptions : never;
116
+ };
117
+ type OperationKey<TType extends OperationType, TInput> = [path: string[], options: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>] | [prefix: string, path: string[], options: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>];
118
+ declare function generateOperationKey<TType extends OperationType, TInput>(path: string[], options?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
119
+
120
+ declare class SharedUtils<TInput> {
121
+ protected readonly path: string[];
122
+ protected readonly options: OperationKeyPrefixOptions;
123
+ constructor(path: string[], options: OperationKeyPrefixOptions);
124
+ /**
125
+ * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
126
+ */
127
+ key<TType extends OperationType>(options?: Omit<OperationKeyOptions<TType, TInput>, 'prefix'>): OperationKey<TType, TInput>;
128
+ }
129
+
111
130
  interface ProcedureUtilsQueryInterceptorOptions<TClientContext extends ClientContext, TInput> {
112
131
  path: string[];
113
132
  context: TClientContext & OperationContext;
@@ -135,7 +154,7 @@ type ProcedureUtilsMutationInterceptor<TClientContext extends ClientContext, TIn
135
154
  * or a function that receives per-call options and returns overridden this.options.
136
155
  */
137
156
  type ProcedureUtilsModifier<T extends object> = Partial<T> | ((options: T) => T);
138
- interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError> {
157
+ interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError> extends OperationKeyPrefixOptions {
139
158
  /**
140
159
  * Key options modifier for .queryKey and .queryOptions
141
160
  * Can be partial options or a function that receives per-call options and returns override this.options.
@@ -207,9 +226,17 @@ interface ProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TO
207
226
  */
208
227
  mutationOptions?: ProcedureUtilsModifier<MutationOptionsIn<TClientContext, TInput, TOutput, TError, unknown>>;
209
228
  }
210
- declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutput, TError> {
211
- private readonly path;
212
- private readonly options;
229
+ declare function isProcedureUtilsOptions(value: unknown): value is ProcedureUtilsOptions<any, any, any, any>;
230
+ /**
231
+ * Merge two procedure utils options where `override` takes priority.
232
+ * A key explicitly set to `undefined` in `override` resets the base value.
233
+ * When both sides define a key: interceptors are concatenated (base ones run first),
234
+ * modifiers are spread-merged when both are plain objects and composed (base applied
235
+ * first) otherwise, with plain objects applied as regular spread merges.
236
+ */
237
+ declare function mergeProcedureUtilsOptions<TClientContext extends ClientContext, TInput, TOutput, TError>(base: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>, override: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>): ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>;
238
+ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutput, TError> extends SharedUtils<TInput> {
239
+ protected readonly options: ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>;
213
240
  /**
214
241
  * Calling corresponding procedure client
215
242
  */
@@ -228,7 +255,7 @@ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutp
228
255
  */
229
256
  streamedKey(...rest: MaybeOptionalOptions<StreamedKeyOptions<TInput>>): DataTag<QueryKey, InferStreamedQueryOutput<TOutput>, TError>;
230
257
  /**
231
- * Configure queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
258
+ * Configure queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
232
259
  * This is built on [TanStack Query streamedQuery](https://tanstack.com/query/latest/docs/reference/streamedQuery)
233
260
  * and works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
234
261
  */
@@ -238,7 +265,7 @@ declare class ProcedureUtils<TClientContext extends ClientContext, TInput, TOutp
238
265
  */
239
266
  liveKey(...rest: MaybeOptionalOptions<QueryKeyOptions<TInput>>): DataTag<QueryKey, InferLiveQueryOutput<TOutput>, TError>;
240
267
  /**
241
- * Configure live queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
268
+ * Configure live queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
242
269
  * Unlike `.streamedOptions` which accumulates chunks, live queries replace the entire result with each new chunk received.
243
270
  * Works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
244
271
  */
@@ -296,25 +323,25 @@ interface RouterUtilsPlugin<T extends AnyNestedClient> extends OrderablePlugin {
296
323
  */
297
324
  initProcedureOptions?(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
298
325
  }
299
-
300
- declare class SharedRouterUtils<TInput> {
301
- private readonly path;
302
- constructor(path: string[]);
303
- /**
304
- * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
305
- */
306
- key<TType extends OperationType>(options?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
326
+ declare class CompositeRouterUtilsPlugin<T extends AnyNestedClient> implements RouterUtilsPlugin<T> {
327
+ protected readonly plugins: RouterUtilsPlugin<T>[];
328
+ readonly name = "~composite";
329
+ constructor(plugins?: RouterUtilsPlugin<T>[]);
330
+ init(options: RouterUtilsOptions<T>): RouterUtilsOptions<T>;
331
+ initProcedureOptions(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
307
332
  }
308
- type RouterUtils<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Public<ProcedureUtils<UClientContext, UInput, UOutput, UError>> & Public<SharedRouterUtils<UInput>> : {
333
+
334
+ type RouterUtils<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Public<ProcedureUtils<UClientContext, UInput, UOutput, UError>> : {
309
335
  [K in keyof T]: T[K] extends AnyNestedClient ? RouterUtils<T[K]> : never;
310
- } & Public<SharedRouterUtils<unknown>>;
336
+ } & Public<SharedUtils<unknown>>;
311
337
  type RouterUtilsScoped<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? ProcedureUtilsOptions<UClientContext, UInput, UOutput, UError> : {
312
338
  [K in keyof T]?: T[K] extends AnyNestedClient ? RouterUtilsScoped<T[K]> : never;
313
339
  };
314
- interface RouterUtilsOptions<T extends AnyNestedClient> {
340
+ interface RouterUtilsOptions<T extends AnyNestedClient> extends OperationKeyPrefixOptions {
315
341
  /**
316
- * Base path for all query keys. Use this to avoid conflicts when mounting
317
- * multiple router utils instances.
342
+ * Base path for all query keys.
343
+ *
344
+ * @internal
318
345
  */
319
346
  path?: string[] | undefined;
320
347
  /**
@@ -356,19 +383,54 @@ interface RouterUtilsOptions<T extends AnyNestedClient> {
356
383
  declare function createRouterUtils<T extends AnyNestedClient>(client: T, options?: NoInfer<RouterUtilsOptions<T>>): RouterUtils<T>;
357
384
 
358
385
  interface ContractUtilsFactory<TClientContext extends ClientContext> {
359
- <TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(procedure: ProcedureContract<TInputSchema, TOutputSchema, TErrorMap>): Public<SharedRouterUtils<InferSchemaInput<TInputSchema>>> & Public<ProcedureUtils<TClientContext, InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>>;
386
+ <T extends RouterContract>(contract: T): RouterUtils<RouterContractClient<T, TClientContext>>;
360
387
  }
361
- interface ContractUtilsFactoryOptions<TClientContext extends ClientContext> extends RouterUtilsOptions<RouterContractClient<RouterContract, TClientContext>> {
388
+ interface ContractUtilsFactoryOptions<TClientContext extends ClientContext> extends Omit<RouterUtilsOptions<RouterContractClient<RouterContract, TClientContext>>, 'path'> {
362
389
  }
363
- declare function createContractUtilsFactory<TClientContext extends ClientContext>(caller: ContractCaller<TClientContext>, options: ContractUtilsFactoryOptions<TClientContext>): ContractUtilsFactory<TClientContext>;
390
+ declare function createContractUtilsFactory<TClientContext extends ClientContext>(clientFactory: ContractClientFactory<TClientContext>, options: ContractUtilsFactoryOptions<TClientContext>): ContractUtilsFactory<TClientContext>;
364
391
  interface ContractJsonifiedUtilsFactory<TClientContext extends ClientContext> {
365
- <TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(procedure: ProcedureContract<TInputSchema, TOutputSchema, TErrorMap>): SharedRouterUtils<InferSchemaInput<TInputSchema>> & ProcedureUtils<TClientContext, InferSchemaInput<TInputSchema>, JsonifiedValue<InferSchemaOutput<TOutputSchema>>, JsonifiedClientError<ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>>;
392
+ <T extends RouterContract>(contract: T): RouterUtils<JsonifiedClient<RouterContractClient<T, TClientContext>>>;
366
393
  }
367
- interface ContractJsonifiedUtilsFactoryOptions<TClientContext extends ClientContext> extends RouterUtilsOptions<JsonifiedClient<RouterContractClient<RouterContract, TClientContext>>> {
394
+ interface ContractJsonifiedUtilsFactoryOptions<TClientContext extends ClientContext> extends Omit<RouterUtilsOptions<JsonifiedClient<RouterContractClient<RouterContract, TClientContext>>>, 'path'> {
368
395
  }
369
- declare function createContractJsonifiedUtilsFactory<TClientContext extends ClientContext>(caller: ContractCaller<TClientContext>, options: ContractJsonifiedUtilsFactoryOptions<TClientContext>): ContractJsonifiedUtilsFactory<TClientContext>;
396
+ declare function createContractJsonifiedUtilsFactory<TClientContext extends ClientContext>(clientFactory: ContractClientFactory<TClientContext>, options: ContractJsonifiedUtilsFactoryOptions<TClientContext>): ContractJsonifiedUtilsFactory<TClientContext>;
370
397
 
371
- declare function generateOperationKey<TType extends OperationType, TInput>(path: string[], state?: OperationKeyOptions<TType, TInput>): OperationKey<TType, TInput>;
398
+ type TanstackQueryMetaOptions<TClientContext extends ClientContext, TInput, TOutput, TError> = Omit<ProcedureUtilsOptions<TClientContext, TInput, TOutput, TError>, 'prefix'>;
399
+ interface TanstackQueryMetaPlugin<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> extends MetaPlugin<TInputSchema, TOutputSchema, TErrorMap> {
400
+ name: '~tanstack-query';
401
+ }
402
+ /**
403
+ * Define base TanStack Query options and interceptors on a procedure contract.
404
+ * Applied multiple times, later options are spread-merged with higher priority
405
+ * while interceptors are concatenated. A key explicitly set to `undefined`
406
+ * resets the value from earlier applications instead of merging.
407
+ *
408
+ * Apply them to router utils with {@link ContractOptionsUtilsPlugin}.
409
+ *
410
+ * @see {@link https://orpc.dev/docs/integrations/tanstack-query#contract-options-plugin TanStack Query Contract Options Plugin Docs}
411
+ */
412
+ declare function tanstackQuery<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap>(options: TanstackQueryMetaOptions<ClientContext, InferSchemaInput<TInputSchema>, InferSchemaOutput<TOutputSchema>, ORPCErrorFromErrorMap<TErrorMap> | ThrowableError>): TanstackQueryMetaPlugin<TInputSchema, TOutputSchema, TErrorMap>;
413
+ declare function getTanstackQueryMeta(procedureOrLazy: {
414
+ '~orpc': {
415
+ meta: Meta;
416
+ };
417
+ }): TanstackQueryMetaOptions<ClientContext, unknown, unknown, ThrowableError> | undefined;
418
+ /**
419
+ * Router utils plugin that applies base options defined via {@link tanstackQuery}
420
+ * on the given router contract. Meta options act as the base layer: options defined
421
+ * on the utils override them, and utils interceptors run after meta interceptors.
422
+ *
423
+ * The contract shape must match the client the utils are created from,
424
+ * so pass the root router contract when utils paths start from the root.
425
+ *
426
+ * @see {@link https://orpc.dev/docs/integrations/tanstack-query#contract-options-plugin TanStack Query Contract Options Plugin Docs}
427
+ */
428
+ declare class ContractOptionsUtilsPlugin<T extends AnyNestedClient = AnyNestedClient> implements RouterUtilsPlugin<T> {
429
+ private readonly contract;
430
+ readonly name = "~contract-options";
431
+ constructor(contract: RouterContract);
432
+ initProcedureOptions(path: string[], options: ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>): ProcedureUtilsOptions<InferClientContext<T>, any, any, InferClientError<T>>;
433
+ }
372
434
 
373
- export { OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedRouterUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, serializableStreamedQuery };
374
- export type { ContractJsonifiedUtilsFactory, ContractJsonifiedUtilsFactoryOptions, ContractUtilsFactory, ContractUtilsFactoryOptions, InferLiveQueryOutput, InferStreamedQueryOutput, InfiniteKeyOptions, InfiniteOptionsIn, InfiniteOptionsOut, MutationKeyOptions, MutationOptionsIn, MutationOptionsOut, OperationContext, OperationKey, OperationKeyOptions, OperationType, ProcedureUtilsInfiniteInterceptor, ProcedureUtilsInfiniteInterceptorOptions, ProcedureUtilsLiveInterceptor, ProcedureUtilsLiveInterceptorOptions, ProcedureUtilsModifier, ProcedureUtilsMutationInterceptor, ProcedureUtilsMutationInterceptorOptions, ProcedureUtilsOptions, ProcedureUtilsQueryInterceptor, ProcedureUtilsQueryInterceptorOptions, ProcedureUtilsStreamedInterceptor, ProcedureUtilsStreamedInterceptorOptions, QueryKeyOptions, QueryOptionsIn, QueryOptionsOut, RouterUtils, RouterUtilsOptions, RouterUtilsScoped, SerializableStreamedQueryOptions, StreamedKeyOptions, StreamedOptionsIn, StreamedOptionsOut, OperationContext as TanstackQueryOperationContext };
435
+ export { CompositeRouterUtilsPlugin, ContractOptionsUtilsPlugin, OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, getTanstackQueryMeta, isProcedureUtilsOptions, mergeProcedureUtilsOptions, serializableStreamedQuery, tanstackQuery };
436
+ export type { ContractJsonifiedUtilsFactory, ContractJsonifiedUtilsFactoryOptions, ContractUtilsFactory, ContractUtilsFactoryOptions, InferLiveQueryOutput, InferStreamedQueryOutput, InfiniteKeyOptions, InfiniteOptionsIn, InfiniteOptionsOut, MutationKeyOptions, MutationOptionsIn, MutationOptionsOut, OperationContext, OperationKey, OperationKeyOptions, OperationKeyPrefixOptions, OperationType, ProcedureUtilsInfiniteInterceptor, ProcedureUtilsInfiniteInterceptorOptions, ProcedureUtilsLiveInterceptor, ProcedureUtilsLiveInterceptorOptions, ProcedureUtilsModifier, ProcedureUtilsMutationInterceptor, ProcedureUtilsMutationInterceptorOptions, ProcedureUtilsOptions, ProcedureUtilsQueryInterceptor, ProcedureUtilsQueryInterceptorOptions, ProcedureUtilsStreamedInterceptor, ProcedureUtilsStreamedInterceptorOptions, QueryKeyOptions, QueryOptionsIn, QueryOptionsOut, RouterUtils, RouterUtilsOptions, RouterUtilsPlugin, RouterUtilsScoped, SerializableStreamedQueryOptions, StreamedKeyOptions, StreamedOptionsIn, StreamedOptionsOut, TanstackQueryMetaOptions, TanstackQueryMetaPlugin, OperationContext as TanstackQueryOperationContext };
package/dist/index.mjs CHANGED
@@ -1,16 +1,8 @@
1
- import { getPathMeta } from '@orpc/contract';
2
- import { sortPlugins, stringifyJSON, resolveMaybeOptionalOptions, intercept, toArray, isAsyncIteratorObject, bindMethods, getOrBind, get, isTypescriptObject } from '@orpc/shared';
1
+ import { resolveBasePathMeta, getRouterContract, ProcedureContract } from '@orpc/contract';
2
+ import { sortPlugins, stringifyJSON, resolveMaybeOptionalOptions, intercept, toArray, isAsyncIteratorObject, isTypescriptObject, bindMethods, getOrBind, get } from '@orpc/shared';
3
3
  import { RECURSIVE_CLIENT_UNWRAP_KEYS } from '@orpc/client';
4
4
  import { skipToken } from '@tanstack/query-core';
5
5
 
6
- function generateOperationKey(path, state = {}) {
7
- return [path, {
8
- ...state.input !== void 0 ? { input: state.input } : {},
9
- ...state.type !== void 0 ? { type: state.type } : {},
10
- ...state.fnOptions !== void 0 ? { fnOptions: state.fnOptions } : {}
11
- }];
12
- }
13
-
14
6
  class CompositeRouterUtilsPlugin {
15
7
  constructor(plugins = []) {
16
8
  this.plugins = plugins;
@@ -35,6 +27,18 @@ class CompositeRouterUtilsPlugin {
35
27
  }
36
28
  }
37
29
 
30
+ function generateOperationKey(path, options = {}) {
31
+ return [
32
+ ...options.prefix !== void 0 ? [options.prefix] : [],
33
+ path,
34
+ {
35
+ ...options.input !== void 0 ? { input: options.input } : {},
36
+ ...options.type !== void 0 ? { type: options.type } : {},
37
+ ...options.fnOptions !== void 0 ? { fnOptions: options.fnOptions } : {}
38
+ }
39
+ ];
40
+ }
41
+
38
42
  function liveQuery(queryFn) {
39
43
  return async (context) => {
40
44
  const stream = await queryFn(context);
@@ -53,6 +57,19 @@ function liveQuery(queryFn) {
53
57
  };
54
58
  }
55
59
 
60
+ class SharedUtils {
61
+ constructor(path, options) {
62
+ this.path = path;
63
+ this.options = options;
64
+ }
65
+ /**
66
+ * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
67
+ */
68
+ key(options = {}) {
69
+ return generateOperationKey(this.path, { ...options, prefix: this.options.prefix });
70
+ }
71
+ }
72
+
56
73
  function serializableStreamedQuery(queryFn, { refetchMode = "reset", maxChunks = Number.POSITIVE_INFINITY } = {}) {
57
74
  return async (context) => {
58
75
  const query = context.client.getQueryCache().find({ queryKey: context.queryKey, exact: true });
@@ -111,16 +128,84 @@ function limitArraySize(items, maxSize) {
111
128
 
112
129
  const OPERATION_CONTEXT_SYMBOL = Symbol.for("ORPC_TANSTACK_QUERY_OPERATION_CONTEXT");
113
130
 
114
- class ProcedureUtils {
115
- constructor(path, client, options = {}) {
116
- this.path = path;
117
- this.options = options;
118
- this.call = client;
131
+ const PROCEDURE_UTILS_INTERCEPTOR_KEYS = [
132
+ "queryInterceptors",
133
+ "streamedInterceptors",
134
+ "liveInterceptors",
135
+ "infiniteInterceptors",
136
+ "mutationInterceptors"
137
+ ];
138
+ const PROCEDURE_UTILS_MODIFIER_KEYS = [
139
+ "queryKey",
140
+ "queryOptions",
141
+ "streamedKey",
142
+ "streamedOptions",
143
+ "liveKey",
144
+ "liveOptions",
145
+ "infiniteKey",
146
+ "infiniteOptions",
147
+ "mutationKey",
148
+ "mutationOptions"
149
+ ];
150
+ function isProcedureUtilsOptions(value) {
151
+ if (!isTypescriptObject(value)) {
152
+ return false;
153
+ }
154
+ for (const key in value) {
155
+ if (value[key] === void 0) {
156
+ continue;
157
+ }
158
+ if (key === "prefix") {
159
+ if (typeof value[key] !== "string") {
160
+ return false;
161
+ }
162
+ } else if (PROCEDURE_UTILS_INTERCEPTOR_KEYS.includes(key)) {
163
+ if (!Array.isArray(value[key]) || value[key].some((i) => typeof i !== "function")) {
164
+ return false;
165
+ }
166
+ } else if (PROCEDURE_UTILS_MODIFIER_KEYS.includes(key)) {
167
+ if (!isTypescriptObject(value[key])) {
168
+ return false;
169
+ }
170
+ }
171
+ }
172
+ return true;
173
+ }
174
+ function mergeProcedureUtilsModifier(base, override) {
175
+ if (typeof base !== "function" && typeof override !== "function") {
176
+ return { ...base, ...override };
177
+ }
178
+ const applyBase = typeof base === "function" ? base : (options) => ({ ...base, ...options });
179
+ const applyOverride = typeof override === "function" ? override : (options) => ({ ...override, ...options });
180
+ return (options) => applyOverride(applyBase(options));
181
+ }
182
+ function mergeProcedureUtilsOptions(base, override) {
183
+ const merged = { ...base, ...override };
184
+ for (const key of PROCEDURE_UTILS_INTERCEPTOR_KEYS) {
185
+ const baseValue = base[key];
186
+ const overrideValue = override[key];
187
+ if (baseValue && overrideValue) {
188
+ merged[key] = [...baseValue, ...overrideValue];
189
+ }
119
190
  }
191
+ for (const key of PROCEDURE_UTILS_MODIFIER_KEYS) {
192
+ const baseValue = base[key];
193
+ const overrideValue = override[key];
194
+ if (baseValue && overrideValue) {
195
+ merged[key] = mergeProcedureUtilsModifier(baseValue, overrideValue);
196
+ }
197
+ }
198
+ return merged;
199
+ }
200
+ class ProcedureUtils extends SharedUtils {
120
201
  /**
121
202
  * Calling corresponding procedure client
122
203
  */
123
204
  call;
205
+ constructor(path, client, options = {}) {
206
+ super(path, options);
207
+ this.call = client;
208
+ }
124
209
  /**
125
210
  * Generate a **full matching** key for [Query Options](https://orpc.dev/docs/integrations/tanstack-query#query-options).
126
211
  */
@@ -131,7 +216,7 @@ class ProcedureUtils {
131
216
  } else if (this.options.queryKey) {
132
217
  optionsIn = { ...this.options.queryKey, ...optionsIn };
133
218
  }
134
- const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "query", input: optionsIn.input });
219
+ const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { prefix: this.options.prefix, type: "query", input: optionsIn.input });
135
220
  return queryKey;
136
221
  }
137
222
  /**
@@ -187,11 +272,11 @@ class ProcedureUtils {
187
272
  } else if (this.options.streamedKey) {
188
273
  optionsIn = { ...this.options.streamedKey, ...optionsIn };
189
274
  }
190
- const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "streamed", input: optionsIn.input, fnOptions: optionsIn.queryFnOptions });
275
+ const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { prefix: this.options.prefix, type: "streamed", input: optionsIn.input, fnOptions: optionsIn.queryFnOptions });
191
276
  return queryKey;
192
277
  }
193
278
  /**
194
- * Configure queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
279
+ * Configure queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
195
280
  * This is built on [TanStack Query streamedQuery](https://tanstack.com/query/latest/docs/reference/streamedQuery)
196
281
  * and works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
197
282
  */
@@ -232,7 +317,7 @@ class ProcedureUtils {
232
317
  async (queryContext) => {
233
318
  const output = await this.call(input, { signal: queryContext.signal, context });
234
319
  if (!isAsyncIteratorObject(output)) {
235
- throw new Error("streamedQuery requires an event iterator output");
320
+ throw new Error("streamedQuery requires an AsyncIteratorObject output");
236
321
  }
237
322
  return output;
238
323
  },
@@ -254,11 +339,11 @@ class ProcedureUtils {
254
339
  } else if (this.options.liveKey) {
255
340
  optionsIn = { ...this.options.liveKey, ...optionsIn };
256
341
  }
257
- const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { type: "live", input: optionsIn.input });
342
+ const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, { prefix: this.options.prefix, type: "live", input: optionsIn.input });
258
343
  return queryKey;
259
344
  }
260
345
  /**
261
- * Configure live queries for [Event Iterator](https://orpc.dev/docs/event-iterator).
346
+ * Configure live queries for [AsyncIteratorObject](https://orpc.dev/docs/async-iterator-object).
262
347
  * Unlike `.streamedOptions` which accumulates chunks, live queries replace the entire result with each new chunk received.
263
348
  * Works with hooks like `useQuery`, `useSuspenseQuery`, or `prefetchQuery`.
264
349
  */
@@ -301,7 +386,7 @@ class ProcedureUtils {
301
386
  context
302
387
  });
303
388
  if (!isAsyncIteratorObject(output)) {
304
- throw new Error("liveQuery requires an event iterator output");
389
+ throw new Error("liveQuery requires an AsyncIteratorObject output");
305
390
  }
306
391
  return output;
307
392
  })(fnContext2);
@@ -321,6 +406,7 @@ class ProcedureUtils {
321
406
  optionsIn = { ...this.options.infiniteKey, ...optionsIn };
322
407
  }
323
408
  const queryKey = optionsIn.queryKey ?? generateOperationKey(this.path, {
409
+ prefix: this.options.prefix,
324
410
  type: "infinite",
325
411
  input: optionsIn.input === skipToken ? skipToken : optionsIn.input(optionsIn.initialPageParam)
326
412
  });
@@ -377,7 +463,7 @@ class ProcedureUtils {
377
463
  } else if (this.options.mutationKey) {
378
464
  optionsIn = { ...this.options.mutationKey, ...optionsIn };
379
465
  }
380
- const mutationKey = optionsIn.mutationKey ?? generateOperationKey(this.path, { type: "mutation" });
466
+ const mutationKey = optionsIn.mutationKey ?? generateOperationKey(this.path, { prefix: this.options.prefix, type: "mutation" });
381
467
  return mutationKey;
382
468
  }
383
469
  /**
@@ -421,41 +507,29 @@ class ProcedureUtils {
421
507
  }
422
508
  }
423
509
 
424
- class SharedRouterUtils {
425
- constructor(path) {
426
- this.path = path;
427
- }
428
- /**
429
- * Generate a **partial matching** key for actions like revalidating queries, checking mutation status, etc.
430
- */
431
- key(options = {}) {
432
- return generateOperationKey(this.path, options);
433
- }
434
- }
435
510
  function createRouterUtils(client, options = {}) {
436
511
  const plugin = new CompositeRouterUtilsPlugin(options.plugins);
437
512
  options = plugin.init(options);
438
513
  return createRouterUtilsInternal(client, options, plugin);
439
514
  }
440
- function createRouterUtilsInternal(client, options = {}, plugin) {
515
+ function createRouterUtilsInternal(client, options, plugin) {
441
516
  const path = toArray(options.path);
442
- const sharedUtils = bindMethods(new SharedRouterUtils(path));
443
- const procedureUtils = typeof client === "function" && (options.scoped === void 0 || isProcedureUtilsOptions(options.scoped)) ? bindMethods(new ProcedureUtils(
517
+ const utils = typeof client === "function" && (options.scoped === void 0 || isProcedureUtilsOptions(options.scoped)) ? bindMethods(new ProcedureUtils(
444
518
  path,
445
519
  client,
446
- plugin.initProcedureOptions(path, {
447
- ...options.scoped,
448
- queryInterceptors: [...toArray(options.queryInterceptors), ...toArray(options.scoped?.queryInterceptors)],
449
- streamedInterceptors: [...toArray(options.streamedInterceptors), ...toArray(options.scoped?.streamedInterceptors)],
450
- liveInterceptors: [...toArray(options.liveInterceptors), ...toArray(options.scoped?.liveInterceptors)],
451
- infiniteInterceptors: [...toArray(options.infiniteInterceptors), ...toArray(options.scoped?.infiniteInterceptors)],
452
- mutationInterceptors: [...toArray(options.mutationInterceptors), ...toArray(options.scoped?.mutationInterceptors)]
453
- })
454
- )) : void 0;
455
- const recursive = new Proxy({
456
- ...sharedUtils,
457
- ...procedureUtils
458
- }, {
520
+ plugin.initProcedureOptions(path, mergeProcedureUtilsOptions(
521
+ {
522
+ prefix: options.prefix,
523
+ queryInterceptors: options.queryInterceptors,
524
+ streamedInterceptors: options.streamedInterceptors,
525
+ liveInterceptors: options.liveInterceptors,
526
+ infiniteInterceptors: options.infiniteInterceptors,
527
+ mutationInterceptors: options.mutationInterceptors
528
+ },
529
+ options.scoped ?? {}
530
+ ))
531
+ )) : bindMethods(new SharedUtils(path, options));
532
+ const recursive = new Proxy(utils, {
459
533
  get(target, prop) {
460
534
  const value = getOrBind(target, prop);
461
535
  const nextClient = get(client, [prop]);
@@ -482,52 +556,55 @@ function createRouterUtilsInternal(client, options = {}, plugin) {
482
556
  });
483
557
  return recursive;
484
558
  }
485
- function isProcedureUtilsOptions(value) {
486
- if (!isTypescriptObject(value)) {
487
- return false;
488
- }
489
- if (value.queryInterceptors !== void 0 && !Array.isArray(value.queryInterceptors)) {
490
- return false;
491
- }
492
- if (value.streamedInterceptors !== void 0 && !Array.isArray(value.streamedInterceptors)) {
493
- return false;
494
- }
495
- if (value.liveInterceptors !== void 0 && !Array.isArray(value.liveInterceptors)) {
496
- return false;
497
- }
498
- if (value.infiniteInterceptors !== void 0 && !Array.isArray(value.infiniteInterceptors)) {
499
- return false;
500
- }
501
- if (value.mutationInterceptors !== void 0 && !Array.isArray(value.mutationInterceptors)) {
502
- return false;
503
- }
504
- return true;
505
- }
506
559
 
507
- function createContractUtilsFactory(caller, options) {
508
- return (procedure) => {
509
- const path = getPathMeta(procedure);
510
- if (!path) {
560
+ function createContractUtilsFactory(clientFactory, options) {
561
+ const factory = (contract) => {
562
+ const client = clientFactory(contract);
563
+ const path = resolveBasePathMeta(contract);
564
+ if (path === void 0) {
511
565
  throw new TypeError(
512
566
  "ContractUtilsFactory: procedure contract must define `meta.path` that matches its path in the root router contract."
513
567
  );
514
568
  }
515
- const scoped = get(options.scoped, path);
516
- if (scoped !== void 0 && (scoped === null || typeof scoped !== "object")) {
517
- throw new TypeError(
518
- `ContractUtilsFactory: "scoped" at path "${path.join(".")}" must be an object or undefined, got "${scoped}".`
519
- );
569
+ return createRouterUtils(client, { ...options, path, scoped: get(options.scoped, path) });
570
+ };
571
+ return factory;
572
+ }
573
+ function createContractJsonifiedUtilsFactory(clientFactory, options) {
574
+ return createContractUtilsFactory(clientFactory, options);
575
+ }
576
+
577
+ function tanstackQuery(options) {
578
+ return {
579
+ name: "~tanstack-query",
580
+ init(meta) {
581
+ const current = meta["~tanstack-query"];
582
+ return {
583
+ ...meta,
584
+ "~tanstack-query": current ? mergeProcedureUtilsOptions(current, options) : options
585
+ };
520
586
  }
521
- const client = (...rest) => caller(procedure, ...rest);
522
- return createRouterUtils(client, {
523
- ...options,
524
- scoped,
525
- path: [...toArray(options.path), ...path]
526
- });
527
587
  };
528
588
  }
529
- function createContractJsonifiedUtilsFactory(caller, options) {
530
- return createContractUtilsFactory(caller, options);
589
+ function getTanstackQueryMeta(procedureOrLazy) {
590
+ return procedureOrLazy["~orpc"].meta["~tanstack-query"];
591
+ }
592
+ class ContractOptionsUtilsPlugin {
593
+ constructor(contract) {
594
+ this.contract = contract;
595
+ }
596
+ name = "~contract-options";
597
+ initProcedureOptions(path, options) {
598
+ const procedure = getRouterContract(this.contract, path);
599
+ if (!(procedure instanceof ProcedureContract)) {
600
+ return options;
601
+ }
602
+ const base = getTanstackQueryMeta(procedure);
603
+ if (!base) {
604
+ return options;
605
+ }
606
+ return mergeProcedureUtilsOptions(base, options);
607
+ }
531
608
  }
532
609
 
533
- export { OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedRouterUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, serializableStreamedQuery };
610
+ export { CompositeRouterUtilsPlugin, ContractOptionsUtilsPlugin, OPERATION_CONTEXT_SYMBOL, ProcedureUtils, SharedUtils, OPERATION_CONTEXT_SYMBOL as TANSTACK_QUERY_OPERATION_CONTEXT_SYMBOL, createContractJsonifiedUtilsFactory, createContractUtilsFactory, createRouterUtils, createRouterUtils as createTanstackQueryUtils, generateOperationKey, getTanstackQueryMeta, isProcedureUtilsOptions, mergeProcedureUtilsOptions, serializableStreamedQuery, tanstackQuery };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/tanstack-query",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.2",
4
+ "version": "2.0.0-beta.20",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.dev",
7
7
  "repository": {
@@ -29,16 +29,16 @@
29
29
  "@tanstack/query-core": ">=5.80.2"
30
30
  },
31
31
  "dependencies": {
32
- "@orpc/contract": "2.0.0-beta.2",
33
- "@orpc/shared": "2.0.0-beta.2",
34
- "@orpc/client": "2.0.0-beta.2",
35
- "@orpc/openapi": "2.0.0-beta.2"
32
+ "@orpc/contract": "2.0.0-beta.20",
33
+ "@orpc/openapi": "2.0.0-beta.20",
34
+ "@orpc/client": "2.0.0-beta.20",
35
+ "@orpc/shared": "2.0.0-beta.20"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@angular/core": "^22.0.1",
39
39
  "@tanstack/angular-query-experimental": "^5.101.0",
40
40
  "@tanstack/query-core": "^5.101.0",
41
- "@tanstack/react-query": "^5.101.0",
41
+ "@tanstack/react-query": "^5.101.2",
42
42
  "@tanstack/solid-query": "^5.101.0",
43
43
  "@tanstack/svelte-query": "^6.1.34",
44
44
  "@tanstack/vue-query": "^5.101.0",