@orpc/client 0.0.0-next.83ec2e8 → 0.0.0-next.84e58e0

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/src/procedure.ts DELETED
@@ -1,108 +0,0 @@
1
- /// <reference lib="dom" />
2
- /// <reference lib="dom.iterable" />
3
-
4
- import type { Promisable } from '@orpc/shared'
5
- import {
6
- ORPC_HEADER,
7
- ORPC_HEADER_VALUE,
8
- type Schema,
9
- type SchemaInput,
10
- type SchemaOutput,
11
- } from '@orpc/contract'
12
- import { trim } from '@orpc/shared'
13
- import { ORPCError } from '@orpc/shared/error'
14
- import { ORPCDeserializer, ORPCSerializer } from '@orpc/transformer'
15
-
16
- export interface ProcedureClient<
17
- TInputSchema extends Schema,
18
- TOutputSchema extends Schema,
19
- TFuncOutput extends SchemaOutput<TOutputSchema>,
20
- > {
21
- (
22
- input: SchemaInput<TInputSchema>,
23
- ): Promise<SchemaOutput<TOutputSchema, TFuncOutput>>
24
- }
25
-
26
- export interface CreateProcedureClientOptions {
27
- /**
28
- * The base url of the server.
29
- */
30
- baseURL: string
31
-
32
- /**
33
- * The fetch function used to make the request.
34
- * @default global fetch
35
- */
36
- fetch?: typeof fetch
37
-
38
- /**
39
- * The headers used to make the request.
40
- * Invoked before the request is made.
41
- */
42
- headers?: (input: unknown) => Promisable<Headers | Record<string, string>>
43
-
44
- /**
45
- * The path of the procedure on server.
46
- */
47
- path: string[]
48
- }
49
-
50
- export function createProcedureClient<
51
- TInputSchema extends Schema,
52
- TOutputSchema extends Schema,
53
- TFuncOutput extends SchemaOutput<TOutputSchema>,
54
- >(
55
- options: CreateProcedureClientOptions,
56
- ): ProcedureClient<TInputSchema, TOutputSchema, TFuncOutput> {
57
- const serializer = new ORPCSerializer()
58
- const deserializer = new ORPCDeserializer()
59
-
60
- const client = async (input: unknown): Promise<unknown> => {
61
- const fetch_ = options.fetch ?? fetch
62
- const url = `${trim(options.baseURL, '/')}/${options.path.map(encodeURIComponent).join('/')}`
63
- let headers = await options.headers?.(input)
64
- headers = headers instanceof Headers ? headers : new Headers(headers)
65
-
66
- const { body, headers: headers_ } = serializer.serialize(input)
67
-
68
- for (const [key, value] of headers_.entries()) {
69
- headers.set(key, value)
70
- }
71
-
72
- headers.set(ORPC_HEADER, ORPC_HEADER_VALUE)
73
-
74
- const response = await fetch_(url, {
75
- method: 'POST',
76
- headers,
77
- body,
78
- })
79
-
80
- const json = await (async () => {
81
- try {
82
- return await deserializer.deserialize(response)
83
- }
84
- catch (e) {
85
- throw new ORPCError({
86
- code: 'INTERNAL_SERVER_ERROR',
87
- message: 'Cannot parse response.',
88
- cause: e,
89
- })
90
- }
91
- })()
92
-
93
- if (!response.ok) {
94
- throw (
95
- ORPCError.fromJSON(json)
96
- ?? new ORPCError({
97
- status: response.status,
98
- code: 'INTERNAL_SERVER_ERROR',
99
- message: 'Internal server error',
100
- })
101
- )
102
- }
103
-
104
- return json
105
- }
106
-
107
- return client as any
108
- }
@@ -1,148 +0,0 @@
1
- import { oc } from '@orpc/contract'
2
- import { os } from '@orpc/server'
3
- import { createFetchHandler } from '@orpc/server/fetch'
4
- import { z } from 'zod'
5
- import { createRouterClient } from './router'
6
-
7
- describe('createRouterClient', () => {
8
- const schema = z.object({
9
- value: z.string(),
10
- })
11
- const ping = os.input(schema).func((_, __, { path }) => path)
12
- const router = os.router({
13
- ping,
14
- nested: {
15
- unique: ping,
16
- },
17
- })
18
- const handler = createFetchHandler({
19
- router,
20
- })
21
- const orpcFetch: typeof fetch = async (...args) => {
22
- const request = new Request(...args)
23
- return await handler({
24
- prefix: '/orpc',
25
- request,
26
- context: {},
27
- })
28
- }
29
-
30
- it('types with contract router', () => {
31
- const schema = z.object({
32
- value: z.string(),
33
- })
34
-
35
- const ping = oc.input(schema)
36
- const pong = oc.output(schema)
37
- const peng = oc.route({})
38
- const router = oc.router({
39
- ping,
40
- pong,
41
- peng,
42
- nested: {
43
- unique: ping,
44
- },
45
- })
46
-
47
- const client = createRouterClient<typeof router>({} as any)
48
-
49
- expectTypeOf(client.ping).toEqualTypeOf<
50
- (input: { value: string }) => Promise<unknown>
51
- >()
52
- expectTypeOf(client.pong).toEqualTypeOf<
53
- (input: unknown) => Promise<{ value: string }>
54
- >()
55
- expectTypeOf(client.peng).toEqualTypeOf<
56
- (input: unknown) => Promise<unknown>
57
- >()
58
-
59
- expectTypeOf(client.nested.unique).toEqualTypeOf<
60
- (input: { value: string }) => Promise<unknown>
61
- >()
62
- })
63
-
64
- it('types with router', () => {
65
- const schema = z.object({
66
- value: z.string(),
67
- })
68
- const ping = os.input(schema).func(() => '')
69
- const pong = os.output(schema).func(() => ({ value: 'string' }))
70
- const peng = os.route({}).func(() => ({ age: 1244 }))
71
-
72
- const router = os.router({
73
- ping,
74
- pong,
75
- peng,
76
- nested: {
77
- unique: ping,
78
- },
79
- })
80
-
81
- const client = createRouterClient<typeof router>({} as any)
82
-
83
- expectTypeOf(client.ping).toEqualTypeOf<
84
- (input: { value: string }) => Promise<string>
85
- >()
86
- expectTypeOf(client.pong).toEqualTypeOf<
87
- (input: unknown) => Promise<{ value: string }>
88
- >()
89
- expectTypeOf(client.peng).toEqualTypeOf<
90
- (input: unknown) => Promise<{ age: number }>
91
- >()
92
- expectTypeOf(client.nested.unique).toEqualTypeOf<
93
- (input: { value: string }) => Promise<string>
94
- >()
95
- })
96
-
97
- it('simple', async () => {
98
- const client = createRouterClient<typeof router>({
99
- baseURL: 'http://localhost:3000/orpc',
100
- fetch: orpcFetch,
101
- })
102
-
103
- const result = await client.ping({ value: 'hello' })
104
- expect(result).toEqual(['ping'])
105
-
106
- const result2 = await client.nested.unique({ value: 'hello' })
107
- expect(result2).toEqual(['nested', 'unique'])
108
- })
109
-
110
- it('on error', () => {
111
- const client = createRouterClient<typeof router>({
112
- baseURL: 'http://localhost:3000/orpc',
113
- fetch: orpcFetch,
114
- })
115
-
116
- // @ts-expect-error - invalid input
117
- expect(client.ping({ value: {} })).rejects.toThrowError(
118
- 'Validation input failed',
119
- )
120
- })
121
-
122
- it('transformer', async () => {
123
- const router = os.router({
124
- ping: os
125
- .input(z.object({ value: z.date() }))
126
- .func(input => input.value),
127
- })
128
-
129
- const handler = createFetchHandler({
130
- router,
131
- })
132
-
133
- const client = createRouterClient<typeof router>({
134
- baseURL: 'http://localhost:3000/orpc',
135
- fetch: (...args) => {
136
- const request = new Request(...args)
137
- return handler({
138
- prefix: '/orpc',
139
- request,
140
- context: {},
141
- })
142
- },
143
- })
144
-
145
- const now = new Date()
146
- expect(await client.ping({ value: now })).toEqual(now)
147
- })
148
- })
package/src/router.ts DELETED
@@ -1,96 +0,0 @@
1
- /// <reference lib="dom" />
2
-
3
- import type {
4
- ContractProcedure,
5
- ContractRouter,
6
- SchemaOutput,
7
- } from '@orpc/contract'
8
- import type { Procedure, Router } from '@orpc/server'
9
- import type { Promisable } from '@orpc/shared'
10
- import { createProcedureClient, type ProcedureClient } from './procedure'
11
-
12
- export type RouterClientWithContractRouter<TRouter extends ContractRouter> = {
13
- [K in keyof TRouter]: TRouter[K] extends ContractProcedure<
14
- infer UInputSchema,
15
- infer UOutputSchema
16
- >
17
- ? ProcedureClient<UInputSchema, UOutputSchema, SchemaOutput<UOutputSchema>>
18
- : TRouter[K] extends ContractRouter
19
- ? RouterClientWithContractRouter<TRouter[K]>
20
- : never
21
- }
22
-
23
- export type RouterClientWithRouter<TRouter extends Router<any>> = {
24
- [K in keyof TRouter]: TRouter[K] extends Procedure<
25
- any,
26
- any,
27
- infer UInputSchema,
28
- infer UOutputSchema,
29
- infer UFuncOutput
30
- >
31
- ? ProcedureClient<UInputSchema, UOutputSchema, UFuncOutput>
32
- : TRouter[K] extends Router<any>
33
- ? RouterClientWithRouter<TRouter[K]>
34
- : never
35
- }
36
-
37
- export interface CreateRouterClientOptions {
38
- /**
39
- * The base url of the server.
40
- */
41
- baseURL: string
42
-
43
- /**
44
- * The fetch function used to make the request.
45
- * @default global fetch
46
- */
47
- fetch?: typeof fetch
48
-
49
- /**
50
- * The headers used to make the request.
51
- * Invoked before the request is made.
52
- */
53
- headers?: (input: unknown) => Promisable<Headers | Record<string, string>>
54
-
55
- /**
56
- * This used for internal purpose only.
57
- *
58
- * @internal
59
- */
60
- path?: string[]
61
- }
62
-
63
- export function createRouterClient<
64
- TRouter extends Router<any> | ContractRouter,
65
- >(
66
- options: CreateRouterClientOptions,
67
- ): TRouter extends Router<any>
68
- ? RouterClientWithRouter<TRouter>
69
- : TRouter extends ContractRouter
70
- ? RouterClientWithContractRouter<TRouter>
71
- : never {
72
- const path = options?.path ?? []
73
-
74
- const client = new Proxy(
75
- createProcedureClient({
76
- baseURL: options.baseURL,
77
- fetch: options.fetch,
78
- headers: options.headers,
79
- path,
80
- }),
81
- {
82
- get(target, key) {
83
- if (typeof key !== 'string') {
84
- return Reflect.get(target, key)
85
- }
86
-
87
- return createRouterClient({
88
- ...options,
89
- path: [...path, key],
90
- })
91
- },
92
- },
93
- )
94
-
95
- return client as any
96
- }