@orpc/server 0.0.0

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