@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
@@ -1,223 +0,0 @@
|
|
1
|
-
import type { MiddlewareMeta } from './middleware'
|
2
|
-
import type { ProcedureImplementer } from './procedure-implementer'
|
3
|
-
import type { Meta } from './types'
|
4
|
-
import { ContractProcedure } from '@orpc/contract'
|
5
|
-
import { z } from 'zod'
|
6
|
-
import { os } from '.'
|
7
|
-
import { type DecoratedProcedure, isProcedure } from './procedure'
|
8
|
-
import { ProcedureBuilder } from './procedure-builder'
|
9
|
-
|
10
|
-
const schema1 = z.object({ id: z.string() })
|
11
|
-
const example1 = { id: '1' }
|
12
|
-
const schema2 = z.object({ name: z.string() })
|
13
|
-
const example2 = { name: 'unnoq' }
|
14
|
-
|
15
|
-
const builder = new ProcedureBuilder<
|
16
|
-
{ auth: boolean },
|
17
|
-
undefined,
|
18
|
-
undefined,
|
19
|
-
undefined
|
20
|
-
>({
|
21
|
-
contract: new ContractProcedure({
|
22
|
-
InputSchema: undefined,
|
23
|
-
OutputSchema: undefined,
|
24
|
-
}),
|
25
|
-
})
|
26
|
-
|
27
|
-
it('input', () => {
|
28
|
-
const builder2 = builder.input(schema1, example1)
|
29
|
-
|
30
|
-
expectTypeOf(builder2).toEqualTypeOf<
|
31
|
-
ProcedureBuilder<{ auth: boolean }, undefined, typeof schema1, undefined>
|
32
|
-
>()
|
33
|
-
|
34
|
-
expect(builder2.zz$pb).toMatchObject({
|
35
|
-
contract: {
|
36
|
-
zz$cp: {
|
37
|
-
InputSchema: schema1,
|
38
|
-
inputExample: example1,
|
39
|
-
},
|
40
|
-
},
|
41
|
-
})
|
42
|
-
})
|
43
|
-
|
44
|
-
it('output', () => {
|
45
|
-
const builder2 = builder.output(schema2, example2)
|
46
|
-
|
47
|
-
expectTypeOf(builder2).toEqualTypeOf<
|
48
|
-
ProcedureBuilder<{ auth: boolean }, undefined, undefined, typeof schema2>
|
49
|
-
>()
|
50
|
-
|
51
|
-
expect(builder2.zz$pb).toMatchObject({
|
52
|
-
contract: {
|
53
|
-
zz$cp: {
|
54
|
-
OutputSchema: schema2,
|
55
|
-
outputExample: example2,
|
56
|
-
},
|
57
|
-
},
|
58
|
-
})
|
59
|
-
})
|
60
|
-
|
61
|
-
it('route', () => {
|
62
|
-
const builder2 = builder.route({
|
63
|
-
method: 'GET',
|
64
|
-
path: '/test',
|
65
|
-
deprecated: true,
|
66
|
-
description: 'des',
|
67
|
-
summary: 'sum',
|
68
|
-
tags: ['hi'],
|
69
|
-
})
|
70
|
-
|
71
|
-
expectTypeOf(builder2).toEqualTypeOf<
|
72
|
-
ProcedureBuilder<{ auth: boolean }, undefined, undefined, undefined>
|
73
|
-
>()
|
74
|
-
|
75
|
-
expect(builder2.zz$pb).toMatchObject({
|
76
|
-
contract: {
|
77
|
-
zz$cp: {
|
78
|
-
method: 'GET',
|
79
|
-
path: '/test',
|
80
|
-
deprecated: true,
|
81
|
-
description: 'des',
|
82
|
-
summary: 'sum',
|
83
|
-
tags: ['hi'],
|
84
|
-
},
|
85
|
-
},
|
86
|
-
})
|
87
|
-
})
|
88
|
-
|
89
|
-
describe('use middleware', () => {
|
90
|
-
it('infer types', () => {
|
91
|
-
const implementer = builder
|
92
|
-
.use((input, context, meta) => {
|
93
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
94
|
-
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
95
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
|
96
|
-
|
97
|
-
return meta.next({
|
98
|
-
context: {
|
99
|
-
userId: '1',
|
100
|
-
},
|
101
|
-
})
|
102
|
-
})
|
103
|
-
.use((input, context, meta) => {
|
104
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
105
|
-
expectTypeOf(context).toEqualTypeOf<
|
106
|
-
{ userId: string } & { auth: boolean }
|
107
|
-
>()
|
108
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
|
109
|
-
|
110
|
-
return meta.next({})
|
111
|
-
})
|
112
|
-
|
113
|
-
expectTypeOf(implementer).toEqualTypeOf<
|
114
|
-
ProcedureImplementer<
|
115
|
-
{ auth: boolean },
|
116
|
-
{ userId: string },
|
117
|
-
undefined,
|
118
|
-
undefined
|
119
|
-
>
|
120
|
-
>()
|
121
|
-
})
|
122
|
-
|
123
|
-
it('map middleware input', () => {
|
124
|
-
// @ts-expect-error mismatch input
|
125
|
-
builder.use((input: { postId: string }) => {
|
126
|
-
return { context: { a: 'a' } }
|
127
|
-
})
|
128
|
-
|
129
|
-
builder.use(
|
130
|
-
(input: { postId: string }, _, meta) => {
|
131
|
-
return meta.next({ context: { a: 'a' } })
|
132
|
-
},
|
133
|
-
// @ts-expect-error mismatch input
|
134
|
-
input => ({ postId: 12455 }),
|
135
|
-
)
|
136
|
-
|
137
|
-
builder.use(
|
138
|
-
(input: { postId: string }, context, meta) => meta.next({}),
|
139
|
-
input => ({ postId: '12455' }),
|
140
|
-
)
|
141
|
-
|
142
|
-
const implementer = builder.input(schema1).use(
|
143
|
-
(input: { id: number }, _, meta) => {
|
144
|
-
return meta.next({
|
145
|
-
context: {
|
146
|
-
userId555: '1',
|
147
|
-
},
|
148
|
-
})
|
149
|
-
},
|
150
|
-
input => ({ id: Number.parseInt(input.id) }),
|
151
|
-
)
|
152
|
-
|
153
|
-
expectTypeOf(implementer).toEqualTypeOf<
|
154
|
-
ProcedureImplementer<
|
155
|
-
{ auth: boolean },
|
156
|
-
{ userId555: string },
|
157
|
-
typeof schema1,
|
158
|
-
undefined
|
159
|
-
>
|
160
|
-
>()
|
161
|
-
})
|
162
|
-
})
|
163
|
-
|
164
|
-
describe('handler', () => {
|
165
|
-
it('infer types', () => {
|
166
|
-
const handler = builder.func((input, context, meta) => {
|
167
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
168
|
-
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
169
|
-
expectTypeOf(meta).toEqualTypeOf<Meta>()
|
170
|
-
})
|
171
|
-
|
172
|
-
expectTypeOf(handler).toEqualTypeOf<
|
173
|
-
DecoratedProcedure<
|
174
|
-
{ auth: boolean },
|
175
|
-
undefined,
|
176
|
-
undefined,
|
177
|
-
undefined,
|
178
|
-
void
|
179
|
-
>
|
180
|
-
>()
|
181
|
-
|
182
|
-
expect(isProcedure(handler)).toBe(true)
|
183
|
-
})
|
184
|
-
|
185
|
-
it('combine middlewares', () => {
|
186
|
-
const mid1 = os.middleware((input, context, meta) => {
|
187
|
-
return meta.next({
|
188
|
-
context: {
|
189
|
-
userId: '1',
|
190
|
-
},
|
191
|
-
})
|
192
|
-
})
|
193
|
-
|
194
|
-
const mid2 = os.middleware((_, __, meta) => meta.next({}))
|
195
|
-
|
196
|
-
const handler = builder
|
197
|
-
.use(mid1)
|
198
|
-
.use(mid2)
|
199
|
-
.func((input, context, meta) => {
|
200
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
201
|
-
expectTypeOf(context).toEqualTypeOf<
|
202
|
-
{ userId: string } & { auth: boolean }
|
203
|
-
>()
|
204
|
-
expectTypeOf(meta).toEqualTypeOf<Meta>()
|
205
|
-
|
206
|
-
return {
|
207
|
-
name: 'unnoq',
|
208
|
-
}
|
209
|
-
})
|
210
|
-
|
211
|
-
expectTypeOf(handler).toEqualTypeOf<
|
212
|
-
DecoratedProcedure<
|
213
|
-
{ auth: boolean },
|
214
|
-
{ userId: string },
|
215
|
-
undefined,
|
216
|
-
undefined,
|
217
|
-
{ name: string }
|
218
|
-
>
|
219
|
-
>()
|
220
|
-
|
221
|
-
expect(handler.zz$p.middlewares).toEqual([mid1, mid2])
|
222
|
-
})
|
223
|
-
})
|
package/src/procedure-builder.ts
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
import type { MapInputMiddleware, Middleware } from './middleware'
|
2
|
-
import type { Context, MergeContext } from './types'
|
3
|
-
import {
|
4
|
-
type ContractProcedure,
|
5
|
-
DecoratedContractProcedure,
|
6
|
-
type RouteOptions,
|
7
|
-
type Schema,
|
8
|
-
type SchemaInput,
|
9
|
-
type SchemaOutput,
|
10
|
-
} from '@orpc/contract'
|
11
|
-
import {
|
12
|
-
type DecoratedProcedure,
|
13
|
-
decorateProcedure,
|
14
|
-
type ProcedureFunc,
|
15
|
-
} from './procedure'
|
16
|
-
import { ProcedureImplementer } from './procedure-implementer'
|
17
|
-
|
18
|
-
export class ProcedureBuilder<
|
19
|
-
TContext extends Context,
|
20
|
-
TExtraContext extends Context,
|
21
|
-
TInputSchema extends Schema,
|
22
|
-
TOutputSchema extends Schema,
|
23
|
-
> {
|
24
|
-
constructor(
|
25
|
-
public zz$pb: {
|
26
|
-
contract: ContractProcedure<TInputSchema, TOutputSchema>
|
27
|
-
middlewares?: Middleware<any, any, any, any>[]
|
28
|
-
},
|
29
|
-
) {}
|
30
|
-
|
31
|
-
/**
|
32
|
-
* Self chainable
|
33
|
-
*/
|
34
|
-
|
35
|
-
route(
|
36
|
-
opts: RouteOptions,
|
37
|
-
): ProcedureBuilder<TContext, TExtraContext, TInputSchema, TOutputSchema> {
|
38
|
-
return new ProcedureBuilder({
|
39
|
-
...this.zz$pb,
|
40
|
-
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).route(
|
41
|
-
opts,
|
42
|
-
),
|
43
|
-
})
|
44
|
-
}
|
45
|
-
|
46
|
-
input<USchema extends Schema = undefined>(
|
47
|
-
schema: USchema,
|
48
|
-
example?: SchemaInput<USchema>,
|
49
|
-
): ProcedureBuilder<TContext, TExtraContext, USchema, TOutputSchema> {
|
50
|
-
return new ProcedureBuilder({
|
51
|
-
...this.zz$pb,
|
52
|
-
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).input(
|
53
|
-
schema,
|
54
|
-
example,
|
55
|
-
),
|
56
|
-
})
|
57
|
-
}
|
58
|
-
|
59
|
-
output<USchema extends Schema = undefined>(
|
60
|
-
schema: USchema,
|
61
|
-
example?: SchemaOutput<USchema>,
|
62
|
-
): ProcedureBuilder<TContext, TExtraContext, TInputSchema, USchema> {
|
63
|
-
return new ProcedureBuilder({
|
64
|
-
...this.zz$pb,
|
65
|
-
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).output(
|
66
|
-
schema,
|
67
|
-
example,
|
68
|
-
),
|
69
|
-
})
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Convert to ProcedureBuilder
|
74
|
-
*/
|
75
|
-
|
76
|
-
use<
|
77
|
-
UExtraContext extends
|
78
|
-
| Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
|
79
|
-
| undefined = undefined,
|
80
|
-
>(
|
81
|
-
middleware: Middleware<
|
82
|
-
MergeContext<TContext, TExtraContext>,
|
83
|
-
UExtraContext,
|
84
|
-
SchemaOutput<TInputSchema>,
|
85
|
-
SchemaInput<TOutputSchema>
|
86
|
-
>,
|
87
|
-
): ProcedureImplementer<
|
88
|
-
TContext,
|
89
|
-
MergeContext<TExtraContext, UExtraContext>,
|
90
|
-
TInputSchema,
|
91
|
-
TOutputSchema
|
92
|
-
>
|
93
|
-
|
94
|
-
use<
|
95
|
-
UExtraContext extends
|
96
|
-
| Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
|
97
|
-
| undefined = undefined,
|
98
|
-
UMappedInput = unknown,
|
99
|
-
>(
|
100
|
-
middleware: Middleware<
|
101
|
-
MergeContext<TContext, TExtraContext>,
|
102
|
-
UExtraContext,
|
103
|
-
UMappedInput,
|
104
|
-
SchemaInput<TOutputSchema>
|
105
|
-
>,
|
106
|
-
mapInput: MapInputMiddleware<SchemaOutput<TInputSchema>, UMappedInput>,
|
107
|
-
): ProcedureImplementer<
|
108
|
-
TContext,
|
109
|
-
MergeContext<TExtraContext, UExtraContext>,
|
110
|
-
TInputSchema,
|
111
|
-
TOutputSchema
|
112
|
-
>
|
113
|
-
|
114
|
-
use(
|
115
|
-
middleware: Middleware<any, any, any, any>,
|
116
|
-
mapInput?: MapInputMiddleware<any, any>,
|
117
|
-
): ProcedureImplementer<any, any, any, any> {
|
118
|
-
if (!mapInput) {
|
119
|
-
return new ProcedureImplementer({
|
120
|
-
contract: this.zz$pb.contract,
|
121
|
-
middlewares: this.zz$pb.middlewares,
|
122
|
-
}).use(middleware)
|
123
|
-
}
|
124
|
-
|
125
|
-
return new ProcedureImplementer({
|
126
|
-
contract: this.zz$pb.contract,
|
127
|
-
middlewares: this.zz$pb.middlewares,
|
128
|
-
}).use(middleware, mapInput)
|
129
|
-
}
|
130
|
-
|
131
|
-
/**
|
132
|
-
* Convert to Procedure
|
133
|
-
*/
|
134
|
-
|
135
|
-
func<UFuncOutput extends SchemaOutput<TOutputSchema>>(
|
136
|
-
func: ProcedureFunc<
|
137
|
-
TContext,
|
138
|
-
TExtraContext,
|
139
|
-
TInputSchema,
|
140
|
-
TOutputSchema,
|
141
|
-
UFuncOutput
|
142
|
-
>,
|
143
|
-
): DecoratedProcedure<
|
144
|
-
TContext,
|
145
|
-
TExtraContext,
|
146
|
-
TInputSchema,
|
147
|
-
TOutputSchema,
|
148
|
-
UFuncOutput
|
149
|
-
> {
|
150
|
-
return decorateProcedure({
|
151
|
-
zz$p: {
|
152
|
-
middlewares: this.zz$pb.middlewares,
|
153
|
-
contract: this.zz$pb.contract,
|
154
|
-
func,
|
155
|
-
},
|
156
|
-
})
|
157
|
-
}
|
158
|
-
}
|
@@ -1,171 +0,0 @@
|
|
1
|
-
import { z } from 'zod'
|
2
|
-
import { createProcedureCaller, os } from '.'
|
3
|
-
|
4
|
-
describe('createProcedureCaller', () => {
|
5
|
-
const path = ['ping']
|
6
|
-
const context = { auth: true }
|
7
|
-
|
8
|
-
const osw = os.context<{ auth?: boolean }>()
|
9
|
-
const procedure = osw
|
10
|
-
.input(z.object({ value: z.string().transform(v => Number(v)) }))
|
11
|
-
.output(z.object({ value: z.number().transform(v => v.toString()) }))
|
12
|
-
.func((input, context, meta) => {
|
13
|
-
expect(context).toEqual(context)
|
14
|
-
expect(meta.path).toBe(path)
|
15
|
-
|
16
|
-
return input
|
17
|
-
})
|
18
|
-
|
19
|
-
it('infer context', () => {
|
20
|
-
createProcedureCaller({
|
21
|
-
procedure,
|
22
|
-
// @ts-expect-error invalid context
|
23
|
-
context: { auth: 123 },
|
24
|
-
})
|
25
|
-
|
26
|
-
createProcedureCaller({
|
27
|
-
procedure,
|
28
|
-
context,
|
29
|
-
})
|
30
|
-
})
|
31
|
-
|
32
|
-
it('with validate', async () => {
|
33
|
-
const caller = createProcedureCaller({
|
34
|
-
procedure,
|
35
|
-
context: async () => context,
|
36
|
-
path,
|
37
|
-
})
|
38
|
-
|
39
|
-
expectTypeOf(caller).toMatchTypeOf<
|
40
|
-
(input: { value: string }) => Promise<{
|
41
|
-
value: string
|
42
|
-
}>
|
43
|
-
>()
|
44
|
-
|
45
|
-
expect(await caller({ value: '123' })).toEqual({ value: '123' })
|
46
|
-
|
47
|
-
// @ts-expect-error - invalid input
|
48
|
-
expect(caller({ value: {} })).rejects.toThrowError(
|
49
|
-
'Validation input failed',
|
50
|
-
)
|
51
|
-
})
|
52
|
-
|
53
|
-
it('without validate and schema', () => {
|
54
|
-
const procedure = osw.func(() => {
|
55
|
-
return { value: true }
|
56
|
-
})
|
57
|
-
|
58
|
-
const caller = createProcedureCaller({
|
59
|
-
procedure,
|
60
|
-
context,
|
61
|
-
})
|
62
|
-
|
63
|
-
expectTypeOf(caller).toMatchTypeOf<
|
64
|
-
(value: unknown) => Promise<{ value: boolean }>
|
65
|
-
>()
|
66
|
-
|
67
|
-
expect(caller({ value: 123 })).resolves.toEqual({ value: true })
|
68
|
-
})
|
69
|
-
|
70
|
-
it('middlewares', () => {
|
71
|
-
const ref = { value: 0 }
|
72
|
-
|
73
|
-
const mid1 = vi.fn(
|
74
|
-
osw.middleware(async (input: { id: string }, context, meta) => {
|
75
|
-
expect(input).toEqual({ id: '1' })
|
76
|
-
|
77
|
-
expect(ref.value).toBe(0)
|
78
|
-
ref.value++
|
79
|
-
|
80
|
-
try {
|
81
|
-
const result = await meta.next({
|
82
|
-
context: {
|
83
|
-
userId: '1',
|
84
|
-
},
|
85
|
-
})
|
86
|
-
expect(ref.value).toBe(5)
|
87
|
-
ref.value++
|
88
|
-
return result
|
89
|
-
}
|
90
|
-
finally {
|
91
|
-
expect(ref.value).toBe(6)
|
92
|
-
ref.value++
|
93
|
-
}
|
94
|
-
}),
|
95
|
-
)
|
96
|
-
|
97
|
-
const mid2 = vi.fn(
|
98
|
-
osw.middleware(async (input, context, meta) => {
|
99
|
-
expect(ref.value).toBe(1)
|
100
|
-
ref.value++
|
101
|
-
|
102
|
-
try {
|
103
|
-
const result = await meta.next({})
|
104
|
-
expect(ref.value).toBe(3)
|
105
|
-
ref.value++
|
106
|
-
return result
|
107
|
-
}
|
108
|
-
finally {
|
109
|
-
expect(ref.value).toBe(4)
|
110
|
-
ref.value++
|
111
|
-
}
|
112
|
-
}),
|
113
|
-
)
|
114
|
-
|
115
|
-
const ping = osw
|
116
|
-
.input(z.object({ id: z.string() }))
|
117
|
-
.use(mid1)
|
118
|
-
.use(mid2)
|
119
|
-
.func((input, context, meta) => {
|
120
|
-
expect(context).toEqual({ userId: '1', auth: false })
|
121
|
-
|
122
|
-
expect(ref.value).toBe(2)
|
123
|
-
ref.value++
|
124
|
-
|
125
|
-
return 'pong'
|
126
|
-
})
|
127
|
-
|
128
|
-
const caller = createProcedureCaller({
|
129
|
-
procedure: ping,
|
130
|
-
context: { auth: false },
|
131
|
-
})
|
132
|
-
|
133
|
-
expect(caller({ id: '1' })).resolves.toEqual('pong')
|
134
|
-
})
|
135
|
-
|
136
|
-
it('accept form data', async () => {
|
137
|
-
const ping = osw
|
138
|
-
.input(z.object({ id: z.number() }))
|
139
|
-
.output(z.object({ id: z.number() }))
|
140
|
-
.func((input, context, meta) => {
|
141
|
-
expect(context).toEqual(context)
|
142
|
-
|
143
|
-
return input
|
144
|
-
})
|
145
|
-
|
146
|
-
const caller = createProcedureCaller({
|
147
|
-
procedure: ping,
|
148
|
-
context,
|
149
|
-
})
|
150
|
-
|
151
|
-
const form = new FormData()
|
152
|
-
form.append('id', '1')
|
153
|
-
|
154
|
-
expect(await caller(form)).toEqual({ id: 1 })
|
155
|
-
})
|
156
|
-
|
157
|
-
it('optional input when possible', async () => {
|
158
|
-
os.func(() => { })()
|
159
|
-
os.func(() => { })({})
|
160
|
-
// @ts-expect-error input is required
|
161
|
-
expect(os.input(z.string()).func(() => { })()).rejects.toThrow()
|
162
|
-
os.input(z.string().optional()).func(() => { })()
|
163
|
-
// @ts-expect-error input is required
|
164
|
-
expect(os.input(z.object({})).func(() => { })()).rejects.toThrow()
|
165
|
-
os.input(z.object({}).optional()).func(() => { })()
|
166
|
-
os.input(z.unknown()).func(() => { })()
|
167
|
-
os.input(z.any()).func(() => { })()
|
168
|
-
// @ts-expect-error input is required
|
169
|
-
expect(os.input(z.boolean()).func(() => { })()).rejects.toThrow()
|
170
|
-
})
|
171
|
-
})
|
package/src/procedure-caller.ts
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
import type { SchemaInput, SchemaOutput } from '@orpc/contract'
|
2
|
-
import type { MiddlewareMeta } from './middleware'
|
3
|
-
import type { Procedure } from './procedure'
|
4
|
-
import type { Context } from './types'
|
5
|
-
import { type Value, value } from '@orpc/shared'
|
6
|
-
import { ORPCError } from '@orpc/shared/error'
|
7
|
-
import { OpenAPIDeserializer } from '@orpc/transformer'
|
8
|
-
import { mergeContext } from './utils'
|
9
|
-
|
10
|
-
export interface CreateProcedureCallerOptions<
|
11
|
-
TProcedure extends Procedure<any, any, any, any, any>,
|
12
|
-
> {
|
13
|
-
procedure: TProcedure
|
14
|
-
|
15
|
-
/**
|
16
|
-
* The context used when calling the procedure.
|
17
|
-
*/
|
18
|
-
context: Value<
|
19
|
-
TProcedure extends Procedure<infer UContext, any, any, any, any>
|
20
|
-
? UContext
|
21
|
-
: never
|
22
|
-
>
|
23
|
-
|
24
|
-
/**
|
25
|
-
* This is helpful for logging and analytics.
|
26
|
-
*
|
27
|
-
* @internal
|
28
|
-
*/
|
29
|
-
path?: string[]
|
30
|
-
}
|
31
|
-
|
32
|
-
export type ProcedureCaller<
|
33
|
-
TProcedure extends Procedure<any, any, any, any, any>,
|
34
|
-
> = TProcedure extends Procedure<
|
35
|
-
any,
|
36
|
-
any,
|
37
|
-
infer UInputSchema,
|
38
|
-
infer UOutputSchema,
|
39
|
-
infer UFuncOutput
|
40
|
-
>
|
41
|
-
? (
|
42
|
-
...input: [input: SchemaInput<UInputSchema> | FormData] | (undefined extends SchemaInput<UInputSchema> ? [] : never)
|
43
|
-
) => Promise<
|
44
|
-
SchemaOutput<UOutputSchema, UFuncOutput>
|
45
|
-
>
|
46
|
-
: never
|
47
|
-
|
48
|
-
export function createProcedureCaller<
|
49
|
-
TProcedure extends Procedure<any, any, any, any, any>,
|
50
|
-
>(
|
51
|
-
options: CreateProcedureCallerOptions<TProcedure>,
|
52
|
-
): ProcedureCaller<TProcedure> {
|
53
|
-
const path = options.path ?? []
|
54
|
-
const procedure = options.procedure
|
55
|
-
|
56
|
-
const caller = async (input: unknown): Promise<unknown> => {
|
57
|
-
const input_ = (() => {
|
58
|
-
if (!(input instanceof FormData)) {
|
59
|
-
return input
|
60
|
-
}
|
61
|
-
|
62
|
-
const transformer = new OpenAPIDeserializer({
|
63
|
-
schema: procedure.zz$p.contract.zz$cp.InputSchema,
|
64
|
-
})
|
65
|
-
|
66
|
-
return transformer.deserializeAsFormData(input)
|
67
|
-
})()
|
68
|
-
|
69
|
-
const validInput = (() => {
|
70
|
-
const schema = procedure.zz$p.contract.zz$cp.InputSchema
|
71
|
-
if (!schema) {
|
72
|
-
return input_
|
73
|
-
}
|
74
|
-
|
75
|
-
try {
|
76
|
-
return schema.parse(input_)
|
77
|
-
}
|
78
|
-
catch (e) {
|
79
|
-
throw new ORPCError({
|
80
|
-
message: 'Validation input failed',
|
81
|
-
code: 'BAD_REQUEST',
|
82
|
-
cause: e,
|
83
|
-
})
|
84
|
-
}
|
85
|
-
})()
|
86
|
-
|
87
|
-
const middlewares = procedure.zz$p.middlewares ?? []
|
88
|
-
let currentMidIndex = 0
|
89
|
-
let currentContext: Context = await value(options.context)
|
90
|
-
|
91
|
-
const next: MiddlewareMeta<unknown>['next'] = async (nextOptions) => {
|
92
|
-
const mid = middlewares[currentMidIndex]
|
93
|
-
currentMidIndex += 1
|
94
|
-
currentContext = mergeContext(currentContext, nextOptions.context)
|
95
|
-
|
96
|
-
if (mid) {
|
97
|
-
return await mid(validInput, currentContext, {
|
98
|
-
path,
|
99
|
-
procedure,
|
100
|
-
next,
|
101
|
-
output: output => ({ output, context: undefined }),
|
102
|
-
})
|
103
|
-
}
|
104
|
-
else {
|
105
|
-
return {
|
106
|
-
output: await await procedure.zz$p.func(validInput, currentContext, {
|
107
|
-
path,
|
108
|
-
procedure,
|
109
|
-
}),
|
110
|
-
context: currentContext,
|
111
|
-
}
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
const output = (await next({})).output
|
116
|
-
|
117
|
-
const validOutput = await (async () => {
|
118
|
-
const schema = procedure.zz$p.contract.zz$cp.OutputSchema
|
119
|
-
if (!schema) {
|
120
|
-
return output
|
121
|
-
}
|
122
|
-
|
123
|
-
const result = await schema.safeParseAsync(output)
|
124
|
-
if (result.error) {
|
125
|
-
throw new ORPCError({
|
126
|
-
message: 'Validation output failed',
|
127
|
-
code: 'INTERNAL_SERVER_ERROR',
|
128
|
-
cause: result.error,
|
129
|
-
})
|
130
|
-
}
|
131
|
-
return result.data
|
132
|
-
})()
|
133
|
-
|
134
|
-
return validOutput
|
135
|
-
}
|
136
|
-
|
137
|
-
return caller as ProcedureCaller<TProcedure>
|
138
|
-
}
|