@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,220 +0,0 @@
|
|
1
|
-
import type { DecoratedProcedure, Meta, MiddlewareMeta } from '.'
|
2
|
-
import { DecoratedContractProcedure } from '@orpc/contract'
|
3
|
-
import { z } from 'zod'
|
4
|
-
import { isProcedure, os } from '.'
|
5
|
-
import { ProcedureImplementer } from './procedure-implementer'
|
6
|
-
|
7
|
-
const p1 = new DecoratedContractProcedure({
|
8
|
-
InputSchema: undefined,
|
9
|
-
OutputSchema: undefined,
|
10
|
-
method: undefined,
|
11
|
-
path: undefined,
|
12
|
-
})
|
13
|
-
const implementer1 = new ProcedureImplementer<
|
14
|
-
{ auth: boolean },
|
15
|
-
undefined,
|
16
|
-
undefined,
|
17
|
-
undefined
|
18
|
-
>({ contract: p1 })
|
19
|
-
|
20
|
-
const schema1 = z.object({ id: z.string() })
|
21
|
-
const schema2 = z.object({ name: z.string() })
|
22
|
-
|
23
|
-
const p2 = new DecoratedContractProcedure({
|
24
|
-
InputSchema: schema1,
|
25
|
-
OutputSchema: schema2,
|
26
|
-
method: 'GET',
|
27
|
-
path: '/test',
|
28
|
-
})
|
29
|
-
|
30
|
-
const implementer2 = new ProcedureImplementer<
|
31
|
-
{ auth: boolean },
|
32
|
-
undefined,
|
33
|
-
typeof schema1,
|
34
|
-
typeof schema2
|
35
|
-
>({ contract: p2 })
|
36
|
-
|
37
|
-
describe('use middleware', () => {
|
38
|
-
it('infer types', () => {
|
39
|
-
const i = implementer1
|
40
|
-
.use((input, context, meta) => {
|
41
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
42
|
-
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
43
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
|
44
|
-
|
45
|
-
return meta.next({
|
46
|
-
context: {
|
47
|
-
userId: '1',
|
48
|
-
},
|
49
|
-
})
|
50
|
-
})
|
51
|
-
.use((input, context, meta) => {
|
52
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
53
|
-
expectTypeOf(context).toEqualTypeOf<
|
54
|
-
{ userId: string } & { auth: boolean }
|
55
|
-
>()
|
56
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<unknown>>()
|
57
|
-
|
58
|
-
return meta.next({})
|
59
|
-
})
|
60
|
-
|
61
|
-
expectTypeOf(i).toEqualTypeOf<
|
62
|
-
ProcedureImplementer<
|
63
|
-
{ auth: boolean },
|
64
|
-
{ userId: string },
|
65
|
-
undefined,
|
66
|
-
undefined
|
67
|
-
>
|
68
|
-
>()
|
69
|
-
})
|
70
|
-
|
71
|
-
it('map middleware input', () => {
|
72
|
-
// @ts-expect-error mismatch input
|
73
|
-
implementer2.use((input: { postId: string }) => {
|
74
|
-
return { context: { a: 'a' } }
|
75
|
-
})
|
76
|
-
|
77
|
-
implementer2.use(
|
78
|
-
(input: { postId: string }, _, meta) => {
|
79
|
-
return meta.next({ context: { a: 'a' } })
|
80
|
-
},
|
81
|
-
// @ts-expect-error mismatch input
|
82
|
-
input => ({ postId: 12455 }),
|
83
|
-
)
|
84
|
-
|
85
|
-
implementer2.use(
|
86
|
-
(input: { postId: string }, context, meta) => meta.next({}),
|
87
|
-
input => ({ postId: '12455' }),
|
88
|
-
)
|
89
|
-
|
90
|
-
const i = implementer2.use(
|
91
|
-
(input: { id: number }, _, meta) => {
|
92
|
-
return meta.next({
|
93
|
-
context: {
|
94
|
-
userIdd: '1',
|
95
|
-
},
|
96
|
-
})
|
97
|
-
},
|
98
|
-
input => ({ id: Number.parseInt(input.id) }),
|
99
|
-
)
|
100
|
-
|
101
|
-
expectTypeOf(i).toEqualTypeOf<
|
102
|
-
ProcedureImplementer<
|
103
|
-
{ auth: boolean },
|
104
|
-
{ userIdd: string },
|
105
|
-
typeof schema1,
|
106
|
-
typeof schema2
|
107
|
-
>
|
108
|
-
>()
|
109
|
-
})
|
110
|
-
})
|
111
|
-
|
112
|
-
describe('output schema', () => {
|
113
|
-
it('auto infer output schema if output schema is not specified', async () => {
|
114
|
-
const sr = os.func(() => ({ a: 1 }))
|
115
|
-
|
116
|
-
const result = await sr.zz$p.func({}, undefined, {
|
117
|
-
method: 'GET',
|
118
|
-
path: '/',
|
119
|
-
} as any)
|
120
|
-
|
121
|
-
expectTypeOf(result).toEqualTypeOf<{ a: number }>()
|
122
|
-
})
|
123
|
-
|
124
|
-
it('not infer output schema if output schema is specified', async () => {
|
125
|
-
const srb1 = new ProcedureImplementer({
|
126
|
-
contract: new DecoratedContractProcedure({
|
127
|
-
OutputSchema: z.unknown(),
|
128
|
-
InputSchema: undefined,
|
129
|
-
}),
|
130
|
-
})
|
131
|
-
|
132
|
-
const sr = srb1.func(() => ({ b: 1 }))
|
133
|
-
|
134
|
-
const result = await sr.zz$p.func({}, {}, {
|
135
|
-
method: 'GET',
|
136
|
-
path: '/',
|
137
|
-
} as any)
|
138
|
-
|
139
|
-
expectTypeOf(result).toEqualTypeOf<unknown>()
|
140
|
-
})
|
141
|
-
})
|
142
|
-
|
143
|
-
describe('handler', () => {
|
144
|
-
it('infer types', () => {
|
145
|
-
const handler = implementer1.func((input, context, meta) => {
|
146
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
147
|
-
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
148
|
-
expectTypeOf(meta).toEqualTypeOf<Meta>()
|
149
|
-
|
150
|
-
return {
|
151
|
-
name: 'unnoq',
|
152
|
-
}
|
153
|
-
})
|
154
|
-
|
155
|
-
expectTypeOf(handler).toEqualTypeOf<
|
156
|
-
DecoratedProcedure<
|
157
|
-
{ auth: boolean },
|
158
|
-
undefined,
|
159
|
-
undefined,
|
160
|
-
undefined,
|
161
|
-
{ name: string }
|
162
|
-
>
|
163
|
-
>()
|
164
|
-
expect(isProcedure(handler)).toBe(true)
|
165
|
-
|
166
|
-
implementer2.func((input, context, meta) => {
|
167
|
-
expectTypeOf(input).toEqualTypeOf<{ id: string }>()
|
168
|
-
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
169
|
-
expectTypeOf(meta).toEqualTypeOf<Meta>()
|
170
|
-
|
171
|
-
return {
|
172
|
-
name: 'unnoq',
|
173
|
-
}
|
174
|
-
})
|
175
|
-
|
176
|
-
// @ts-expect-error mismatch output
|
177
|
-
implementer2.func(() => {})
|
178
|
-
})
|
179
|
-
|
180
|
-
it('combine middlewares', () => {
|
181
|
-
const mid1 = os.middleware((input, context, meta) => {
|
182
|
-
return meta.next({
|
183
|
-
context: {
|
184
|
-
userId: '1',
|
185
|
-
},
|
186
|
-
})
|
187
|
-
})
|
188
|
-
|
189
|
-
const mid2 = os.middleware((input, context, meta) => {
|
190
|
-
return meta.next({ })
|
191
|
-
})
|
192
|
-
|
193
|
-
const handler = implementer2
|
194
|
-
.use(mid1)
|
195
|
-
.use(mid2)
|
196
|
-
.func((input, context, meta) => {
|
197
|
-
expectTypeOf(input).toEqualTypeOf<{ id: string }>()
|
198
|
-
expectTypeOf(context).toEqualTypeOf<
|
199
|
-
{ auth: boolean } & { userId: string }
|
200
|
-
>()
|
201
|
-
expectTypeOf(meta).toEqualTypeOf<Meta>()
|
202
|
-
|
203
|
-
return {
|
204
|
-
name: 'unnoq',
|
205
|
-
}
|
206
|
-
})
|
207
|
-
|
208
|
-
expectTypeOf(handler).toEqualTypeOf<
|
209
|
-
DecoratedProcedure<
|
210
|
-
{ auth: boolean },
|
211
|
-
{ userId: string },
|
212
|
-
typeof schema1,
|
213
|
-
typeof schema2,
|
214
|
-
{ name: string }
|
215
|
-
>
|
216
|
-
>()
|
217
|
-
|
218
|
-
expect(handler.zz$p.middlewares).toEqual([mid1, mid2])
|
219
|
-
})
|
220
|
-
})
|
@@ -1,102 +0,0 @@
|
|
1
|
-
import type { ContractProcedure, Schema, SchemaInput, SchemaOutput } from '@orpc/contract'
|
2
|
-
import type { Context, MergeContext } from './types'
|
3
|
-
import {
|
4
|
-
decorateMiddleware,
|
5
|
-
type MapInputMiddleware,
|
6
|
-
type Middleware,
|
7
|
-
} from './middleware'
|
8
|
-
import {
|
9
|
-
type DecoratedProcedure,
|
10
|
-
decorateProcedure,
|
11
|
-
type ProcedureFunc,
|
12
|
-
} from './procedure'
|
13
|
-
|
14
|
-
export class ProcedureImplementer<
|
15
|
-
TContext extends Context,
|
16
|
-
TExtraContext extends Context,
|
17
|
-
TInputSchema extends Schema,
|
18
|
-
TOutputSchema extends Schema,
|
19
|
-
> {
|
20
|
-
constructor(
|
21
|
-
public zz$pi: {
|
22
|
-
contract: ContractProcedure<TInputSchema, TOutputSchema>
|
23
|
-
middlewares?: Middleware<any, any, any, any>[]
|
24
|
-
},
|
25
|
-
) {}
|
26
|
-
|
27
|
-
use<
|
28
|
-
UExtraContext extends
|
29
|
-
| Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
|
30
|
-
| undefined = undefined,
|
31
|
-
>(
|
32
|
-
middleware: Middleware<
|
33
|
-
MergeContext<TContext, TExtraContext>,
|
34
|
-
UExtraContext,
|
35
|
-
SchemaOutput<TInputSchema>,
|
36
|
-
SchemaInput<TOutputSchema>
|
37
|
-
>,
|
38
|
-
): ProcedureImplementer<
|
39
|
-
TContext,
|
40
|
-
MergeContext<TExtraContext, UExtraContext>,
|
41
|
-
TInputSchema,
|
42
|
-
TOutputSchema
|
43
|
-
>
|
44
|
-
|
45
|
-
use<
|
46
|
-
UExtraContext extends
|
47
|
-
| Partial<MergeContext<Context, MergeContext<TContext, TExtraContext>>>
|
48
|
-
| undefined = undefined,
|
49
|
-
UMappedInput = unknown,
|
50
|
-
>(
|
51
|
-
middleware: Middleware<
|
52
|
-
MergeContext<TContext, TExtraContext>,
|
53
|
-
UExtraContext,
|
54
|
-
UMappedInput,
|
55
|
-
SchemaInput<TOutputSchema>
|
56
|
-
>,
|
57
|
-
mapInput: MapInputMiddleware<SchemaOutput<TInputSchema>, UMappedInput>,
|
58
|
-
): ProcedureImplementer<
|
59
|
-
TContext,
|
60
|
-
MergeContext<TExtraContext, UExtraContext>,
|
61
|
-
TInputSchema,
|
62
|
-
TOutputSchema
|
63
|
-
>
|
64
|
-
|
65
|
-
use(
|
66
|
-
middleware: Middleware<any, any, any, any>,
|
67
|
-
mapInput?: MapInputMiddleware<any, any>,
|
68
|
-
): ProcedureImplementer<any, any, any, any> {
|
69
|
-
const middleware_ = mapInput
|
70
|
-
? decorateMiddleware(middleware).mapInput(mapInput)
|
71
|
-
: middleware
|
72
|
-
|
73
|
-
return new ProcedureImplementer({
|
74
|
-
...this.zz$pi,
|
75
|
-
middlewares: [...(this.zz$pi.middlewares ?? []), middleware_],
|
76
|
-
})
|
77
|
-
}
|
78
|
-
|
79
|
-
func<UFuncOutput extends SchemaOutput<TOutputSchema>>(
|
80
|
-
func: ProcedureFunc<
|
81
|
-
TContext,
|
82
|
-
TExtraContext,
|
83
|
-
TInputSchema,
|
84
|
-
TOutputSchema,
|
85
|
-
UFuncOutput
|
86
|
-
>,
|
87
|
-
): DecoratedProcedure<
|
88
|
-
TContext,
|
89
|
-
TExtraContext,
|
90
|
-
TInputSchema,
|
91
|
-
TOutputSchema,
|
92
|
-
UFuncOutput
|
93
|
-
> {
|
94
|
-
return decorateProcedure({
|
95
|
-
zz$p: {
|
96
|
-
middlewares: this.zz$pi.middlewares,
|
97
|
-
contract: this.zz$pi.contract,
|
98
|
-
func,
|
99
|
-
},
|
100
|
-
})
|
101
|
-
}
|
102
|
-
}
|
package/src/procedure.test.ts
DELETED
@@ -1,317 +0,0 @@
|
|
1
|
-
import type { MiddlewareMeta } from '.'
|
2
|
-
import { ContractProcedure, DecoratedContractProcedure } from '@orpc/contract'
|
3
|
-
import { z } from 'zod'
|
4
|
-
import { os } from '.'
|
5
|
-
import {
|
6
|
-
type DecoratedProcedure,
|
7
|
-
decorateProcedure,
|
8
|
-
isProcedure,
|
9
|
-
Procedure,
|
10
|
-
} from './procedure'
|
11
|
-
|
12
|
-
it('isProcedure', () => {
|
13
|
-
expect(
|
14
|
-
isProcedure(
|
15
|
-
decorateProcedure(
|
16
|
-
new Procedure({
|
17
|
-
contract: new ContractProcedure({
|
18
|
-
InputSchema: undefined,
|
19
|
-
OutputSchema: undefined,
|
20
|
-
}),
|
21
|
-
func: () => {},
|
22
|
-
}),
|
23
|
-
),
|
24
|
-
),
|
25
|
-
).toBe(true)
|
26
|
-
expect({
|
27
|
-
zz$p: {
|
28
|
-
contract: new DecoratedContractProcedure({
|
29
|
-
InputSchema: undefined,
|
30
|
-
OutputSchema: undefined,
|
31
|
-
}),
|
32
|
-
func: () => {},
|
33
|
-
},
|
34
|
-
}).toSatisfy(isProcedure)
|
35
|
-
|
36
|
-
expect({
|
37
|
-
zz$p: {
|
38
|
-
contract: new DecoratedContractProcedure({
|
39
|
-
InputSchema: undefined,
|
40
|
-
OutputSchema: undefined,
|
41
|
-
}),
|
42
|
-
},
|
43
|
-
}).not.toSatisfy(isProcedure)
|
44
|
-
|
45
|
-
expect({
|
46
|
-
zz$p: {
|
47
|
-
handler: () => {},
|
48
|
-
},
|
49
|
-
}).not.toSatisfy(isProcedure)
|
50
|
-
|
51
|
-
expect({}).not.toSatisfy(isProcedure)
|
52
|
-
expect(12233).not.toSatisfy(isProcedure)
|
53
|
-
expect('12233').not.toSatisfy(isProcedure)
|
54
|
-
expect(undefined).not.toSatisfy(isProcedure)
|
55
|
-
expect(null).not.toSatisfy(isProcedure)
|
56
|
-
})
|
57
|
-
|
58
|
-
describe('route method', () => {
|
59
|
-
it('sets route options correctly', () => {
|
60
|
-
const p = os.context<{ auth: boolean }>().func(() => {
|
61
|
-
return 'test'
|
62
|
-
})
|
63
|
-
|
64
|
-
const p2 = p.route({ path: '/test', method: 'GET' })
|
65
|
-
|
66
|
-
expect(p2.zz$p.contract.zz$cp.path).toBe('/test')
|
67
|
-
expect(p2.zz$p.contract.zz$cp.method).toBe('GET')
|
68
|
-
})
|
69
|
-
|
70
|
-
it('preserves existing context and handler', () => {
|
71
|
-
const handler = () => 'test'
|
72
|
-
const p = os.context<{ auth: boolean }>().func(handler)
|
73
|
-
|
74
|
-
const p2 = p.route({ path: '/test' })
|
75
|
-
|
76
|
-
expect(p2.zz$p.func).toBe(handler)
|
77
|
-
// Context type is preserved through the route method
|
78
|
-
expectTypeOf(p2).toEqualTypeOf<
|
79
|
-
DecoratedProcedure<
|
80
|
-
{ auth: boolean },
|
81
|
-
undefined,
|
82
|
-
undefined,
|
83
|
-
undefined,
|
84
|
-
string
|
85
|
-
>
|
86
|
-
>()
|
87
|
-
})
|
88
|
-
|
89
|
-
it('works with prefix method', () => {
|
90
|
-
const p = os
|
91
|
-
.context<{ auth: boolean }>()
|
92
|
-
.route({ path: '/api', method: 'POST' })
|
93
|
-
.func(() => 'test')
|
94
|
-
|
95
|
-
const p2 = p.prefix('/v1')
|
96
|
-
|
97
|
-
expect(p2.zz$p.contract.zz$cp.path).toBe('/v1/api')
|
98
|
-
expect(p2.zz$p.contract.zz$cp.method).toBe('POST')
|
99
|
-
})
|
100
|
-
|
101
|
-
it('works with middleware', () => {
|
102
|
-
const mid = os.middleware((_, __, meta) => meta.next({ context: { userId: '1' } }))
|
103
|
-
|
104
|
-
const p = os
|
105
|
-
.context<{ auth: boolean }>()
|
106
|
-
.route({ path: '/test' })
|
107
|
-
.use(mid)
|
108
|
-
.func((input, context) => {
|
109
|
-
expectTypeOf(context).toEqualTypeOf<
|
110
|
-
{ auth: boolean } & { userId: string }
|
111
|
-
>()
|
112
|
-
return 'test'
|
113
|
-
})
|
114
|
-
|
115
|
-
expect(p.zz$p.contract.zz$cp.path).toBe('/test')
|
116
|
-
expect(p.zz$p.middlewares).toEqual([mid])
|
117
|
-
})
|
118
|
-
|
119
|
-
it('overrides existing route options', () => {
|
120
|
-
const p = os
|
121
|
-
.context<{ auth: boolean }>()
|
122
|
-
.route({ path: '/test1', method: 'GET' })
|
123
|
-
.func(() => 'test')
|
124
|
-
|
125
|
-
const p2 = p.route({ path: '/test2', method: 'POST' })
|
126
|
-
|
127
|
-
expect(p2.zz$p.contract.zz$cp.path).toBe('/test2')
|
128
|
-
expect(p2.zz$p.contract.zz$cp.method).toBe('POST')
|
129
|
-
})
|
130
|
-
|
131
|
-
it('preserves input/output schemas', () => {
|
132
|
-
const inputSchema = z.object({ id: z.number() })
|
133
|
-
const outputSchema = z.string()
|
134
|
-
const p = os
|
135
|
-
.context<{ auth: boolean }>()
|
136
|
-
.input(inputSchema)
|
137
|
-
.output(outputSchema)
|
138
|
-
.route({ path: '/test' })
|
139
|
-
.func((input) => {
|
140
|
-
expectTypeOf(input).toEqualTypeOf<{ id: number }>()
|
141
|
-
return 'test'
|
142
|
-
})
|
143
|
-
|
144
|
-
const p2 = p.route({ path: '/test2' })
|
145
|
-
|
146
|
-
// Type checking that schemas are preserved
|
147
|
-
expectTypeOf(p2).toEqualTypeOf<
|
148
|
-
DecoratedProcedure<
|
149
|
-
{ auth: boolean },
|
150
|
-
undefined,
|
151
|
-
typeof inputSchema,
|
152
|
-
typeof outputSchema,
|
153
|
-
string
|
154
|
-
>
|
155
|
-
>()
|
156
|
-
})
|
157
|
-
})
|
158
|
-
|
159
|
-
it('prefix method', () => {
|
160
|
-
const p = os.context<{ auth: boolean }>().func(() => {
|
161
|
-
return 'unnoq'
|
162
|
-
})
|
163
|
-
|
164
|
-
const p2 = p.prefix('/test')
|
165
|
-
|
166
|
-
expect(p2.zz$p.contract.zz$cp.path).toBe(undefined)
|
167
|
-
|
168
|
-
const p3 = os
|
169
|
-
.context<{ auth: boolean }>()
|
170
|
-
.route({ path: '/test1' })
|
171
|
-
.func(() => {
|
172
|
-
return 'unnoq'
|
173
|
-
})
|
174
|
-
|
175
|
-
const p4 = p3.prefix('/test')
|
176
|
-
expect(p4.zz$p.contract.zz$cp.path).toBe('/test/test1')
|
177
|
-
})
|
178
|
-
|
179
|
-
describe('use middleware', () => {
|
180
|
-
it('infer types', () => {
|
181
|
-
const p1 = os
|
182
|
-
.context<{ auth: boolean }>()
|
183
|
-
.use((_, __, meta) => {
|
184
|
-
return meta.next({ context: { postId: 'string' } })
|
185
|
-
})
|
186
|
-
.func(() => {
|
187
|
-
return 'unnoq'
|
188
|
-
})
|
189
|
-
|
190
|
-
const p2 = p1
|
191
|
-
.use((input, context, meta) => {
|
192
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
193
|
-
expectTypeOf(context).toEqualTypeOf<
|
194
|
-
{ auth: boolean } & { postId: string }
|
195
|
-
>()
|
196
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<string>>()
|
197
|
-
|
198
|
-
return meta.next({
|
199
|
-
context: {
|
200
|
-
userId: '1',
|
201
|
-
},
|
202
|
-
})
|
203
|
-
})
|
204
|
-
.use((input, context, meta) => {
|
205
|
-
expectTypeOf(input).toEqualTypeOf<unknown>()
|
206
|
-
expectTypeOf(context).toEqualTypeOf<
|
207
|
-
{ userId: string } & { postId: string } & { auth: boolean }
|
208
|
-
>()
|
209
|
-
expectTypeOf(meta).toEqualTypeOf<MiddlewareMeta<string>>()
|
210
|
-
|
211
|
-
return meta.next({})
|
212
|
-
})
|
213
|
-
|
214
|
-
expectTypeOf(p2).toEqualTypeOf<
|
215
|
-
DecoratedProcedure<
|
216
|
-
{ auth: boolean },
|
217
|
-
{ postId: string } & { userId: string },
|
218
|
-
undefined,
|
219
|
-
undefined,
|
220
|
-
string
|
221
|
-
>
|
222
|
-
>()
|
223
|
-
})
|
224
|
-
|
225
|
-
it('can map input', () => {
|
226
|
-
const mid = os.middleware((input: { id: number }, __, meta) => {
|
227
|
-
return meta.next({})
|
228
|
-
})
|
229
|
-
|
230
|
-
os.input(z.object({ postId: z.number() })).use(mid, (input) => {
|
231
|
-
expectTypeOf(input).toEqualTypeOf<{ postId: number }>()
|
232
|
-
|
233
|
-
return {
|
234
|
-
id: input.postId,
|
235
|
-
}
|
236
|
-
})
|
237
|
-
|
238
|
-
// @ts-expect-error mismatch input
|
239
|
-
os.input(z.object({ postId: z.number() })).use(mid)
|
240
|
-
|
241
|
-
// @ts-expect-error mismatch input
|
242
|
-
os.input(z.object({ postId: z.number() })).use(mid, (input) => {
|
243
|
-
return {
|
244
|
-
wrong: input.postId,
|
245
|
-
}
|
246
|
-
})
|
247
|
-
})
|
248
|
-
|
249
|
-
it('add middlewares to beginning', () => {
|
250
|
-
const mid1 = vi.fn()
|
251
|
-
const mid2 = vi.fn()
|
252
|
-
const mid3 = vi.fn()
|
253
|
-
|
254
|
-
const p1 = os.use(mid1).func(() => 'unnoq')
|
255
|
-
const p2 = p1.use(mid2).use(mid3)
|
256
|
-
|
257
|
-
expect(p2.zz$p.middlewares).toEqual([mid3, mid2, mid1])
|
258
|
-
})
|
259
|
-
})
|
260
|
-
|
261
|
-
describe('server action', () => {
|
262
|
-
it('only accept undefined context', () => {
|
263
|
-
expectTypeOf(os.func(() => {})).toMatchTypeOf<(...args: any[]) => any>()
|
264
|
-
expectTypeOf(
|
265
|
-
os.context<{ auth: boolean } | undefined>().func(() => {}),
|
266
|
-
).toMatchTypeOf<(...args: any[]) => any>()
|
267
|
-
expectTypeOf(
|
268
|
-
os.context<{ auth: boolean }>().func(() => {}),
|
269
|
-
).not.toMatchTypeOf<(...args: any[]) => any>()
|
270
|
-
})
|
271
|
-
|
272
|
-
it('infer types', () => {
|
273
|
-
const p = os
|
274
|
-
.input(z.object({ id: z.number() }))
|
275
|
-
.output(z.string())
|
276
|
-
.func(() => 'string')
|
277
|
-
|
278
|
-
expectTypeOf(p).toMatchTypeOf<
|
279
|
-
(input: { id: number } | FormData) => Promise<string>
|
280
|
-
>()
|
281
|
-
|
282
|
-
const p2 = os.input(z.object({ id: z.number() })).func(() => 12333)
|
283
|
-
|
284
|
-
expectTypeOf(p2).toMatchTypeOf<
|
285
|
-
(input: { id: number } | FormData) => Promise<number>
|
286
|
-
>()
|
287
|
-
})
|
288
|
-
|
289
|
-
it('works with input', async () => {
|
290
|
-
const p = os
|
291
|
-
.input(z.object({ id: z.number(), date: z.date() }))
|
292
|
-
.func(async (input, context) => {
|
293
|
-
expect(context).toBe(undefined)
|
294
|
-
return input
|
295
|
-
})
|
296
|
-
|
297
|
-
expect(await p({ id: 123, date: new Date('2022-01-01') })).toEqual({
|
298
|
-
id: 123,
|
299
|
-
date: new Date('2022-01-01'),
|
300
|
-
})
|
301
|
-
})
|
302
|
-
|
303
|
-
it('can deserialize form data', async () => {
|
304
|
-
const p = os
|
305
|
-
.input(z.object({ id: z.number(), nested: z.object({ date: z.date() }) }))
|
306
|
-
.func(async input => input)
|
307
|
-
|
308
|
-
const form = new FormData()
|
309
|
-
form.append('id', '123')
|
310
|
-
form.append('nested[date]', '2022-01-01')
|
311
|
-
|
312
|
-
expect(await p(form)).toEqual({
|
313
|
-
id: 123,
|
314
|
-
nested: { date: new Date('2022-01-01') },
|
315
|
-
})
|
316
|
-
})
|
317
|
-
})
|