@orpc/server 0.2.1 → 0.3.1
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-26DTFWOI.js → chunk-YYGRQD4L.js} +26 -36
- package/dist/chunk-YYGRQD4L.js.map +1 -0
- package/dist/fetch.js +12 -12
- package/dist/fetch.js.map +1 -1
- package/dist/index.js +9 -15
- package/dist/index.js.map +1 -1
- package/dist/src/adapters/fetch.d.ts +2 -2
- package/dist/src/adapters/fetch.d.ts.map +1 -1
- package/dist/src/builder.d.ts +2 -2
- package/dist/src/builder.d.ts.map +1 -1
- package/dist/src/procedure-builder.d.ts +2 -2
- package/dist/src/procedure-builder.d.ts.map +1 -1
- package/dist/src/procedure-caller.d.ts +7 -16
- package/dist/src/procedure-caller.d.ts.map +1 -1
- package/dist/src/procedure-implementer.d.ts +2 -2
- package/dist/src/procedure-implementer.d.ts.map +1 -1
- package/dist/src/procedure.d.ts +11 -10
- package/dist/src/procedure.d.ts.map +1 -1
- package/dist/src/router-caller.d.ts +8 -17
- package/dist/src/router-caller.d.ts.map +1 -1
- package/dist/src/router.d.ts +2 -2
- package/dist/src/router.d.ts.map +1 -1
- package/dist/src/types.d.ts +0 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -6
- package/src/adapters/fetch.test.ts +18 -18
- package/src/adapters/fetch.ts +9 -5
- package/src/builder.test.ts +4 -4
- package/src/builder.ts +6 -6
- package/src/middleware.test.ts +1 -1
- package/src/procedure-builder.test.ts +2 -2
- package/src/procedure-builder.ts +6 -6
- package/src/procedure-caller.test.ts +27 -36
- package/src/procedure-caller.ts +36 -44
- package/src/procedure-implementer.test.ts +8 -8
- package/src/procedure-implementer.ts +6 -6
- package/src/procedure.test.ts +20 -20
- package/src/procedure.ts +30 -45
- package/src/router-builder.test.ts +4 -4
- package/src/router-caller.test.ts +5 -52
- package/src/router-caller.ts +11 -31
- package/src/router-implementer.test.ts +6 -6
- package/src/router.test-d.ts +2 -2
- package/src/router.test.ts +10 -10
- package/src/router.ts +4 -4
- package/src/types.ts +0 -1
- package/dist/chunk-26DTFWOI.js.map +0 -1
package/src/procedure.test.ts
CHANGED
@@ -18,7 +18,7 @@ it('isProcedure', () => {
|
|
18
18
|
InputSchema: undefined,
|
19
19
|
OutputSchema: undefined,
|
20
20
|
}),
|
21
|
-
|
21
|
+
func: () => {},
|
22
22
|
}),
|
23
23
|
),
|
24
24
|
),
|
@@ -29,7 +29,7 @@ it('isProcedure', () => {
|
|
29
29
|
InputSchema: undefined,
|
30
30
|
OutputSchema: undefined,
|
31
31
|
}),
|
32
|
-
|
32
|
+
func: () => {},
|
33
33
|
},
|
34
34
|
}).toSatisfy(isProcedure)
|
35
35
|
|
@@ -57,7 +57,7 @@ it('isProcedure', () => {
|
|
57
57
|
|
58
58
|
describe('route method', () => {
|
59
59
|
it('sets route options correctly', () => {
|
60
|
-
const p = os.context<{ auth: boolean }>().
|
60
|
+
const p = os.context<{ auth: boolean }>().func(() => {
|
61
61
|
return 'test'
|
62
62
|
})
|
63
63
|
|
@@ -69,11 +69,11 @@ describe('route method', () => {
|
|
69
69
|
|
70
70
|
it('preserves existing context and handler', () => {
|
71
71
|
const handler = () => 'test'
|
72
|
-
const p = os.context<{ auth: boolean }>().
|
72
|
+
const p = os.context<{ auth: boolean }>().func(handler)
|
73
73
|
|
74
74
|
const p2 = p.route({ path: '/test' })
|
75
75
|
|
76
|
-
expect(p2.zz$p.
|
76
|
+
expect(p2.zz$p.func).toBe(handler)
|
77
77
|
// Context type is preserved through the route method
|
78
78
|
expectTypeOf(p2).toEqualTypeOf<
|
79
79
|
DecoratedProcedure<
|
@@ -90,7 +90,7 @@ describe('route method', () => {
|
|
90
90
|
const p = os
|
91
91
|
.context<{ auth: boolean }>()
|
92
92
|
.route({ path: '/api', method: 'POST' })
|
93
|
-
.
|
93
|
+
.func(() => 'test')
|
94
94
|
|
95
95
|
const p2 = p.prefix('/v1')
|
96
96
|
|
@@ -105,7 +105,7 @@ describe('route method', () => {
|
|
105
105
|
.context<{ auth: boolean }>()
|
106
106
|
.route({ path: '/test' })
|
107
107
|
.use(mid)
|
108
|
-
.
|
108
|
+
.func((input, context) => {
|
109
109
|
expectTypeOf(context).toEqualTypeOf<
|
110
110
|
{ auth: boolean } & { userId: string }
|
111
111
|
>()
|
@@ -120,7 +120,7 @@ describe('route method', () => {
|
|
120
120
|
const p = os
|
121
121
|
.context<{ auth: boolean }>()
|
122
122
|
.route({ path: '/test1', method: 'GET' })
|
123
|
-
.
|
123
|
+
.func(() => 'test')
|
124
124
|
|
125
125
|
const p2 = p.route({ path: '/test2', method: 'POST' })
|
126
126
|
|
@@ -136,7 +136,7 @@ describe('route method', () => {
|
|
136
136
|
.input(inputSchema)
|
137
137
|
.output(outputSchema)
|
138
138
|
.route({ path: '/test' })
|
139
|
-
.
|
139
|
+
.func((input) => {
|
140
140
|
expectTypeOf(input).toEqualTypeOf<{ id: number }>()
|
141
141
|
return 'test'
|
142
142
|
})
|
@@ -157,7 +157,7 @@ describe('route method', () => {
|
|
157
157
|
})
|
158
158
|
|
159
159
|
it('prefix method', () => {
|
160
|
-
const p = os.context<{ auth: boolean }>().
|
160
|
+
const p = os.context<{ auth: boolean }>().func(() => {
|
161
161
|
return 'unnoq'
|
162
162
|
})
|
163
163
|
|
@@ -168,7 +168,7 @@ it('prefix method', () => {
|
|
168
168
|
const p3 = os
|
169
169
|
.context<{ auth: boolean }>()
|
170
170
|
.route({ path: '/test1' })
|
171
|
-
.
|
171
|
+
.func(() => {
|
172
172
|
return 'unnoq'
|
173
173
|
})
|
174
174
|
|
@@ -183,7 +183,7 @@ describe('use middleware', () => {
|
|
183
183
|
.use((_, __, meta) => {
|
184
184
|
return meta.next({ context: { postId: 'string' } })
|
185
185
|
})
|
186
|
-
.
|
186
|
+
.func(() => {
|
187
187
|
return 'unnoq'
|
188
188
|
})
|
189
189
|
|
@@ -251,7 +251,7 @@ describe('use middleware', () => {
|
|
251
251
|
const mid2 = vi.fn()
|
252
252
|
const mid3 = vi.fn()
|
253
253
|
|
254
|
-
const p1 = os.use(mid1).
|
254
|
+
const p1 = os.use(mid1).func(() => 'unnoq')
|
255
255
|
const p2 = p1.use(mid2).use(mid3)
|
256
256
|
|
257
257
|
expect(p2.zz$p.middlewares).toEqual([mid3, mid2, mid1])
|
@@ -260,12 +260,12 @@ describe('use middleware', () => {
|
|
260
260
|
|
261
261
|
describe('server action', () => {
|
262
262
|
it('only accept undefined context', () => {
|
263
|
-
expectTypeOf(os.
|
263
|
+
expectTypeOf(os.func(() => {})).toMatchTypeOf<(...args: any[]) => any>()
|
264
264
|
expectTypeOf(
|
265
|
-
os.context<{ auth: boolean } | undefined>().
|
265
|
+
os.context<{ auth: boolean } | undefined>().func(() => {}),
|
266
266
|
).toMatchTypeOf<(...args: any[]) => any>()
|
267
267
|
expectTypeOf(
|
268
|
-
os.context<{ auth: boolean }>().
|
268
|
+
os.context<{ auth: boolean }>().func(() => {}),
|
269
269
|
).not.toMatchTypeOf<(...args: any[]) => any>()
|
270
270
|
})
|
271
271
|
|
@@ -273,13 +273,13 @@ describe('server action', () => {
|
|
273
273
|
const p = os
|
274
274
|
.input(z.object({ id: z.number() }))
|
275
275
|
.output(z.string())
|
276
|
-
.
|
276
|
+
.func(() => 'string')
|
277
277
|
|
278
278
|
expectTypeOf(p).toMatchTypeOf<
|
279
279
|
(input: { id: number } | FormData) => Promise<string>
|
280
280
|
>()
|
281
281
|
|
282
|
-
const p2 = os.input(z.object({ id: z.number() })).
|
282
|
+
const p2 = os.input(z.object({ id: z.number() })).func(() => 12333)
|
283
283
|
|
284
284
|
expectTypeOf(p2).toMatchTypeOf<
|
285
285
|
(input: { id: number } | FormData) => Promise<number>
|
@@ -289,7 +289,7 @@ describe('server action', () => {
|
|
289
289
|
it('works with input', async () => {
|
290
290
|
const p = os
|
291
291
|
.input(z.object({ id: z.number(), date: z.date() }))
|
292
|
-
.
|
292
|
+
.func(async (input, context) => {
|
293
293
|
expect(context).toBe(undefined)
|
294
294
|
return input
|
295
295
|
})
|
@@ -303,7 +303,7 @@ describe('server action', () => {
|
|
303
303
|
it('can deserialize form data', async () => {
|
304
304
|
const p = os
|
305
305
|
.input(z.object({ id: z.number(), nested: z.object({ date: z.date() }) }))
|
306
|
-
.
|
306
|
+
.func(async input => input)
|
307
307
|
|
308
308
|
const form = new FormData()
|
309
309
|
form.append('id', '123')
|
package/src/procedure.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { Promisable } from '@orpc/shared'
|
2
|
+
import type { ProcedureCaller } from './procedure-caller'
|
2
3
|
import type { Context, MergeContext, Meta } from './types'
|
3
4
|
import {
|
4
5
|
type ContractProcedure,
|
@@ -10,7 +11,6 @@ import {
|
|
10
11
|
type SchemaInput,
|
11
12
|
type SchemaOutput,
|
12
13
|
} from '@orpc/contract'
|
13
|
-
import { OpenAPIDeserializer } from '@orpc/transformer'
|
14
14
|
import {
|
15
15
|
decorateMiddleware,
|
16
16
|
type MapInputMiddleware,
|
@@ -23,18 +23,18 @@ export class Procedure<
|
|
23
23
|
TExtraContext extends Context,
|
24
24
|
TInputSchema extends Schema,
|
25
25
|
TOutputSchema extends Schema,
|
26
|
-
|
26
|
+
TFuncOutput extends SchemaOutput<TOutputSchema>,
|
27
27
|
> {
|
28
28
|
constructor(
|
29
29
|
public zz$p: {
|
30
30
|
middlewares?: Middleware<any, any, any, any>[]
|
31
31
|
contract: ContractProcedure<TInputSchema, TOutputSchema>
|
32
|
-
|
32
|
+
func: ProcedureFunc<
|
33
33
|
TContext,
|
34
34
|
TExtraContext,
|
35
35
|
TInputSchema,
|
36
36
|
TOutputSchema,
|
37
|
-
|
37
|
+
TFuncOutput
|
38
38
|
>
|
39
39
|
},
|
40
40
|
) {}
|
@@ -45,13 +45,13 @@ export type DecoratedProcedure<
|
|
45
45
|
TExtraContext extends Context,
|
46
46
|
TInputSchema extends Schema,
|
47
47
|
TOutputSchema extends Schema,
|
48
|
-
|
48
|
+
TFuncOutput extends SchemaOutput<TOutputSchema>,
|
49
49
|
> = Procedure<
|
50
50
|
TContext,
|
51
51
|
TExtraContext,
|
52
52
|
TInputSchema,
|
53
53
|
TOutputSchema,
|
54
|
-
|
54
|
+
TFuncOutput
|
55
55
|
> & {
|
56
56
|
prefix: (
|
57
57
|
prefix: HTTPPath,
|
@@ -60,7 +60,7 @@ export type DecoratedProcedure<
|
|
60
60
|
TExtraContext,
|
61
61
|
TInputSchema,
|
62
62
|
TOutputSchema,
|
63
|
-
|
63
|
+
TFuncOutput
|
64
64
|
>
|
65
65
|
|
66
66
|
route: (
|
@@ -70,7 +70,7 @@ export type DecoratedProcedure<
|
|
70
70
|
TExtraContext,
|
71
71
|
TInputSchema,
|
72
72
|
TOutputSchema,
|
73
|
-
|
73
|
+
TFuncOutput
|
74
74
|
>
|
75
75
|
|
76
76
|
use: (<
|
@@ -82,14 +82,14 @@ export type DecoratedProcedure<
|
|
82
82
|
MergeContext<TContext, TExtraContext>,
|
83
83
|
UExtraContext,
|
84
84
|
SchemaOutput<TInputSchema>,
|
85
|
-
SchemaInput<TOutputSchema,
|
85
|
+
SchemaInput<TOutputSchema, TFuncOutput>
|
86
86
|
>,
|
87
87
|
) => DecoratedProcedure<
|
88
88
|
TContext,
|
89
89
|
MergeContext<TExtraContext, UExtraContext>,
|
90
90
|
TInputSchema,
|
91
91
|
TOutputSchema,
|
92
|
-
|
92
|
+
TFuncOutput
|
93
93
|
>) & (<
|
94
94
|
UExtraContext extends
|
95
95
|
| Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
|
@@ -100,10 +100,10 @@ export type DecoratedProcedure<
|
|
100
100
|
MergeContext<TContext, TExtraContext>,
|
101
101
|
UExtraContext,
|
102
102
|
UMappedInput,
|
103
|
-
SchemaInput<TOutputSchema,
|
103
|
+
SchemaInput<TOutputSchema, TFuncOutput>
|
104
104
|
>,
|
105
105
|
mapInput: MapInputMiddleware<
|
106
|
-
SchemaOutput<TInputSchema,
|
106
|
+
SchemaOutput<TInputSchema, TFuncOutput>,
|
107
107
|
UMappedInput
|
108
108
|
>,
|
109
109
|
) => DecoratedProcedure<
|
@@ -111,15 +111,19 @@ export type DecoratedProcedure<
|
|
111
111
|
MergeContext<TExtraContext, UExtraContext>,
|
112
112
|
TInputSchema,
|
113
113
|
TOutputSchema,
|
114
|
-
|
114
|
+
TFuncOutput
|
115
115
|
>)
|
116
116
|
} & (undefined extends TContext
|
117
|
-
?
|
118
|
-
|
119
|
-
|
117
|
+
? ProcedureCaller<Procedure<
|
118
|
+
TContext,
|
119
|
+
TExtraContext,
|
120
|
+
TInputSchema,
|
121
|
+
TOutputSchema,
|
122
|
+
TFuncOutput
|
123
|
+
>>
|
120
124
|
: unknown)
|
121
125
|
|
122
|
-
export interface
|
126
|
+
export interface ProcedureFunc<
|
123
127
|
TContext extends Context,
|
124
128
|
TExtraContext extends Context,
|
125
129
|
TInputSchema extends Schema,
|
@@ -140,49 +144,30 @@ export function decorateProcedure<
|
|
140
144
|
TExtraContext extends Context,
|
141
145
|
TInputSchema extends Schema,
|
142
146
|
TOutputSchema extends Schema,
|
143
|
-
|
147
|
+
TFuncOutput extends SchemaOutput<TOutputSchema>,
|
144
148
|
>(
|
145
149
|
procedure: Procedure<
|
146
150
|
TContext,
|
147
151
|
TExtraContext,
|
148
152
|
TInputSchema,
|
149
153
|
TOutputSchema,
|
150
|
-
|
154
|
+
TFuncOutput
|
151
155
|
>,
|
152
156
|
): DecoratedProcedure<
|
153
157
|
TContext,
|
154
158
|
TExtraContext,
|
155
159
|
TInputSchema,
|
156
160
|
TOutputSchema,
|
157
|
-
|
161
|
+
TFuncOutput
|
158
162
|
> {
|
159
163
|
if (DECORATED_PROCEDURE_SYMBOL in procedure) {
|
160
164
|
return procedure as any
|
161
165
|
}
|
162
166
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
const transformer = new OpenAPIDeserializer({
|
169
|
-
schema: procedure.zz$p.contract.zz$cp.InputSchema,
|
170
|
-
})
|
171
|
-
|
172
|
-
return transformer.deserializeAsFormData(input)
|
173
|
-
})()
|
174
|
-
|
175
|
-
const procedureCaller = createProcedureCaller({
|
176
|
-
procedure,
|
177
|
-
context: undefined as any,
|
178
|
-
internal: false,
|
179
|
-
validate: true,
|
180
|
-
})
|
181
|
-
|
182
|
-
return await procedureCaller(input_ as any)
|
183
|
-
}
|
184
|
-
|
185
|
-
return Object.assign(serverAction, {
|
167
|
+
return Object.assign(createProcedureCaller({
|
168
|
+
procedure,
|
169
|
+
context: undefined as any,
|
170
|
+
}), {
|
186
171
|
[DECORATED_PROCEDURE_SYMBOL]: true,
|
187
172
|
zz$p: procedure.zz$p,
|
188
173
|
|
@@ -246,7 +231,7 @@ export function isProcedure(item: unknown): item is WELL_DEFINED_PROCEDURE {
|
|
246
231
|
&& item.zz$p !== null
|
247
232
|
&& 'contract' in item.zz$p
|
248
233
|
&& isContractProcedure(item.zz$p.contract)
|
249
|
-
&& '
|
250
|
-
&& typeof item.zz$p.
|
234
|
+
&& 'func' in item.zz$p
|
235
|
+
&& typeof item.zz$p.func === 'function'
|
251
236
|
)
|
252
237
|
}
|
@@ -6,10 +6,10 @@ import { RouterBuilder } from './router-builder'
|
|
6
6
|
const builder = new RouterBuilder<undefined, undefined>({})
|
7
7
|
const ping = os
|
8
8
|
.route({ method: 'GET', path: '/ping', tags: ['ping'] })
|
9
|
-
.
|
9
|
+
.func(() => 'ping')
|
10
10
|
const pong = os
|
11
11
|
.output(z.object({ id: z.string() }))
|
12
|
-
.
|
12
|
+
.func(() => ({ id: '123' }))
|
13
13
|
|
14
14
|
describe('prefix', () => {
|
15
15
|
it('chainable prefix', () => {
|
@@ -80,7 +80,7 @@ describe('middleware', () => {
|
|
80
80
|
InputSchema: undefined,
|
81
81
|
OutputSchema: undefined,
|
82
82
|
}),
|
83
|
-
|
83
|
+
func: () => {},
|
84
84
|
})
|
85
85
|
|
86
86
|
const decorated = decorateProcedure({
|
@@ -89,7 +89,7 @@ describe('middleware', () => {
|
|
89
89
|
InputSchema: undefined,
|
90
90
|
OutputSchema: undefined,
|
91
91
|
}),
|
92
|
-
|
92
|
+
func: () => {},
|
93
93
|
},
|
94
94
|
})
|
95
95
|
|
@@ -2,24 +2,22 @@ import { z } from 'zod'
|
|
2
2
|
import { createRouterCaller, os } from '.'
|
3
3
|
|
4
4
|
describe('createRouterCaller', () => {
|
5
|
-
|
6
|
-
|
5
|
+
const internal = false
|
6
|
+
const context = { auth: true }
|
7
7
|
|
8
8
|
const osw = os.context<{ auth?: boolean }>()
|
9
9
|
|
10
10
|
const ping = osw
|
11
11
|
.input(z.object({ value: z.string().transform(v => Number(v)) }))
|
12
12
|
.output(z.object({ value: z.number().transform(v => v.toString()) }))
|
13
|
-
.
|
13
|
+
.func((input, context, meta) => {
|
14
14
|
expect(context).toEqual(context)
|
15
|
-
expect(meta.internal).toEqual(internal)
|
16
15
|
|
17
16
|
return input
|
18
17
|
})
|
19
18
|
|
20
|
-
const pong = osw.
|
19
|
+
const pong = osw.func((_, context, meta) => {
|
21
20
|
expect(context).toEqual(context)
|
22
|
-
expect(meta.internal).toBe(internal)
|
23
21
|
|
24
22
|
return { value: true }
|
25
23
|
})
|
@@ -50,7 +48,6 @@ describe('createRouterCaller', () => {
|
|
50
48
|
const caller = createRouterCaller({
|
51
49
|
router,
|
52
50
|
context,
|
53
|
-
internal,
|
54
51
|
})
|
55
52
|
|
56
53
|
expectTypeOf(caller.ping).toMatchTypeOf<
|
@@ -98,52 +95,8 @@ describe('createRouterCaller', () => {
|
|
98
95
|
)
|
99
96
|
})
|
100
97
|
|
101
|
-
it('without validate', () => {
|
102
|
-
internal = true
|
103
|
-
context = { auth: false }
|
104
|
-
|
105
|
-
const caller = createRouterCaller({
|
106
|
-
router,
|
107
|
-
context,
|
108
|
-
internal,
|
109
|
-
validate: false,
|
110
|
-
})
|
111
|
-
|
112
|
-
expectTypeOf(caller.ping).toMatchTypeOf<
|
113
|
-
(input: { value: number }) => Promise<{
|
114
|
-
value: number
|
115
|
-
}>
|
116
|
-
>()
|
117
|
-
|
118
|
-
expectTypeOf(caller.pong).toMatchTypeOf<
|
119
|
-
(input: unknown) => Promise<{
|
120
|
-
value: boolean
|
121
|
-
}>
|
122
|
-
>()
|
123
|
-
|
124
|
-
expectTypeOf(caller.nested.ping).toMatchTypeOf<
|
125
|
-
(input: { value: number }) => Promise<{
|
126
|
-
value: number
|
127
|
-
}>
|
128
|
-
>()
|
129
|
-
|
130
|
-
expectTypeOf(caller.nested.pong).toMatchTypeOf<
|
131
|
-
(input: unknown) => Promise<{
|
132
|
-
value: boolean
|
133
|
-
}>
|
134
|
-
>()
|
135
|
-
|
136
|
-
expect(caller.ping({ value: 123 })).resolves.toEqual({ value: 123 })
|
137
|
-
expect(caller.pong({ value: 123 })).resolves.toEqual({ value: true })
|
138
|
-
expect(caller.nested.ping({ value: 123 })).resolves.toEqual({ value: 123 })
|
139
|
-
expect(caller.nested.pong({ value: 123 })).resolves.toEqual({ value: true })
|
140
|
-
|
141
|
-
// @ts-expect-error it's not validate so bellow still works
|
142
|
-
expect(caller.ping({ value: '123' })).resolves.toEqual({ value: '123' })
|
143
|
-
})
|
144
|
-
|
145
98
|
it('path', () => {
|
146
|
-
const ping = osw.
|
99
|
+
const ping = osw.func((_, __, { path }) => {
|
147
100
|
return path
|
148
101
|
})
|
149
102
|
|
package/src/router-caller.ts
CHANGED
@@ -1,59 +1,43 @@
|
|
1
|
-
import type {} from '@orpc/
|
1
|
+
import type { Value } from '@orpc/shared'
|
2
2
|
import type { Router } from './router'
|
3
3
|
import { isProcedure, type Procedure } from './procedure'
|
4
4
|
import { createProcedureCaller, type ProcedureCaller } from './procedure-caller'
|
5
5
|
|
6
6
|
export interface CreateRouterCallerOptions<
|
7
7
|
TRouter extends Router<any>,
|
8
|
-
TValidate extends boolean,
|
9
8
|
> {
|
10
9
|
router: TRouter
|
11
10
|
|
12
11
|
/**
|
13
12
|
* The context used when calling the procedure.
|
14
13
|
*/
|
15
|
-
context:
|
14
|
+
context: Value<
|
15
|
+
TRouter extends Router<infer UContext> ? UContext : never
|
16
|
+
>
|
16
17
|
|
17
18
|
/**
|
18
19
|
* This is helpful for logging and analytics.
|
19
|
-
*/
|
20
|
-
basePath?: string[]
|
21
|
-
|
22
|
-
/**
|
23
|
-
* This flag helpful when you want bypass some logics not necessary to internal server calls.
|
24
|
-
*
|
25
|
-
* @default true
|
26
|
-
*/
|
27
|
-
internal?: boolean
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Indicate whether validate input and output.
|
31
20
|
*
|
32
|
-
* @
|
21
|
+
* @internal
|
33
22
|
*/
|
34
|
-
|
23
|
+
basePath?: string[]
|
35
24
|
}
|
36
25
|
|
37
26
|
export type RouterCaller<
|
38
27
|
TRouter extends Router<any>,
|
39
|
-
TValidate extends boolean,
|
40
28
|
> = {
|
41
29
|
[K in keyof TRouter]: TRouter[K] extends Procedure<any, any, any, any, any>
|
42
|
-
? ProcedureCaller<TRouter[K]
|
30
|
+
? ProcedureCaller<TRouter[K]>
|
43
31
|
: TRouter[K] extends Router<any>
|
44
|
-
? RouterCaller<TRouter[K]
|
32
|
+
? RouterCaller<TRouter[K]>
|
45
33
|
: never
|
46
34
|
}
|
47
35
|
|
48
36
|
export function createRouterCaller<
|
49
37
|
TRouter extends Router<any>,
|
50
|
-
TValidate extends boolean = true,
|
51
38
|
>(
|
52
|
-
options: CreateRouterCallerOptions<TRouter
|
53
|
-
): RouterCaller<TRouter
|
54
|
-
const internal = options.internal ?? true
|
55
|
-
const validate = options.validate ?? true
|
56
|
-
|
39
|
+
options: CreateRouterCallerOptions<TRouter>,
|
40
|
+
): RouterCaller<TRouter> {
|
57
41
|
const caller: Record<string, unknown> = {}
|
58
42
|
|
59
43
|
for (const key in options.router) {
|
@@ -65,8 +49,6 @@ export function createRouterCaller<
|
|
65
49
|
procedure: item,
|
66
50
|
context: options.context as any,
|
67
51
|
path,
|
68
|
-
internal,
|
69
|
-
validate,
|
70
52
|
})
|
71
53
|
}
|
72
54
|
else {
|
@@ -74,11 +56,9 @@ export function createRouterCaller<
|
|
74
56
|
router: item as any,
|
75
57
|
context: options.context,
|
76
58
|
basePath: path,
|
77
|
-
internal,
|
78
|
-
validate,
|
79
59
|
})
|
80
60
|
}
|
81
61
|
}
|
82
62
|
|
83
|
-
return caller as RouterCaller<TRouter
|
63
|
+
return caller as RouterCaller<TRouter>
|
84
64
|
}
|
@@ -17,15 +17,15 @@ const cr = oc.router({
|
|
17
17
|
|
18
18
|
const osw = os.context<{ auth: boolean }>().contract(cr)
|
19
19
|
|
20
|
-
const p1 = osw.p1.
|
20
|
+
const p1 = osw.p1.func(() => {
|
21
21
|
return 'unnoq'
|
22
22
|
})
|
23
23
|
|
24
|
-
const p2 = osw.nested.p2.
|
24
|
+
const p2 = osw.nested.p2.func(() => {
|
25
25
|
return 'unnoq'
|
26
26
|
})
|
27
27
|
|
28
|
-
const p3 = osw.nested2.p3.
|
28
|
+
const p3 = osw.nested2.p3.func(() => {
|
29
29
|
return 'unnoq'
|
30
30
|
})
|
31
31
|
|
@@ -37,7 +37,7 @@ it('required all procedure match', () => {
|
|
37
37
|
implementer.router({
|
38
38
|
p1,
|
39
39
|
nested: {
|
40
|
-
p2: os.contract(cp2).
|
40
|
+
p2: os.contract(cp2).func(() => ''),
|
41
41
|
},
|
42
42
|
nested2: {
|
43
43
|
p3,
|
@@ -47,7 +47,7 @@ it('required all procedure match', () => {
|
|
47
47
|
expect(() => {
|
48
48
|
implementer.router({
|
49
49
|
// @ts-expect-error p1 is mismatch
|
50
|
-
p1: os.
|
50
|
+
p1: os.func(() => {}),
|
51
51
|
nested: {
|
52
52
|
p2,
|
53
53
|
},
|
@@ -76,7 +76,7 @@ it('required all procedure match', () => {
|
|
76
76
|
p1: os
|
77
77
|
.input(z.string())
|
78
78
|
.output(z.string())
|
79
|
-
.
|
79
|
+
.func(() => 'unnoq'),
|
80
80
|
nested: {
|
81
81
|
p2,
|
82
82
|
},
|
package/src/router.test-d.ts
CHANGED
@@ -6,11 +6,11 @@ const router = os.router({
|
|
6
6
|
ping: os
|
7
7
|
.input(z.object({ ping: z.string().transform(() => 1) }))
|
8
8
|
.output(z.object({ pong: z.number().transform(() => '1') }))
|
9
|
-
.
|
9
|
+
.func(() => ({ pong: 1 })),
|
10
10
|
user: {
|
11
11
|
find: os
|
12
12
|
.input(z.object({ find: z.number().transform(() => '1') }))
|
13
|
-
.
|
13
|
+
.func(() => ({ user: { id: 1 } }))
|
14
14
|
,
|
15
15
|
},
|
16
16
|
})
|
package/src/router.test.ts
CHANGED
@@ -6,22 +6,22 @@ it('require procedure match context', () => {
|
|
6
6
|
const osw = os.context<{ auth: boolean, userId: string }>()
|
7
7
|
|
8
8
|
osw.router({
|
9
|
-
ping: osw.context<{ auth: boolean }>().
|
9
|
+
ping: osw.context<{ auth: boolean }>().func(() => {
|
10
10
|
return { pong: 'ping' }
|
11
11
|
}),
|
12
12
|
|
13
13
|
// @ts-expect-error userId is not match
|
14
|
-
ping2: osw.context<{ userId: number }>().
|
14
|
+
ping2: osw.context<{ userId: number }>().func(() => {
|
15
15
|
return { name: 'unnoq' }
|
16
16
|
}),
|
17
17
|
|
18
18
|
nested: {
|
19
|
-
ping: osw.context<{ auth: boolean }>().
|
19
|
+
ping: osw.context<{ auth: boolean }>().func(() => {
|
20
20
|
return { pong: 'ping' }
|
21
21
|
}),
|
22
22
|
|
23
23
|
// @ts-expect-error userId is not match
|
24
|
-
ping2: osw.context<{ userId: number }>().
|
24
|
+
ping2: osw.context<{ userId: number }>().func(() => {
|
25
25
|
return { name: 'unnoq' }
|
26
26
|
}),
|
27
27
|
},
|
@@ -31,10 +31,10 @@ it('require procedure match context', () => {
|
|
31
31
|
it('require match contract', () => {
|
32
32
|
const pingContract = oc.route({ method: 'GET', path: '/ping' })
|
33
33
|
const pongContract = oc.input(z.string()).output(z.string())
|
34
|
-
const ping = os.contract(pingContract).
|
34
|
+
const ping = os.contract(pingContract).func(() => {
|
35
35
|
return 'ping'
|
36
36
|
})
|
37
|
-
const pong = os.contract(pongContract).
|
37
|
+
const pong = os.contract(pongContract).func(() => {
|
38
38
|
return 'pong'
|
39
39
|
})
|
40
40
|
|
@@ -85,7 +85,7 @@ it('require match contract', () => {
|
|
85
85
|
nested: {
|
86
86
|
ping,
|
87
87
|
// @ts-expect-error nested.pong is mismatch
|
88
|
-
pong: os.
|
88
|
+
pong: os.func(() => 'ping'),
|
89
89
|
},
|
90
90
|
}
|
91
91
|
|
@@ -120,18 +120,18 @@ it('toContractRouter', () => {
|
|
120
120
|
const osw = os.contract(contract)
|
121
121
|
|
122
122
|
const router = osw.router({
|
123
|
-
p1: osw.p1.
|
123
|
+
p1: osw.p1.func(() => {
|
124
124
|
return 'unnoq'
|
125
125
|
}),
|
126
126
|
|
127
127
|
nested: osw.nested.router({
|
128
|
-
p2: osw.nested.p2.
|
128
|
+
p2: osw.nested.p2.func(() => {
|
129
129
|
return 'unnoq'
|
130
130
|
}),
|
131
131
|
}),
|
132
132
|
|
133
133
|
nested2: {
|
134
|
-
p3: osw.nested2.p3.
|
134
|
+
p3: osw.nested2.p3.func(() => {
|
135
135
|
return 'unnoq'
|
136
136
|
}),
|
137
137
|
},
|