Skip to content

feat(pinia-colada): Pinia Colada integration#1686

Merged
dinwwwh merged 15 commits into
middleapi:mainfrom
dinwwwh:claude/vue-colada-orpc-v2-582745
Jul 20, 2026
Merged

feat(pinia-colada): Pinia Colada integration#1686
dinwwwh merged 15 commits into
middleapi:mainfrom
dinwwwh:claude/vue-colada-orpc-v2-582745

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Jul 18, 2026

Copy link
Copy Markdown
Member

Summary

Adds @orpc/pinia-colada, the Pinia Colada integration for oRPC v2 (successor of v1's @orpc/vue-colada), plus a documentation page.

import { createPiniaColadaUtils } from '@orpc/pinia-colada'

const orpc = createPiniaColadaUtils(client)

// reactive inputs via the useQuery callback form, like defineQueryOptions
const query = useQuery(() => orpc.planet.find.queryOptions({ input: { id: id.value } }))

const pages = useInfiniteQuery(() => orpc.planet.list.infiniteOptions({
  input: (offset: number) => ({ limit: 10, offset }),
  initialPageParam: 0,
  getNextPageParam: lastPage => lastPage.nextOffset,
}))

const mutation = useMutation(orpc.planet.create.mutationOptions())

queryCache.invalidateQueries({ key: orpc.planet.key() })

What you get

  • .queryOptions, .streamedOptions, .liveOptions, .infiniteOptions, and .mutationOptions for useQuery, useInfiniteQuery, and useMutation, working with both the direct and callback (() => options) forms and composing with defineQueryOptions / defineInfiniteQueryOptions
  • Options take plain values only, following Pinia Colada's defineQueryOptions pattern — reactivity happens at the useQuery call site
  • Streamed and live queries for AsyncIteratorObject procedures: streamed queries accumulate chunks as they arrive (with refetchMode and maxChunks), live queries always show the latest chunk
  • .key for partial matching (invalidation), plus .queryKey / .streamedKey / .liveKey / .infiniteKey / .mutationKey returning tagged keys so cache reads like queryCache.getQueryData infer data types
  • Inputs are serialized into entry keys, so native types (Date, URL, BigInt, ...) work in keys out of the box
  • prefix option to mount multiple utils over the same client without key collisions
  • Feature parity with @orpc/tanstack-query: interceptors, per-procedure scoped defaults, plugins, and an operation context for configuring links per operation type
  • Targets @pinia/colada >= 1.0

Tests

Unit, type, and e2e tests (real Vue components against an RPCHandler-backed client) with 100% coverage on all source files.

…gins

Port the Pinia Colada integration from the 1.x branch onto v2 client APIs,
targeting @pinia/colada >= 1.0:

- Keep the v1 public surface: buildKey, .key(), .call, .queryOptions(),
  .mutationOptions(), createORPCVueColadaUtils
- Adopt v2 conventions from @orpc/tanstack-query: class-based ProcedureUtils /
  SharedRouterUtils and RECURSIVE_CLIENT_UNWRAP_KEYS guards in the router proxy
- Use RPCJsonSerializer for entry keys, skipping serialization for undefined
  input (the v2 serializer maps undefined to null, which would break Pinia
  Colada partial key matching)
- Port the tanstack-query interceptor & plugin system: query/mutation
  interceptors with operation context (VUE_COLADA_OPERATION_CONTEXT_SYMBOL),
  option modifiers, scoped per-procedure options, and orderable
  RouterUtilsPlugin composed via CompositeRouterUtilsPlugin

Includes unit, type, and e2e tests with 100% coverage on all source files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
orpc Ready Ready Preview, Comment Jul 19, 2026 1:06pm

@pkg-pr-new

pkg-pr-new Bot commented Jul 18, 2026

Copy link
Copy Markdown
More templates

@orpc/arktype

npm i https://pkg.pr.new/middleapi/orpc/@orpc/arktype@1686

@orpc/bun

npm i https://pkg.pr.new/middleapi/orpc/@orpc/bun@1686

@orpc/client

npm i https://pkg.pr.new/middleapi/orpc/@orpc/client@1686

@orpc/cloudflare

npm i https://pkg.pr.new/middleapi/orpc/@orpc/cloudflare@1686

@orpc/contract

npm i https://pkg.pr.new/middleapi/orpc/@orpc/contract@1686

@orpc/experimental-effect

npm i https://pkg.pr.new/middleapi/orpc/@orpc/experimental-effect@1686

@orpc/evlog

npm i https://pkg.pr.new/middleapi/orpc/@orpc/evlog@1686

@orpc/json-schema

npm i https://pkg.pr.new/middleapi/orpc/@orpc/json-schema@1686

@orpc/nest

npm i https://pkg.pr.new/middleapi/orpc/@orpc/nest@1686

@orpc/next

npm i https://pkg.pr.new/middleapi/orpc/@orpc/next@1686

@orpc/openapi

npm i https://pkg.pr.new/middleapi/orpc/@orpc/openapi@1686

@orpc/opentelemetry

npm i https://pkg.pr.new/middleapi/orpc/@orpc/opentelemetry@1686

@orpc/pinia-colada

npm i https://pkg.pr.new/middleapi/orpc/@orpc/pinia-colada@1686

@orpc/pino

npm i https://pkg.pr.new/middleapi/orpc/@orpc/pino@1686

@orpc/publisher

npm i https://pkg.pr.new/middleapi/orpc/@orpc/publisher@1686

@orpc/ratelimit

npm i https://pkg.pr.new/middleapi/orpc/@orpc/ratelimit@1686

@orpc/server

npm i https://pkg.pr.new/middleapi/orpc/@orpc/server@1686

@orpc/shared

npm i https://pkg.pr.new/middleapi/orpc/@orpc/shared@1686

@orpc/tanstack-query

npm i https://pkg.pr.new/middleapi/orpc/@orpc/tanstack-query@1686

@orpc/trpc

npm i https://pkg.pr.new/middleapi/orpc/@orpc/trpc@1686

@orpc/valibot

npm i https://pkg.pr.new/middleapi/orpc/@orpc/valibot@1686

@orpc/zod

npm i https://pkg.pr.new/middleapi/orpc/@orpc/zod@1686

commit: 6c39ab7

@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing dinwwwh:claude/vue-colada-orpc-v2-582745 (6c39ab7) with main (62a40c4)

Open in CodSpeed

@pullfrog

pullfrog Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes — added the new @orpc/vue-colada package, mirroring @orpc/tanstack-query v2 architecture while adapting key serialization and option types for Pinia Colada.

  • Add packages/vue-colada with build config, types, and README.
  • Implement buildKey/ProcedureUtils/RouterUtils/plugin system supporting MaybeRefOrGetter inputs/contexts, interceptors, scoped options, and query/mutation option modifiers.
  • Add unit, type, and e2e tests against real Pinia Colada + Vue components.
  • Register *.test.tsx under the root jsdom vitest project.

ℹ️ @orpc/vue-colada missing from root devDependencies

Every other non-runtime-excluded workspace package is listed in package.json#devDependencies. Adding @orpc/vue-colada there keeps the root manifest consistent with the monorepo convention, even though the workspace already resolves it.

ℹ️ Nitpicks

  • packages/vue-colada/tests/e2e.test.tsx:32 — comment typo: "whe should" → "we should".

Pullfrog  | View workflow run | via Pullfrog | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@pullfrog

pullfrog Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes — added the new @orpc/vue-colada package, mirroring @orpc/tanstack-query v2 architecture while adapting key serialization and option types for Pinia Colada.

  • Add packages/vue-colada with build config, types, and README.
  • Implement buildKey/ProcedureUtils/RouterUtils/plugin system supporting MaybeRefOrGetter inputs/contexts, interceptors, scoped options, and query/mutation option modifiers.
  • Add unit, type, and e2e tests against real Pinia Colada + Vue components.
  • Register *.test.tsx under the root jsdom vitest project.

ℹ️ @orpc/vue-colada missing from root devDependencies

Every other non-runtime-excluded workspace package is listed in package.json#devDependencies. Adding @orpc/vue-colada there keeps the root manifest consistent with the monorepo convention, even though the workspace already resolves it.

ℹ️ Nitpicks

  • packages/vue-colada/tests/e2e.test.tsx:32 — comment typo: "whe should" → "we should".

Pullfrog  | View workflow run | via Pullfrog | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test body

Pullfrog  | Fix it ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@pullfrog

pullfrog Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes — added the new @orpc/vue-colada package, mirroring @orpc/tanstack-query v2 architecture while adapting key serialization and option types for Pinia Colada.

  • Add packages/vue-colada with build config, types, and README.
  • Implement buildKey/ProcedureUtils/RouterUtils/plugin system supporting MaybeRefOrGetter inputs/contexts, interceptors, scoped options, and query/mutation option modifiers.
  • Add unit, type, and e2e tests against real Pinia Colada + Vue components.
  • Register *.test.tsx under the root jsdom vitest project.

ℹ️ @orpc/vue-colada missing from root devDependencies

Every other non-runtime-excluded workspace package is listed in package.json#devDependencies. Adding @orpc/vue-colada there keeps the root manifest consistent with the monorepo convention, even though the workspace already resolves it.

Inline finding

packages/vue-colada/tests/e2e.test.tsx:32 — comment typo: "whe should" → "we should" (and optionally "put error case" → "put the error case").

Pullfrog  | View workflow run | via Pullfrog | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@dinwwwh dinwwwh changed the title feat(vue-colada): port @orpc/vue-colada to v2 with interceptors & plugins feat(vue-colada): Pinia Colada integration Jul 19, 2026
…s pattern

Align with Pinia Colada's built-in defineQueryOptions: queryOptions() and
mutationOptions() no longer accept MaybeRefOrGetter input/context values and
now return plain DefineQueryOptionsTagged / DefineMutationOptionsTagged
options (typed entry keys, no computed key). For reactive inputs, pass a
callback to useQuery — useQuery(() => orpc.x.queryOptions({ input: id.value }))
— matching the tanstack-query integration behavior and composing cleanly with
defineQueryOptions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — reactivity moved to Pinia Colada's defineQueryOptions/useQuery callback pattern, and tests/typecheck/build all pass.

Reviewed changes — since the prior review, the integration was refactored to align with @pinia/colada >= 1.0's plain-value options pattern.

  • Removed MaybeRefOrGetter from queryOptions()/mutationOptions() input/context in favor of plain values; reactivity is now the caller's responsibility via useQuery(() => …)/defineQueryOptions(...).
  • Updated type wrappers in src/types.ts to use DefineQueryOptions/DefineQueryOptionsTagged and UseMutationOptions/DefineMutationOptionsTagged.
  • Switched e2e and type tests to the callback form (e.g. useQuery(() => pingQueryOptions(id.value))).
  • Added @ts-expect-error tests asserting refs/getters are rejected for input and context.

ℹ️ Nitpicks

  • Root package.json devDependencies still doesn't list @orpc/vue-colada like @orpc/next and @orpc/tanstack-query.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread packages/pinia-colada/tests/e2e.test.tsx Outdated
Add ProcedureUtils.infiniteOptions built on Pinia Colada's useInfiniteQuery:
input as a (pageParam) => input function (matching the tanstack-query
integration), required initialPageParam/getNextPageParam passthrough, entry
keys generated with type 'infinite' from the initial page param, and plain
DefineInfiniteQueryOptionsTagged output composing with useInfiniteQuery
callback form and defineInfiniteQueryOptions.

Includes dedicated infiniteInterceptors (root, scoped, plugin-injected) and
an infiniteOptions modifier, wired through the same merge order as query and
mutation interceptors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes — added infinite query support on top of the v2 Pinia Colada port and merged latest main.

  • Added .infiniteOptions() to ProcedureUtils with DefineInfiniteQueryOptions input and useInfiniteQuery-compatible output.
  • Added infiniteInterceptors and infiniteOptions modifiers, wired through RouterUtilsOptions, scoped options, and plugin composition.
  • Updated OperationType and buildKey to include 'infinite' entries.
  • Added unit, .test-d.ts, and e2e coverage for infinite queries.
  • Merged latest main into the branch.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

Comment thread packages/pinia-colada/tests/e2e.test.tsx
@dinwwwh
dinwwwh marked this pull request as draft July 19, 2026 07:37
Add standalone key builders on procedure utils, mirroring the tanstack-query
integration: .queryKey() and .infiniteKey() return EntryKeyTagged keys so
cache reads like queryCache.getQueryData infer data types, and .mutationKey()
returns the same key (or per-input key function) used by .mutationOptions.
Each accepts a { key } override and has a matching queryKey/infiniteKey/
mutationKey modifier in ProcedureUtilsOptions (usable via scoped options and
plugins). The *Options builders now route through these methods so key
modifiers apply consistently everywhere.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the public RouterUtilsOptions.path option (the recursion path is now
purely internal) and add a dedicated prefix option instead. When set, the
prefix becomes the first element of every entry key —
[prefix, path, { input, type }] — so multiple router utils mounted over the
same client cannot collide, and partial key matching (invalidation, cache
reads) never crosses between prefixed and un-prefixed instances.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dinwwwh and others added 3 commits July 19, 2026 15:38
Extract BuildKeyPrefixOptions and carry prefix through ProcedureUtilsOptions
and the SharedRouterUtils options object instead of extra constructor
parameters, and drop redundant toArray wrapping around interceptor lists.
Rename @orpc/vue-colada to @orpc/pinia-colada to match the name of the
library it integrates with. Public names follow: createPiniaColadaUtils
(replacing createORPCVueColadaUtils, aligned with createTanstackQueryUtils),
PINIA_COLADA_OPERATION_CONTEXT_SYMBOL and PiniaColadaOperationContext.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dinwwwh dinwwwh changed the title feat(vue-colada): Pinia Colada integration feat(pinia-colada): Pinia Colada integration for v2 Jul 19, 2026
@dinwwwh dinwwwh changed the title feat(pinia-colada): Pinia Colada integration for v2 feat(pinia-colada): Pinia Colada integration Jul 19, 2026
Add .streamedOptions and .liveOptions (with .streamedKey/.liveKey) for
AsyncIteratorObject procedures, ported from the tanstack-query integration.
Chunks are published progressively through the query entry's public state ref:
streamed queries accumulate chunks into an array (with refetchMode
reset/append/replace and maxChunks via fnOptions, included in the entry key),
while live queries replace the result with each new chunk.

Both come with dedicated interceptors, option/key modifiers, scoped and
plugin support, and 'streamed'/'live' operation context types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bring the streamed/live e2e cases up to the same rigor as the regular
useQuery case: typesafe error handling, partial key invalidation matching by
operation type, gated chunks so intermediate streaming states are asserted
deterministically (first chunk visible while the stream is still open),
append-mode refetch with maxChunks, and reactive input switching to a fresh
entry via the useQuery callback form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…a Colada

Replace the fake-entry unit tests for serializableStreamedQuery and liveQuery
with tests that mount real useQuery components backed by a real query cache,
proving users actually observe streamed data live: chunks appear (or replace
the value) reactively while asyncStatus is still loading, driven by manually
gated streams. Covers all refetch modes, maxChunks, reset-to-pending on
refetch, the empty live stream error, and cancellation via
queryCache.cancelQueries keeping already-received data without an error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move the real-Pinia-Colada tests for serializableStreamedQuery and liveQuery
from tests/ back next to their source files as src/*.test.tsx, with the
mount and chunk-stream helpers inlined per file instead of imported from a
shared module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The integration is not tied to defineQueryOptions/defineInfiniteQueryOptions;
document the option utilities against useQuery/useInfiniteQuery/useMutation
only and keep the reactive-inputs guidance to the useQuery callback form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dinwwwh
dinwwwh marked this pull request as ready for review July 19, 2026 13:05

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes — adds the @orpc/pinia-colada integration package with query/mutation option builders, streamed/live/infinite query support, key utilities, plugins, interceptors, scoped defaults, and documentation.

  • Add @orpc/pinia-colada package — builders for useQuery, useInfiniteQuery, and useMutation that accept plain-value options, plus .key() / .queryKey() / .streamedKey() / .liveKey() / .infiniteKey() / .mutationKey() helpers.
  • Streamed and live query supportserializableStreamedQuery accumulates AsyncIteratorObject chunks and liveQuery publishes the latest chunk, both validated with real Pinia Colada + Vue component tests.
  • Router-shaped utilities and pluginscreatePiniaColadaUtils produces a recursive proxy mirroring the router, supports prefix, scoped defaults, interceptor chains, and ordered RouterUtilsPlugin hooks.
  • Add integration docs and sidebar entry — new apps/content/docs/integrations/pinia-colada.md covers setup, options, keys, reactivity, interceptors, plugins, and operation context.

Pullfrog  | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏

@dinwwwh
dinwwwh merged commit e12f7c3 into middleapi:main Jul 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant