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