@trpc/server 10.0.0-alpha.20 → 10.0.0-alpha.23

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.
Files changed (198) hide show
  1. package/adapters/aws-lambda/dist/trpc-server-adapters-aws-lambda.cjs.d.ts +1 -0
  2. package/adapters/aws-lambda/dist/trpc-server-adapters-aws-lambda.cjs.dev.js +90 -0
  3. package/adapters/aws-lambda/dist/trpc-server-adapters-aws-lambda.cjs.js +7 -0
  4. package/adapters/aws-lambda/dist/trpc-server-adapters-aws-lambda.cjs.prod.js +90 -0
  5. package/adapters/aws-lambda/dist/trpc-server-adapters-aws-lambda.esm.js +86 -0
  6. package/adapters/express/dist/trpc-server-adapters-express.cjs.dev.js +4 -4
  7. package/adapters/express/dist/trpc-server-adapters-express.cjs.prod.js +4 -4
  8. package/adapters/express/dist/trpc-server-adapters-express.esm.js +4 -4
  9. package/adapters/fastify/dist/trpc-server-adapters-fastify.cjs.dev.js +5 -5
  10. package/adapters/fastify/dist/trpc-server-adapters-fastify.cjs.prod.js +5 -5
  11. package/adapters/fastify/dist/trpc-server-adapters-fastify.esm.js +5 -5
  12. package/adapters/fastify/index.js +1 -1
  13. package/adapters/fetch/index.d.ts +1 -0
  14. package/adapters/fetch/index.js +1 -0
  15. package/adapters/next/dist/trpc-server-adapters-next.cjs.dev.js +4 -4
  16. package/adapters/next/dist/trpc-server-adapters-next.cjs.prod.js +4 -4
  17. package/adapters/next/dist/trpc-server-adapters-next.esm.js +4 -4
  18. package/adapters/node-http/dist/trpc-server-adapters-node-http.cjs.dev.js +4 -4
  19. package/adapters/node-http/dist/trpc-server-adapters-node-http.cjs.prod.js +4 -4
  20. package/adapters/node-http/dist/trpc-server-adapters-node-http.esm.js +4 -4
  21. package/adapters/standalone/dist/trpc-server-adapters-standalone.cjs.dev.js +4 -4
  22. package/adapters/standalone/dist/trpc-server-adapters-standalone.cjs.prod.js +4 -4
  23. package/adapters/standalone/dist/trpc-server-adapters-standalone.esm.js +4 -4
  24. package/adapters/ws/dist/trpc-server-adapters-ws.cjs.dev.js +2 -2
  25. package/adapters/ws/dist/trpc-server-adapters-ws.cjs.prod.js +2 -2
  26. package/adapters/ws/dist/trpc-server-adapters-ws.esm.js +2 -2
  27. package/dist/TRPCError-7971540a.mjs +65 -0
  28. package/dist/{transformTRPCResponse-43a869de.js → TRPCError-ddec3395.js} +18 -59
  29. package/dist/TRPCError.d.ts +3 -3
  30. package/dist/TRPCError.d.ts.map +1 -1
  31. package/dist/adapters/express.js +5 -5
  32. package/dist/adapters/express.mjs +5 -5
  33. package/dist/adapters/fastify/fastifyRequestHandler.d.ts.map +1 -1
  34. package/dist/adapters/fastify/index.js +7 -8
  35. package/dist/adapters/fastify/index.mjs +6 -7
  36. package/dist/adapters/fetch/fetchRequestHandler.d.ts +8 -0
  37. package/dist/adapters/fetch/fetchRequestHandler.d.ts.map +1 -0
  38. package/dist/adapters/fetch/index.d.ts +3 -0
  39. package/dist/adapters/fetch/index.d.ts.map +1 -0
  40. package/dist/adapters/fetch/index.js +69 -0
  41. package/dist/adapters/fetch/index.mjs +65 -0
  42. package/dist/adapters/fetch/index.ts.js +1 -0
  43. package/dist/adapters/fetch/types.d.ts +21 -0
  44. package/dist/adapters/fetch/types.d.ts.map +1 -0
  45. package/dist/adapters/next.d.ts.map +1 -1
  46. package/dist/adapters/next.js +9 -10
  47. package/dist/adapters/next.mjs +8 -9
  48. package/dist/adapters/node-http/index.js +5 -5
  49. package/dist/adapters/node-http/index.mjs +5 -5
  50. package/dist/adapters/node-http/nodeHTTPRequestHandler.d.ts.map +1 -1
  51. package/dist/adapters/node-http/types.d.ts +9 -7
  52. package/dist/adapters/node-http/types.d.ts.map +1 -1
  53. package/dist/adapters/standalone.d.ts.map +1 -1
  54. package/dist/adapters/standalone.js +11 -8
  55. package/dist/adapters/standalone.mjs +11 -7
  56. package/dist/adapters/ws.d.ts +4 -4
  57. package/dist/adapters/ws.d.ts.map +1 -1
  58. package/dist/adapters/ws.js +117 -80
  59. package/dist/adapters/ws.mjs +112 -75
  60. package/dist/assertNotBrowser.d.ts.map +1 -1
  61. package/dist/{codes-7a3d4f65.mjs → envelopes-1deb2fa7.mjs} +19 -1
  62. package/dist/{codes-7f46544e.js → envelopes-a953b930.js} +18 -0
  63. package/dist/http/index.d.ts +1 -1
  64. package/dist/http/internals/getHTTPStatusCode.d.ts +1 -0
  65. package/dist/http/internals/getHTTPStatusCode.d.ts.map +1 -1
  66. package/dist/http/internals/types.d.ts +5 -4
  67. package/dist/http/internals/types.d.ts.map +1 -1
  68. package/dist/http/resolveHTTPResponse.d.ts +1 -1
  69. package/dist/http/resolveHTTPResponse.d.ts.map +1 -1
  70. package/dist/http/{ResponseMeta.d.ts → responseMeta.d.ts} +1 -1
  71. package/dist/http/responseMeta.d.ts.map +1 -0
  72. package/dist/index.d.ts +0 -1
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +45 -54
  75. package/dist/index.mjs +40 -47
  76. package/dist/internals/{BaseHandlerOptions.d.ts → baseHandlerOptions.d.ts} +2 -2
  77. package/dist/internals/{BaseHandlerOptions.d.ts.map → baseHandlerOptions.d.ts.map} +1 -1
  78. package/dist/internals/callProcedure.d.ts +2 -2
  79. package/dist/internals/callProcedure.d.ts.map +1 -1
  80. package/dist/internals/errors.d.ts +1 -0
  81. package/dist/internals/errors.d.ts.map +1 -1
  82. package/dist/internals/middlewares.d.ts +5 -2
  83. package/dist/internals/middlewares.d.ts.map +1 -1
  84. package/dist/internals/{OnErrorFunction.d.ts → onErrorFunction.d.ts} +1 -1
  85. package/dist/internals/{OnErrorFunction.d.ts.map → onErrorFunction.d.ts.map} +1 -1
  86. package/dist/internals/procedure.d.ts +20 -14
  87. package/dist/internals/procedure.d.ts.map +1 -1
  88. package/dist/internals/transformTRPCResponse.d.ts +4 -2
  89. package/dist/internals/transformTRPCResponse.d.ts.map +1 -1
  90. package/dist/{nodeHTTPRequestHandler-5fccb3bb.mjs → nodeHTTPRequestHandler-1cdb6383.mjs} +2 -3
  91. package/dist/{nodeHTTPRequestHandler-7d71ac09.js → nodeHTTPRequestHandler-848f07b5.js} +4 -5
  92. package/dist/observable/index.d.ts +5 -0
  93. package/dist/observable/index.d.ts.map +1 -0
  94. package/dist/observable/index.js +204 -0
  95. package/dist/observable/index.mjs +195 -0
  96. package/dist/observable/index.ts.js +1 -0
  97. package/dist/observable/internals/identity.d.ts +2 -0
  98. package/dist/observable/internals/identity.d.ts.map +1 -0
  99. package/dist/observable/internals/observableToPromise.d.ts +10 -0
  100. package/dist/observable/internals/observableToPromise.d.ts.map +1 -0
  101. package/dist/observable/internals/pipe.d.ts +4 -0
  102. package/dist/observable/internals/pipe.d.ts.map +1 -0
  103. package/dist/observable/observable.d.ts +5 -0
  104. package/dist/observable/observable.d.ts.map +1 -0
  105. package/dist/observable/operators/index.d.ts +4 -0
  106. package/dist/observable/operators/index.d.ts.map +1 -0
  107. package/dist/observable/operators/map.d.ts +3 -0
  108. package/dist/observable/operators/map.d.ts.map +1 -0
  109. package/dist/observable/operators/share.d.ts +6 -0
  110. package/dist/observable/operators/share.d.ts.map +1 -0
  111. package/dist/observable/operators/tap.d.ts +3 -0
  112. package/dist/observable/operators/tap.d.ts.map +1 -0
  113. package/dist/observable/types.d.ts +29 -0
  114. package/dist/observable/types.d.ts.map +1 -0
  115. package/dist/observable-137ea1bd.mjs +105 -0
  116. package/dist/observable-3aa4d911.js +108 -0
  117. package/dist/{resolveHTTPResponse-3292a84a.mjs → resolveHTTPResponse-54a79e6c.mjs} +18 -23
  118. package/dist/{resolveHTTPResponse-c3777a47.js → resolveHTTPResponse-ec3dccaa.js} +24 -29
  119. package/dist/router.d.ts +31 -27
  120. package/dist/router.d.ts.map +1 -1
  121. package/dist/rpc/codes.d.ts +2 -0
  122. package/dist/rpc/codes.d.ts.map +1 -1
  123. package/dist/rpc/envelopes.d.ts +61 -39
  124. package/dist/rpc/envelopes.d.ts.map +1 -1
  125. package/dist/rpc/index.js +7 -3
  126. package/dist/rpc/index.mjs +1 -1
  127. package/dist/subscription.d.ts +3 -52
  128. package/dist/subscription.d.ts.map +1 -1
  129. package/dist/subscription.js +44 -0
  130. package/dist/subscription.mjs +40 -0
  131. package/dist/subscription.ts.js +1 -0
  132. package/dist/transformTRPCResponse-333bed6c.js +56 -0
  133. package/dist/transformTRPCResponse-e0cba527.mjs +53 -0
  134. package/dist/types.d.ts +8 -0
  135. package/dist/types.d.ts.map +1 -1
  136. package/observable/index.d.ts +1 -0
  137. package/observable/index.js +1 -0
  138. package/package.json +30 -8
  139. package/rpc/dist/trpc-server-rpc.cjs.dev.js +1 -1
  140. package/rpc/dist/trpc-server-rpc.cjs.prod.js +1 -1
  141. package/rpc/dist/trpc-server-rpc.esm.js +1 -1
  142. package/src/TRPCError.ts +2 -2
  143. package/src/adapters/fastify/fastifyRequestHandler.ts +0 -1
  144. package/src/adapters/fastify/fastifyTRPCPlugin.ts +1 -1
  145. package/src/adapters/fetch/fetchRequestHandler.ts +61 -0
  146. package/src/adapters/fetch/index.ts +2 -0
  147. package/src/adapters/fetch/types.ts +28 -0
  148. package/src/adapters/next.ts +3 -5
  149. package/src/adapters/node-http/nodeHTTPRequestHandler.ts +0 -1
  150. package/src/adapters/node-http/types.ts +9 -7
  151. package/src/adapters/standalone.ts +10 -3
  152. package/src/adapters/ws.ts +115 -77
  153. package/src/assertNotBrowser.ts +1 -0
  154. package/src/http/index.ts +1 -1
  155. package/src/http/internals/getHTTPStatusCode.ts +1 -0
  156. package/src/http/internals/types.ts +5 -6
  157. package/src/http/resolveHTTPResponse.ts +20 -24
  158. package/src/http/{ResponseMeta.ts → responseMeta.ts} +0 -0
  159. package/src/index.ts +0 -1
  160. package/src/internals/{BaseHandlerOptions.ts → baseHandlerOptions.ts} +1 -1
  161. package/src/internals/callProcedure.ts +6 -3
  162. package/src/internals/errors.ts +20 -4
  163. package/src/internals/middlewares.ts +6 -2
  164. package/src/internals/{OnErrorFunction.ts → onErrorFunction.ts} +0 -0
  165. package/src/internals/procedure.ts +102 -42
  166. package/src/internals/transformTRPCResponse.ts +20 -15
  167. package/src/observable/index.ts +4 -0
  168. package/src/observable/internals/identity.ts +3 -0
  169. package/src/observable/internals/observableToPromise.ts +49 -0
  170. package/src/observable/internals/pipe.ts +22 -0
  171. package/src/observable/observable.test.ts +101 -0
  172. package/src/observable/observable.ts +75 -0
  173. package/src/observable/operators/index.ts +3 -0
  174. package/src/observable/operators/map.test.ts +92 -0
  175. package/src/observable/operators/map.ts +25 -0
  176. package/src/observable/operators/share.test.ts +60 -0
  177. package/src/observable/operators/share.ts +67 -0
  178. package/src/observable/operators/tap.ts +26 -0
  179. package/src/observable/types.ts +69 -0
  180. package/src/router.ts +96 -37
  181. package/src/rpc/codes.ts +1 -0
  182. package/src/rpc/envelopes.ts +87 -68
  183. package/src/subscription.ts +5 -123
  184. package/src/types.ts +7 -0
  185. package/dist/http/ResponseMeta.d.ts.map +0 -1
  186. package/dist/internals/wrapCallSafe.d.ts +0 -16
  187. package/dist/internals/wrapCallSafe.d.ts.map +0 -1
  188. package/dist/subscription-0d8a48ec.mjs +0 -133
  189. package/dist/subscription-41611bc2.js +0 -136
  190. package/dist/transformTRPCResponse-ff424ff4.mjs +0 -105
  191. package/src/internals/wrapCallSafe.ts +0 -19
  192. package/ws/dist/trpc-server-ws.cjs.d.ts +0 -1
  193. package/ws/dist/trpc-server-ws.cjs.dev.js +0 -15
  194. package/ws/dist/trpc-server-ws.cjs.js +0 -7
  195. package/ws/dist/trpc-server-ws.cjs.prod.js +0 -15
  196. package/ws/dist/trpc-server-ws.esm.js +0 -11
  197. package/ws/index.d.ts +0 -1
  198. package/ws/index.js +0 -1
@@ -2,9 +2,13 @@
2
2
  import { TRPCError } from '../TRPCError';
3
3
  import { assertNotBrowser } from '../assertNotBrowser';
4
4
  import { ProcedureType } from '../router';
5
- import { getErrorFromUnknown } from './errors';
6
- import { MiddlewareFunction, middlewareMarker } from './middlewares';
7
- import { wrapCallSafe } from './wrapCallSafe';
5
+ import { InferLast } from '../types';
6
+ import { getCauseFromUnknown, getErrorFromUnknown } from './errors';
7
+ import {
8
+ MiddlewareFunction,
9
+ MiddlewareResult,
10
+ middlewareMarker,
11
+ } from './middlewares';
8
12
 
9
13
  assertNotBrowser();
10
14
 
@@ -44,11 +48,12 @@ export type ProcedureResolver<TContext, TInput, TOutput> = (opts: {
44
48
  type: ProcedureType;
45
49
  }) => Promise<TOutput> | TOutput;
46
50
 
47
- interface ProcedureOptions<TContext, TInput, TOutput, TParsedOutput> {
48
- middlewares: Array<MiddlewareFunction<any, any>>;
51
+ interface ProcedureOptions<TContext, TMeta, TInput, TOutput, TParsedOutput> {
52
+ middlewares: Array<MiddlewareFunction<any, any, any>>;
49
53
  resolver: ProcedureResolver<TContext, TInput, TOutput>;
50
54
  inputParser: ProcedureParser<TInput>;
51
55
  outputParser: ProcedureParser<TParsedOutput>;
56
+ meta: TMeta;
52
57
  }
53
58
 
54
59
  /**
@@ -100,21 +105,29 @@ function getParseFn<T>(procedureParser: ProcedureParser<T>): ParseFn<T> {
100
105
  export class Procedure<
101
106
  TInputContext,
102
107
  TContext,
108
+ TMeta,
103
109
  TInput,
104
110
  TParsedInput,
105
111
  TOutput,
106
112
  TParsedOutput,
107
113
  TFinalOutput = unknown extends TParsedOutput ? TOutput : TParsedOutput,
108
114
  > {
109
- private middlewares: Readonly<Array<MiddlewareFunction<any, any>>>;
115
+ private middlewares: Readonly<Array<MiddlewareFunction<any, any, any>>>;
110
116
  private resolver: ProcedureResolver<TContext, TParsedInput, TOutput>;
111
117
  private readonly inputParser: ProcedureParser<TParsedInput>;
112
118
  private parseInputFn: ParseFn<TParsedInput>;
113
119
  private readonly outputParser: ProcedureParser<TFinalOutput>;
114
120
  private parseOutputFn: ParseFn<TFinalOutput>;
121
+ public readonly meta: TMeta;
115
122
 
116
123
  constructor(
117
- opts: ProcedureOptions<TContext, TParsedInput, TOutput, TFinalOutput>,
124
+ opts: ProcedureOptions<
125
+ TContext,
126
+ TMeta,
127
+ TParsedInput,
128
+ TOutput,
129
+ TFinalOutput
130
+ >,
118
131
  ) {
119
132
  this.middlewares = opts.middlewares;
120
133
  this.resolver = opts.resolver;
@@ -122,6 +135,7 @@ export class Procedure<
122
135
  this.parseInputFn = getParseFn(this.inputParser);
123
136
  this.outputParser = opts.outputParser;
124
137
  this.parseOutputFn = getParseFn(this.outputParser);
138
+ this.meta = opts.meta;
125
139
  }
126
140
 
127
141
  private async parseInput(rawInput: unknown): Promise<TParsedInput> {
@@ -130,7 +144,7 @@ export class Procedure<
130
144
  } catch (cause) {
131
145
  throw new TRPCError({
132
146
  code: 'BAD_REQUEST',
133
- cause,
147
+ cause: getCauseFromUnknown(cause),
134
148
  });
135
149
  }
136
150
  }
@@ -141,7 +155,7 @@ export class Procedure<
141
155
  } catch (cause) {
142
156
  throw new TRPCError({
143
157
  code: 'INTERNAL_SERVER_ERROR',
144
- cause,
158
+ cause: getCauseFromUnknown(cause),
145
159
  message: 'Output validation failed',
146
160
  });
147
161
  }
@@ -156,9 +170,13 @@ export class Procedure<
156
170
  ): Promise<TFinalOutput> {
157
171
  // wrap the actual resolver and treat as the last "middleware"
158
172
  const middlewaresWithResolver = this.middlewares.concat([
159
- async ({ ctx }: { ctx: TContext }) => {
173
+ async ({ ctx }: { ctx: any }) => {
160
174
  const input = await this.parseInput(opts.rawInput);
161
- const rawOutput = await this.resolver({ ...opts, ctx, input });
175
+ const rawOutput = await this.resolver({
176
+ ...opts,
177
+ ctx,
178
+ input,
179
+ });
162
180
  const data = await this.parseOutput(rawOutput);
163
181
  return {
164
182
  marker: middlewareMarker,
@@ -169,30 +187,40 @@ export class Procedure<
169
187
  },
170
188
  ]);
171
189
 
172
- // create `next()` calls in resolvers
173
- const nextFns = middlewaresWithResolver.map((fn, index) => {
174
- return async (nextOpts?: { ctx: TContext }) => {
175
- const res = await wrapCallSafe(() =>
176
- fn({
177
- ctx: nextOpts ? nextOpts.ctx : opts.ctx,
178
- type: opts.type,
179
- path: opts.path,
180
- rawInput: opts.rawInput,
181
- next: nextFns[index + 1],
182
- }),
183
- );
184
- if (res.ok) {
185
- return res.data;
186
- }
190
+ // run the middlewares recursively with the resolver as the last one
191
+ const callRecursive = async (
192
+ callOpts: { ctx: any; index: number } = {
193
+ index: 0,
194
+ ctx: opts.ctx,
195
+ },
196
+ ): Promise<MiddlewareResult<any>> => {
197
+ try {
198
+ const result = await middlewaresWithResolver[callOpts.index]({
199
+ ctx: callOpts.ctx,
200
+ type: opts.type,
201
+ path: opts.path,
202
+ rawInput: opts.rawInput,
203
+ meta: this.meta,
204
+ next: async (nextOpts?: { ctx: any }) => {
205
+ return await callRecursive({
206
+ index: callOpts.index + 1,
207
+ ctx: nextOpts ? nextOpts.ctx : callOpts.ctx,
208
+ });
209
+ },
210
+ });
211
+ return result;
212
+ } catch (cause) {
187
213
  return {
188
- ok: false as const,
189
- error: getErrorFromUnknown(res.error),
214
+ ctx: callOpts.ctx,
215
+ ok: false,
216
+ error: getErrorFromUnknown(cause),
217
+ marker: middlewareMarker,
190
218
  };
191
- };
192
- });
219
+ }
220
+ };
193
221
 
194
222
  // there's always at least one "next" since we wrap this.resolver in a middleware
195
- const result = await nextFns[0]();
223
+ const result = await callRecursive();
196
224
  if (!result) {
197
225
  throw new TRPCError({
198
226
  code: 'INTERNAL_SERVER_ERROR',
@@ -213,14 +241,21 @@ export class Procedure<
213
241
  * @param middlewares
214
242
  */
215
243
  public inheritMiddlewares(
216
- middlewares: MiddlewareFunction<TInputContext, TContext>[],
244
+ middlewares: MiddlewareFunction<TInputContext, TContext, TMeta>[],
217
245
  ): this {
218
246
  const Constructor: {
219
247
  new (
220
- opts: ProcedureOptions<TContext, TParsedInput, TOutput, TFinalOutput>,
248
+ opts: ProcedureOptions<
249
+ TContext,
250
+ TMeta,
251
+ TParsedInput,
252
+ TOutput,
253
+ TFinalOutput
254
+ >,
221
255
  ): Procedure<
222
256
  TInputContext,
223
257
  TContext,
258
+ TMeta,
224
259
  TInput,
225
260
  TParsedInput,
226
261
  TOutput,
@@ -233,20 +268,23 @@ export class Procedure<
233
268
  resolver: this.resolver,
234
269
  inputParser: this.inputParser,
235
270
  outputParser: this.outputParser,
271
+ meta: this.meta,
236
272
  });
237
273
 
238
274
  return instance as any;
239
275
  }
240
276
  }
241
277
 
242
- export type CreateProcedureWithInput<TContext, TInput, TOutput> = {
278
+ export type CreateProcedureWithInput<TContext, TMeta, TInput, TOutput> = {
243
279
  input: ProcedureParser<TInput>;
244
280
  output?: ProcedureParser<TOutput>;
245
- resolve: ProcedureResolver<TContext, TInput, TOutput>;
281
+ meta?: TMeta;
282
+ resolve: ProcedureResolver<TContext, TInput, InferLast<TOutput>>;
246
283
  };
247
284
 
248
285
  export type CreateProcedureWithInputOutputParser<
249
286
  TContext,
287
+ TMeta,
250
288
  TInput,
251
289
  TParsedInput,
252
290
  TOutput,
@@ -254,18 +292,26 @@ export type CreateProcedureWithInputOutputParser<
254
292
  > = {
255
293
  input: ProcedureParserWithInputOutput<TInput, TParsedInput>;
256
294
  output?: ProcedureParserWithInputOutput<TOutput, TParsedOutput>;
257
- resolve: ProcedureResolver<TContext, TParsedInput, TOutput>;
295
+ meta?: TMeta;
296
+ resolve: ProcedureResolver<TContext, TParsedInput, InferLast<TOutput>>;
258
297
  };
259
298
 
260
- export type CreateProcedureWithoutInput<TContext, TOutput, TParsedOutput> = {
299
+ export type CreateProcedureWithoutInput<
300
+ TContext,
301
+ TMeta,
302
+ TOutput,
303
+ TParsedOutput,
304
+ > = {
261
305
  output?:
262
306
  | ProcedureParserWithInputOutput<TOutput, TParsedOutput>
263
307
  | ProcedureParser<TOutput>;
264
- resolve: ProcedureResolver<TContext, undefined, TOutput>;
308
+ meta?: TMeta;
309
+ resolve: ProcedureResolver<TContext, undefined, InferLast<TOutput>>;
265
310
  };
266
311
 
267
312
  export type CreateProcedureOptions<
268
313
  TContext,
314
+ TMeta = undefined,
269
315
  TInput = undefined,
270
316
  TParsedInput = undefined,
271
317
  TOutput = undefined,
@@ -273,16 +319,18 @@ export type CreateProcedureOptions<
273
319
  > =
274
320
  | CreateProcedureWithInputOutputParser<
275
321
  TContext,
322
+ TMeta,
276
323
  TInput,
277
324
  TParsedInput,
278
325
  TOutput,
279
326
  TParsedOutput
280
327
  >
281
- | CreateProcedureWithInput<TContext, TInput, TOutput>
282
- | CreateProcedureWithoutInput<TContext, TOutput, TParsedOutput>;
328
+ | CreateProcedureWithInput<TContext, TMeta, TInput, TOutput>
329
+ | CreateProcedureWithoutInput<TContext, TMeta, TOutput, TParsedOutput>;
283
330
 
284
331
  export function createProcedure<
285
332
  TContext,
333
+ TMeta,
286
334
  TInput,
287
335
  TParsedInput,
288
336
  TOutput,
@@ -290,12 +338,21 @@ export function createProcedure<
290
338
  >(
291
339
  opts: CreateProcedureOptions<
292
340
  TContext,
341
+ TMeta,
293
342
  TInput,
294
343
  TParsedInput,
295
344
  TOutput,
296
345
  TParsedOutput
297
346
  >,
298
- ): Procedure<unknown, TContext, TInput, TParsedInput, TOutput, TParsedOutput> {
347
+ ): Procedure<
348
+ unknown,
349
+ TContext,
350
+ TMeta,
351
+ TInput,
352
+ TParsedInput,
353
+ TOutput,
354
+ TParsedOutput
355
+ > {
299
356
  const inputParser =
300
357
  'input' in opts
301
358
  ? opts.input
@@ -319,14 +376,16 @@ export function createProcedure<
319
376
  resolver: opts.resolve as any,
320
377
  middlewares: [],
321
378
  outputParser: outputParser as any,
379
+ meta: opts.meta as any,
322
380
  });
323
381
  }
324
382
 
325
383
  export type inferProcedureFromOptions<
326
384
  TInputContext,
327
- TOptions extends CreateProcedureOptions<any, any, any, any, any>,
385
+ TOptions extends CreateProcedureOptions<any, any, any, any, any, any>,
328
386
  > = TOptions extends CreateProcedureOptions<
329
387
  infer TContext,
388
+ infer TMeta,
330
389
  infer TInput,
331
390
  infer TParsedInput,
332
391
  infer TOutput,
@@ -335,6 +394,7 @@ export type inferProcedureFromOptions<
335
394
  ? Procedure<
336
395
  TInputContext,
337
396
  TContext,
397
+ TMeta,
338
398
  unknown extends TInput ? undefined : TInput,
339
399
  unknown extends TParsedInput ? undefined : TParsedInput,
340
400
  TOutput,
@@ -1,33 +1,38 @@
1
1
  import { AnyRouter } from '../router';
2
- import { TRPCResponse } from '../rpc';
2
+ import { TRPCResponse, TRPCResponseMessage } from '../rpc';
3
3
 
4
- function transformTRPCResponseItem(
5
- router: AnyRouter,
6
- item: TRPCResponse,
7
- ): TRPCResponse {
4
+ function transformTRPCResponseItem<
5
+ TResponseItem extends TRPCResponse | TRPCResponseMessage,
6
+ >(router: AnyRouter, item: TResponseItem): TResponseItem {
8
7
  if ('error' in item) {
9
8
  return {
10
9
  ...item,
11
10
  error: router._def.transformer.output.serialize(item.error),
12
11
  };
13
12
  }
14
- if (item.result.type !== 'data') {
15
- return item;
13
+
14
+ if ('data' in item.result) {
15
+ return {
16
+ ...item,
17
+ result: {
18
+ ...item.result,
19
+ data: router._def.transformer.output.serialize(item.result.data),
20
+ },
21
+ };
16
22
  }
17
- return {
18
- ...item,
19
- result: {
20
- ...item.result,
21
- data: router._def.transformer.output.serialize(item.result.data),
22
- },
23
- };
23
+
24
+ return item;
24
25
  }
25
26
 
26
27
  /**
27
28
  * Takes a unserialized `TRPCResponse` and serializes it with the router's transformers
28
29
  **/
29
30
  export function transformTRPCResponse<
30
- TResponse extends TRPCResponse | TRPCResponse[],
31
+ TResponse extends
32
+ | TRPCResponse
33
+ | TRPCResponse[]
34
+ | TRPCResponseMessage
35
+ | TRPCResponseMessage[],
31
36
  >(router: AnyRouter, itemOrItems: TResponse) {
32
37
  return Array.isArray(itemOrItems)
33
38
  ? itemOrItems.map((item) => transformTRPCResponseItem(router, item))
@@ -0,0 +1,4 @@
1
+ export * from './observable';
2
+ export * from './types';
3
+ export * from './operators';
4
+ export { observableToPromise } from './internals/observableToPromise';
@@ -0,0 +1,3 @@
1
+ export function identity<T>(x: T): T {
2
+ return x;
3
+ }
@@ -0,0 +1,49 @@
1
+ import { Observable } from '../types';
2
+
3
+ export class ObservableAbortError extends Error {
4
+ constructor(message: string) {
5
+ super(message);
6
+ this.name = 'ObservableAbortError';
7
+ Object.setPrototypeOf(this, ObservableAbortError.prototype);
8
+ }
9
+ }
10
+
11
+ /** @internal */
12
+ export function observableToPromise<TValue>(
13
+ observable: Observable<TValue, unknown>,
14
+ ) {
15
+ let abort: () => void;
16
+ const promise = new Promise<TValue>((resolve, reject) => {
17
+ let isDone = false;
18
+ function onDone() {
19
+ if (isDone) {
20
+ return;
21
+ }
22
+ isDone = true;
23
+ reject(new ObservableAbortError('This operation was cancelled.'));
24
+ obs$.unsubscribe();
25
+ }
26
+ const obs$ = observable.subscribe({
27
+ next(data) {
28
+ isDone = true;
29
+ resolve(data);
30
+ onDone();
31
+ },
32
+ error(data) {
33
+ isDone = true;
34
+ reject(data);
35
+ onDone();
36
+ },
37
+ complete() {
38
+ isDone = true;
39
+ onDone();
40
+ },
41
+ });
42
+ abort = onDone;
43
+ });
44
+ return {
45
+ promise,
46
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
47
+ abort: abort!,
48
+ };
49
+ }
@@ -0,0 +1,22 @@
1
+ import { UnaryFunction } from '../types';
2
+ import { identity } from './identity';
3
+
4
+ /** @internal */
5
+ export function pipeFromArray<T, R>(
6
+ fns: Array<UnaryFunction<T, R>>,
7
+ ): UnaryFunction<T, R> {
8
+ if (fns.length === 0) {
9
+ return identity as UnaryFunction<any, any>;
10
+ }
11
+
12
+ if (fns.length === 1) {
13
+ return fns[0];
14
+ }
15
+
16
+ return function piped(input: T): R {
17
+ return fns.reduce(
18
+ (prev: any, fn: UnaryFunction<T, R>) => fn(prev),
19
+ input as any,
20
+ );
21
+ };
22
+ }
@@ -0,0 +1,101 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import { observable, share, tap } from '.';
3
+
4
+ test('vanilla observable - complete()', () => {
5
+ const obs = observable<number, Error>((observer) => {
6
+ observer.next(1);
7
+ observer.complete();
8
+ });
9
+
10
+ const next = jest.fn();
11
+ const error = jest.fn();
12
+ const complete = jest.fn();
13
+ obs.subscribe({
14
+ next,
15
+ error,
16
+ complete,
17
+ });
18
+ expect(next.mock.calls).toHaveLength(1);
19
+ expect(complete.mock.calls).toHaveLength(1);
20
+ expect(error.mock.calls).toHaveLength(0);
21
+ expect(next.mock.calls[0][0]).toBe(1);
22
+ });
23
+
24
+ test('vanilla observable - unsubscribe()', () => {
25
+ const obs$ = observable<number, Error>((observer) => {
26
+ observer.next(1);
27
+ });
28
+
29
+ const next = jest.fn();
30
+ const error = jest.fn();
31
+ const complete = jest.fn();
32
+ const sub = obs$.subscribe({
33
+ next,
34
+ error,
35
+ complete,
36
+ });
37
+ sub.unsubscribe();
38
+ expect(next.mock.calls).toHaveLength(1);
39
+ expect(complete.mock.calls).toHaveLength(0);
40
+ expect(error.mock.calls).toHaveLength(0);
41
+ expect(next.mock.calls[0][0]).toBe(1);
42
+ });
43
+
44
+ test('pipe - combine operators', () => {
45
+ const taps = {
46
+ next: jest.fn(),
47
+ complete: jest.fn(),
48
+ error: jest.fn(),
49
+ };
50
+ const obs = observable<number, Error>((observer) => {
51
+ observer.next(1);
52
+ }).pipe(
53
+ // operators:
54
+ share(),
55
+ tap(taps),
56
+ );
57
+ {
58
+ const next = jest.fn();
59
+ const error = jest.fn();
60
+ const complete = jest.fn();
61
+ obs.subscribe({
62
+ next,
63
+ error,
64
+ complete,
65
+ });
66
+ expect(next.mock.calls).toHaveLength(1);
67
+ expect(complete.mock.calls).toHaveLength(0);
68
+ expect(error.mock.calls).toHaveLength(0);
69
+ expect(next.mock.calls[0][0]).toBe(1);
70
+ }
71
+
72
+ {
73
+ const next = jest.fn();
74
+ const error = jest.fn();
75
+ const complete = jest.fn();
76
+ obs.subscribe({
77
+ next,
78
+ error,
79
+ complete,
80
+ });
81
+ expect(next.mock.calls).toHaveLength(0);
82
+ expect(complete.mock.calls).toHaveLength(0);
83
+ expect(error.mock.calls).toHaveLength(0);
84
+ }
85
+
86
+ expect({
87
+ next: taps.next.mock.calls,
88
+ error: taps.error.mock.calls,
89
+ complete: taps.complete.mock.calls,
90
+ }).toMatchInlineSnapshot(`
91
+ Object {
92
+ "complete": Array [],
93
+ "error": Array [],
94
+ "next": Array [
95
+ Array [
96
+ 1,
97
+ ],
98
+ ],
99
+ }
100
+ `);
101
+ });
@@ -0,0 +1,75 @@
1
+ import { pipeFromArray } from './internals/pipe';
2
+ import { Observable, Observer, OperatorFunction, TeardownLogic } from './types';
3
+
4
+ export type inferObservableValue<
5
+ TObservable extends Observable<unknown, unknown>,
6
+ > = TObservable extends Observable<infer TValue, unknown> ? TValue : never;
7
+
8
+ export function isObservable(x: unknown): x is Observable<unknown, unknown> {
9
+ return typeof x === 'object' && x !== null && 'subscribe' in x;
10
+ }
11
+
12
+ export function observable<TValue, TError = unknown>(
13
+ subscribe: (observer: Observer<TValue, TError>) => TeardownLogic,
14
+ ): Observable<TValue, TError> {
15
+ const self: Observable<TValue, TError> = {
16
+ subscribe(observer) {
17
+ let teardownRef: TeardownLogic | null = null;
18
+ let isDone = false;
19
+ let unsubscribed = false;
20
+ let teardownImmediately = false;
21
+ function unsubscribe() {
22
+ if (teardownRef === null) {
23
+ teardownImmediately = true;
24
+ return;
25
+ }
26
+ if (unsubscribed) {
27
+ return;
28
+ }
29
+ unsubscribed = true;
30
+
31
+ if (typeof teardownRef === 'function') {
32
+ teardownRef();
33
+ } else if (teardownRef) {
34
+ teardownRef.unsubscribe();
35
+ }
36
+ }
37
+ teardownRef = subscribe({
38
+ next(value) {
39
+ if (isDone) {
40
+ return;
41
+ }
42
+ observer.next?.(value);
43
+ },
44
+ error(err) {
45
+ if (isDone) {
46
+ return;
47
+ }
48
+ isDone = true;
49
+ observer.error?.(err);
50
+ unsubscribe();
51
+ },
52
+ complete() {
53
+ if (isDone) {
54
+ return;
55
+ }
56
+ isDone = true;
57
+ observer.complete?.();
58
+ unsubscribe();
59
+ },
60
+ });
61
+ if (teardownImmediately) {
62
+ unsubscribe();
63
+ }
64
+ return {
65
+ unsubscribe,
66
+ };
67
+ },
68
+ pipe(
69
+ ...operations: OperatorFunction<any, any, any, any>[]
70
+ ): Observable<any, any> {
71
+ return pipeFromArray(operations)(self) as any;
72
+ },
73
+ };
74
+ return self;
75
+ }
@@ -0,0 +1,3 @@
1
+ export * from './share';
2
+ export * from './map';
3
+ export * from './tap';