Skip to content

Commit c0088c7

Browse files
authored
feat(query, vue-colada)!: update utils options (#209)
* strategy options * router query utils options * sync tests * procedure utils options
1 parent 56cbd20 commit c0088c7

23 files changed

Lines changed: 218 additions & 174 deletions

apps/content/docs/pinia-colada.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ orpc.planet.find.queryOptions({ input: { id: 123 } })
6161
Prevent key conflicts by passing a unique base key when creating your utils:
6262

6363
```ts
64-
const userORPC = createORPCVueColadaUtils(userClient, ['user'])
65-
const postORPC = createORPCVueColadaUtils(postClient, ['post'])
64+
const userORPC = createORPCVueColadaUtils(userClient, {
65+
path: ['user']
66+
})
67+
const postORPC = createORPCVueColadaUtils(postClient, {
68+
path: ['post']
69+
})
6670
```
6771

6872
## Query Options Utility

apps/content/docs/tanstack-query/react.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ orpc.planet.find.queryOptions({ input: { id: 123 } })
5757
Prevent key conflicts by passing a unique base key when creating your utils:
5858

5959
```ts
60-
const userORPC = createORPCReactQueryUtils(userClient, ['user'])
61-
const postORPC = createORPCReactQueryUtils(postClient, ['post'])
60+
const userORPC = createORPCReactQueryUtils(userClient, {
61+
path: ['user']
62+
})
63+
const postORPC = createORPCReactQueryUtils(postClient, {
64+
path: ['post']
65+
})
6266
```
6367

6468
## Using React Context

apps/content/docs/tanstack-query/vue.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ orpc.planet.find.queryOptions({ input: { id: 123 } })
5757
Prevent key conflicts by passing a unique base key when creating your utils:
5858

5959
```ts
60-
const userORPC = createORPCVueQueryUtils(userClient, ['user'])
61-
const postORPC = createORPCVueQueryUtils(postClient, ['post'])
60+
const userORPC = createORPCVueQueryUtils(userClient, {
61+
path: ['user']
62+
})
63+
const postORPC = createORPCVueQueryUtils(postClient, {
64+
path: ['post']
65+
})
6266
```

packages/openapi/src/openapi-generator.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ export class OpenAPIGenerator {
8585
ref.requestBody = {
8686
required: true,
8787
content: toOpenAPIEventIteratorContent(
88-
this.converter.convert(details.yields, 'input'),
89-
this.converter.convert(details.returns, 'input'),
88+
this.converter.convert(details.yields, { strategy: 'input' }),
89+
this.converter.convert(details.returns, { strategy: 'input' }),
9090
),
9191
}
9292

@@ -95,7 +95,7 @@ export class OpenAPIGenerator {
9595

9696
const dynamicParams = getDynamicParams(def.route.path)
9797
const inputStructure = fallbackContractConfig('defaultInputStructure', def.route.inputStructure)
98-
let [required, schema] = this.converter.convert(def.inputSchema, 'input')
98+
let [required, schema] = this.converter.convert(def.inputSchema, { strategy: 'input' })
9999

100100
if (isAnySchema(schema) && !dynamicParams?.length) {
101101
return
@@ -203,15 +203,15 @@ export class OpenAPIGenerator {
203203
ref.responses[status] = {
204204
description,
205205
content: toOpenAPIEventIteratorContent(
206-
this.converter.convert(eventIteratorSchemaDetails.yields, 'output'),
207-
this.converter.convert(eventIteratorSchemaDetails.returns, 'output'),
206+
this.converter.convert(eventIteratorSchemaDetails.yields, { strategy: 'output' }),
207+
this.converter.convert(eventIteratorSchemaDetails.returns, { strategy: 'output' }),
208208
),
209209
}
210210

211211
return
212212
}
213213

214-
const [_, json] = this.converter.convert(outputSchema, 'output')
214+
const [_, json] = this.converter.convert(outputSchema, { strategy: 'output' })
215215

216216
ref.responses ??= {}
217217
ref.responses[status] = {
@@ -267,7 +267,7 @@ export class OpenAPIGenerator {
267267
const status = fallbackORPCErrorStatus(code, config.status)
268268
const message = fallbackORPCErrorMessage(code, config.message)
269269

270-
const [dataRequired, dataSchema] = this.converter.convert(config.data, 'output')
270+
const [dataRequired, dataSchema] = this.converter.convert(config.data, { strategy: 'output' })
271271

272272
errors[status] ??= []
273273
errors[status].push({

packages/openapi/src/schema-converter.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,25 @@ describe('compositeSchemaConverter', () => {
2424
const schema = z.object({})
2525

2626
it('fallback to any if no condition is matched', () => {
27-
expect(converter.convert(schema, 'input')).toEqual([false, {}])
27+
expect(converter.convert(schema, { strategy: 'input' })).toEqual([false, {}])
2828

2929
expect(converter1.condition).toBeCalledTimes(1)
30-
expect(converter1.condition).toBeCalledWith(schema, 'input')
30+
expect(converter1.condition).toBeCalledWith(schema, { strategy: 'input' })
3131
expect(converter1.convert).not.toHaveBeenCalled()
3232
expect(converter2.condition).toBeCalledTimes(1)
33-
expect(converter2.condition).toBeCalledWith(schema, 'input')
33+
expect(converter2.condition).toBeCalledWith(schema, { strategy: 'input' })
3434
expect(converter2.convert).not.toHaveBeenCalled()
3535
})
3636

3737
it('return result of first converter if condition is matched', () => {
3838
converter1.condition.mockReturnValue(true)
3939
converter1.convert.mockReturnValue('__MATCHED__')
4040

41-
expect(converter.convert(schema, 'input')).toEqual('__MATCHED__')
41+
expect(converter.convert(schema, { strategy: 'input' })).toEqual('__MATCHED__')
4242

4343
expect(converter1.condition).toBeCalledTimes(1)
4444
expect(converter1.convert).toHaveBeenCalled()
45-
expect(converter1.convert).toBeCalledWith(schema, 'input')
45+
expect(converter1.convert).toBeCalledWith(schema, { strategy: 'input' })
4646

4747
expect(converter2.condition).not.toHaveBeenCalled()
4848
expect(converter2.convert).not.toHaveBeenCalled()

packages/openapi/src/schema-converter.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import type { Schema } from '@orpc/contract'
22
import type { JSONSchema } from './schema'
33

4-
export type SchemaConvertStrategy = 'input' | 'output'
4+
export interface SchemaConvertOptions {
5+
strategy: 'input' | 'output'
6+
}
57

68
export interface SchemaConverter {
7-
convert(schema: Schema, strategy: SchemaConvertStrategy): [required: boolean, jsonSchema: JSONSchema]
9+
convert(schema: Schema, options: SchemaConvertOptions): [required: boolean, jsonSchema: JSONSchema]
810
}
911

1012
export interface ConditionalSchemaConverter extends SchemaConverter {
11-
condition(schema: Schema, strategy: SchemaConvertStrategy): boolean
13+
condition(schema: Schema, options: SchemaConvertOptions): boolean
1214
}
1315

1416
export class CompositeSchemaConverter implements SchemaConverter {
@@ -18,10 +20,10 @@ export class CompositeSchemaConverter implements SchemaConverter {
1820
this.converters = converters
1921
}
2022

21-
convert(schema: Schema, strategy: SchemaConvertStrategy): [required: boolean, jsonSchema: JSONSchema] {
23+
convert(schema: Schema, options: SchemaConvertOptions): [required: boolean, jsonSchema: JSONSchema] {
2224
for (const converter of this.converters) {
23-
if (converter.condition(schema, strategy)) {
24-
return converter.convert(schema, strategy)
25+
if (converter.condition(schema, options)) {
26+
return converter.convert(schema, options)
2527
}
2628
}
2729

packages/react-query/src/procedure-utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('createProcedureUtils', () => {
1111
const controller = new AbortController()
1212
const signal = controller.signal
1313
const client = vi.fn().mockResolvedValue('__output__')
14-
const utils = createProcedureUtils(client, ['ping'])
14+
const utils = createProcedureUtils(client, { path: ['ping'] })
1515

1616
it('.call', () => {
1717
expect(utils.call).toBe(client)

packages/react-query/src/procedure-utils.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,40 @@ export interface ProcedureUtils<TClientContext extends ClientContext, TInput, TO
2222
): MutationOptions<TInput, TOutput, TError, UMutationContext>
2323
}
2424

25+
export interface CreateProcedureUtilsOptions {
26+
path: string[]
27+
}
28+
2529
export function createProcedureUtils<TClientContext extends ClientContext, TInput, TOutput, TError extends Error>(
2630
client: Client<TClientContext, TInput, TOutput, TError>,
27-
path: string[],
31+
options: CreateProcedureUtilsOptions,
2832
): ProcedureUtils<TClientContext, TInput, TOutput, TError> {
2933
return {
3034
call: client,
3135

32-
queryOptions(...[options = {} as any]) {
36+
queryOptions(...[optionsIn = {} as any]) {
3337
return {
34-
queryKey: buildKey(path, { type: 'query', input: options.input }),
35-
queryFn: ({ signal }) => client(options.input, { signal, context: options.context }),
36-
...options,
38+
queryKey: buildKey(options.path, { type: 'query', input: optionsIn.input }),
39+
queryFn: ({ signal }) => client(optionsIn.input, { signal, context: optionsIn.context }),
40+
...optionsIn,
3741
}
3842
},
3943

40-
infiniteOptions(options) {
44+
infiniteOptions(optionsIn) {
4145
return {
42-
queryKey: buildKey(path, { type: 'infinite', input: options.input(options.initialPageParam) as any }),
46+
queryKey: buildKey(options.path, { type: 'infinite', input: optionsIn.input(optionsIn.initialPageParam) as any }),
4347
queryFn: ({ pageParam, signal }) => {
44-
return client(options.input(pageParam as any), { signal, context: options.context as any })
48+
return client(optionsIn.input(pageParam as any), { signal, context: optionsIn.context as any })
4549
},
46-
...(options as any),
50+
...(optionsIn as any),
4751
}
4852
},
4953

50-
mutationOptions(...[options = {} as any]) {
54+
mutationOptions(...[optionsIn = {} as any]) {
5155
return {
52-
mutationKey: buildKey(path, { type: 'mutation' }),
53-
mutationFn: input => client(input, { context: options.context }),
54-
...(options as any),
56+
mutationKey: buildKey(options.path, { type: 'mutation' }),
57+
mutationFn: input => client(input, { context: optionsIn.context }),
58+
...(optionsIn as any),
5559
}
5660
},
5761
}

packages/react-query/src/router-utils.test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ describe('createRouterUtils', () => {
1515
client.key.pong = vi.fn()
1616

1717
it('works', () => {
18-
const utils = createRouterUtils(client, ['__base__']) as any
18+
const utils = createRouterUtils(client, {
19+
path: ['__base__'],
20+
}) as any
1921

2022
expect(generalUtilsSpy).toHaveBeenCalledTimes(1)
2123
expect(generalUtilsSpy).toHaveBeenCalledWith(['__base__'])
2224
expect(procedureUtilsSpy).toHaveBeenCalledTimes(1)
23-
expect(procedureUtilsSpy).toHaveBeenCalledWith(client, ['__base__'])
25+
expect(procedureUtilsSpy).toHaveBeenCalledWith(client, { path: ['__base__'] })
2426

2527
expect(utils.key()).toEqual(generalUtilsSpy.mock.results[0]!.value.key())
2628
expect(utils.queryOptions().queryKey).toEqual(procedureUtilsSpy.mock.results[0]!.value.queryOptions().queryKey)
@@ -31,7 +33,7 @@ describe('createRouterUtils', () => {
3133
expect(generalUtilsSpy).toHaveBeenCalledTimes(1)
3234
expect(generalUtilsSpy).toHaveBeenCalledWith(['__base__', 'key'])
3335
expect(procedureUtilsSpy).toHaveBeenCalledTimes(1)
34-
expect(procedureUtilsSpy).toHaveBeenCalledWith(client.key, ['__base__', 'key'])
36+
expect(procedureUtilsSpy).toHaveBeenCalledWith(client.key, { path: ['__base__', 'key'] })
3537

3638
expect(keyUtils.key()).toEqual(generalUtilsSpy.mock.results[0]!.value.key())
3739
expect(keyUtils.queryOptions().queryKey).toEqual(procedureUtilsSpy.mock.results[0]!.value.queryOptions().queryKey)
@@ -44,15 +46,17 @@ describe('createRouterUtils', () => {
4446
expect(generalUtilsSpy).toHaveBeenNthCalledWith(2, ['__base__', 'key', 'pong'])
4547

4648
expect(procedureUtilsSpy).toHaveBeenCalledTimes(2)
47-
expect(procedureUtilsSpy).toHaveBeenNthCalledWith(1, client.key, ['__base__', 'key'])
48-
expect(procedureUtilsSpy).toHaveBeenNthCalledWith(2, client.key.pong, ['__base__', 'key', 'pong'])
49+
expect(procedureUtilsSpy).toHaveBeenNthCalledWith(1, client.key, { path: ['__base__', 'key'] })
50+
expect(procedureUtilsSpy).toHaveBeenNthCalledWith(2, client.key.pong, { path: ['__base__', 'key', 'pong'] })
4951

5052
expect(pongUtils.key()).toEqual(generalUtilsSpy.mock.results[1]!.value.key())
5153
expect(pongUtils.queryOptions().queryKey).toEqual(procedureUtilsSpy.mock.results[1]!.value.queryOptions().queryKey)
5254
})
5355

5456
it('not recursive on symbol', async () => {
55-
const utils = createRouterUtils(client, ['__base__']) as any
57+
const utils = createRouterUtils(client, {
58+
path: ['__base__'],
59+
}) as any
5660

5761
expect(utils[Symbol.for('a')]).toBe(undefined)
5862
})

packages/react-query/src/router-utils.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@ export type RouterUtils<T extends NestedClient<any>> =
99
[K in keyof T]: T[K] extends NestedClient<any> ? RouterUtils<T[K]> : never
1010
} & GeneralUtils<unknown>
1111

12-
/**
13-
* @param client - Any kind of oRPC clients: `createRouterClient`, `createORPCClient`, ...
14-
* @param path - The base path for query key, when it it will be prefix to all keys
15-
*/
12+
export interface CreateRouterUtilsOptions {
13+
path?: string[]
14+
}
15+
1616
export function createRouterUtils<T extends NestedClient<any>>(
1717
client: T,
18-
path: string[] = [],
18+
options: CreateRouterUtilsOptions = {},
1919
): RouterUtils<T> {
20+
const path = options.path ?? []
21+
2022
const generalUtils = createGeneralUtils(path)
21-
const procedureUtils = createProcedureUtils(client as any, path)
23+
const procedureUtils = createProcedureUtils(client as any, { path })
2224

2325
const recursive = new Proxy({
2426
...generalUtils,
@@ -31,7 +33,7 @@ export function createRouterUtils<T extends NestedClient<any>>(
3133
return value
3234
}
3335

34-
const nextUtils = createRouterUtils((client as any)[prop], [...path, prop])
36+
const nextUtils = createRouterUtils((client as any)[prop], { ...options, path: [...path, prop] })
3537

3638
if (typeof value !== 'function') {
3739
return nextUtils

0 commit comments

Comments
 (0)