@orpc/server 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/chunk-ACLC6USM.js +262 -0
- package/dist/chunk-ACLC6USM.js.map +1 -0
- package/dist/fetch.js +648 -0
- package/dist/fetch.js.map +1 -0
- package/dist/index.js +403 -0
- package/dist/index.js.map +1 -0
- package/dist/src/adapters/fetch.d.ts +36 -0
- package/dist/src/adapters/fetch.d.ts.map +1 -0
- package/dist/src/builder.d.ts +49 -0
- package/dist/src/builder.d.ts.map +1 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/middleware.d.ts +16 -0
- package/dist/src/middleware.d.ts.map +1 -0
- package/dist/src/procedure-builder.d.ts +31 -0
- package/dist/src/procedure-builder.d.ts.map +1 -0
- package/dist/src/procedure-caller.d.ts +33 -0
- package/dist/src/procedure-caller.d.ts.map +1 -0
- package/dist/src/procedure-implementer.d.ts +19 -0
- package/dist/src/procedure-implementer.d.ts.map +1 -0
- package/dist/src/procedure.d.ts +29 -0
- package/dist/src/procedure.d.ts.map +1 -0
- package/dist/src/router-builder.d.ts +22 -0
- package/dist/src/router-builder.d.ts.map +1 -0
- package/dist/src/router-caller.d.ts +36 -0
- package/dist/src/router-caller.d.ts.map +1 -0
- package/dist/src/router-implementer.d.ts +20 -0
- package/dist/src/router-implementer.d.ts.map +1 -0
- package/dist/src/router.d.ts +14 -0
- package/dist/src/router.d.ts.map +1 -0
- package/dist/src/types.d.ts +18 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +57 -0
- package/src/adapters/fetch.test.ts +399 -0
- package/src/adapters/fetch.ts +228 -0
- package/src/builder.test.ts +362 -0
- package/src/builder.ts +236 -0
- package/src/index.ts +16 -0
- package/src/middleware.test.ts +279 -0
- package/src/middleware.ts +119 -0
- package/src/procedure-builder.test.ts +219 -0
- package/src/procedure-builder.ts +158 -0
- package/src/procedure-caller.test.ts +210 -0
- package/src/procedure-caller.ts +165 -0
- package/src/procedure-implementer.test.ts +215 -0
- package/src/procedure-implementer.ts +103 -0
- package/src/procedure.test.ts +312 -0
- package/src/procedure.ts +251 -0
- package/src/router-builder.test.ts +106 -0
- package/src/router-builder.ts +120 -0
- package/src/router-caller.test.ts +173 -0
- package/src/router-caller.ts +95 -0
- package/src/router-implementer.test.ts +116 -0
- package/src/router-implementer.ts +110 -0
- package/src/router.test.ts +142 -0
- package/src/router.ts +69 -0
- package/src/types.test.ts +18 -0
- package/src/types.ts +28 -0
- package/src/utils.test.ts +243 -0
- package/src/utils.ts +95 -0
@@ -0,0 +1,219 @@
|
|
1
|
+
import { ContractProcedure } from '@orpc/contract'
|
2
|
+
import { z } from 'zod'
|
3
|
+
import { type DecoratedProcedure, isProcedure } from './procedure'
|
4
|
+
import { ProcedureBuilder } from './procedure-builder'
|
5
|
+
import type { ProcedureImplementer } from './procedure-implementer'
|
6
|
+
import type { Meta } from './types'
|
7
|
+
|
8
|
+
const schema1 = z.object({ id: z.string() })
|
9
|
+
const example1 = { id: '1' }
|
10
|
+
const schema2 = z.object({ name: z.string() })
|
11
|
+
const example2 = { name: 'dinwwwh' }
|
12
|
+
|
13
|
+
const builder = new ProcedureBuilder<
|
14
|
+
{ auth: boolean },
|
15
|
+
undefined,
|
16
|
+
undefined,
|
17
|
+
undefined
|
18
|
+
>({
|
19
|
+
contract: new ContractProcedure({
|
20
|
+
InputSchema: undefined,
|
21
|
+
OutputSchema: undefined,
|
22
|
+
}),
|
23
|
+
})
|
24
|
+
|
25
|
+
it('input', () => {
|
26
|
+
const builder2 = builder.input(schema1, example1)
|
27
|
+
|
28
|
+
expectTypeOf(builder2).toEqualTypeOf<
|
29
|
+
ProcedureBuilder<{ auth: boolean }, undefined, typeof schema1, undefined>
|
30
|
+
>()
|
31
|
+
|
32
|
+
expect(builder2.zz$pb).toMatchObject({
|
33
|
+
contract: {
|
34
|
+
zz$cp: {
|
35
|
+
InputSchema: schema1,
|
36
|
+
inputExample: example1,
|
37
|
+
},
|
38
|
+
},
|
39
|
+
})
|
40
|
+
})
|
41
|
+
|
42
|
+
it('output', () => {
|
43
|
+
const builder2 = builder.output(schema2, example2)
|
44
|
+
|
45
|
+
expectTypeOf(builder2).toEqualTypeOf<
|
46
|
+
ProcedureBuilder<{ auth: boolean }, undefined, undefined, typeof schema2>
|
47
|
+
>()
|
48
|
+
|
49
|
+
expect(builder2.zz$pb).toMatchObject({
|
50
|
+
contract: {
|
51
|
+
zz$cp: {
|
52
|
+
OutputSchema: schema2,
|
53
|
+
outputExample: example2,
|
54
|
+
},
|
55
|
+
},
|
56
|
+
})
|
57
|
+
})
|
58
|
+
|
59
|
+
it('route', () => {
|
60
|
+
const builder2 = builder.route({
|
61
|
+
method: 'GET',
|
62
|
+
path: '/test',
|
63
|
+
deprecated: true,
|
64
|
+
description: 'des',
|
65
|
+
summary: 'sum',
|
66
|
+
tags: ['hi'],
|
67
|
+
})
|
68
|
+
|
69
|
+
expectTypeOf(builder2).toEqualTypeOf<
|
70
|
+
ProcedureBuilder<{ auth: boolean }, undefined, undefined, undefined>
|
71
|
+
>()
|
72
|
+
|
73
|
+
expect(builder2.zz$pb).toMatchObject({
|
74
|
+
contract: {
|
75
|
+
zz$cp: {
|
76
|
+
method: 'GET',
|
77
|
+
path: '/test',
|
78
|
+
deprecated: true,
|
79
|
+
description: 'des',
|
80
|
+
summary: 'sum',
|
81
|
+
tags: ['hi'],
|
82
|
+
},
|
83
|
+
},
|
84
|
+
})
|
85
|
+
})
|
86
|
+
|
87
|
+
describe('use middleware', () => {
|
88
|
+
it('infer types', () => {
|
89
|
+
const implementer = builder
|
90
|
+
.use((input, context, meta) => {
|
91
|
+
expectTypeOf(input).toEqualTypeOf<unknown>()
|
92
|
+
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
93
|
+
expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
|
94
|
+
|
95
|
+
return {
|
96
|
+
context: {
|
97
|
+
userId: '1',
|
98
|
+
},
|
99
|
+
}
|
100
|
+
})
|
101
|
+
.use((input, context, meta) => {
|
102
|
+
expectTypeOf(input).toEqualTypeOf<unknown>()
|
103
|
+
expectTypeOf(context).toEqualTypeOf<
|
104
|
+
{ userId: string } & { auth: boolean }
|
105
|
+
>()
|
106
|
+
expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
|
107
|
+
})
|
108
|
+
|
109
|
+
expectTypeOf(implementer).toEqualTypeOf<
|
110
|
+
ProcedureImplementer<
|
111
|
+
{ auth: boolean },
|
112
|
+
{ userId: string },
|
113
|
+
undefined,
|
114
|
+
undefined
|
115
|
+
>
|
116
|
+
>()
|
117
|
+
})
|
118
|
+
|
119
|
+
it('map middleware input', () => {
|
120
|
+
// @ts-expect-error mismatch input
|
121
|
+
builder.use((input: { postId: string }) => {
|
122
|
+
return { context: { a: 'a' } }
|
123
|
+
})
|
124
|
+
|
125
|
+
builder.use(
|
126
|
+
(input: { postId: string }) => {
|
127
|
+
return { context: { a: 'a' } }
|
128
|
+
},
|
129
|
+
// @ts-expect-error mismatch input
|
130
|
+
(input) => ({ postId: 12455 }),
|
131
|
+
)
|
132
|
+
|
133
|
+
builder.use(
|
134
|
+
(input: { postId: string }) => {},
|
135
|
+
(input) => ({ postId: '12455' }),
|
136
|
+
)
|
137
|
+
|
138
|
+
const implementer = builder.input(schema1).use(
|
139
|
+
(input: { id: number }) => {
|
140
|
+
return {
|
141
|
+
context: {
|
142
|
+
userId555: '1',
|
143
|
+
},
|
144
|
+
}
|
145
|
+
},
|
146
|
+
(input) => ({ id: Number.parseInt(input.id) }),
|
147
|
+
)
|
148
|
+
|
149
|
+
expectTypeOf(implementer).toEqualTypeOf<
|
150
|
+
ProcedureImplementer<
|
151
|
+
{ auth: boolean },
|
152
|
+
{ userId555: string },
|
153
|
+
typeof schema1,
|
154
|
+
undefined
|
155
|
+
>
|
156
|
+
>()
|
157
|
+
})
|
158
|
+
})
|
159
|
+
|
160
|
+
describe('handler', () => {
|
161
|
+
it('infer types', () => {
|
162
|
+
const handler = builder.handler((input, context, meta) => {
|
163
|
+
expectTypeOf(input).toEqualTypeOf<unknown>()
|
164
|
+
expectTypeOf(context).toEqualTypeOf<{ auth: boolean }>()
|
165
|
+
expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
|
166
|
+
})
|
167
|
+
|
168
|
+
expectTypeOf(handler).toEqualTypeOf<
|
169
|
+
DecoratedProcedure<
|
170
|
+
{ auth: boolean },
|
171
|
+
undefined,
|
172
|
+
undefined,
|
173
|
+
undefined,
|
174
|
+
void
|
175
|
+
>
|
176
|
+
>()
|
177
|
+
|
178
|
+
expect(isProcedure(handler)).toBe(true)
|
179
|
+
})
|
180
|
+
|
181
|
+
it('combine middlewares', () => {
|
182
|
+
const mid1 = () => {
|
183
|
+
return {
|
184
|
+
context: {
|
185
|
+
userId: '1',
|
186
|
+
},
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
const mid2 = () => {}
|
191
|
+
|
192
|
+
const handler = builder
|
193
|
+
.use(mid1)
|
194
|
+
.use(mid2)
|
195
|
+
.handler((input, context, meta) => {
|
196
|
+
expectTypeOf(input).toEqualTypeOf<unknown>()
|
197
|
+
expectTypeOf(context).toEqualTypeOf<
|
198
|
+
{ userId: string } & { auth: boolean }
|
199
|
+
>()
|
200
|
+
expectTypeOf(meta).toEqualTypeOf<Meta<unknown>>()
|
201
|
+
|
202
|
+
return {
|
203
|
+
name: 'dinwwwh',
|
204
|
+
}
|
205
|
+
})
|
206
|
+
|
207
|
+
expectTypeOf(handler).toEqualTypeOf<
|
208
|
+
DecoratedProcedure<
|
209
|
+
{ auth: boolean },
|
210
|
+
{ userId: string },
|
211
|
+
undefined,
|
212
|
+
undefined,
|
213
|
+
{ name: string }
|
214
|
+
>
|
215
|
+
>()
|
216
|
+
|
217
|
+
expect(handler.zz$p.middlewares).toEqual([mid1, mid2])
|
218
|
+
})
|
219
|
+
})
|
@@ -0,0 +1,158 @@
|
|
1
|
+
import {
|
2
|
+
type ContractProcedure,
|
3
|
+
DecoratedContractProcedure,
|
4
|
+
type RouteOptions,
|
5
|
+
type Schema,
|
6
|
+
type SchemaInput,
|
7
|
+
type SchemaOutput,
|
8
|
+
} from '@orpc/contract'
|
9
|
+
import type { MapInputMiddleware, Middleware } from './middleware'
|
10
|
+
import {
|
11
|
+
type DecoratedProcedure,
|
12
|
+
type ProcedureHandler,
|
13
|
+
decorateProcedure,
|
14
|
+
} from './procedure'
|
15
|
+
import { ProcedureImplementer } from './procedure-implementer'
|
16
|
+
import type { Context, MergeContext } from './types'
|
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
|
+
SchemaOutput<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
|
+
SchemaOutput<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
|
+
handler<UHandlerOutput extends SchemaOutput<TOutputSchema>>(
|
136
|
+
handler: ProcedureHandler<
|
137
|
+
TContext,
|
138
|
+
TExtraContext,
|
139
|
+
TInputSchema,
|
140
|
+
TOutputSchema,
|
141
|
+
UHandlerOutput
|
142
|
+
>,
|
143
|
+
): DecoratedProcedure<
|
144
|
+
TContext,
|
145
|
+
TExtraContext,
|
146
|
+
TInputSchema,
|
147
|
+
TOutputSchema,
|
148
|
+
UHandlerOutput
|
149
|
+
> {
|
150
|
+
return decorateProcedure({
|
151
|
+
zz$p: {
|
152
|
+
middlewares: this.zz$pb.middlewares,
|
153
|
+
contract: this.zz$pb.contract,
|
154
|
+
handler,
|
155
|
+
},
|
156
|
+
})
|
157
|
+
}
|
158
|
+
}
|
@@ -0,0 +1,210 @@
|
|
1
|
+
import { z } from 'zod'
|
2
|
+
import { os, createProcedureCaller } from '.'
|
3
|
+
|
4
|
+
describe('createProcedureCaller', () => {
|
5
|
+
let internal = false
|
6
|
+
let path = ['ping']
|
7
|
+
let context = { auth: true }
|
8
|
+
|
9
|
+
const osw = os.context<{ auth?: boolean }>()
|
10
|
+
const procedure = osw
|
11
|
+
.input(z.object({ value: z.string().transform((v) => Number(v)) }))
|
12
|
+
.output(z.object({ value: z.number().transform((v) => v.toString()) }))
|
13
|
+
.handler((input, context, meta) => {
|
14
|
+
expect(context).toEqual(context)
|
15
|
+
expect(meta.internal).toBe(internal)
|
16
|
+
expect(meta.path).toBe(path)
|
17
|
+
|
18
|
+
return input
|
19
|
+
})
|
20
|
+
|
21
|
+
it('infer context', () => {
|
22
|
+
createProcedureCaller({
|
23
|
+
procedure,
|
24
|
+
// @ts-expect-error invalid context
|
25
|
+
context: { auth: 123 },
|
26
|
+
})
|
27
|
+
|
28
|
+
createProcedureCaller({
|
29
|
+
procedure,
|
30
|
+
context,
|
31
|
+
})
|
32
|
+
})
|
33
|
+
|
34
|
+
it('with validate', async () => {
|
35
|
+
const caller = createProcedureCaller({
|
36
|
+
procedure,
|
37
|
+
context,
|
38
|
+
internal,
|
39
|
+
path,
|
40
|
+
})
|
41
|
+
|
42
|
+
expectTypeOf(caller).toMatchTypeOf<
|
43
|
+
(input: { value: string }) => Promise<{
|
44
|
+
value: string
|
45
|
+
}>
|
46
|
+
>()
|
47
|
+
|
48
|
+
expect(await caller({ value: '123' })).toEqual({ value: '123' })
|
49
|
+
|
50
|
+
// @ts-expect-error
|
51
|
+
expect(caller({ value: {} })).rejects.toThrowError(
|
52
|
+
'Validation input failed',
|
53
|
+
)
|
54
|
+
})
|
55
|
+
|
56
|
+
it('without validate', async () => {
|
57
|
+
internal = true
|
58
|
+
path = []
|
59
|
+
context = { auth: false }
|
60
|
+
|
61
|
+
const caller = createProcedureCaller({
|
62
|
+
procedure,
|
63
|
+
context,
|
64
|
+
internal,
|
65
|
+
path,
|
66
|
+
validate: false,
|
67
|
+
})
|
68
|
+
|
69
|
+
expectTypeOf(caller).toMatchTypeOf<
|
70
|
+
(input: { value: number }) => Promise<{
|
71
|
+
value: number
|
72
|
+
}>
|
73
|
+
>()
|
74
|
+
|
75
|
+
expect(await caller({ value: 123 })).toEqual({ value: 123 })
|
76
|
+
|
77
|
+
// @ts-expect-error it's not validate so bellow still works
|
78
|
+
expect(await caller({ value: '123' })).toEqual({ value: '123' })
|
79
|
+
})
|
80
|
+
|
81
|
+
it('without validate and schema', () => {
|
82
|
+
const procedure = osw.handler(() => {
|
83
|
+
return { value: true }
|
84
|
+
})
|
85
|
+
|
86
|
+
const caller = createProcedureCaller({
|
87
|
+
procedure,
|
88
|
+
context,
|
89
|
+
internal,
|
90
|
+
validate: false,
|
91
|
+
})
|
92
|
+
|
93
|
+
expectTypeOf(caller).toMatchTypeOf<
|
94
|
+
(value: unknown) => Promise<{ value: boolean }>
|
95
|
+
>()
|
96
|
+
|
97
|
+
expect(caller({ value: 123 })).resolves.toEqual({ value: true })
|
98
|
+
})
|
99
|
+
|
100
|
+
it('middlewares', () => {
|
101
|
+
const ref = { value: 0 }
|
102
|
+
|
103
|
+
const mid1 = vi.fn(
|
104
|
+
osw.middleware((input: { id: string }, context, meta) => {
|
105
|
+
expect(input).toEqual({ id: '1' })
|
106
|
+
|
107
|
+
expect(ref.value).toBe(0)
|
108
|
+
ref.value++
|
109
|
+
|
110
|
+
meta.onSuccess(() => {
|
111
|
+
expect(ref.value).toBe(7)
|
112
|
+
ref.value++
|
113
|
+
})
|
114
|
+
|
115
|
+
meta.onFinish(() => {
|
116
|
+
expect(ref.value).toBe(8)
|
117
|
+
ref.value++
|
118
|
+
})
|
119
|
+
|
120
|
+
return {
|
121
|
+
context: {
|
122
|
+
userId: '1',
|
123
|
+
},
|
124
|
+
}
|
125
|
+
}),
|
126
|
+
)
|
127
|
+
|
128
|
+
const mid2 = vi.fn(
|
129
|
+
osw.middleware((input, context, meta) => {
|
130
|
+
expect(ref.value).toBe(1)
|
131
|
+
ref.value++
|
132
|
+
|
133
|
+
meta.onSuccess(() => {
|
134
|
+
expect(ref.value).toBe(5)
|
135
|
+
ref.value++
|
136
|
+
})
|
137
|
+
|
138
|
+
meta.onFinish(() => {
|
139
|
+
expect(ref.value).toBe(6)
|
140
|
+
ref.value++
|
141
|
+
})
|
142
|
+
}),
|
143
|
+
)
|
144
|
+
|
145
|
+
const ping = osw
|
146
|
+
.input(z.object({ id: z.string() }))
|
147
|
+
.use(mid1)
|
148
|
+
.use(mid2)
|
149
|
+
.handler((input, context, meta) => {
|
150
|
+
expect(context).toEqual({ userId: '1', auth: false })
|
151
|
+
|
152
|
+
expect(ref.value).toBe(2)
|
153
|
+
ref.value++
|
154
|
+
|
155
|
+
meta.onSuccess(() => {
|
156
|
+
expect(ref.value).toBe(3)
|
157
|
+
ref.value++
|
158
|
+
})
|
159
|
+
|
160
|
+
meta.onFinish(() => {
|
161
|
+
expect(ref.value).toBe(4)
|
162
|
+
ref.value++
|
163
|
+
})
|
164
|
+
|
165
|
+
return 'pong'
|
166
|
+
})
|
167
|
+
|
168
|
+
const caller = createProcedureCaller({
|
169
|
+
procedure: ping,
|
170
|
+
context: { auth: false },
|
171
|
+
})
|
172
|
+
|
173
|
+
expect(caller({ id: '1' })).resolves.toEqual('pong')
|
174
|
+
})
|
175
|
+
|
176
|
+
it('hooks', async () => {
|
177
|
+
const ref = { value: 0 }
|
178
|
+
|
179
|
+
const caller = createProcedureCaller({
|
180
|
+
procedure: procedure,
|
181
|
+
context: context,
|
182
|
+
internal: internal,
|
183
|
+
path: path,
|
184
|
+
hooks: (context, meta) => {
|
185
|
+
expect(context).toEqual(context)
|
186
|
+
expect(meta.internal).toBe(internal)
|
187
|
+
expect(meta.path).toBe(path)
|
188
|
+
expect(meta.procedure).toBe(procedure)
|
189
|
+
|
190
|
+
expect(ref.value).toBe(0)
|
191
|
+
ref.value++
|
192
|
+
|
193
|
+
meta.onSuccess(() => {
|
194
|
+
expect(ref.value).toBe(1)
|
195
|
+
ref.value++
|
196
|
+
})
|
197
|
+
|
198
|
+
meta.onFinish(() => {
|
199
|
+
expect(ref.value).toBe(2)
|
200
|
+
ref.value++
|
201
|
+
|
202
|
+
throw new Error('foo')
|
203
|
+
})
|
204
|
+
},
|
205
|
+
})
|
206
|
+
|
207
|
+
await expect(caller({ value: '1243' })).rejects.toThrow('foo')
|
208
|
+
expect(ref.value).toBe(3)
|
209
|
+
})
|
210
|
+
})
|