Skip to content

Commit 0240b0d

Browse files
authored
feat(colada): partial input key support (#514)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added a warning to the Pinia Colada integration guide, notifying users about its unstable status and potential for breaking changes. - **New Features** - Enhanced key generation to include a type property, distinguishing between 'query' and 'mutation' operations. - **Bug Fixes** - Improved handling and serialization of input data for key generation, ensuring more consistent and structured output. - **Chores** - Updated `@pinia/colada` dependency versions to `^0.16.0` across relevant packages. - Adjusted type assertions and test expectations to align with updated key structure and input handling. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent a689803 commit 0240b0d

10 files changed

Lines changed: 57 additions & 52 deletions

File tree

apps/content/docs/pinia-colada.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ description: Seamlessly integrate oRPC with Pinia Colada
1111
This documentation assumes you are already familiar with [Pinia Colada](https://pinia-colada.esm.dev/). If you need a refresher, please review the official Pinia Colada documentation before proceeding.
1212
:::
1313

14+
::: warning
15+
[Pinia Colada](https://pinia-colada.esm.dev/) is still in an unstable stage. As a result, oRPC's integration with Pinia Colada may introduce breaking changes in the future to keep up with its ongoing development.
16+
:::
17+
1418
## Installation
1519

1620
::: code-group

apps/content/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"@orpc/vue-colada": "workspace:*",
2222
"@orpc/vue-query": "workspace:*",
2323
"@orpc/zod": "workspace:*",
24-
"@pinia/colada": "^0.15.3",
24+
"@pinia/colada": "^0.16.0",
2525
"@shikijs/vitepress-twoslash": "^3.0.0",
2626
"@tanstack/react-query": "^5.75.7",
2727
"@tanstack/solid-query": "^5.72.3",

packages/vue-colada/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@
3838
"type:check": "tsc -b"
3939
},
4040
"peerDependencies": {
41-
"@pinia/colada": ">=0.13.5",
41+
"@pinia/colada": ">=0.16.0",
4242
"vue": ">=3.3.0"
4343
},
4444
"dependencies": {
4545
"@orpc/client": "workspace:*",
4646
"@orpc/shared": "workspace:*"
4747
},
4848
"devDependencies": {
49-
"@pinia/colada": "^0.15.3",
49+
"@pinia/colada": "^0.16.0",
5050
"pinia": "^3.0.2",
5151
"vue": "^3.5.14"
5252
}

packages/vue-colada/src/key.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { buildKey } from './key'
22

33
describe('buildKey', () => {
44
it('works', () => {
5-
expect(buildKey(['path'])).toEqual(['path'])
6-
expect(buildKey(['path', 'path2'], { input: { a: 1 } }))
7-
.toEqual(['path', 'path2', { input: '{"json":{"a":1},"meta":[]}' }])
8-
expect(buildKey(['path'], { input: undefined }))
9-
.toEqual(['path'])
5+
expect(buildKey(['path'])).toEqual([['path'], {}])
6+
expect(buildKey(['path', 'path2'], { input: { a: 1 } })).toEqual([['path', 'path2'], { input: { a: 1 } }])
7+
expect(buildKey(['path'], { input: undefined })).toEqual([['path'], {}])
8+
expect(buildKey(['path', 'path2'], { type: 'query' })).toEqual([['path', 'path2'], { type: 'query' }])
9+
expect(buildKey(['path'], { type: undefined })).toEqual([['path'], {}])
10+
expect(buildKey(['path', 'path2'], { type: 'query', input: { a: 1 } })).toEqual([['path', 'path2'], { type: 'query', input: { a: 1 } }])
1011

1112
const date = new Date()
12-
expect(buildKey(['path', 'path2'], { input: { a: date } }))
13-
.toEqual(['path', 'path2', { input: `{"json":{"a":"${date.toISOString()}"},"meta":[[1,"a"]]}` }])
13+
expect(buildKey(['path', 'path2'], { input: { a: date } })).toEqual([['path', 'path2'], { input: { a: date.toISOString() } }])
1414
})
1515
})

packages/vue-colada/src/key.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1+
import type { PartialDeep } from '@orpc/shared'
12
import type { EntryKey } from '@pinia/colada'
23
import { StandardRPCJsonSerializer } from '@orpc/client/standard'
3-
import { stringifyJSON } from '@orpc/shared'
44

55
export interface BuildKeyOptions<TInput> {
6-
input?: TInput
6+
type?: 'query' | 'mutation'
7+
input?: PartialDeep<TInput>
78
}
89

910
export function buildKey<TInput>(
1011
path: string[],
11-
options?: BuildKeyOptions<TInput>,
12+
options: BuildKeyOptions<TInput> = {},
1213
): EntryKey {
13-
if (options?.input === undefined) {
14-
return path
15-
}
14+
const [json] = new StandardRPCJsonSerializer().serialize(options.input)
1615

17-
const [json, meta] = new StandardRPCJsonSerializer().serialize(options.input)
16+
const withInput = json !== undefined ? { input: json } : {}
17+
const withType = options.type !== undefined ? { type: options.type } : {}
1818

1919
return [
20-
...path,
21-
{ input: stringifyJSON({ json, meta }) },
20+
path,
21+
{
22+
...withInput,
23+
...withType as any,
24+
},
2225
]
2326
}

packages/vue-colada/src/procedure-utils.test.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ const controller = new AbortController()
88
const signal = controller.signal
99

1010
beforeEach(() => {
11-
buildKeySpy.mockClear()
12-
13-
buildKeySpy.mockReturnValue(['__mocked__'])
11+
vi.clearAllMocks()
1412
})
1513

1614
it('.call', () => {
@@ -35,9 +33,9 @@ describe('queryOptions', () => {
3533
it('works', async () => {
3634
const options = utils.queryOptions({ input: 1 }) as any
3735

38-
expect(options.key.value).toEqual(['__mocked__'])
36+
expect(options.key.value).toBe(buildKeySpy.mock.results[0]!.value)
3937
expect(buildKeySpy).toHaveBeenCalledTimes(1)
40-
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: 1 })
38+
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: 1, type: 'query' })
4139

4240
client.mockResolvedValueOnce('__mocked__')
4341
await expect((options as any).query({ signal })).resolves.toEqual('__mocked__')
@@ -49,9 +47,9 @@ describe('queryOptions', () => {
4947
const input = ref(1)
5048
const options = utils.queryOptions({ input }) as any
5149

52-
expect(options.key.value).toEqual(['__mocked__'])
50+
expect(options.key.value).toBe(buildKeySpy.mock.results[0]!.value)
5351
expect(buildKeySpy).toHaveBeenCalledTimes(1)
54-
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: 1 })
52+
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: 1, type: 'query' })
5553

5654
client.mockResolvedValueOnce('__mocked__')
5755
await expect((options as any).query({ signal })).resolves.toEqual('__mocked__')
@@ -65,9 +63,9 @@ describe('queryOptions', () => {
6563

6664
const options = utils.queryOptions({ context: ref({ batch: true }) }) as any
6765

68-
expect(options.key.value).toEqual(['__mocked__'])
66+
expect(options.key.value).toBe(buildKeySpy.mock.results[0]!.value)
6967
expect(buildKeySpy).toHaveBeenCalledTimes(1)
70-
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { })
68+
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { type: 'query' })
7169

7270
client.mockResolvedValueOnce('__mocked__')
7371
await expect((options as any).query({ signal })).resolves.toEqual('__mocked__')
@@ -89,9 +87,9 @@ describe('mutationOptions', () => {
8987
it('works', async () => {
9088
const options = utils.mutationOptions() as any
9189

92-
expect(options.key('__input__')).toEqual(['__mocked__'])
90+
expect(options.key('__input__')).toBe(buildKeySpy.mock.results[0]!.value)
9391
expect(buildKeySpy).toHaveBeenCalledTimes(1)
94-
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: '__input__' })
92+
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: '__input__', type: 'mutation' })
9593

9694
client.mockResolvedValueOnce('__mocked__')
9795
await expect(options.mutation(1)).resolves.toEqual('__mocked__')
@@ -107,9 +105,9 @@ describe('mutationOptions', () => {
107105

108106
const options = utils.mutationOptions({ context: ref({ batch: true }) }) as any
109107

110-
expect(options.key('__input__')).toEqual(['__mocked__'])
108+
expect(options.key('__input__')).toBe(buildKeySpy.mock.results[0]!.value)
111109
expect(buildKeySpy).toHaveBeenCalledTimes(1)
112-
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: '__input__' })
110+
expect(buildKeySpy).toHaveBeenCalledWith(['ping'], { input: '__input__', type: 'mutation' })
113111

114112
client.mockResolvedValueOnce('__mocked__')
115113
await expect(options.mutation(1)).resolves.toEqual('__mocked__')

packages/vue-colada/src/procedure-utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface ProcedureUtils<TClientContext extends ClientContext, TInput, TO
2222
...rest: MaybeOptionalOptions<
2323
QueryOptionsIn<TClientContext, TInput, TOutput, TError, UInitialData>
2424
>
25-
): QueryOptions<TOutput, TError, UInitialData>
25+
): NoInfer<QueryOptions<TOutput, TError, UInitialData>>
2626

2727
/**
2828
* Generate options used for useMutation/...
@@ -33,7 +33,7 @@ export interface ProcedureUtils<TClientContext extends ClientContext, TInput, TO
3333
...rest: MaybeOptionalOptions<
3434
MutationOptionsIn<TClientContext, TInput, TOutput, TError, UMutationContext>
3535
>
36-
): MutationOptions<TInput, TOutput, TError, UMutationContext>
36+
): NoInfer<MutationOptions<TInput, TOutput, TError, UMutationContext>>
3737
}
3838

3939
export interface CreateProcedureUtilsOptions {
@@ -49,15 +49,15 @@ export function createProcedureUtils<TClientContext extends ClientContext, TInpu
4949

5050
queryOptions(...[{ input, context, ...rest } = {}]) {
5151
return {
52-
key: computed(() => buildKey(options.path, { input: toValue(input) })),
52+
key: computed(() => buildKey(options.path, { type: 'query', input: toValue(input) as any })),
5353
query: ({ signal }) => client(toValue(input) as any, { signal, context: toValue(context) as any }),
5454
...(rest as any),
5555
}
5656
},
5757

5858
mutationOptions(...[{ context, ...rest } = {}]) {
5959
return {
60-
key: input => buildKey(options.path, { input }),
60+
key: input => buildKey(options.path, { type: 'mutation', input: input as any }),
6161
mutation: input => client(input, { context: toValue(context) as any }),
6262
...(rest as any),
6363
}

packages/vue-colada/src/router-utils.test-d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ import type { RouterUtils } from './router-utils'
99
it('RouterUtils', () => {
1010
const utils = {} as RouterUtils<RouterClient<typeof router, { batch?: boolean }>>
1111

12-
expectTypeOf(utils).toMatchTypeOf<GeneralUtils<unknown>>()
13-
expectTypeOf(utils.nested).toMatchTypeOf<GeneralUtils<unknown>>()
12+
expectTypeOf(utils).toExtend<GeneralUtils<unknown>>()
13+
expectTypeOf(utils.nested).toExtend<GeneralUtils<unknown>>()
1414

15-
expectTypeOf(utils.ping).toMatchTypeOf<GeneralUtils<{ input: number }>>()
16-
expectTypeOf(utils.nested.ping).toMatchTypeOf<GeneralUtils<{ input: number }>>()
15+
expectTypeOf(utils.ping).toExtend<GeneralUtils<{ input: number }>>()
16+
expectTypeOf(utils.nested.ping).toExtend<GeneralUtils<{ input: number }>>()
1717

18-
expectTypeOf(utils.ping).toMatchTypeOf<
18+
expectTypeOf(utils.ping).toExtend<
1919
ProcedureUtils<{ batch?: boolean }, { input: number }, { output: string }, ErrorFromErrorMap<typeof baseErrorMap>>
2020
>()
21-
expectTypeOf(utils.nested.ping).toMatchTypeOf<
21+
expectTypeOf(utils.nested.ping).toExtend<
2222
ProcedureUtils<{ batch?: boolean }, { input: number }, { output: string }, ErrorFromErrorMap<typeof baseErrorMap>>
2323
>()
2424

25-
expectTypeOf(utils.pong).toMatchTypeOf<
25+
expectTypeOf(utils.pong).toExtend<
2626
ProcedureUtils<{ batch?: boolean }, unknown, unknown, Error>
2727
>()
28-
expectTypeOf(utils.nested.pong).toMatchTypeOf<
28+
expectTypeOf(utils.nested.pong).toExtend<
2929
ProcedureUtils<{ batch?: boolean }, unknown, unknown, Error>
3030
>()
3131
})

packages/vue-colada/tests/e2e.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ it('case: with useQuery', async () => {
4949
await vi.waitFor(() => expect(mounted.vm.query.data.value).toEqual({ output: '123' }))
5050

5151
expect(
52-
mounted.vm.queryCache.getQueryData(orpc.nested.ping.key({ input: { input: 123 } })),
52+
mounted.vm.queryCache.getQueryData(orpc.nested.ping.key({ type: 'query', input: { input: 123 } })),
5353
).toEqual({ output: '123' })
5454

5555
mounted.vm.setId(456)

pnpm-lock.yaml

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)