@orpc/server 0.0.0-next.b15d206 → 0.0.0-next.ef3ba82

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/dist/{chunk-TDFYNRZV.js → chunk-CVLK2PBB.js} +0 -1
  2. package/dist/fetch.js +74 -650
  3. package/dist/index.js +1 -2
  4. package/dist/src/builder.d.ts +0 -1
  5. package/dist/src/fetch/handle.d.ts +6 -0
  6. package/dist/src/fetch/handler.d.ts +2 -0
  7. package/dist/src/fetch/index.d.ts +3 -0
  8. package/dist/src/{adapters/fetch.d.ts → fetch/types.d.ts} +8 -16
  9. package/dist/src/index.d.ts +0 -1
  10. package/dist/src/middleware.d.ts +0 -1
  11. package/dist/src/procedure-builder.d.ts +0 -1
  12. package/dist/src/procedure-caller.d.ts +0 -1
  13. package/dist/src/procedure-implementer.d.ts +0 -1
  14. package/dist/src/procedure.d.ts +0 -1
  15. package/dist/src/router-builder.d.ts +0 -1
  16. package/dist/src/router-caller.d.ts +0 -1
  17. package/dist/src/router-implementer.d.ts +0 -1
  18. package/dist/src/router.d.ts +0 -1
  19. package/dist/src/types.d.ts +0 -1
  20. package/dist/src/utils.d.ts +0 -1
  21. package/package.json +14 -18
  22. package/dist/chunk-TDFYNRZV.js.map +0 -1
  23. package/dist/fetch.js.map +0 -1
  24. package/dist/index.js.map +0 -1
  25. package/dist/src/adapters/fetch.d.ts.map +0 -1
  26. package/dist/src/builder.d.ts.map +0 -1
  27. package/dist/src/index.d.ts.map +0 -1
  28. package/dist/src/middleware.d.ts.map +0 -1
  29. package/dist/src/procedure-builder.d.ts.map +0 -1
  30. package/dist/src/procedure-caller.d.ts.map +0 -1
  31. package/dist/src/procedure-implementer.d.ts.map +0 -1
  32. package/dist/src/procedure.d.ts.map +0 -1
  33. package/dist/src/router-builder.d.ts.map +0 -1
  34. package/dist/src/router-caller.d.ts.map +0 -1
  35. package/dist/src/router-implementer.d.ts.map +0 -1
  36. package/dist/src/router.d.ts.map +0 -1
  37. package/dist/src/types.d.ts.map +0 -1
  38. package/dist/src/utils.d.ts.map +0 -1
  39. package/dist/tsconfig.tsbuildinfo +0 -1
  40. package/src/adapters/fetch.test.ts +0 -629
  41. package/src/adapters/fetch.ts +0 -290
  42. package/src/builder.test.ts +0 -371
  43. package/src/builder.ts +0 -238
  44. package/src/index.ts +0 -16
  45. package/src/middleware.test.ts +0 -260
  46. package/src/middleware.ts +0 -136
  47. package/src/procedure-builder.test.ts +0 -223
  48. package/src/procedure-builder.ts +0 -158
  49. package/src/procedure-caller.test.ts +0 -171
  50. package/src/procedure-caller.ts +0 -138
  51. package/src/procedure-implementer.test.ts +0 -220
  52. package/src/procedure-implementer.ts +0 -102
  53. package/src/procedure.test.ts +0 -317
  54. package/src/procedure.ts +0 -237
  55. package/src/router-builder.test.ts +0 -106
  56. package/src/router-builder.ts +0 -122
  57. package/src/router-caller.test.ts +0 -126
  58. package/src/router-caller.ts +0 -64
  59. package/src/router-implementer.test.ts +0 -116
  60. package/src/router-implementer.ts +0 -113
  61. package/src/router.test-d.ts +0 -48
  62. package/src/router.test.ts +0 -142
  63. package/src/router.ts +0 -91
  64. package/src/types.test.ts +0 -18
  65. package/src/types.ts +0 -13
  66. package/src/utils.test.ts +0 -16
  67. 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
- }
@@ -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
- })