orpc-fn 0.3.0 → 0.5.0

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.
Files changed (95) hide show
  1. package/README.md +146 -5
  2. package/dist/client.d.ts +29 -0
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +49 -0
  5. package/dist/client.js.map +1 -1
  6. package/dist/create-fn.d.ts.map +1 -1
  7. package/dist/create-fn.js +2 -8
  8. package/dist/create-fn.js.map +1 -1
  9. package/dist/hono.d.ts +12 -1
  10. package/dist/hono.d.ts.map +1 -1
  11. package/dist/hono.js +15 -1
  12. package/dist/hono.js.map +1 -1
  13. package/dist/live/fn-live.d.ts +1 -6
  14. package/dist/live/fn-live.d.ts.map +1 -1
  15. package/dist/live/fn-live.js +2 -18
  16. package/dist/live/fn-live.js.map +1 -1
  17. package/dist/live/index.d.ts +3 -1
  18. package/dist/live/index.d.ts.map +1 -1
  19. package/dist/live/index.js +2 -0
  20. package/dist/live/index.js.map +1 -1
  21. package/dist/live/invalidation-stream.d.ts +52 -0
  22. package/dist/live/invalidation-stream.d.ts.map +1 -0
  23. package/dist/live/invalidation-stream.js +98 -0
  24. package/dist/live/invalidation-stream.js.map +1 -0
  25. package/dist/live/ioredis.d.ts +1 -0
  26. package/dist/live/ioredis.d.ts.map +1 -1
  27. package/dist/live/ioredis.js +1 -0
  28. package/dist/live/ioredis.js.map +1 -1
  29. package/dist/live/memory.d.ts +2 -1
  30. package/dist/live/memory.d.ts.map +1 -1
  31. package/dist/live/memory.js +6 -1
  32. package/dist/live/memory.js.map +1 -1
  33. package/dist/live/pub-sub.d.ts +5 -0
  34. package/dist/live/pub-sub.d.ts.map +1 -1
  35. package/dist/live/pub-sub.js +36 -15
  36. package/dist/live/pub-sub.js.map +1 -1
  37. package/dist/live/redis-bun.d.ts +3 -0
  38. package/dist/live/redis-bun.d.ts.map +1 -1
  39. package/dist/live/redis-bun.js +1 -0
  40. package/dist/live/redis-bun.js.map +1 -1
  41. package/dist/live/redis.d.ts +4 -1
  42. package/dist/live/redis.d.ts.map +1 -1
  43. package/dist/live/redis.js +14 -2
  44. package/dist/live/redis.js.map +1 -1
  45. package/dist/live/scoped-change-bus.d.ts +45 -0
  46. package/dist/live/scoped-change-bus.d.ts.map +1 -0
  47. package/dist/live/scoped-change-bus.js +38 -0
  48. package/dist/live/scoped-change-bus.js.map +1 -0
  49. package/dist/live/transport.d.ts +11 -0
  50. package/dist/live/transport.d.ts.map +1 -1
  51. package/dist/live/transport.js.map +1 -1
  52. package/dist/otel.d.ts +5 -0
  53. package/dist/otel.d.ts.map +1 -1
  54. package/dist/otel.js +7 -0
  55. package/dist/otel.js.map +1 -1
  56. package/dist/procedure-cli.d.ts +25 -0
  57. package/dist/procedure-cli.d.ts.map +1 -0
  58. package/dist/procedure-cli.js +67 -0
  59. package/dist/procedure-cli.js.map +1 -0
  60. package/dist/react.d.ts +116 -0
  61. package/dist/react.d.ts.map +1 -0
  62. package/dist/react.js +156 -0
  63. package/dist/react.js.map +1 -0
  64. package/dist/realtime.d.ts +114 -0
  65. package/dist/realtime.d.ts.map +1 -0
  66. package/dist/realtime.js +316 -0
  67. package/dist/realtime.js.map +1 -0
  68. package/dist/vue/testing.d.ts +67 -0
  69. package/dist/vue/testing.d.ts.map +1 -0
  70. package/dist/vue/testing.js +225 -0
  71. package/dist/vue/testing.js.map +1 -0
  72. package/dist/vue.d.ts +211 -0
  73. package/dist/vue.d.ts.map +1 -0
  74. package/dist/vue.js +312 -0
  75. package/dist/vue.js.map +1 -0
  76. package/package.json +51 -4
  77. package/src/client.ts +57 -0
  78. package/src/create-fn.ts +2 -7
  79. package/src/hono.ts +22 -2
  80. package/src/live/fn-live.ts +3 -22
  81. package/src/live/index.ts +12 -1
  82. package/src/live/invalidation-stream.ts +142 -0
  83. package/src/live/ioredis.ts +2 -0
  84. package/src/live/memory.ts +11 -2
  85. package/src/live/pub-sub.ts +48 -17
  86. package/src/live/redis-bun.ts +3 -0
  87. package/src/live/redis.ts +33 -6
  88. package/src/live/scoped-change-bus.ts +98 -0
  89. package/src/live/transport.ts +12 -0
  90. package/src/otel.ts +8 -0
  91. package/src/procedure-cli.ts +99 -0
  92. package/src/react.ts +355 -0
  93. package/src/realtime.ts +416 -0
  94. package/src/vue/testing.ts +296 -0
  95. package/src/vue.ts +783 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../../src/vue/testing.ts"],"names":[],"mappings":"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","sourcesContent":["import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query'\nimport { createApp, effectScope } from 'vue'\nimport { provideOrpc } from '../vue.js'\n\ntype Method = (...args: never[]) => unknown\ntype MockFactory = (implementation: Method) => Method\n\nexport type OrpcMock<T> = T & {\n\t/** Reset every method mock created so far (calls `mockReset` when the factory provides it). */\n\t$reset: () => void\n}\n\nexport type CreateOrpcMockOptions = {\n\t/** Wraps each method, e.g. `mock` from `bun:test` or `vi.fn`, so calls can be asserted. */\n\tfn?: MockFactory\n\t/** Namespace `.key()` results (default: `[namespace]`). */\n\tkeys?: Record<string, readonly unknown[]>\n\t/** Explicit namespace shapes merged over the auto-mock. */\n\toverrides?: Record<string, unknown>\n}\n\nconst emptyAsyncIterable = () => ({\n\tasync *[Symbol.asyncIterator]() {}\n})\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n\ttypeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * A deep stand-in for oRPC utils or a client: `o.order.key()` is `['order']`,\n * `o.order.get.call()` resolves an empty stream, `.key()`/`.queryKey()` on a\n * procedure return `[]`, and any other method returns `{}`. The same path\n * always returns the same mock, so calls can be asserted. Type it as your\n * utils: `createOrpcMock<typeof orpc>({ fn: mock })`.\n */\nexport function createOrpcMock<T = Record<string, unknown>>(\n\toptions: CreateOrpcMockOptions = {}\n): OrpcMock<T> {\n\tconst { fn = (implementation) => implementation, keys, overrides } = options\n\tconst created: Method[] = []\n\tconst method = (implementation: Method) => {\n\t\tconst wrapped = fn(implementation)\n\t\tcreated.push(wrapped)\n\t\treturn wrapped\n\t}\n\tconst reset = () => {\n\t\tfor (const wrapped of created) {\n\t\t\t;(wrapped as { mockReset?: () => void }).mockReset?.()\n\t\t}\n\t}\n\n\tconst procedures = new Map<string, Record<string, unknown>>()\n\tconst procedure = (path: string) => {\n\t\tlet found = procedures.get(path)\n\t\tif (!found) {\n\t\t\tconst methods = new Map<string, Method>()\n\t\t\tfound = new Proxy(\n\t\t\t\t{},\n\t\t\t\t{\n\t\t\t\t\tget(_target, name) {\n\t\t\t\t\t\tif (typeof name === 'symbol') return undefined\n\t\t\t\t\t\tlet existing = methods.get(name)\n\t\t\t\t\t\tif (!existing) {\n\t\t\t\t\t\t\texisting = method(\n\t\t\t\t\t\t\t\tname === 'call'\n\t\t\t\t\t\t\t\t\t? async () => emptyAsyncIterable()\n\t\t\t\t\t\t\t\t\t: name === 'key' || name === 'queryKey'\n\t\t\t\t\t\t\t\t\t\t? () => []\n\t\t\t\t\t\t\t\t\t\t: () => ({})\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tmethods.set(name, existing)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn existing\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t)\n\t\t\tprocedures.set(path, found)\n\t\t}\n\t\treturn found\n\t}\n\n\tconst namespaces = new Map<string, Record<string, unknown>>()\n\tconst namespace = (name: string) => {\n\t\tlet found = namespaces.get(name)\n\t\tif (!found) {\n\t\t\tconst override = overrides?.[name]\n\t\t\tconst target = isObject(override) ? { ...override } : {}\n\t\t\tfound = new Proxy(target, {\n\t\t\t\tget(shape, key) {\n\t\t\t\t\tif (typeof key === 'symbol') return undefined\n\t\t\t\t\tif (key === 'key') return () => keys?.[name] ?? [name]\n\t\t\t\t\tif (key in shape) return shape[key]\n\t\t\t\t\treturn procedure(`${name}.${key}`)\n\t\t\t\t}\n\t\t\t})\n\t\t\tnamespaces.set(name, found)\n\t\t}\n\t\treturn found\n\t}\n\n\t// The proxy answers every path at runtime; `T` is the shape tests read it as.\n\treturn new Proxy({ $reset: reset } as OrpcMock<T>, {\n\t\tget(_target, key) {\n\t\t\tif (key === '$reset') return reset\n\t\t\tif (typeof key === 'symbol') return undefined\n\t\t\tconst override = overrides?.[key]\n\t\t\tif (override !== undefined && !isObject(override)) return override\n\t\t\treturn namespace(key)\n\t\t}\n\t})\n}\n\nexport type TestConnection<T> = {\n\tinput: unknown\n\tsignal: AbortSignal | undefined\n\treadonly closed: boolean\n\t/** Deliver an event. Resolves once the consumer asked for the next one, or the stream closed. */\n\tpush: (event: T) => Promise<void>\n\t/** End the stream normally (`done`). */\n\tend: () => void\n\t/** Fail the stream. */\n\tfail: (error: Error) => void\n}\n\nexport type TestStream<T> = {\n\t/** Pass as the subscribe function; works for any `(input, …, { signal })` shape. */\n\tsubscribe: (...args: unknown[]) => Promise<AsyncIterable<T>>\n\t/** Every connection opened so far, oldest first. */\n\tconnections: TestConnection<T>[]\n\t/** Resolves when at least `count` connections have been opened. */\n\topened: (count?: number) => Promise<TestConnection<T>>\n\t/** Push into the newest connection. */\n\tpush: (event: T) => Promise<void>\n\tend: () => void\n\tfail: (error: Error) => void\n}\n\n/**\n * A controllable stand-in for an oRPC event iterator, for driving\n * subscriptions and live queries in tests without timers.\n */\nexport function createTestStream<T>(): TestStream<T> {\n\tconst connections: TestConnection<T>[] = []\n\tconst openWaiters: { count: number; resolve: () => void }[] = []\n\n\tfunction open(args: unknown[]): TestConnection<T> {\n\t\tconst options = [...args]\n\t\t\t.reverse()\n\t\t\t.find(\n\t\t\t\t(arg): arg is { signal?: AbortSignal } =>\n\t\t\t\t\tisObject(arg) && 'signal' in arg\n\t\t\t)\n\n\t\ttype Queued = {\n\t\t\tresult: IteratorResult<T, undefined>\n\t\t\tdelivered: () => void\n\t\t}\n\t\tconst queue: Queued[] = []\n\t\tlet failure: Error | null = null\n\t\tlet closed = false\n\t\tlet pending: {\n\t\t\tresolve: (result: IteratorResult<T, undefined>) => void\n\t\t\treject: (error: Error) => void\n\t\t} | null = null\n\t\t// The event the consumer holds; it is processed once it asks for the next.\n\t\tlet handedOut: (() => void) | null = null\n\n\t\tconst settle = () => {\n\t\t\tif (!pending) return\n\t\t\tconst current = pending\n\t\t\tif (failure) {\n\t\t\t\tpending = null\n\t\t\t\tcurrent.reject(failure)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = queue.shift()\n\t\t\tif (!next) return\n\t\t\tpending = null\n\t\t\thandedOut = next.delivered\n\t\t\tcurrent.resolve(next.result)\n\t\t}\n\n\t\tconst close = () => {\n\t\t\tclosed = true\n\t\t\thandedOut?.()\n\t\t\thandedOut = null\n\t\t\tfor (const queued of queue) queued.delivered()\n\t\t}\n\n\t\t// oRPC rejects a pending `next()` with an AbortError when the call is aborted.\n\t\toptions?.signal?.addEventListener('abort', () => {\n\t\t\tconst abort = new Error('This operation was aborted')\n\t\t\tabort.name = 'AbortError'\n\t\t\tfailure = abort\n\t\t\tsettle()\n\t\t\tclose()\n\t\t})\n\n\t\tconst connection: TestConnection<T> = {\n\t\t\tinput: args[0],\n\t\t\tsignal: options?.signal,\n\t\t\tget closed() {\n\t\t\t\treturn closed\n\t\t\t},\n\t\t\tpush(event) {\n\t\t\t\tif (closed) return Promise.resolve()\n\t\t\t\treturn new Promise<void>((delivered) => {\n\t\t\t\t\tqueue.push({ result: { done: false, value: event }, delivered })\n\t\t\t\t\tsettle()\n\t\t\t\t})\n\t\t\t},\n\t\t\tend() {\n\t\t\t\tconst done = { done: true as const, value: undefined }\n\t\t\t\tqueue.push({ result: done, delivered: () => {} })\n\t\t\t\tsettle()\n\t\t\t\tclosed = true\n\t\t\t},\n\t\t\tfail(error) {\n\t\t\t\tfailure = error\n\t\t\t\tsettle()\n\t\t\t\tclose()\n\t\t\t}\n\t\t}\n\n\t\tconst iterator: AsyncIterator<T, undefined> = {\n\t\t\tnext() {\n\t\t\t\thandedOut?.()\n\t\t\t\thandedOut = null\n\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\tpending = { resolve, reject }\n\t\t\t\t\tsettle()\n\t\t\t\t})\n\t\t\t},\n\t\t\tasync return() {\n\t\t\t\tclose()\n\t\t\t\tpending?.resolve({ done: true, value: undefined })\n\t\t\t\tpending = null\n\t\t\t\treturn { done: true, value: undefined }\n\t\t\t}\n\t\t}\n\n\t\tconnections.push(connection)\n\t\tfor (const waiter of [...openWaiters]) {\n\t\t\tif (connections.length < waiter.count) continue\n\t\t\topenWaiters.splice(openWaiters.indexOf(waiter), 1)\n\t\t\twaiter.resolve()\n\t\t}\n\t\treturn Object.assign(connection, {\n\t\t\t[Symbol.asyncIterator]: () => iterator\n\t\t})\n\t}\n\n\tconst latest = () => {\n\t\tconst connection = connections.at(-1)\n\t\tif (!connection) throw new Error('createTestStream: no connection opened')\n\t\treturn connection\n\t}\n\n\treturn {\n\t\tsubscribe: async (...args) =>\n\t\t\topen(args) as TestConnection<T> & AsyncIterable<T>,\n\t\tconnections,\n\t\topened: (count = 1) =>\n\t\t\tnew Promise((resolve) => {\n\t\t\t\tconst done = () => resolve(connections[count - 1] as TestConnection<T>)\n\t\t\t\tif (connections.length >= count) done()\n\t\t\t\telse openWaiters.push({ count, resolve: done })\n\t\t\t}),\n\t\tpush: (event) => latest().push(event),\n\t\tend: () => latest().end(),\n\t\tfail: (error) => latest().fail(error)\n\t}\n}\n\n/**\n * Run composables inside a real Vue app with a `QueryClient` and the provided\n * oRPC client, without a DOM. `stop()` disposes the scope, closing streams.\n */\nexport function withOrpcApp<T>(\n\tsetup: () => T,\n\toptions: {\n\t\tutils?: unknown\n\t\tclient?: unknown\n\t\tqueryClient?: QueryClient\n\t} = {}\n) {\n\tconst queryClient =\n\t\toptions.queryClient ??\n\t\tnew QueryClient({ defaultOptions: { queries: { retry: false } } })\n\tconst app = createApp({ render: () => null })\n\tapp.use(VueQueryPlugin, { queryClient })\n\tprovideOrpc(app, { client: options.client, utils: options.utils })\n\tconst scope = effectScope()\n\tconst result = app.runWithContext(() => scope.run(setup)) as T\n\treturn { result, queryClient, app, stop: () => scope.stop() }\n}\n"]}
package/dist/vue.d.ts ADDED
@@ -0,0 +1,211 @@
1
+ import { type DefaultError, type FetchQueryOptions, type InferDataFromTag, type InfiniteData, type InvalidateQueryFilters, type MutationObserverOptions, type UseInfiniteQueryOptions, type UseInfiniteQueryReturnType, type UseMutationReturnType, type UseQueryReturnType, type Updater, type QueryKey, type UseQueryOptions, useQuery as useVueQuery } from '@tanstack/vue-query';
2
+ import { type App, type MaybeRefOrGetter, type Ref } from 'vue';
3
+ import { type InvalidationStreamOptions, type LiveConnectionStatus } from './realtime.js';
4
+ export type { InvalidationDomain, LiveConnectionStatus } from './realtime.js';
5
+ /**
6
+ * Register your client types once so every composable infers them:
7
+ *
8
+ * ```ts
9
+ * declare module 'orpc-fn/vue' {
10
+ * interface Register { utils: typeof orpc; client: typeof client }
11
+ * }
12
+ * ```
13
+ */
14
+ export interface Register {
15
+ }
16
+ export type RegisteredOrpcUtils = Register extends {
17
+ utils: infer T;
18
+ } ? T : {
19
+ 'orpc-fn/vue: register your utils with `declare module "orpc-fn/vue" { interface Register { utils: typeof orpc } }`, or pass `orpc`': never;
20
+ };
21
+ export type RegisteredOrpcClient = Register extends {
22
+ client: infer T;
23
+ } ? T : unknown;
24
+ /** An explicit `<TData>`, else the data type oRPC tagged on the key. */
25
+ type CachedData<TData, TKey extends QueryKey> = [TData] extends [never] ? InferDataFromTag<unknown, TKey> : TData;
26
+ /**
27
+ * Make an oRPC client and its TanStack Query utils the app's default. A
28
+ * surface that talks to another API (an embed with its own auth) passes
29
+ * `orpc` to each composable instead and never needs this.
30
+ */
31
+ export declare function provideOrpc<TClient, TUtils>(app: App, orpc: {
32
+ client: TClient;
33
+ utils: TUtils;
34
+ }): void;
35
+ /** The client and utils from {@link provideOrpc}. */
36
+ export declare function useOrpc(): {
37
+ client: RegisteredOrpcClient;
38
+ utils: RegisteredOrpcUtils;
39
+ };
40
+ /**
41
+ * Picks the stream to open from the utils. A procedure's `call` fits as is:
42
+ * `(o) => o.order.watch.call`. The composable passes the input and an abort signal.
43
+ */
44
+ export type OrpcSubscribeFn<TInput, TEvent, TOrpc = RegisteredOrpcUtils> = (orpc: TOrpc) => (input: TInput, options: {
45
+ signal: AbortSignal;
46
+ }) => Promise<AsyncIterable<TEvent>>;
47
+ export interface UseSubscriptionOptions<TEvent, TOrpc = RegisteredOrpcUtils> {
48
+ /** Start the stream on its own (default: true). With false, call `connect()`. */
49
+ immediate?: MaybeRefOrGetter<boolean> | undefined;
50
+ onEvent?: (event: TEvent, meta?: {
51
+ connectionId: number;
52
+ }) => void;
53
+ onError?: ((error: Error) => void) | undefined;
54
+ /** Every successful connect; `connectionId > 1` is a reconnect. */
55
+ onConnect?: (connectionId: number) => void;
56
+ onClose?: () => void;
57
+ /** Events kept in `events` (default: 100). 1 keeps only `latestEvent`. */
58
+ maxEvents?: number;
59
+ /** Reconnect when the input changes (default: true). */
60
+ autoReconnectOnInputChange?: boolean;
61
+ /**
62
+ * After a connect, reconnect with backoff when the stream ends or errors
63
+ * unexpectedly (proxy idle timeout, network blip). Deliberate teardown
64
+ * does not retry. Default: true.
65
+ */
66
+ autoReconnectOnClose?: boolean;
67
+ orpc?: MaybeRefOrGetter<TOrpc> | undefined;
68
+ /**
69
+ * Close the stream while the page is hidden (default: true), so a
70
+ * background tab holds no server connection. It reconnects, and a live
71
+ * route re-sends its snapshot, when the page is visible again.
72
+ */
73
+ respectVisibility?: boolean | undefined;
74
+ }
75
+ export interface UseSubscriptionReturn<TEvent> {
76
+ events: Ref<TEvent[]>;
77
+ latestEvent: Ref<TEvent | undefined>;
78
+ status: Ref<LiveConnectionStatus>;
79
+ error: Ref<Error | null>;
80
+ isConnected: Ref<boolean>;
81
+ connect: () => Promise<void>;
82
+ disconnect: () => Promise<void>;
83
+ clearEvents: () => void;
84
+ }
85
+ /**
86
+ * An oRPC event iterator as reactive state, with backoff reconnects and a
87
+ * pause while the page is hidden. Closed when the owning effect scope stops.
88
+ */
89
+ export declare function useOrpcSubscription<TInput, TEvent, TOrpc = RegisteredOrpcUtils>(input: MaybeRefOrGetter<TInput>, subscribeFn: OrpcSubscribeFn<TInput, TEvent, TOrpc>, options?: UseSubscriptionOptions<TEvent, TOrpc>): UseSubscriptionReturn<TEvent>;
90
+ /**
91
+ * TanStack Query composables that receive the oRPC utils, so call sites read
92
+ * `useQuery((o) => o.order.get.queryOptions({ input }))`. Pass `orpc` to bind
93
+ * another client than the provided one.
94
+ */
95
+ export declare function useApiClient<TOrpc = RegisteredOrpcUtils>(clientOptions?: {
96
+ orpc?: MaybeRefOrGetter<TOrpc> | undefined;
97
+ }): {
98
+ useQuery: <TQueryFnData, TError = Error, TData = TQueryFnData, TQueryKey extends QueryKey = readonly unknown[]>(optionsFn: (orpc: TOrpc) => UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>) => UseQueryReturnType<TData, TError>;
99
+ useInfiniteQuery: <TQueryFnData, TError = Error, TData = InfiniteData<TQueryFnData, unknown>, TQueryKey extends QueryKey = readonly unknown[], TPageParam = unknown>(optionsFn: (orpc: TOrpc) => UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>) => UseInfiniteQueryReturnType<TData, TError>;
100
+ useMutation: {
101
+ <TData = unknown, TError = Error, TVariables = void, TContext = unknown>(optionsFn: (orpc: TOrpc) => MutationObserverOptions<TData, TError, TVariables, TContext>, config: {
102
+ initialInput: TVariables;
103
+ }): UseMutationReturnType<TData, TError, TVariables, TContext> & {
104
+ inputData: Ref<TVariables>;
105
+ mutate: (variables?: TVariables) => void;
106
+ mutateAsync: (variables?: TVariables) => Promise<TData>;
107
+ };
108
+ <TData = unknown, TError = Error, TVariables = void, TContext = unknown>(optionsFn: (orpc: TOrpc) => MutationObserverOptions<TData, TError, TVariables, TContext>): UseMutationReturnType<TData, TError, TVariables, TContext>;
109
+ };
110
+ useSubscription: <TInput, TEvent>(input: MaybeRefOrGetter<TInput>, subscribeFn: OrpcSubscribeFn<TInput, TEvent, TOrpc>, options?: UseSubscriptionOptions<TEvent, TOrpc>) => UseSubscriptionReturn<TEvent>;
111
+ invalidate: (keyFn: (orpc: TOrpc) => QueryKey, filters?: Omit<InvalidateQueryFilters, 'queryKey'>) => Promise<void>;
112
+ /** Route preloading and hover-to-prefetch. */
113
+ prefetch: <TQueryFnData, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(optionsFn: (orpc: TOrpc) => FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>) => Promise<void>;
114
+ /** Data is typed from oRPC's tagged key; pass `<TData>` for an untagged one. */
115
+ getQueryData: <TData = never, TKey extends QueryKey = QueryKey>(keyFn: (orpc: TOrpc) => TKey) => CachedData<TData, TKey> | undefined;
116
+ /** Optimistic updates, typed like `getQueryData`. */
117
+ setQueryData: <TData = never, TKey extends QueryKey = QueryKey>(keyFn: (orpc: TOrpc) => TKey, updater: Updater<CachedData<TData, TKey> | undefined, CachedData<TData, TKey> | undefined>) => NoInfer<CachedData<TData, TKey>> | undefined;
118
+ cancelQueries: (keyFn: (orpc: TOrpc) => QueryKey) => Promise<void>;
119
+ removeQueries: (keyFn: (orpc: TOrpc) => QueryKey) => void;
120
+ isFetching: (keyFn?: (orpc: TOrpc) => QueryKey) => number;
121
+ queryClient: import("@tanstack/vue-query").QueryClient;
122
+ };
123
+ type ApplyEvent<TStreamEvent, TData> = (event: TStreamEvent, previous: TData | undefined) => TData | undefined;
124
+ type LiveQueryOptions<TInput, TRouteData, TStreamEvent, TData, TOrpc, TSubscriptionInput> = {
125
+ immediate?: MaybeRefOrGetter<boolean>;
126
+ orpc?: MaybeRefOrGetter<TOrpc>;
127
+ /** Input for the stream when it differs from the query's. */
128
+ subscriptionInput?: MaybeRefOrGetter<TSubscriptionInput>;
129
+ /**
130
+ * Convert the route output once at fetch time into a differently typed
131
+ * cache; `applyEvent` then reduces stream events into that cache.
132
+ */
133
+ select?: (data: TRouteData) => TData;
134
+ /**
135
+ * The raw route output of a seed before `select` drops fields. `input` is
136
+ * what the seed was fetched for, so a seed that resolves after the input
137
+ * moved on can be told apart.
138
+ */
139
+ onSeed?: (data: TRouteData, input: TInput) => void;
140
+ /**
141
+ * Fold a stream event into the cached data. Required when the stream sends
142
+ * something other than the cached type (an `fnLive` patch route, or a
143
+ * `select`ed cache). Return `undefined` to skip the write.
144
+ */
145
+ applyEvent?: ApplyEvent<TStreamEvent, NoInfer<TData>>;
146
+ onEvent?: (event: TStreamEvent, meta?: {
147
+ connectionId: number;
148
+ }) => void;
149
+ onError?: (error: Error) => void;
150
+ /**
151
+ * Reconcile a fetched seed with what the stream already wrote. The HTTP
152
+ * request can resolve last, so a plain overwrite would drop events that
153
+ * arrived while it was in flight. Default: take the fetched value.
154
+ */
155
+ mergeSeed?: (fetched: NoInfer<TData>, cached: NoInfer<TData> | undefined) => NoInfer<TData>;
156
+ /**
157
+ * Show the previous key's data while a new key loads (default: true). Pass
158
+ * false when the key says which entity is shown, not just how it is
159
+ * filtered: another conversation's timeline must not stand in for this one.
160
+ */
161
+ keepPreviousData?: boolean;
162
+ /** Pause the stream while the page is hidden (default: true). */
163
+ respectVisibility?: boolean;
164
+ };
165
+ type LiveQueryReturn<TData, TError> = ReturnType<typeof useVueQuery<TData, TError>> & {
166
+ liveStatus: Ref<LiveConnectionStatus>;
167
+ };
168
+ /**
169
+ * The client half of `fnLive`: the HTTP query seeds the cache, and the live
170
+ * route's stream writes each snapshot into the same cache entry. Marked
171
+ * `meta.live`, so invalidation streams leave it alone.
172
+ *
173
+ * One signature, not overloads: TypeScript fixes an untyped callback's
174
+ * parameters at the first overload it tries, which made valid calls fail.
175
+ */
176
+ export declare function useLiveQuery<TInput, TRouteData, TStreamEvent, TData = TRouteData, TError = Error, TOrpc = RegisteredOrpcUtils, TSubscriptionInput = TInput>(input: MaybeRefOrGetter<TInput>, queryOptionsFn: (input: TInput, orpc: TOrpc) => UseQueryOptions<TRouteData, TError> & {
177
+ queryKey: QueryKey;
178
+ }, subscribeFn: OrpcSubscribeFn<NoInfer<TSubscriptionInput>, TStreamEvent, TOrpc>, ...options: [TStreamEvent] extends [TData] ? [
179
+ options?: LiveQueryOptions<TInput, TRouteData, TStreamEvent, TData, TOrpc, TSubscriptionInput>
180
+ ] : [
181
+ options: LiveQueryOptions<TInput, TRouteData, TStreamEvent, TData, TOrpc, TSubscriptionInput> & {
182
+ applyEvent: ApplyEvent<TStreamEvent, NoInfer<TData>>;
183
+ }
184
+ ]): LiveQueryReturn<TData, TError>;
185
+ /**
186
+ * Treat a stream as a "something changed" ping: invalidate `keyFn` on each
187
+ * event. Prefer {@link useLiveQuery} when the stream carries the data itself.
188
+ */
189
+ export declare function useSubscriptionInvalidates<TInput, TEvent, TOrpc = RegisteredOrpcUtils>(input: MaybeRefOrGetter<TInput>, subscribeFn: OrpcSubscribeFn<TInput, TEvent, TOrpc>, keyFn: (orpc: TOrpc) => QueryKey, options?: Pick<UseSubscriptionOptions<TEvent, TOrpc>, 'immediate' | 'maxEvents' | 'respectVisibility' | 'orpc'> & {
190
+ onEvent?: (event: TEvent) => void;
191
+ /** Return false to skip invalidation for this event. */
192
+ shouldInvalidate?: (event: TEvent) => boolean;
193
+ }): UseSubscriptionReturn<TEvent>;
194
+ /**
195
+ * One app-wide stream of `{ domain }` change events that keeps list and count
196
+ * queries fresh: each event invalidates its domain's query keys (debounced),
197
+ * and a reconnect that proves healthy invalidates every domain to cover
198
+ * events lost while it was down. Call once, in the signed-in shell.
199
+ *
200
+ * ```ts
201
+ * useInvalidationStream({}, (o) => o.realtime.subscribeChanges.call, {
202
+ * domains: { order: { debounceMs: 100, queryKeys: [orpc.order.key()] } }
203
+ * })
204
+ * ```
205
+ */
206
+ export declare function useInvalidationStream<TInput, TEvent extends {
207
+ domain: string;
208
+ }, TOrpc = RegisteredOrpcUtils>(input: MaybeRefOrGetter<TInput>, subscribe: OrpcSubscribeFn<TInput, TEvent, TOrpc>, options: InvalidationStreamOptions<TEvent> & Pick<UseSubscriptionOptions<TEvent, TOrpc>, 'immediate' | 'respectVisibility' | 'orpc'>): UseSubscriptionReturn<TEvent>;
209
+ /** Localized text for a failed query: your fallback unless the server marked its message user-safe. */
210
+ export declare function useQueryErrorMessage(error: MaybeRefOrGetter<unknown>, fallback: MaybeRefOrGetter<string>): import("vue").ComputedRef<string | null>;
211
+ //# sourceMappingURL=vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../src/vue.ts"],"names":[],"mappings":"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"}
package/dist/vue.js ADDED
@@ -0,0 +1,312 @@
1
+ import { focusManager, hashKey, keepPreviousData, useInfiniteQuery as useVueInfiniteQuery, useMutation as useVueMutation, useQuery as useVueQuery, useQueryClient } from '@tanstack/vue-query';
2
+ import { computed, getCurrentScope, hasInjectionContext, inject, onScopeDispose, ref, shallowRef, toValue, watch } from 'vue';
3
+ import { userFacingErrorMessage } from './client.js';
4
+ import { createInvalidationCoordinator, createStreamScope, createSubscriptionRunner, seedQueryFn } from './realtime.js';
5
+ const orpcKey = Symbol('orpc-fn');
6
+ /**
7
+ * Make an oRPC client and its TanStack Query utils the app's default. A
8
+ * surface that talks to another API (an embed with its own auth) passes
9
+ * `orpc` to each composable instead and never needs this.
10
+ */
11
+ export function provideOrpc(app, orpc) {
12
+ app.provide(orpcKey, orpc);
13
+ }
14
+ const missingOrpc = () => new Error('orpc-fn/vue: no oRPC client provided. Call provideOrpc(app, { client, utils }) or pass `orpc` to the composable.');
15
+ /** The client and utils from {@link provideOrpc}. */
16
+ export function useOrpc() {
17
+ const provided = hasInjectionContext() ? inject(orpcKey, null) : null;
18
+ if (!provided)
19
+ throw missingOrpc();
20
+ return provided;
21
+ }
22
+ /** Resolve the provided utils now; fail only when they are needed and missing. */
23
+ function useUtilsGetter(explicit) {
24
+ if (explicit)
25
+ return () => toValue(explicit);
26
+ const provided = hasInjectionContext() ? inject(orpcKey, null) : null;
27
+ return () => {
28
+ if (!provided)
29
+ throw missingOrpc();
30
+ return provided.utils;
31
+ };
32
+ }
33
+ let documentVisible = null;
34
+ /**
35
+ * Whether the page is visible, from TanStack's `focusManager` (which follows
36
+ * `visibilitychange` in browsers). Live streams pause while it is false.
37
+ */
38
+ function useDocumentVisible() {
39
+ if (!documentVisible) {
40
+ const visible = ref(focusManager.isFocused());
41
+ focusManager.subscribe((focused) => {
42
+ visible.value = focused;
43
+ });
44
+ documentVisible = visible;
45
+ }
46
+ return documentVisible;
47
+ }
48
+ function resolveQueryEnabled(enabled) {
49
+ if (enabled === undefined)
50
+ return true;
51
+ if (typeof enabled === 'function')
52
+ return Boolean(enabled());
53
+ return Boolean(toValue(enabled));
54
+ }
55
+ /**
56
+ * An oRPC event iterator as reactive state, with backoff reconnects and a
57
+ * pause while the page is hidden. Closed when the owning effect scope stops.
58
+ */
59
+ export function useOrpcSubscription(input, subscribeFn, options = {}) {
60
+ const { immediate = true, maxEvents = 100, autoReconnectOnInputChange = true, autoReconnectOnClose = true, respectVisibility = true } = options;
61
+ const getUtils = useUtilsGetter(options.orpc);
62
+ const visible = useDocumentVisible();
63
+ // May a stream run at all? This gates a manual connect() too.
64
+ const isStreamAllowed = computed(() => !respectVisibility || visible.value);
65
+ // Should it start on its own? That is what `immediate` means.
66
+ const shouldAutoConnect = computed(() => toValue(immediate) && isStreamAllowed.value);
67
+ // Shallow: event payloads are replaced, never mutated, so deep proxies are wasted work.
68
+ const events = shallowRef([]);
69
+ const latestEvent = shallowRef(undefined);
70
+ const status = ref('idle');
71
+ const error = ref(null);
72
+ const runner = createSubscriptionRunner({
73
+ open: (signal) => subscribeFn(getUtils())(toValue(input), { signal }),
74
+ canConnect: () => isStreamAllowed.value,
75
+ shouldReconnect: () => autoReconnectOnClose && shouldAutoConnect.value,
76
+ onStatus: (next) => {
77
+ status.value = next;
78
+ if (next === 'connecting')
79
+ error.value = null;
80
+ },
81
+ onEvent: (event, connectionId) => {
82
+ latestEvent.value = event;
83
+ if (maxEvents > 1) {
84
+ events.value = [...events.value.slice(-(maxEvents - 1)), event];
85
+ }
86
+ options.onEvent?.(event, { connectionId });
87
+ },
88
+ onError: (err) => {
89
+ error.value = err;
90
+ options.onError?.(err);
91
+ },
92
+ onConnect: options.onConnect,
93
+ onClose: options.onClose
94
+ });
95
+ function clearEvents() {
96
+ events.value = [];
97
+ latestEvent.value = undefined;
98
+ }
99
+ if (autoReconnectOnInputChange) {
100
+ watch(() => toValue(input), async () => {
101
+ const wasLive = runner.isLive();
102
+ if (runner.getStatus() !== 'idle') {
103
+ await runner.disconnect();
104
+ clearEvents();
105
+ }
106
+ // Reconnect in auto mode, or in manual mode when it was running.
107
+ if (shouldAutoConnect.value || (wasLive && isStreamAllowed.value)) {
108
+ await runner.start();
109
+ }
110
+ }, { deep: true });
111
+ }
112
+ // Visibility closes the stream in both modes; only the re-open waits for `immediate`.
113
+ watch(isStreamAllowed, (allowed) => {
114
+ if (!allowed)
115
+ void runner.disconnect();
116
+ else if (toValue(immediate)) {
117
+ error.value = null;
118
+ void runner.start();
119
+ }
120
+ }, { immediate: true });
121
+ watch(() => toValue(immediate), (auto) => {
122
+ if (!auto)
123
+ void runner.disconnect();
124
+ else if (isStreamAllowed.value) {
125
+ error.value = null;
126
+ void runner.start();
127
+ }
128
+ });
129
+ // A detached effect scope may own the stream, not just a component.
130
+ if (getCurrentScope())
131
+ onScopeDispose(() => void runner.dispose());
132
+ return {
133
+ events,
134
+ latestEvent,
135
+ status,
136
+ error,
137
+ isConnected: computed(() => status.value === 'connected'),
138
+ connect: runner.connect,
139
+ disconnect: runner.disconnect,
140
+ clearEvents
141
+ };
142
+ }
143
+ /**
144
+ * TanStack Query composables that receive the oRPC utils, so call sites read
145
+ * `useQuery((o) => o.order.get.queryOptions({ input }))`. Pass `orpc` to bind
146
+ * another client than the provided one.
147
+ */
148
+ export function useApiClient(clientOptions) {
149
+ const queryClient = useQueryClient();
150
+ const getO = useUtilsGetter(clientOptions?.orpc);
151
+ // Each wrapper forwards TanStack's own generics, so `select`, typed errors,
152
+ // page params and oRPC's tagged keys infer exactly as with vue-query itself.
153
+ function useQuery(optionsFn) {
154
+ // A computed is a ref at runtime; TypeScript cannot relate a computed of
155
+ // the generic options to vue-query's MaybeRef parameter, so it is asserted.
156
+ const options = computed(() => optionsFn(getO()));
157
+ return useVueQuery(options);
158
+ }
159
+ /** `useInfiniteQuery((o) => o.order.list.infiniteOptions({ input, initialPageParam, getNextPageParam }))` */
160
+ function useInfiniteQuery(optionsFn) {
161
+ const options = computed(() => optionsFn(getO()));
162
+ return useVueInfiniteQuery(options);
163
+ }
164
+ function useMutation(optionsFn, config) {
165
+ const mutation = useVueMutation(computed(() => optionsFn(getO())));
166
+ if (config?.initialInput === undefined)
167
+ return mutation;
168
+ const inputData = ref(config.initialInput);
169
+ return {
170
+ ...mutation,
171
+ inputData,
172
+ mutate: (variables) => mutation.mutate(variables ?? inputData.value),
173
+ mutateAsync: (variables) => mutation.mutateAsync(variables ?? inputData.value)
174
+ };
175
+ }
176
+ function useSubscription(input, subscribeFn, options = {}) {
177
+ return useOrpcSubscription(input, subscribeFn, {
178
+ ...options,
179
+ orpc: getO
180
+ });
181
+ }
182
+ const keyOf = (keyFn) => keyFn(getO());
183
+ return {
184
+ useQuery,
185
+ useInfiniteQuery,
186
+ useMutation,
187
+ useSubscription,
188
+ invalidate: (keyFn, filters) => queryClient.invalidateQueries({ queryKey: keyOf(keyFn), ...filters }),
189
+ /** Route preloading and hover-to-prefetch. */
190
+ prefetch: (optionsFn) => queryClient.prefetchQuery(optionsFn(getO())),
191
+ /** Data is typed from oRPC's tagged key; pass `<TData>` for an untagged one. */
192
+ getQueryData: (keyFn) => queryClient.getQueryData(keyOf(keyFn)),
193
+ /** Optimistic updates, typed like `getQueryData`. */
194
+ setQueryData: (keyFn, updater) => queryClient.setQueryData(keyOf(keyFn), updater),
195
+ cancelQueries: (keyFn) => queryClient.cancelQueries({ queryKey: keyOf(keyFn) }),
196
+ removeQueries: (keyFn) => queryClient.removeQueries({ queryKey: keyOf(keyFn) }),
197
+ isFetching: (keyFn) => queryClient.isFetching(keyFn ? { queryKey: keyOf(keyFn) } : {}),
198
+ queryClient
199
+ };
200
+ }
201
+ export function useLiveQuery(input, queryOptionsFn, subscribeFn, options = {}) {
202
+ const queryClient = useQueryClient();
203
+ const getO = useUtilsGetter(options.orpc);
204
+ const visible = useDocumentVisible();
205
+ // Without `applyEvent` the stream event is the cache type (the first overload).
206
+ const applyEvent = options.applyEvent ?? ((event) => event);
207
+ // Recomputed when the input changes, not once per stream event.
208
+ const queryKey = computed(() => queryOptionsFn(toValue(input), getO()).queryKey);
209
+ const queryHash = computed(() => hashKey(queryKey.value));
210
+ const scope = createStreamScope();
211
+ const subscription = useOrpcSubscription(computed(() => (options.subscriptionInput === undefined
212
+ ? toValue(input)
213
+ : toValue(options.subscriptionInput))), subscribeFn, {
214
+ immediate: options.immediate,
215
+ respectVisibility: options.respectVisibility,
216
+ onError: options.onError,
217
+ maxEvents: 1,
218
+ orpc: getO,
219
+ onConnect: (connectionId) => scope.open(connectionId, queryHash.value),
220
+ onEvent: (event, meta) => {
221
+ // The consumer callback must not see an event for a scope no longer shown.
222
+ if (!meta || !scope.owns(meta.connectionId, queryHash.value))
223
+ return;
224
+ const key = queryKey.value;
225
+ const next = applyEvent(event, queryClient.getQueryData(key));
226
+ if (next !== undefined)
227
+ queryClient.setQueryData(key, next);
228
+ options.onEvent?.(event, meta);
229
+ }
230
+ });
231
+ const query = useVueQuery(computed(() => {
232
+ const inputValue = toValue(input);
233
+ // oRPC query options are plain objects at runtime; vue-query's type
234
+ // wraps fields in MaybeRefDeep, so `queryFn` is read through one shape.
235
+ const raw = queryOptionsFn(inputValue, getO());
236
+ const wrapsSeed = options.select || options.mergeSeed;
237
+ const queryFn = raw.queryFn && wrapsSeed
238
+ ? seedQueryFn(raw.queryFn, {
239
+ input: inputValue,
240
+ readCache: () => queryClient.getQueryData(raw.queryKey),
241
+ select: options.select,
242
+ onSeed: options.onSeed,
243
+ mergeSeed: options.mergeSeed
244
+ })
245
+ : raw.queryFn;
246
+ return {
247
+ ...raw,
248
+ ...(queryFn ? { queryFn } : {}),
249
+ enabled: visible.value && resolveQueryEnabled(raw.enabled),
250
+ ...(options.keepPreviousData === false
251
+ ? {}
252
+ : { placeholderData: keepPreviousData }),
253
+ staleTime: Number.POSITIVE_INFINITY,
254
+ meta: { live: true }
255
+ };
256
+ }));
257
+ return Object.assign(query, { liveStatus: subscription.status });
258
+ }
259
+ /**
260
+ * Treat a stream as a "something changed" ping: invalidate `keyFn` on each
261
+ * event. Prefer {@link useLiveQuery} when the stream carries the data itself.
262
+ */
263
+ export function useSubscriptionInvalidates(input, subscribeFn, keyFn, options = {}) {
264
+ const { onEvent, shouldInvalidate, ...subscriptionOptions } = options;
265
+ const { useSubscription, invalidate } = useApiClient({
266
+ orpc: options.orpc
267
+ });
268
+ return useSubscription(input, subscribeFn, {
269
+ ...subscriptionOptions,
270
+ onEvent: (event) => {
271
+ onEvent?.(event);
272
+ if (shouldInvalidate?.(event) === false)
273
+ return;
274
+ void invalidate(keyFn);
275
+ }
276
+ });
277
+ }
278
+ /**
279
+ * One app-wide stream of `{ domain }` change events that keeps list and count
280
+ * queries fresh: each event invalidates its domain's query keys (debounced),
281
+ * and a reconnect that proves healthy invalidates every domain to cover
282
+ * events lost while it was down. Call once, in the signed-in shell.
283
+ *
284
+ * ```ts
285
+ * useInvalidationStream({}, (o) => o.realtime.subscribeChanges.call, {
286
+ * domains: { order: { debounceMs: 100, queryKeys: [orpc.order.key()] } }
287
+ * })
288
+ * ```
289
+ */
290
+ export function useInvalidationStream(input, subscribe, options) {
291
+ const coordinator = createInvalidationCoordinator(useQueryClient(), options);
292
+ if (getCurrentScope())
293
+ onScopeDispose(coordinator.dispose);
294
+ return useOrpcSubscription(input, subscribe, {
295
+ immediate: options.immediate,
296
+ respectVisibility: options.respectVisibility,
297
+ orpc: options.orpc,
298
+ maxEvents: 1,
299
+ onEvent: coordinator.event,
300
+ onConnect: coordinator.connect,
301
+ onError: coordinator.lost,
302
+ onClose: coordinator.lost
303
+ });
304
+ }
305
+ /** Localized text for a failed query: your fallback unless the server marked its message user-safe. */
306
+ export function useQueryErrorMessage(error, fallback) {
307
+ return computed(() => {
308
+ const err = toValue(error);
309
+ return err ? userFacingErrorMessage(err, toValue(fallback)) : null;
310
+ });
311
+ }
312
+ //# sourceMappingURL=vue.js.map