Skip to content

feat(tanstack-query): define base options and interceptors via contract meta#1705

Merged
dinwwwh merged 23 commits into
middleapi:mainfrom
dinwwwh:claude/tanstack-query-meta-plugin-edfe5e
Jul 25, 2026
Merged

feat(tanstack-query): define base options and interceptors via contract meta#1705
dinwwwh merged 23 commits into
middleapi:mainfrom
dinwwwh:claude/tanstack-query-meta-plugin-edfe5e

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Jul 21, 2026

Copy link
Copy Markdown
Member

Summary

Define base TanStack Query options and interceptors directly on a procedure contract via tanstackQuery, and apply them automatically with the new ContractOptionsUtilsPlugin.

export const contract = {
  planet: {
    find: oc
      .input(z.object({ id: z.number() }))
      .meta(tanstackQuery({
        queryOptions: {
          staleTime: 60 * 1000,
        },
      })),
  },
}

const orpc = createTanstackQueryUtils(client, {
  plugins: [new ContractOptionsUtilsPlugin(contract)],
})
  • tanstackQuery infers input, output, and error types from the contract, supports all procedure utils options (keys, options, interceptors), and merges when applied multiple times
  • ContractOptionsUtilsPlugin applies meta options as the base layer: utils level options override them and utils interceptors run after meta interceptors
  • Merging is consistent across all layers: interceptors concatenate, plain option objects spread-merge, and any pair involving a function modifier composes
  • getTanstackQueryMeta reads the stored options for custom integrations
  • Docs cover the plugin, the reference-only nature of contract types, and passing runtime values such as router utils through mutation meta

@vercel

vercel Bot commented Jul 21, 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 25, 2026 1:20am

@pkg-pr-new

pkg-pr-new Bot commented Jul 21, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1705

@orpc/arktype

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

@orpc/bun

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

@orpc/client

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

@orpc/cloudflare

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

@orpc/contract

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

@orpc/experimental-effect

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

@orpc/evlog

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

@orpc/json-schema

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

@orpc/nest

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

@orpc/next

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

@orpc/openapi

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

@orpc/opentelemetry

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

@orpc/pinia-colada

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

@orpc/pino

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

@orpc/publisher

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

@orpc/ratelimit

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

@orpc/server

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

@orpc/shared

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

@orpc/tanstack-query

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

@orpc/trpc

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

@orpc/valibot

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

@orpc/zod

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

commit: 89a3c90

@codecov

codecov Bot commented Jul 21, 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 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing dinwwwh:claude/tanstack-query-meta-plugin-edfe5e (89a3c90) with main (deb9e75)

Open in CodSpeed

@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 — one minor API-surface note inline.

Reviewed changes — added tanstackQueryMeta, getTanstackQueryMeta, and ContractMetaPlugin so base TanStack Query options and interceptors can be defined on a procedure contract and applied automatically as the default layer under utils options.

  • packages/tanstack-query/src/meta.ts — introduces the tanstackQueryMeta contract meta plugin, getTanstackQueryMeta reader, and ContractMetaPlugin router utils plugin.
  • packages/tanstack-query/src/procedure-utils.ts — adds mergeProcedureUtilsOptions/mergeProcedureUtilsModifier so option modifiers spread-merge and interceptors concatenate across layers.
  • packages/tanstack-query/src/router-utils.ts — switches global/scoped per-procedure option merging to mergeProcedureUtilsOptions to keep semantics consistent.
  • packages/tanstack-query/src/index.ts — exports the new ./meta module and now also exports ./plugin.
  • Tests and docs — adds meta.test.ts/meta.test-d.ts, updates the router-utils.test.ts mock, and documents the contract meta plugin.

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

Comment thread packages/tanstack-query/src/index.ts
@pullfrog

pullfrog Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Heads-up: the inline suggestion in my review on packages/tanstack-query/src/index.ts was malformed — the suggested replacement included extra lines by mistake. Please ignore that suggestion entirely.

The actual feedback is just a nit: export * from './plugin' now also makes CompositeRouterUtilsPlugin public. If that class is meant to stay internal, consider scoping the export to RouterUtilsPlugin only or marking CompositeRouterUtilsPlugin as @internal. Everything else looks good to merge.

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

@dinwwwh
dinwwwh marked this pull request as draft July 21, 2026 12:07
…ery-meta-plugin-edfe5e

# Conflicts:
#	packages/tanstack-query/src/procedure-utils.ts
#	packages/tanstack-query/src/router-utils.test.ts
#	packages/tanstack-query/src/router-utils.ts
@dinwwwh dinwwwh changed the title feat(tanstack-query): contract meta for base query/mutation options feat(tanstack-query): define base options and interceptors via contract meta Jul 23, 2026

@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.

Reviewed changes — the new commit changes mixed object/function modifier merging from "replace" to "compose," so a plain-object modifier now spreads into a function modifier's input rather than being discarded.

  • Compose mixed object and function modifiersmergeProcedureUtilsModifier now wraps the plain-object side in a function so it participates in composition instead of being replaced, and a new test validates both orderings.

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

Comment thread packages/tanstack-query/src/procedure-utils.ts

@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 — the refactor is clean. The one open thread from the prior review remains a pre-existing concern unrelated to this delta.

Reviewed changes — refactored isProcedureUtilsOptions from a private function in router-utils.ts into an exported utility in procedure-utils.ts with more comprehensive key validation, and reworked mock setup in router-utils tests to use importOriginal.

  • Move isProcedureUtilsOptions to procedure-utils.ts — the type guard now validates all known keys (prefix, interceptor arrays, modifier keys) via key-lookup arrays instead of only checking interceptor types.
  • Export isProcedureUtilsOptions — the function becomes part of the public API via export * from './procedure-utils'.
  • Update router-utils.test.ts mock — uses importOriginal so real exports from procedure-utils pass through while ProcedureUtils remains mocked.

Pullfrog  | Fix it ➔View workflow run | Using DeepSeek Pro (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.

Reviewed changesisProcedureUtilsOptions now accepts unknown keys instead of rejecting them, and the router-utils test for invalid scoped options was simplified and aligned with the new detection logic.

  • isProcedureUtilsOptions allows unknown keys — the loop skips unrecognized keys rather than returning false, so extra properties mixed into scoped options don't prevent procedure-utils detection.
  • Simplified router-utils.test.ts — replaced the parameterized interceptor-only test with a single test that validates the correct behavior with queryInterceptors: { invalid: true } and verifies nested child.queryOptions resolution.

Pullfrog  | Fix it ➔View workflow run | Using DeepSeek Pro (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.

ℹ️ No new issues from this delta — the one open thread from a prior review (9b1fdac) remains unaddressed.

Reviewed changes — tightened isProcedureUtilsOptions validation so interceptor array elements are checked for function type, and simplified the modifier-key check by removing a now-redundant typeof guard.

  • Strengthen interceptor validationisProcedureUtilsOptions now rejects interceptor arrays containing non-function elements (e.g. [{ invalid: true }]), catching bad inputs that would cause runtime errors downstream.
  • Simplify modifier-key check — dropped the typeof value[key] !== 'function' guard since isTypescriptObject (from @standardserver/shared) already covers functions per its contract: "Checks whether the provided container is a typescript object (object or function)."

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

Copilot AI 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.

Pull request overview

Adds a contract-level configuration mechanism for the TanStack Query integration by storing “base” procedure utils options/interceptors in contract meta and applying them automatically when building router utils. This fits the @orpc/tanstack-query package by enabling reusable, contract-authored defaults that are merged consistently with existing utils-level configuration.

Changes:

  • Introduces tanstackQuery() + getTanstackQueryMeta() and a ContractOptionsUtilsPlugin to store/apply base options via contract meta.
  • Centralizes procedure utils option merging/validation with mergeProcedureUtilsOptions() and moves isProcedureUtilsOptions() into procedure-utils.ts.
  • Updates tests and documentation to cover contract meta options and plugin usage.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/tanstack-query/src/router-utils.ts Uses centralized merge/validation when initializing per-procedure utils options.
packages/tanstack-query/src/router-utils.test.ts Adjusts mocking and scoped-options tests to align with new validation/merge behavior.
packages/tanstack-query/src/procedure-utils.ts Adds isProcedureUtilsOptions + option/modifier merge utilities.
packages/tanstack-query/src/procedure-utils.test.ts Adds runtime-shape tests for isProcedureUtilsOptions.
packages/tanstack-query/src/meta.ts New contract meta API (tanstackQuery, getTanstackQueryMeta) and ContractOptionsUtilsPlugin.
packages/tanstack-query/src/meta.test.ts Tests meta storage/merging and plugin application through createRouterUtils.
packages/tanstack-query/src/meta.test-d.ts Adds type-level assertions for tanstackQuery inference and invalid options.
packages/tanstack-query/src/index.ts Exposes meta and plugin exports publicly.
apps/content/docs/integrations/tanstack-query.md Documents the new Contract Options Plugin and contract-meta caveats/examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/tanstack-query/src/procedure-utils.ts

@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 — refactored mergeProcedureUtilsOptions from per-key manual code to loop-based merging, added undefined reset semantics so explicit undefined on any interceptor or modifier key clears the base value, and switched router-utils.ts to use mergeProcedureUtilsOptions for the global+scoped options merge instead of manual toArray concatenation.

  • Refactor mergeProcedureUtilsOptions — replaced 12 lines of per-key merge calls with two loops over PROCEDURE_UTILS_INTERCEPTOR_KEYS and PROCEDURE_UTILS_MODIFIER_KEYS. Keys set to undefined in the override now reset the base value (consistent across both interceptors and modifiers).
  • Tighten mergeProcedureUtilsModifier signature — params changed from optional to required, reflecting that callers always supply both.
  • Unify router-level mergecreateRouterUtilsInternal now calls mergeProcedureUtilsOptions(globalBase, scoped) instead of manually wrapping each interceptor list with [...toArray(options.X), ...toArray(options.scoped?.X)].
  • Docs update — the contract options description notes that passing undefined explicitly resets the value from lower layers.
  • New test — validates that meta(tanstackQuery({ queryOptions: undefined })) removes previously-set values.

Pullfrog  | View workflow run | Using DeepSeek Pro (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.

✅ No new issues found.

Reviewed changes — relocated mergeProcedureUtilsOptions unit tests from meta.test.ts to procedure-utils.test.ts, removed now-unnecessary toArray wrapping of interceptor values in router-utils.ts, and updated test assertions to reflect that mergeProcedureUtilsOptions handles the global+scoped interceptor merge internally.

  • Move mergeProcedureUtilsOptions tests to procedure-utils.test.ts — the six merge tests (override by key presence, undefined reset, interceptor concat, plain-object spread, function composition, mixed composition) now live alongside their implementation instead of in meta.test.ts.
  • Drop toArray wrapping in router-utils.ts — interceptor values passed to mergeProcedureUtilsOptions no longer go through toArray since the merge function correctly handles undefined via its if (baseValue && overrideValue) guard and the initial spread.
  • Simplify router-utils.test.ts assertions — removed the emptyInterceptors fixture and updated expected ProcedureUtils constructor args since empty interceptor arrays are no longer materialized by manual concatenation.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@dinwwwh
dinwwwh merged commit 6c2c35e into middleapi:main Jul 25, 2026
11 checks passed
dinwwwh added a commit that referenced this pull request Jul 25, 2026
… meta (#1718)

## Summary

Port of #1705 to `@orpc/pinia-colada`. Define base Pinia Colada options
and interceptors directly on a procedure contract via `piniaColada`, and
apply them automatically with the new `ContractOptionsUtilsPlugin`.

```ts
export const contract = {
  planet: {
    find: oc
      .input(z.object({ id: z.number() }))
      .meta(piniaColada({
        queryOptions: {
          staleTime: 60 * 1000,
        },
      })),
  },
}

const orpc = createPiniaColadaUtils(client, {
  plugins: [new ContractOptionsUtilsPlugin(contract)],
})
```

- `piniaColada` infers input, output, and error types from the contract,
supports all procedure utils options (keys, options, interceptors), and
merges when applied multiple times
- `ContractOptionsUtilsPlugin` applies meta options as the base layer:
utils level options override them and utils interceptors run after meta
interceptors
- Merging is consistent across all layers: interceptors concatenate,
plain option objects spread-merge, any pair involving a function
modifier composes, and a key explicitly set to `undefined` resets the
value from lower layers
- `getPiniaColadaMeta` reads the stored options for custom integrations
- `UseMutationFnContext` now matches the runtime merged mutation
context, so values provided by a global `onMutate` are typed inside
mutation interceptors via `UseMutationContextCommon` augmentation
- Docs cover the plugin, the reference-only nature of contract types,
and passing runtime values such as router utils through a global
`onMutate` hook for optimistic updates
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.

2 participants