@orpc/server 0.1.0 → 0.1.2

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 (65) hide show
  1. package/dist/chunk-26DTFWOI.js +200 -0
  2. package/dist/chunk-26DTFWOI.js.map +1 -0
  3. package/dist/fetch.js +87 -91
  4. package/dist/fetch.js.map +1 -1
  5. package/dist/index.js +6 -9
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/adapters/fetch.d.ts +9 -3
  8. package/dist/src/adapters/fetch.d.ts.map +1 -1
  9. package/dist/src/builder.d.ts +4 -4
  10. package/dist/src/builder.d.ts.map +1 -1
  11. package/dist/src/index.d.ts +2 -2
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/middleware.d.ts +17 -7
  14. package/dist/src/middleware.d.ts.map +1 -1
  15. package/dist/src/procedure-builder.d.ts +4 -4
  16. package/dist/src/procedure-builder.d.ts.map +1 -1
  17. package/dist/src/procedure-caller.d.ts +0 -5
  18. package/dist/src/procedure-caller.d.ts.map +1 -1
  19. package/dist/src/procedure-implementer.d.ts +4 -5
  20. package/dist/src/procedure-implementer.d.ts.map +1 -1
  21. package/dist/src/procedure.d.ts +8 -9
  22. package/dist/src/procedure.d.ts.map +1 -1
  23. package/dist/src/router-builder.d.ts +2 -2
  24. package/dist/src/router-builder.d.ts.map +1 -1
  25. package/dist/src/router-caller.d.ts +1 -6
  26. package/dist/src/router-caller.d.ts.map +1 -1
  27. package/dist/src/router-implementer.d.ts +2 -2
  28. package/dist/src/router-implementer.d.ts.map +1 -1
  29. package/dist/src/router.d.ts +1 -1
  30. package/dist/src/router.d.ts.map +1 -1
  31. package/dist/src/types.d.ts +1 -10
  32. package/dist/src/types.d.ts.map +1 -1
  33. package/dist/src/utils.d.ts +1 -2
  34. package/dist/src/utils.d.ts.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +5 -5
  37. package/src/adapters/fetch.test.ts +32 -17
  38. package/src/adapters/fetch.ts +134 -123
  39. package/src/builder.test.ts +48 -39
  40. package/src/builder.ts +32 -30
  41. package/src/index.ts +2 -2
  42. package/src/middleware.test.ts +54 -73
  43. package/src/middleware.ts +39 -22
  44. package/src/procedure-builder.test.ts +26 -22
  45. package/src/procedure-builder.ts +15 -15
  46. package/src/procedure-caller.test.ts +25 -70
  47. package/src/procedure-caller.ts +69 -88
  48. package/src/procedure-implementer.test.ts +27 -22
  49. package/src/procedure-implementer.ts +16 -17
  50. package/src/procedure.test.ts +17 -12
  51. package/src/procedure.ts +46 -45
  52. package/src/router-builder.test.ts +4 -4
  53. package/src/router-builder.ts +12 -10
  54. package/src/router-caller.test.ts +6 -6
  55. package/src/router-caller.ts +5 -16
  56. package/src/router-implementer.test.ts +12 -12
  57. package/src/router-implementer.ts +9 -6
  58. package/src/router.test.ts +4 -4
  59. package/src/router.ts +12 -10
  60. package/src/types.test.ts +1 -1
  61. package/src/types.ts +1 -15
  62. package/src/utils.test.ts +2 -229
  63. package/src/utils.ts +5 -84
  64. package/dist/chunk-ACLC6USM.js +0 -262
  65. package/dist/chunk-ACLC6USM.js.map +0 -1
package/src/builder.ts CHANGED
@@ -1,34 +1,34 @@
1
+ import type { IsEqual } from '@orpc/shared'
2
+ import type { HandledRouter, Router } from './router'
3
+ import type { Context, MergeContext } from './types'
1
4
  import {
2
5
  ContractProcedure,
3
6
  type ContractRouter,
4
7
  type HTTPPath,
8
+ isContractProcedure,
5
9
  type RouteOptions,
6
10
  type Schema,
7
11
  type SchemaInput,
8
12
  type SchemaOutput,
9
- isContractProcedure,
10
13
  } from '@orpc/contract'
11
- import type { IsEqual } from '@orpc/shared'
12
14
  import {
13
15
  type DecoratedMiddleware,
16
+ decorateMiddleware,
14
17
  type MapInputMiddleware,
15
18
  type Middleware,
16
- decorateMiddleware,
17
19
  } from './middleware'
18
20
  import {
19
21
  type DecoratedProcedure,
20
- type ProcedureHandler,
21
22
  decorateProcedure,
23
+ type ProcedureHandler,
22
24
  } from './procedure'
23
25
  import { ProcedureBuilder } from './procedure-builder'
24
26
  import { ProcedureImplementer } from './procedure-implementer'
25
- import type { HandledRouter, Router } from './router'
26
27
  import { RouterBuilder } from './router-builder'
27
28
  import {
28
29
  type ChainedRouterImplementer,
29
30
  chainRouterImplementer,
30
31
  } from './router-implementer'
31
- import type { Context, MergeContext } from './types'
32
32
 
33
33
  export class Builder<TContext extends Context, TExtraContext extends Context> {
34
34
  constructor(
@@ -49,8 +49,8 @@ export class Builder<TContext extends Context, TExtraContext extends Context> {
49
49
 
50
50
  use<
51
51
  UExtraContext extends
52
- | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
53
- | undefined = undefined,
52
+ | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
53
+ | undefined = undefined,
54
54
  >(
55
55
  middleware: Middleware<
56
56
  MergeContext<TContext, TExtraContext>,
@@ -62,8 +62,8 @@ export class Builder<TContext extends Context, TExtraContext extends Context> {
62
62
 
63
63
  use<
64
64
  UExtraContext extends
65
- | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
66
- | undefined = undefined,
65
+ | Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
66
+ | undefined = undefined,
67
67
  UMappedInput = unknown,
68
68
  >(
69
69
  middleware: Middleware<
@@ -146,12 +146,12 @@ export class Builder<TContext extends Context, TExtraContext extends Context> {
146
146
  UHandlerOutput
147
147
  >,
148
148
  ): DecoratedProcedure<
149
- TContext,
150
- TExtraContext,
151
- undefined,
152
- undefined,
153
- UHandlerOutput
154
- > {
149
+ TContext,
150
+ TExtraContext,
151
+ undefined,
152
+ undefined,
153
+ UHandlerOutput
154
+ > {
155
155
  return decorateProcedure({
156
156
  zz$p: {
157
157
  middlewares: this.zz$b.middlewares,
@@ -171,13 +171,13 @@ export class Builder<TContext extends Context, TExtraContext extends Context> {
171
171
  contract<UContract extends ContractProcedure<any, any> | ContractRouter>(
172
172
  contract: UContract,
173
173
  ): UContract extends ContractProcedure<
174
- infer UInputSchema,
175
- infer UOutputSchema
176
- >
177
- ? ProcedureImplementer<TContext, TExtraContext, UInputSchema, UOutputSchema>
178
- : UContract extends ContractRouter
179
- ? ChainedRouterImplementer<TContext, UContract, TExtraContext>
180
- : never {
174
+ infer UInputSchema,
175
+ infer UOutputSchema
176
+ >
177
+ ? ProcedureImplementer<TContext, TExtraContext, UInputSchema, UOutputSchema>
178
+ : UContract extends ContractRouter
179
+ ? ChainedRouterImplementer<TContext, UContract, TExtraContext>
180
+ : never {
181
181
  if (isContractProcedure(contract)) {
182
182
  return new ProcedureImplementer({
183
183
  contract,
@@ -195,19 +195,21 @@ export class Builder<TContext extends Context, TExtraContext extends Context> {
195
195
  * Create ExtendedMiddleware
196
196
  */
197
197
 
198
- middleware<UExtraContext extends Context = undefined, TInput = unknown>(
198
+ // TODO: TOutput always any, infer not work at all, because TOutput used inside middleware params,
199
+ // solution (maybe): create new generic for .output() method
200
+ middleware<UExtraContext extends Context = undefined, TInput = unknown, TOutput = any>(
199
201
  middleware: Middleware<
200
202
  MergeContext<TContext, TExtraContext>,
201
203
  UExtraContext,
202
204
  TInput,
203
- unknown
205
+ TOutput
204
206
  >,
205
207
  ): DecoratedMiddleware<
206
- MergeContext<TContext, TExtraContext>,
207
- UExtraContext,
208
- TInput,
209
- unknown
210
- > {
208
+ MergeContext<TContext, TExtraContext>,
209
+ UExtraContext,
210
+ TInput,
211
+ TOutput
212
+ > {
211
213
  return decorateMiddleware(middleware)
212
214
  }
213
215
 
package/src/index.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import { Builder } from './builder'
2
2
 
3
3
  export * from './builder'
4
- export * from '@orpc/shared/error'
5
4
  export * from './middleware'
6
5
  export * from './procedure'
7
- export * from './procedure-caller'
8
6
  export * from './procedure-builder'
7
+ export * from './procedure-caller'
9
8
  export * from './procedure-implementer'
10
9
  export * from './router'
11
10
  export * from './router-caller'
12
11
  export * from './router-implementer'
13
12
  export * from './types'
14
13
  export * from './utils'
14
+ export * from '@orpc/shared/error'
15
15
 
16
16
  export const os = new Builder<undefined | Record<string, unknown>, undefined>()
@@ -1,9 +1,6 @@
1
- import {
2
- type DecoratedMiddleware,
3
- type Middleware,
4
- decorateMiddleware,
5
- } from './middleware'
6
- import type { Meta } from './types'
1
+ import type { DecoratedMiddleware, Middleware, MiddlewareMeta } from './middleware'
2
+ import { os } from '.'
3
+ import { decorateMiddleware } from './middleware'
7
4
 
8
5
  describe('middleware', () => {
9
6
  it('just a function', () => {
@@ -15,13 +12,9 @@ describe('middleware', () => {
15
12
  > = (input, context, meta) => {
16
13
  expectTypeOf(input).toEqualTypeOf<unknown>()
17
14
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
18
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
15
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta< unknown>>()
19
16
 
20
- return {
21
- context: {
22
- userId: '1',
23
- },
24
- }
17
+ return meta.next({ context: { userId: '1' } })
25
18
  }
26
19
  })
27
20
 
@@ -34,16 +27,12 @@ describe('middleware', () => {
34
27
  > = (input, context, meta) => {
35
28
  expectTypeOf(input).toEqualTypeOf<unknown>()
36
29
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
37
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
30
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta< unknown>>()
38
31
 
39
- return {
40
- context: {
41
- userId: '1',
42
- },
43
- }
32
+ return meta.next({ context: { userId: '1' } })
44
33
  }
45
34
 
46
- // @ts-expect-error mid is not return extra context
35
+ // @ts-expect-error mid must call next
47
36
  const mid2: Middleware<
48
37
  { auth: boolean },
49
38
  { userId: string },
@@ -52,7 +41,7 @@ describe('middleware', () => {
52
41
  > = (input, context, meta) => {
53
42
  expectTypeOf(input).toEqualTypeOf<unknown>()
54
43
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
55
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
44
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta< unknown>>()
56
45
  }
57
46
 
58
47
  // @ts-expect-error mid return invalid context
@@ -64,42 +53,13 @@ describe('middleware', () => {
64
53
  > = (input, context, meta) => {
65
54
  expectTypeOf(input).toEqualTypeOf<unknown>()
66
55
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
67
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
56
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
68
57
 
69
- return {
58
+ return meta.next({
70
59
  context: {
71
60
  valid: false,
72
61
  },
73
- }
74
- }
75
- })
76
-
77
- it('not allow return if has no extra context', () => {
78
- const mid: Middleware<{ auth: boolean }, undefined, unknown, unknown> = (
79
- input,
80
- context,
81
- meta,
82
- ) => {
83
- expectTypeOf(input).toEqualTypeOf<unknown>()
84
- expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
85
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
86
- }
87
-
88
- // @ts-expect-error mid2 is not return extra context
89
- const mid2: Middleware<{ auth: boolean }, undefined, unknown, unknown> = (
90
- input,
91
- context,
92
- meta,
93
- ) => {
94
- expectTypeOf(input).toEqualTypeOf<unknown>()
95
- expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
96
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
97
-
98
- return {
99
- context: {
100
- userId: '1',
101
- },
102
- }
62
+ })
103
63
  }
104
64
  })
105
65
  })
@@ -114,13 +74,13 @@ describe('decorateMiddleware', () => {
114
74
  >((input, context, meta) => {
115
75
  expectTypeOf(input).toEqualTypeOf<{ id: string }>()
116
76
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
117
- expectTypeOf(meta).toEqualTypeOf<Meta<{ name: string }>>()
77
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<{ name: string }>>()
118
78
 
119
- return {
79
+ return meta.next({
120
80
  context: {
121
81
  userId: '1',
122
82
  },
123
- }
83
+ })
124
84
  })
125
85
 
126
86
  expectTypeOf(mid).toEqualTypeOf<
@@ -148,16 +108,16 @@ describe('decorateMiddleware', () => {
148
108
  undefined,
149
109
  { id: string },
150
110
  { name: string }
151
- >(() => {}).concat((input, context, meta) => {
111
+ >((_, __, meta) => meta.next({})).concat(async (input, context, meta) => {
152
112
  expectTypeOf(input).toEqualTypeOf<{ id: string }>()
153
113
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
154
- expectTypeOf(meta).toEqualTypeOf<Meta<{ name: string }>>()
114
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<{ name: string }>>()
155
115
 
156
- return {
116
+ return meta.next({
157
117
  context: {
158
118
  userId: '1',
159
119
  },
160
- }
120
+ })
161
121
  })
162
122
 
163
123
  expectTypeOf(mid).toEqualTypeOf<
@@ -176,9 +136,9 @@ describe('decorateMiddleware', () => {
176
136
  undefined,
177
137
  unknown,
178
138
  unknown
179
- >(() => {})
180
- .concat((input: { id: string }) => {})
181
- .concat((input: { status: string }) => {})
139
+ >((_, __, meta) => meta.next({}))
140
+ .concat((input: { id: string }, _, meta) => meta.next({}))
141
+ .concat((input: { status: string }, _, meta) => meta.next({}))
182
142
 
183
143
  expectTypeOf(mid).toEqualTypeOf<
184
144
  DecoratedMiddleware<
@@ -190,20 +150,20 @@ describe('decorateMiddleware', () => {
190
150
  >()
191
151
 
192
152
  // MID2 isn't usable because input type is wrong
193
- const mid2 = mid.concat((input: { id: number }) => {})
153
+ const mid2 = mid.concat((input: { id: number }, _, meta) => meta.next({}))
194
154
  expectTypeOf(mid2).toMatchTypeOf<
195
155
  DecoratedMiddleware<
196
156
  { auth: boolean },
197
157
  undefined,
198
- { id: never; status: string },
158
+ { id: never, status: string },
199
159
  unknown
200
160
  >
201
161
  >()
202
162
  })
203
163
 
204
164
  it('concat: deep copy', () => {
205
- const middleware = decorateMiddleware(() => {})
206
- const mid2 = middleware.concat(() => {})
165
+ const middleware = decorateMiddleware((_, __, meta) => meta.next({}))
166
+ const mid2 = middleware.concat((_, __, meta) => meta.next({}))
207
167
  expect(mid2).not.toBe(middleware)
208
168
  })
209
169
 
@@ -213,13 +173,11 @@ describe('decorateMiddleware', () => {
213
173
  undefined,
214
174
  unknown,
215
175
  unknown
216
- >(() => {})
176
+ >((_, __, meta) => meta.next({}))
217
177
 
218
178
  const mid2 = middleware.concat(
219
- (input: { postId: number }) => {
220
- return { context: { a: 'a' } }
221
- },
222
- (input) => ({ postId: 12455 }),
179
+ (input: { postId: number }, _, meta) => meta.next({ context: { a: 'a' } }),
180
+ input => ({ postId: 12455 }),
223
181
  )
224
182
 
225
183
  // mid2 input is unknown, because it's map input does not expect anything
@@ -229,9 +187,11 @@ describe('decorateMiddleware', () => {
229
187
 
230
188
  const fn = vi.fn()
231
189
  const mid3 = middleware.concat(
232
- (input: { postId: string }) => {
190
+ (input: { postId: string }, _, meta) => {
233
191
  fn()
234
192
  expect(input).toEqual({ postId: '123' })
193
+
194
+ return meta.next({})
235
195
  },
236
196
  (input: { postId: number }) => {
237
197
  fn()
@@ -242,7 +202,7 @@ describe('decorateMiddleware', () => {
242
202
  },
243
203
  )
244
204
 
245
- await mid3({ postId: 123 }, {} as any, {} as any)
205
+ await mid3({ postId: 123 }, {} as any, { next: () => {} } as any)
246
206
  expect(fn).toHaveBeenCalledTimes(2)
247
207
 
248
208
  // INPUT now follow expect types from map not from middleware
@@ -277,3 +237,24 @@ describe('decorateMiddleware', () => {
277
237
  expect(fn).toHaveBeenCalledWith({ id: '1' }, undefined, {})
278
238
  })
279
239
  })
240
+
241
+ it('middleware can output', async () => {
242
+ let mid2Called = false
243
+ let handlerCalled = false
244
+ const ping = os
245
+ .use((input, ctx, meta) => {
246
+ return meta.output('from middleware')
247
+ })
248
+ .use((input, ctx, meta) => {
249
+ mid2Called = true
250
+ return meta.output('from middleware 2')
251
+ })
252
+ .handler(() => {
253
+ handlerCalled = true
254
+ return 'from handler'
255
+ })
256
+
257
+ expect(await ping(undefined)).toBe('from middleware')
258
+ expect(mid2Called).toBeFalsy()
259
+ expect(handlerCalled).toBeFalsy()
260
+ })
package/src/middleware.ts CHANGED
@@ -1,6 +1,21 @@
1
- import type { Context, MergeContext, Meta, Promisable } from './types'
1
+ import type { Promisable } from '@orpc/shared'
2
+ import type { Context, MergeContext, Meta } from './types'
2
3
  import { mergeContext } from './utils'
3
4
 
5
+ export type MiddlewareResult<TExtraContext extends Context, TOutput> = Promisable<{
6
+ output: TOutput
7
+ context: TExtraContext
8
+ }>
9
+
10
+ export interface MiddlewareMeta<
11
+ TOutput,
12
+ > extends Meta {
13
+ next: <UExtraContext extends Context = undefined>(
14
+ options: UExtraContext extends undefined ? { context?: UExtraContext } : { context: UExtraContext }
15
+ ) => MiddlewareResult<UExtraContext, TOutput>
16
+ output: <UOutput>(output: UOutput) => MiddlewareResult<undefined, UOutput>
17
+ }
18
+
4
19
  export interface Middleware<
5
20
  TContext extends Context,
6
21
  TExtraContext extends Context,
@@ -10,9 +25,9 @@ export interface Middleware<
10
25
  (
11
26
  input: TInput,
12
27
  context: TContext,
13
- meta: Meta<TOutput>,
28
+ meta: MiddlewareMeta<TOutput>,
14
29
  ): Promisable<
15
- TExtraContext extends undefined ? void : { context: TExtraContext }
30
+ MiddlewareResult<TExtraContext, TOutput>
16
31
  >
17
32
  }
18
33
 
@@ -26,22 +41,23 @@ export interface DecoratedMiddleware<
26
41
  TInput,
27
42
  TOutput,
28
43
  > extends Middleware<TContext, TExtraContext, TInput, TOutput> {
29
- concat<UExtraContext extends Context = undefined, UInput = TInput>(
44
+ concat: (<
45
+ UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined,
46
+ UInput = TInput,
47
+ >(
30
48
  middleware: Middleware<
31
49
  MergeContext<TContext, TExtraContext>,
32
50
  UExtraContext,
33
51
  UInput & TInput,
34
52
  TOutput
35
53
  >,
36
- ): DecoratedMiddleware<
54
+ ) => DecoratedMiddleware<
37
55
  TContext,
38
56
  MergeContext<TExtraContext, UExtraContext>,
39
57
  TInput & UInput,
40
58
  TOutput
41
- >
42
-
43
- concat<
44
- UExtraContext extends Context = undefined,
59
+ >) & (<
60
+ UExtraContext extends Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>> | undefined = undefined,
45
61
  UInput = TInput,
46
62
  UMappedInput = unknown,
47
63
  >(
@@ -52,16 +68,16 @@ export interface DecoratedMiddleware<
52
68
  TOutput
53
69
  >,
54
70
  mapInput: MapInputMiddleware<UInput, UMappedInput>,
55
- ): DecoratedMiddleware<
71
+ ) => DecoratedMiddleware<
56
72
  TContext,
57
73
  MergeContext<TExtraContext, UExtraContext>,
58
74
  TInput & UInput,
59
75
  TOutput
60
- >
76
+ >)
61
77
 
62
- mapInput<UInput = unknown>(
78
+ mapInput: <UInput = unknown>(
63
79
  map: MapInputMiddleware<UInput, TInput>,
64
- ): DecoratedMiddleware<TContext, TExtraContext, UInput, TOutput>
80
+ ) => DecoratedMiddleware<TContext, TExtraContext, UInput, TOutput>
65
81
  }
66
82
 
67
83
  const decoratedMiddlewareSymbol = Symbol('🔒decoratedMiddleware')
@@ -81,7 +97,7 @@ export function decorateMiddleware<
81
97
  const concat = (
82
98
  concatMiddleware: Middleware<any, any, any, any>,
83
99
  mapInput?: MapInputMiddleware<any, any>,
84
- ) => {
100
+ ): Middleware<any, any, any, any> => {
85
101
  const concatMiddleware_ = mapInput
86
102
  ? decorateMiddleware(concatMiddleware).mapInput(mapInput)
87
103
  : concatMiddleware
@@ -91,15 +107,16 @@ export function decorateMiddleware<
91
107
  const context_ = context as any
92
108
  const meta_ = meta as any
93
109
 
94
- const m1 = await middleware(input_, context_, meta_, ...rest)
95
- const m2 = await concatMiddleware_(
96
- input_,
97
- mergeContext(context_, m1?.context),
98
- meta_,
99
- ...rest,
100
- )
110
+ const next: MiddlewareMeta<any>['next'] = async (options) => {
111
+ return concatMiddleware_(input_, mergeContext(context_, options.context), meta_, ...rest)
112
+ }
113
+
114
+ const m1 = await middleware(input_, context_, {
115
+ ...meta_,
116
+ next,
117
+ }, ...rest)
101
118
 
102
- return { context: mergeContext(m1?.context, m2?.context) }
119
+ return m1
103
120
  })
104
121
  }
105
122
 
@@ -1,9 +1,11 @@
1
+ import type { MiddlewareMeta } from './middleware'
2
+ import type { ProcedureImplementer } from './procedure-implementer'
3
+ import type { Meta } from './types'
1
4
  import { ContractProcedure } from '@orpc/contract'
2
5
  import { z } from 'zod'
6
+ import { os } from '.'
3
7
  import { type DecoratedProcedure, isProcedure } from './procedure'
4
8
  import { ProcedureBuilder } from './procedure-builder'
5
- import type { ProcedureImplementer } from './procedure-implementer'
6
- import type { Meta } from './types'
7
9
 
8
10
  const schema1 = z.object({ id: z.string() })
9
11
  const example1 = { id: '1' }
@@ -90,20 +92,22 @@ describe('use middleware', () => {
90
92
  .use((input, context, meta) => {
91
93
  expectTypeOf(input).toEqualTypeOf<unknown>()
92
94
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
93
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
95
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
94
96
 
95
- return {
97
+ return meta.next({
96
98
  context: {
97
99
  userId: '1',
98
100
  },
99
- }
101
+ })
100
102
  })
101
103
  .use((input, context, meta) => {
102
104
  expectTypeOf(input).toEqualTypeOf<unknown>()
103
105
  expectTypeOf(context).toEqualTypeOf<
104
106
  { userId: string } & { auth: boolean }
105
107
  >()
106
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
108
+ expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
109
+
110
+ return meta.next({})
107
111
  })
108
112
 
109
113
  expectTypeOf(implementer).toEqualTypeOf<
@@ -123,27 +127,27 @@ describe('use middleware', () => {
123
127
  })
124
128
 
125
129
  builder.use(
126
- (input: { postId: string }) => {
127
- return { context: { a: 'a' } }
130
+ (input: { postId: string }, _, meta) => {
131
+ return meta.next({ context: { a: 'a' } })
128
132
  },
129
133
  // @ts-expect-error mismatch input
130
- (input) => ({ postId: 12455 }),
134
+ input => ({ postId: 12455 }),
131
135
  )
132
136
 
133
137
  builder.use(
134
- (input: { postId: string }) => {},
135
- (input) => ({ postId: '12455' }),
138
+ (input: { postId: string }, context, meta) => meta.next({}),
139
+ input => ({ postId: '12455' }),
136
140
  )
137
141
 
138
142
  const implementer = builder.input(schema1).use(
139
- (input: { id: number }) => {
140
- return {
143
+ (input: { id: number }, _, meta) => {
144
+ return meta.next({
141
145
  context: {
142
146
  userId555: '1',
143
147
  },
144
- }
148
+ })
145
149
  },
146
- (input) => ({ id: Number.parseInt(input.id) }),
150
+ input => ({ id: Number.parseInt(input.id) }),
147
151
  )
148
152
 
149
153
  expectTypeOf(implementer).toEqualTypeOf<
@@ -162,7 +166,7 @@ describe('handler', () => {
162
166
  const handler = builder.handler((input, context, meta) => {
163
167
  expectTypeOf(input).toEqualTypeOf<unknown>()
164
168
  expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
165
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
169
+ expectTypeOf(meta).toEqualTypeOf<Meta>()
166
170
  })
167
171
 
168
172
  expectTypeOf(handler).toEqualTypeOf<
@@ -179,15 +183,15 @@ describe('handler', () => {
179
183
  })
180
184
 
181
185
  it('combine middlewares', () => {
182
- const mid1 = () => {
183
- return {
186
+ const mid1 = os.middleware((input, context, meta) => {
187
+ return meta.next({
184
188
  context: {
185
189
  userId: '1',
186
190
  },
187
- }
188
- }
191
+ })
192
+ })
189
193
 
190
- const mid2 = () => {}
194
+ const mid2 = os.middleware((_, __, meta) => meta.next({}))
191
195
 
192
196
  const handler = builder
193
197
  .use(mid1)
@@ -197,7 +201,7 @@ describe('handler', () => {
197
201
  expectTypeOf(context).toEqualTypeOf<
198
202
  { userId: string } & { auth: boolean }
199
203
  >()
200
- expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
204
+ expectTypeOf(meta).toEqualTypeOf<Meta>()
201
205
 
202
206
  return {
203
207
  name: 'unnoq',