orpc-fn 0.4.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.
- package/README.md +146 -4
- package/dist/client.d.ts +29 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +49 -0
- package/dist/client.js.map +1 -1
- package/dist/create-fn.d.ts.map +1 -1
- package/dist/create-fn.js +0 -1
- package/dist/create-fn.js.map +1 -1
- package/dist/hono.d.ts +12 -1
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +15 -1
- package/dist/hono.js.map +1 -1
- package/dist/live/fn-live.d.ts +1 -6
- package/dist/live/fn-live.d.ts.map +1 -1
- package/dist/live/fn-live.js +2 -18
- package/dist/live/fn-live.js.map +1 -1
- package/dist/live/index.d.ts +3 -1
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js +2 -0
- package/dist/live/index.js.map +1 -1
- package/dist/live/invalidation-stream.d.ts +52 -0
- package/dist/live/invalidation-stream.d.ts.map +1 -0
- package/dist/live/invalidation-stream.js +98 -0
- package/dist/live/invalidation-stream.js.map +1 -0
- package/dist/live/ioredis.d.ts +1 -0
- package/dist/live/ioredis.d.ts.map +1 -1
- package/dist/live/ioredis.js +1 -0
- package/dist/live/ioredis.js.map +1 -1
- package/dist/live/memory.d.ts +2 -1
- package/dist/live/memory.d.ts.map +1 -1
- package/dist/live/memory.js +6 -1
- package/dist/live/memory.js.map +1 -1
- package/dist/live/pub-sub.d.ts +5 -0
- package/dist/live/pub-sub.d.ts.map +1 -1
- package/dist/live/pub-sub.js +16 -3
- package/dist/live/pub-sub.js.map +1 -1
- package/dist/live/redis-bun.d.ts +3 -0
- package/dist/live/redis-bun.d.ts.map +1 -1
- package/dist/live/redis-bun.js +1 -0
- package/dist/live/redis-bun.js.map +1 -1
- package/dist/live/redis.d.ts +4 -1
- package/dist/live/redis.d.ts.map +1 -1
- package/dist/live/redis.js +14 -2
- package/dist/live/redis.js.map +1 -1
- package/dist/live/scoped-change-bus.d.ts +45 -0
- package/dist/live/scoped-change-bus.d.ts.map +1 -0
- package/dist/live/scoped-change-bus.js +38 -0
- package/dist/live/scoped-change-bus.js.map +1 -0
- package/dist/live/transport.d.ts +11 -0
- package/dist/live/transport.d.ts.map +1 -1
- package/dist/live/transport.js.map +1 -1
- package/dist/procedure-cli.d.ts +25 -0
- package/dist/procedure-cli.d.ts.map +1 -0
- package/dist/procedure-cli.js +67 -0
- package/dist/procedure-cli.js.map +1 -0
- package/dist/react.d.ts +116 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +156 -0
- package/dist/react.js.map +1 -0
- package/dist/realtime.d.ts +114 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/realtime.js +316 -0
- package/dist/realtime.js.map +1 -0
- package/dist/vue/testing.d.ts +67 -0
- package/dist/vue/testing.d.ts.map +1 -0
- package/dist/vue/testing.js +225 -0
- package/dist/vue/testing.js.map +1 -0
- package/dist/vue.d.ts +211 -0
- package/dist/vue.d.ts.map +1 -0
- package/dist/vue.js +312 -0
- package/dist/vue.js.map +1 -0
- package/package.json +51 -3
- package/src/client.ts +57 -0
- package/src/create-fn.ts +0 -1
- package/src/hono.ts +22 -2
- package/src/live/fn-live.ts +3 -22
- package/src/live/index.ts +12 -1
- package/src/live/invalidation-stream.ts +142 -0
- package/src/live/ioredis.ts +2 -0
- package/src/live/memory.ts +11 -2
- package/src/live/pub-sub.ts +23 -2
- package/src/live/redis-bun.ts +3 -0
- package/src/live/redis.ts +33 -6
- package/src/live/scoped-change-bus.ts +98 -0
- package/src/live/transport.ts +12 -0
- package/src/procedure-cli.ts +99 -0
- package/src/react.ts +355 -0
- package/src/realtime.ts +416 -0
- package/src/vue/testing.ts +296 -0
- package/src/vue.ts +783 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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","sourcesContent":["// Framework-free subscription and invalidation logic shared by `orpc-fn/vue`\n// and `orpc-fn/react`. Not a public subpath: each framework wraps it.\nimport type { FnLogger } from './logger.js'\n\nexport type LiveConnectionStatus =\n\t| 'idle'\n\t| 'connecting'\n\t| 'connected'\n\t| 'error'\n\t| 'closed'\n\nconst BASE_RECONNECT_DELAY_MS = 1000\nconst MAX_RECONNECT_DELAY_MS = 15_000\n\n/**\n * Backoff for attempt N (1-based): exponential from 1s capped at 15s, plus\n * 0-25% jitter so a fleet of clients doesn't thundering-herd a recovering\n * server. The delay is capped, never the attempts: a dead network keeps\n * retrying at the ceiling instead of killing the stream for good.\n */\nexport function nextReconnectDelayMs(\n\terrorCount: number,\n\trandom: () => number = Math.random\n): number {\n\tconst attempt = Math.max(1, errorCount)\n\tconst base = Math.min(\n\t\tBASE_RECONNECT_DELAY_MS * 2 ** (attempt - 1),\n\t\tMAX_RECONNECT_DELAY_MS\n\t)\n\treturn Math.round(base + base * 0.25 * random())\n}\n\ntype SubscriptionRunnerOptions<TEvent> = {\n\topen: (signal: AbortSignal) => Promise<AsyncIterable<TEvent>>\n\tonEvent: (event: TEvent, connectionId: number) => void\n\tonStatus: (status: LiveConnectionStatus) => void\n\tonConnect?: ((connectionId: number) => void) | undefined\n\tonError?: ((error: Error) => void) | undefined\n\tonClose?: (() => void) | undefined\n\t/** May a stream run at all right now (e.g. the app is in the foreground)? */\n\tcanConnect: () => boolean\n\t/** Reconnect with backoff after an unexpected end? Checked when scheduling and firing. */\n\tshouldReconnect: () => boolean\n}\n\nexport type SubscriptionRunner = ReturnType<typeof createSubscriptionRunner>\n\n/**\n * One oRPC event-iterator stream with generation-guarded connects, abortable\n * teardown and backoff reconnects. Every connect claims a new connection id;\n * a superseded attempt closes its own iterator and never reports events.\n */\nexport function createSubscriptionRunner<TEvent>(\n\toptions: SubscriptionRunnerOptions<TEvent>\n) {\n\tlet status: LiveConnectionStatus = 'idle'\n\tlet abortController: AbortController | null = null\n\tlet iterator: AsyncIterator<TEvent> | null = null\n\tlet connectPromise: Promise<void> | null = null\n\tlet activeConnectionId = 0\n\t/** Set by deliberate teardown so stream-end does not schedule a retry. */\n\tlet intentionalDisconnect = false\n\tlet errorCount = 0\n\tlet reconnectTimer: ReturnType<typeof setTimeout> | null = null\n\tlet disposed = false\n\n\tconst setStatus = (next: LiveConnectionStatus) => {\n\t\tstatus = next\n\t\toptions.onStatus(next)\n\t}\n\n\tfunction clearReconnectTimer() {\n\t\tif (reconnectTimer === null) return\n\t\tclearTimeout(reconnectTimer)\n\t\treconnectTimer = null\n\t}\n\n\tfunction scheduleReconnect() {\n\t\tif (intentionalDisconnect || disposed || reconnectTimer !== null) return\n\t\tif (!options.shouldReconnect()) return\n\t\treconnectTimer = setTimeout(() => {\n\t\t\treconnectTimer = null\n\t\t\tif (disposed || intentionalDisconnect || !options.shouldReconnect())\n\t\t\t\treturn\n\t\t\tvoid connect()\n\t\t}, nextReconnectDelayMs(errorCount))\n\t}\n\n\tfunction handleUnexpectedEnd(error: Error | null) {\n\t\terrorCount += 1\n\t\t// Close the socket of a failed stream; on React Native an unaborted\n\t\t// expo/fetch request keeps holding a connection from the device's pool.\n\t\tabortController?.abort()\n\t\tabortController = null\n\t\titerator = null\n\t\tif (error) {\n\t\t\tsetStatus('error')\n\t\t\toptions.onError?.(error)\n\t\t} else {\n\t\t\tsetStatus('closed')\n\t\t\toptions.onClose?.()\n\t\t}\n\t\tscheduleReconnect()\n\t}\n\n\tasync function connect(): Promise<void> {\n\t\tif (disposed || !options.canConnect()) return\n\t\tif (connectPromise) return connectPromise\n\t\tif (status === 'connected' || reconnectTimer !== null) return\n\n\t\tintentionalDisconnect = false\n\t\tconst thisConnect = (async () => {\n\t\t\tsetStatus('connecting')\n\t\t\t// Claim the generation and controller before awaiting, so a\n\t\t\t// disconnect while opening supersedes this attempt.\n\t\t\tconst controller = new AbortController()\n\t\t\tabortController = controller\n\t\t\tconst connectionId = ++activeConnectionId\n\t\t\ttry {\n\t\t\t\tconst iterable = await options.open(controller.signal)\n\t\t\t\tconst localIterator = iterable[Symbol.asyncIterator]()\n\t\t\t\tif (connectionId !== activeConnectionId || controller.signal.aborted) {\n\t\t\t\t\tawait closeIterator(localIterator)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\titerator = localIterator\n\t\t\t\tsetStatus('connected')\n\t\t\t\toptions.onConnect?.(connectionId)\n\t\t\t\tvoid consume(localIterator, connectionId)\n\t\t\t} catch (error) {\n\t\t\t\tif (connectionId !== activeConnectionId || controller.signal.aborted)\n\t\t\t\t\treturn\n\t\t\t\thandleUnexpectedEnd(toError(error))\n\t\t\t}\n\t\t})()\n\t\tconnectPromise = thisConnect\n\t\ttry {\n\t\t\tawait thisConnect\n\t\t} finally {\n\t\t\tif (connectPromise === thisConnect) connectPromise = null\n\t\t}\n\t}\n\n\tasync function consume(\n\t\tlocalIterator: AsyncIterator<TEvent>,\n\t\tconnectionId: number\n\t) {\n\t\ttry {\n\t\t\twhile (status === 'connected' && connectionId === activeConnectionId) {\n\t\t\t\tconst result = await localIterator.next()\n\t\t\t\tif (status !== 'connected' || connectionId !== activeConnectionId)\n\t\t\t\t\treturn\n\t\t\t\tif (result.done) {\n\t\t\t\t\t// Proxy or idle end after a live connect: recoverable.\n\t\t\t\t\tif (!intentionalDisconnect) handleUnexpectedEnd(null)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Reset backoff only once the stream delivers. A server that accepts\n\t\t\t\t// and then dies before yielding must keep escalating.\n\t\t\t\terrorCount = 0\n\t\t\t\toptions.onEvent(result.value, connectionId)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (connectionId !== activeConnectionId) return\n\t\t\tif (abortController?.signal.aborted || intentionalDisconnect) {\n\t\t\t\tsetStatus('closed')\n\t\t\t\toptions.onClose?.()\n\t\t\t\treturn\n\t\t\t}\n\t\t\thandleUnexpectedEnd(toError(error))\n\t\t}\n\t}\n\n\tasync function disconnect(): Promise<void> {\n\t\tintentionalDisconnect = true\n\t\tclearReconnectTimer()\n\t\tif (status === 'idle') return\n\n\t\tactiveConnectionId++\n\t\tabortController?.abort()\n\t\t// A fresh connect() may start while the superseded attempt winds down.\n\t\tconnectPromise = null\n\t\tconst localIterator = iterator\n\t\titerator = null\n\t\tabortController = null\n\t\tif (status !== 'closed') {\n\t\t\tsetStatus('closed')\n\t\t\toptions.onClose?.()\n\t\t}\n\t\tawait closeIterator(localIterator)\n\t}\n\n\treturn {\n\t\tconnect,\n\t\tdisconnect,\n\t\t/** Connect with a fresh retry budget (input change, foreground, re-enable). */\n\t\tstart() {\n\t\t\terrorCount = 0\n\t\t\tintentionalDisconnect = false\n\t\t\treturn connect()\n\t\t},\n\t\t/** Connected, connecting, or waiting to reconnect. */\n\t\tisLive: () =>\n\t\t\tstatus === 'connected' ||\n\t\t\tstatus === 'connecting' ||\n\t\t\treconnectTimer !== null,\n\t\tgetStatus: () => status,\n\t\tdispose() {\n\t\t\tdisposed = true\n\t\t\treturn disconnect()\n\t\t}\n\t}\n}\n\nasync function closeIterator<T>(iterator: AsyncIterator<T> | null) {\n\ttry {\n\t\tawait iterator?.return?.(undefined)\n\t} catch {\n\t\t// Cleanup errors are not the caller's concern.\n\t}\n}\n\nconst toError = (error: unknown) =>\n\terror instanceof Error ? error : new Error(String(error))\n\ntype QueryKeyLike = readonly unknown[]\n\n/** The part of a TanStack `QueryClient` the coordinator uses. */\ntype InvalidatingQueryClient = {\n\tinvalidateQueries(filters: {\n\t\tqueryKey: QueryKeyLike\n\t\trefetchType?: 'active' | 'inactive' | 'all' | 'none'\n\t\tpredicate?: (query: {\n\t\t\tmeta?: Record<string, unknown> | undefined\n\t\t}) => boolean\n\t}): Promise<unknown>\n}\n\nexport type InvalidationDomain = {\n\t/**\n\t * Batch a burst of events into one invalidation (ms). The window runs from\n\t * the first event, so a steady stream cannot postpone the refresh forever.\n\t */\n\tdebounceMs?: number\n\tqueryKeys: readonly QueryKeyLike[]\n}\n\nexport type InvalidationStreamOptions<TEvent extends { domain: string }> = {\n\t/** Query keys to invalidate per event `domain`. Unmapped domains are ignored. */\n\tdomains: { [K in TEvent['domain']]?: InvalidationDomain }\n\t/**\n\t * Passed to `invalidateQueries`. Default: TanStack's `'active'`, which marks\n\t * inactive queries stale so they refetch on their next use. `'all'` also\n\t * refetches every cached query of the domain now, on each event.\n\t */\n\trefetchType?: 'active' | 'inactive' | 'all' | 'none'\n\t/** Every event, after its domain is invalidated (alerts, chimes). */\n\tonEvent?: (event: TEvent) => void\n\t/** Receives one `invalidation_stream.disconnected` warning per minute at most. */\n\tlogger?: Pick<FnLogger, 'warn'>\n}\n\n/**\n * How long a reconnected stream must stay up, having delivered nothing, before\n * it counts as working. Waiting for an event alone would leave a quiet\n * reconnect stale until the next change; not waiting at all lets a stream that\n * dies the instant it opens refetch everything once per retry.\n */\nconst SETTLE_MS = 1_500\nconst DISCONNECT_LOG_INTERVAL_MS = 60_000\n\n/**\n * Turns a stream of `{ domain }` change events into debounced\n * `invalidateQueries` calls. Live queries (`meta.live`) are skipped: their own\n * stream keeps them current. Events published while the stream was down are\n * lost, so a reconnect that proves healthy invalidates every mapped domain.\n */\nexport function createInvalidationCoordinator<\n\tTEvent extends { domain: string }\n>(\n\tqueryClient: InvalidatingQueryClient,\n\toptions: InvalidationStreamOptions<TEvent>\n) {\n\tconst timers = new Map<string, ReturnType<typeof setTimeout>>()\n\tlet settleTimer: ReturnType<typeof setTimeout> | null = null\n\tlet catchUpPending = false\n\tlet lastLostLogAt = Number.NEGATIVE_INFINITY\n\n\tconst domainConfig = (domain: string): InvalidationDomain | undefined =>\n\t\tObject.hasOwn(options.domains, domain)\n\t\t\t? (options.domains as Record<string, InvalidationDomain | undefined>)[\n\t\t\t\t\tdomain\n\t\t\t\t]\n\t\t\t: undefined\n\n\tfunction invalidate(config: InvalidationDomain) {\n\t\tfor (const queryKey of config.queryKeys) {\n\t\t\tvoid queryClient.invalidateQueries({\n\t\t\t\tqueryKey,\n\t\t\t\t...(options.refetchType ? { refetchType: options.refetchType } : {}),\n\t\t\t\tpredicate: (query) => query.meta?.live !== true\n\t\t\t})\n\t\t}\n\t}\n\n\tfunction invalidateAll() {\n\t\tfor (const config of Object.values(options.domains)) {\n\t\t\tif (config) invalidate(config as InvalidationDomain)\n\t\t}\n\t}\n\n\tfunction clearSettleTimer() {\n\t\tif (settleTimer === null) return\n\t\tclearTimeout(settleTimer)\n\t\tsettleTimer = null\n\t}\n\n\tfunction markHealthy() {\n\t\tclearSettleTimer()\n\t\tif (!catchUpPending) return\n\t\tcatchUpPending = false\n\t\tinvalidateAll()\n\t}\n\n\treturn {\n\t\tevent(event: TEvent) {\n\t\t\t// A delivered event proves the connection; no need to wait it out.\n\t\t\tmarkHealthy()\n\n\t\t\t// The stream is typed, but a JavaScript caller or a newer server may send anything.\n\t\t\tconst domain: unknown = (event as { domain?: unknown } | null)?.domain\n\t\t\tif (typeof domain !== 'string') return\n\n\t\t\tconst config = domainConfig(domain)\n\t\t\tconst delay = config?.debounceMs ?? 0\n\t\t\tif (config && delay <= 0) {\n\t\t\t\tinvalidate(config)\n\t\t\t} else if (config && !timers.has(domain)) {\n\t\t\t\tconst timer = setTimeout(() => {\n\t\t\t\t\ttimers.delete(domain)\n\t\t\t\t\tinvalidate(config)\n\t\t\t\t}, delay)\n\t\t\t\ttimers.set(domain, timer)\n\t\t\t}\n\n\t\t\toptions.onEvent?.(event)\n\t\t},\n\t\tconnect(connectionId: number) {\n\t\t\tclearSettleTimer()\n\t\t\tcatchUpPending ||= connectionId > 1\n\t\t\tsettleTimer = setTimeout(markHealthy, SETTLE_MS)\n\t\t},\n\t\tlost() {\n\t\t\t// Reconnecting is the subscription's job; this connection can no longer settle.\n\t\t\tclearSettleTimer()\n\t\t\tconst now = Date.now()\n\t\t\tif (now - lastLostLogAt < DISCONNECT_LOG_INTERVAL_MS) return\n\t\t\tlastLostLogAt = now\n\t\t\toptions.logger?.warn('invalidation_stream.disconnected')\n\t\t},\n\t\tdispose() {\n\t\t\tclearSettleTimer()\n\t\t\tfor (const timer of timers.values()) clearTimeout(timer)\n\t\t\ttimers.clear()\n\t\t\tcatchUpPending = false\n\t\t}\n\t}\n}\n\n/**\n * Which connection and query key the open live stream belongs to. An event\n * counts only while both still match: the input changes synchronously but the\n * stream is torn down asynchronously, so a frame in flight from the previous\n * subscription would otherwise land in the new key (and, with\n * `staleTime: Infinity`, stay there).\n */\nexport function createStreamScope() {\n\tlet openConnectionId: number | null = null\n\tlet openKeyHash: string | null = null\n\treturn {\n\t\topen(connectionId: number, keyHash: string) {\n\t\t\topenConnectionId = connectionId\n\t\t\topenKeyHash = keyHash\n\t\t},\n\t\towns: (connectionId: number, keyHash: string) =>\n\t\t\tconnectionId === openConnectionId && keyHash === openKeyHash\n\t}\n}\n\n/**\n * Wrap a live query's HTTP `queryFn`: report the raw seed, convert it with\n * `select`, and reconcile it with what the stream already wrote. The cache is\n * read after the request resolves, because stream events can arrive while it\n * is in flight.\n */\nexport function seedQueryFn<TRouteData, TData, TInput>(\n\tqueryFn: (context: unknown) => Promise<TRouteData>,\n\toptions: {\n\t\tinput: TInput\n\t\treadCache: () => TData | undefined\n\t\tselect?: ((data: TRouteData) => TData) | undefined\n\t\tonSeed?: ((data: TRouteData, input: TInput) => void) | undefined\n\t\tmergeSeed?:\n\t\t\t| ((fetched: TData, cached: TData | undefined) => TData)\n\t\t\t| undefined\n\t}\n) {\n\tconst { select, onSeed, mergeSeed } = options\n\treturn async (context: unknown): Promise<TData> => {\n\t\tconst fetched = await queryFn(context)\n\t\tonSeed?.(fetched, options.input)\n\t\t// Without `select` the route output is the cache type.\n\t\tconst data = select ? select(fetched) : (fetched as unknown as TData)\n\t\treturn mergeSeed ? mergeSeed(data, options.readCache()) : data\n\t}\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/vue-query';
|
|
2
|
+
type Method = (...args: never[]) => unknown;
|
|
3
|
+
type MockFactory = (implementation: Method) => Method;
|
|
4
|
+
export type OrpcMock<T> = T & {
|
|
5
|
+
/** Reset every method mock created so far (calls `mockReset` when the factory provides it). */
|
|
6
|
+
$reset: () => void;
|
|
7
|
+
};
|
|
8
|
+
export type CreateOrpcMockOptions = {
|
|
9
|
+
/** Wraps each method, e.g. `mock` from `bun:test` or `vi.fn`, so calls can be asserted. */
|
|
10
|
+
fn?: MockFactory;
|
|
11
|
+
/** Namespace `.key()` results (default: `[namespace]`). */
|
|
12
|
+
keys?: Record<string, readonly unknown[]>;
|
|
13
|
+
/** Explicit namespace shapes merged over the auto-mock. */
|
|
14
|
+
overrides?: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* A deep stand-in for oRPC utils or a client: `o.order.key()` is `['order']`,
|
|
18
|
+
* `o.order.get.call()` resolves an empty stream, `.key()`/`.queryKey()` on a
|
|
19
|
+
* procedure return `[]`, and any other method returns `{}`. The same path
|
|
20
|
+
* always returns the same mock, so calls can be asserted. Type it as your
|
|
21
|
+
* utils: `createOrpcMock<typeof orpc>({ fn: mock })`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createOrpcMock<T = Record<string, unknown>>(options?: CreateOrpcMockOptions): OrpcMock<T>;
|
|
24
|
+
export type TestConnection<T> = {
|
|
25
|
+
input: unknown;
|
|
26
|
+
signal: AbortSignal | undefined;
|
|
27
|
+
readonly closed: boolean;
|
|
28
|
+
/** Deliver an event. Resolves once the consumer asked for the next one, or the stream closed. */
|
|
29
|
+
push: (event: T) => Promise<void>;
|
|
30
|
+
/** End the stream normally (`done`). */
|
|
31
|
+
end: () => void;
|
|
32
|
+
/** Fail the stream. */
|
|
33
|
+
fail: (error: Error) => void;
|
|
34
|
+
};
|
|
35
|
+
export type TestStream<T> = {
|
|
36
|
+
/** Pass as the subscribe function; works for any `(input, …, { signal })` shape. */
|
|
37
|
+
subscribe: (...args: unknown[]) => Promise<AsyncIterable<T>>;
|
|
38
|
+
/** Every connection opened so far, oldest first. */
|
|
39
|
+
connections: TestConnection<T>[];
|
|
40
|
+
/** Resolves when at least `count` connections have been opened. */
|
|
41
|
+
opened: (count?: number) => Promise<TestConnection<T>>;
|
|
42
|
+
/** Push into the newest connection. */
|
|
43
|
+
push: (event: T) => Promise<void>;
|
|
44
|
+
end: () => void;
|
|
45
|
+
fail: (error: Error) => void;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* A controllable stand-in for an oRPC event iterator, for driving
|
|
49
|
+
* subscriptions and live queries in tests without timers.
|
|
50
|
+
*/
|
|
51
|
+
export declare function createTestStream<T>(): TestStream<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Run composables inside a real Vue app with a `QueryClient` and the provided
|
|
54
|
+
* oRPC client, without a DOM. `stop()` disposes the scope, closing streams.
|
|
55
|
+
*/
|
|
56
|
+
export declare function withOrpcApp<T>(setup: () => T, options?: {
|
|
57
|
+
utils?: unknown;
|
|
58
|
+
client?: unknown;
|
|
59
|
+
queryClient?: QueryClient;
|
|
60
|
+
}): {
|
|
61
|
+
result: T;
|
|
62
|
+
queryClient: QueryClient;
|
|
63
|
+
app: import("vue").App<Element>;
|
|
64
|
+
stop: () => void;
|
|
65
|
+
};
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/vue/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAkB,MAAM,qBAAqB,CAAA;AAIjE,KAAK,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAA;AAC3C,KAAK,WAAW,GAAG,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAA;AAErD,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG;IAC7B,+FAA+F;IAC/F,MAAM,EAAE,MAAM,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,2FAA2F;IAC3F,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAA;IACzC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAA;AASD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,OAAO,GAAE,qBAA0B,GACjC,QAAQ,CAAC,CAAC,CAAC,CAyEb;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,iGAAiG;IACjG,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,wCAAwC;IACxC,GAAG,EAAE,MAAM,IAAI,CAAA;IACf,uBAAuB;IACvB,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;IAC3B,oFAAoF;IACpF,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5D,oDAAoD;IACpD,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,CAAA;IAChC,mEAAmE;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;IACtD,uCAAuC;IACvC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,GAAG,EAAE,MAAM,IAAI,CAAA;IACf,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC5B,CAAA;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAmInD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC5B,KAAK,EAAE,MAAM,CAAC,EACd,OAAO,GAAE;IACR,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;CACpB;;;;;EAWN"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query';
|
|
2
|
+
import { createApp, effectScope } from 'vue';
|
|
3
|
+
import { provideOrpc } from '../vue.js';
|
|
4
|
+
const emptyAsyncIterable = () => ({
|
|
5
|
+
async *[Symbol.asyncIterator]() { }
|
|
6
|
+
});
|
|
7
|
+
const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
8
|
+
/**
|
|
9
|
+
* A deep stand-in for oRPC utils or a client: `o.order.key()` is `['order']`,
|
|
10
|
+
* `o.order.get.call()` resolves an empty stream, `.key()`/`.queryKey()` on a
|
|
11
|
+
* procedure return `[]`, and any other method returns `{}`. The same path
|
|
12
|
+
* always returns the same mock, so calls can be asserted. Type it as your
|
|
13
|
+
* utils: `createOrpcMock<typeof orpc>({ fn: mock })`.
|
|
14
|
+
*/
|
|
15
|
+
export function createOrpcMock(options = {}) {
|
|
16
|
+
const { fn = (implementation) => implementation, keys, overrides } = options;
|
|
17
|
+
const created = [];
|
|
18
|
+
const method = (implementation) => {
|
|
19
|
+
const wrapped = fn(implementation);
|
|
20
|
+
created.push(wrapped);
|
|
21
|
+
return wrapped;
|
|
22
|
+
};
|
|
23
|
+
const reset = () => {
|
|
24
|
+
for (const wrapped of created) {
|
|
25
|
+
;
|
|
26
|
+
wrapped.mockReset?.();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const procedures = new Map();
|
|
30
|
+
const procedure = (path) => {
|
|
31
|
+
let found = procedures.get(path);
|
|
32
|
+
if (!found) {
|
|
33
|
+
const methods = new Map();
|
|
34
|
+
found = new Proxy({}, {
|
|
35
|
+
get(_target, name) {
|
|
36
|
+
if (typeof name === 'symbol')
|
|
37
|
+
return undefined;
|
|
38
|
+
let existing = methods.get(name);
|
|
39
|
+
if (!existing) {
|
|
40
|
+
existing = method(name === 'call'
|
|
41
|
+
? async () => emptyAsyncIterable()
|
|
42
|
+
: name === 'key' || name === 'queryKey'
|
|
43
|
+
? () => []
|
|
44
|
+
: () => ({}));
|
|
45
|
+
methods.set(name, existing);
|
|
46
|
+
}
|
|
47
|
+
return existing;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
procedures.set(path, found);
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
};
|
|
54
|
+
const namespaces = new Map();
|
|
55
|
+
const namespace = (name) => {
|
|
56
|
+
let found = namespaces.get(name);
|
|
57
|
+
if (!found) {
|
|
58
|
+
const override = overrides?.[name];
|
|
59
|
+
const target = isObject(override) ? { ...override } : {};
|
|
60
|
+
found = new Proxy(target, {
|
|
61
|
+
get(shape, key) {
|
|
62
|
+
if (typeof key === 'symbol')
|
|
63
|
+
return undefined;
|
|
64
|
+
if (key === 'key')
|
|
65
|
+
return () => keys?.[name] ?? [name];
|
|
66
|
+
if (key in shape)
|
|
67
|
+
return shape[key];
|
|
68
|
+
return procedure(`${name}.${key}`);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
namespaces.set(name, found);
|
|
72
|
+
}
|
|
73
|
+
return found;
|
|
74
|
+
};
|
|
75
|
+
// The proxy answers every path at runtime; `T` is the shape tests read it as.
|
|
76
|
+
return new Proxy({ $reset: reset }, {
|
|
77
|
+
get(_target, key) {
|
|
78
|
+
if (key === '$reset')
|
|
79
|
+
return reset;
|
|
80
|
+
if (typeof key === 'symbol')
|
|
81
|
+
return undefined;
|
|
82
|
+
const override = overrides?.[key];
|
|
83
|
+
if (override !== undefined && !isObject(override))
|
|
84
|
+
return override;
|
|
85
|
+
return namespace(key);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A controllable stand-in for an oRPC event iterator, for driving
|
|
91
|
+
* subscriptions and live queries in tests without timers.
|
|
92
|
+
*/
|
|
93
|
+
export function createTestStream() {
|
|
94
|
+
const connections = [];
|
|
95
|
+
const openWaiters = [];
|
|
96
|
+
function open(args) {
|
|
97
|
+
const options = [...args]
|
|
98
|
+
.reverse()
|
|
99
|
+
.find((arg) => isObject(arg) && 'signal' in arg);
|
|
100
|
+
const queue = [];
|
|
101
|
+
let failure = null;
|
|
102
|
+
let closed = false;
|
|
103
|
+
let pending = null;
|
|
104
|
+
// The event the consumer holds; it is processed once it asks for the next.
|
|
105
|
+
let handedOut = null;
|
|
106
|
+
const settle = () => {
|
|
107
|
+
if (!pending)
|
|
108
|
+
return;
|
|
109
|
+
const current = pending;
|
|
110
|
+
if (failure) {
|
|
111
|
+
pending = null;
|
|
112
|
+
current.reject(failure);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const next = queue.shift();
|
|
116
|
+
if (!next)
|
|
117
|
+
return;
|
|
118
|
+
pending = null;
|
|
119
|
+
handedOut = next.delivered;
|
|
120
|
+
current.resolve(next.result);
|
|
121
|
+
};
|
|
122
|
+
const close = () => {
|
|
123
|
+
closed = true;
|
|
124
|
+
handedOut?.();
|
|
125
|
+
handedOut = null;
|
|
126
|
+
for (const queued of queue)
|
|
127
|
+
queued.delivered();
|
|
128
|
+
};
|
|
129
|
+
// oRPC rejects a pending `next()` with an AbortError when the call is aborted.
|
|
130
|
+
options?.signal?.addEventListener('abort', () => {
|
|
131
|
+
const abort = new Error('This operation was aborted');
|
|
132
|
+
abort.name = 'AbortError';
|
|
133
|
+
failure = abort;
|
|
134
|
+
settle();
|
|
135
|
+
close();
|
|
136
|
+
});
|
|
137
|
+
const connection = {
|
|
138
|
+
input: args[0],
|
|
139
|
+
signal: options?.signal,
|
|
140
|
+
get closed() {
|
|
141
|
+
return closed;
|
|
142
|
+
},
|
|
143
|
+
push(event) {
|
|
144
|
+
if (closed)
|
|
145
|
+
return Promise.resolve();
|
|
146
|
+
return new Promise((delivered) => {
|
|
147
|
+
queue.push({ result: { done: false, value: event }, delivered });
|
|
148
|
+
settle();
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
end() {
|
|
152
|
+
const done = { done: true, value: undefined };
|
|
153
|
+
queue.push({ result: done, delivered: () => { } });
|
|
154
|
+
settle();
|
|
155
|
+
closed = true;
|
|
156
|
+
},
|
|
157
|
+
fail(error) {
|
|
158
|
+
failure = error;
|
|
159
|
+
settle();
|
|
160
|
+
close();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const iterator = {
|
|
164
|
+
next() {
|
|
165
|
+
handedOut?.();
|
|
166
|
+
handedOut = null;
|
|
167
|
+
return new Promise((resolve, reject) => {
|
|
168
|
+
pending = { resolve, reject };
|
|
169
|
+
settle();
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
async return() {
|
|
173
|
+
close();
|
|
174
|
+
pending?.resolve({ done: true, value: undefined });
|
|
175
|
+
pending = null;
|
|
176
|
+
return { done: true, value: undefined };
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
connections.push(connection);
|
|
180
|
+
for (const waiter of [...openWaiters]) {
|
|
181
|
+
if (connections.length < waiter.count)
|
|
182
|
+
continue;
|
|
183
|
+
openWaiters.splice(openWaiters.indexOf(waiter), 1);
|
|
184
|
+
waiter.resolve();
|
|
185
|
+
}
|
|
186
|
+
return Object.assign(connection, {
|
|
187
|
+
[Symbol.asyncIterator]: () => iterator
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const latest = () => {
|
|
191
|
+
const connection = connections.at(-1);
|
|
192
|
+
if (!connection)
|
|
193
|
+
throw new Error('createTestStream: no connection opened');
|
|
194
|
+
return connection;
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
subscribe: async (...args) => open(args),
|
|
198
|
+
connections,
|
|
199
|
+
opened: (count = 1) => new Promise((resolve) => {
|
|
200
|
+
const done = () => resolve(connections[count - 1]);
|
|
201
|
+
if (connections.length >= count)
|
|
202
|
+
done();
|
|
203
|
+
else
|
|
204
|
+
openWaiters.push({ count, resolve: done });
|
|
205
|
+
}),
|
|
206
|
+
push: (event) => latest().push(event),
|
|
207
|
+
end: () => latest().end(),
|
|
208
|
+
fail: (error) => latest().fail(error)
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Run composables inside a real Vue app with a `QueryClient` and the provided
|
|
213
|
+
* oRPC client, without a DOM. `stop()` disposes the scope, closing streams.
|
|
214
|
+
*/
|
|
215
|
+
export function withOrpcApp(setup, options = {}) {
|
|
216
|
+
const queryClient = options.queryClient ??
|
|
217
|
+
new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
|
218
|
+
const app = createApp({ render: () => null });
|
|
219
|
+
app.use(VueQueryPlugin, { queryClient });
|
|
220
|
+
provideOrpc(app, { client: options.client, utils: options.utils });
|
|
221
|
+
const scope = effectScope();
|
|
222
|
+
const result = app.runWithContext(() => scope.run(setup));
|
|
223
|
+
return { result, queryClient, app, stop: () => scope.stop() };
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -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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"}
|