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
package/README.md
CHANGED
|
@@ -130,13 +130,49 @@ The `subscribe` route runs builder middleware and the same fn guards/extras/meta
|
|
|
130
130
|
- `reauthorize` can check access before each live update. Initial authorization covers idle streams; apps that need immediate revocation should close those streams.
|
|
131
131
|
- `safePublish` logs publish errors instead of throwing them; it does not retry or guarantee delivery.
|
|
132
132
|
|
|
133
|
-
**`createPubSub`** returns a typed `subscribe` route plus `publish`, `publishMany` (one atomic round-trip across channels) and typed `getSubscriptionChannelName({ input, context })` / `getPublishChannelName(event)` methods. The shared partial-input `getChannelName` method is deprecated. Publishers pass the event schema's input type; subscribers, filters and channel resolvers get its output type. The raw event travels in oRPC's JSON format, so `Date`, `Map`, `Set` and `BigInt` survive, and each receiver parses it once. Options include `filterFn`, `authFn`, `mirrorChannel`, `overflowMarker`, `procedure`, configured guards and `meta`. Channels may be static or use `channel: { subscribe: ({ input, context }) => key, publish: (parsedEvent) => key }`. Carry publishing tenant keys in the event. A factory `namespace` prefixes channels, mirrors and backlog keys. Each pub/sub definition subscribes to each channel once and parses each payload once for all local subscribers. Each subscriber then runs its filter in arrival order as it reads; its bounded queue holds events before filtering, so `onDrop` counts unfiltered events. Abort and drain release a subscription at once, even one that is not being read. A lost subscription is retried with exponential backoff and jitter. **`createPublisher`** is the publish-only half.
|
|
133
|
+
**`createPubSub`** returns a typed `subscribe` route plus `publish`, `publishMany` (one atomic round-trip across channels) and typed `getSubscriptionChannelName({ input, context })` / `getPublishChannelName(event)` methods. The shared partial-input `getChannelName` method is deprecated. Publishers pass the event schema's input type; subscribers, filters and channel resolvers get its output type. The raw event travels in oRPC's JSON format, so `Date`, `Map`, `Set` and `BigInt` survive, and each receiver parses it once. Options include `filterFn`, `authFn`, `mirrorChannel`, `overflowMarker`, `procedure`, configured guards and `meta`. Channels may be static or use `channel: { subscribe: ({ input, context }) => key, publish: (parsedEvent) => key }`. Carry publishing tenant keys in the event. A factory `namespace` prefixes channels, mirrors and backlog keys. Each pub/sub definition subscribes to each channel once and parses each payload once for all local subscribers. Each subscriber then runs its filter in arrival order as it reads; its bounded queue holds events before filtering, so `onDrop` counts unfiltered events. Abort and drain release a subscription at once, even one that is not being read. A lost subscription is retried with exponential backoff and jitter. `safePublish` logs a failed publish (`pubsub.publish_failed`) instead of throwing, as on `fnLive`. **`createPublisher`** is the publish-only half.
|
|
134
|
+
|
|
135
|
+
**`defineScopedChangeBus`** binds `createPubSub` to one scope rule, for buses that tell everyone in a scope (usually an organization) "this changed". Each bus names a channel `prefix`; events go to `${prefix}:${scope}`. Publishing is safe by default, since buses publish after committed writes. `bus.channel` lets an `fnLive` share the bus's events.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { defineScopedChangeBus, invalidationStream } from 'orpc-fn/live'
|
|
139
|
+
|
|
140
|
+
const defineChangeBus = defineScopedChangeBus(createPubSub, {
|
|
141
|
+
subscribe: (context) => activeOrganizationId(context), // throw to refuse
|
|
142
|
+
publish: (event: { organizationId: string }) => event.organizationId
|
|
143
|
+
})
|
|
144
|
+
export const dealChanges = defineChangeBus({
|
|
145
|
+
name: 'deal.subscribe',
|
|
146
|
+
prefix: 'deal:change',
|
|
147
|
+
inputSchema: z.object({}),
|
|
148
|
+
eventSchema: z.object({ organizationId: z.string(), dealId: z.string() })
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**`invalidationStream`** fans several streams into one stream of `{ domain }` events, so a client holds one connection and invalidates queries per domain. `events` optionally forwards fields from a source event, for example to raise an alert. Sources are called with `{}` and the caller's context. Equal events that queue while the consumer is busy collapse into one. When one source ends (a deploy drain) the stream ends, when one throws the stream throws, and every source is closed either way.
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
export const subscribeChanges = fn({
|
|
156
|
+
name: 'realtime.subscribeChanges',
|
|
157
|
+
stream: true,
|
|
158
|
+
input: z.object({}),
|
|
159
|
+
handler: ({ context, signal }) =>
|
|
160
|
+
invalidationStream({
|
|
161
|
+
context,
|
|
162
|
+
signal,
|
|
163
|
+
sources: { deal: dealChanges.subscribe, workItem: workItemChanges.subscribe },
|
|
164
|
+
events: { deal: (event) => (event.kind === 'won' ? { dealId: event.dealId } : undefined) }
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
On the client, `useInvalidationStream` from `orpc-fn/vue` or `orpc-fn/react` consumes it; its `domains` map is typed from the route's domains.
|
|
134
170
|
|
|
135
171
|
**Graceful shutdown:** `await shutdown()` stops new subscriptions/publication, cancels initialization/retries, ends existing streams and awaits cleanup. It closes a supplied transport only with `ownsTransport: true`, and a lazy `transport: () => …` only if it was ever created; it is never created during or after shutdown. A custom transport whose pending `subscribe` cannot be cancelled may resolve later; that late subscription is immediately released. `drainPubSubSubscribers()` remains a synchronous, nonterminal operation. Both are per factory.
|
|
136
172
|
|
|
137
173
|
Recent event IDs deduplicate replay/live overlap; legacy payloads remain readable. Replay is bounded and TTL-limited, so it is not durable resume. A snapshot may already include a queued delta: reducers must use revisions or idempotence. See [the revision example](examples/adoption/revisions.ts). Parsing ingress, replay staging and subscriber queues are bounded; positive queue/TTL/time options are validated.
|
|
138
174
|
|
|
139
|
-
**Transports** implement `PubSubTransport` (`publish(messages, backlog?)`, `readBacklog(channel)`, `subscribe(channel, listener, onLost, { onReconnect }?)`):
|
|
175
|
+
**Transports** implement `PubSubTransport` (`publish(messages, backlog?)`, `readBacklog(channel)`, `subscribe(channel, listener, onLost, { onReconnect }?)` and optional `stats()`):
|
|
140
176
|
|
|
141
177
|
| Subpath | Client | Notes |
|
|
142
178
|
|---|---|---|
|
|
@@ -144,7 +180,16 @@ Recent event IDs deduplicate replay/live overlap; legacy payloads remain readabl
|
|
|
144
180
|
| `orpc-fn/live/ioredis` | ioredis 5 | Dedicated subscriber via `duplicate()`; ioredis re-subscribes itself |
|
|
145
181
|
| `orpc-fn/live/memory` | none | Tests and single-process dev |
|
|
146
182
|
|
|
147
|
-
A subscriber connection that is lost, or cannot restore its channels after a reconnect, is closed and replaced; nothing it still emits is delivered. The Redis transports publish and maintain backlogs with one Lua script, sent by SHA, with a fallback to `EVAL` when Redis returns `NOSCRIPT`. Await `transport.close()` when the app owns its lifecycle.
|
|
183
|
+
A subscriber connection that is lost, or cannot restore its channels after a reconnect, is closed and replaced; nothing it still emits is delivered. The Redis transports publish and maintain backlogs with one Lua script, sent by SHA, with a fallback to `EVAL` when Redis returns `NOSCRIPT`. Await `transport.close()` when the app owns its lifecycle.
|
|
184
|
+
|
|
185
|
+
All three return `stats()`: `{ channels, listeners, subscriberConnected }` on this instance. With `activePubSubSubscriberCount()` from `createFn` that covers pub/sub gauges; a transport opens no connection until the first subscribe, so it can be created eagerly:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const transport = bunRedisTransport(redis)
|
|
189
|
+
createFn({ /* … */, pubsub: { transport, ownsTransport: true } })
|
|
190
|
+
meter.createObservableGauge('pubsub_subscribed_channels').addCallback((g) => g.observe(transport.stats().channels))
|
|
191
|
+
meter.createObservableGauge('pubsub_redis_subscriber_connected').addCallback((g) => g.observe(transport.stats().subscriberConnected ? 1 : 0))
|
|
192
|
+
``` The Redis Lua batching adapter supports standalone Redis; Redis Cluster requires compatible key slots and is not promised by this adapter.
|
|
148
193
|
|
|
149
194
|
`streamLiveSnapshots`, `fnLivePatch` and `throwInitialSnapshotError` are exported for custom streams.
|
|
150
195
|
|
|
@@ -196,6 +241,32 @@ The adapter installs the SDK list/call handlers on a low-level `Server` (also ac
|
|
|
196
241
|
|
|
197
242
|
Sanitized tool-name collisions between distinct procedures throw; identical aliases are deduplicated. Override `name` to resolve deliberate collisions. Tool names are the sanitized `fn` names (`user.me` becomes `user-me`). Input schemas carry the same JSON Schema as your OpenAPI docs (dates become `string`/`date-time`), and validation turns them back into `Date`s. Validation returns the raw arguments, and `call(procedure, args, { context })` parses those: transforms/refinements must be pure: SDK validation and procedure execution may run them more than once, always on raw input. `readOnlyHint` defaults to GET routes; pass `readOnly` to change it. `hasTag(tag)` also works as an oRPC `OpenAPIHandler` filter.
|
|
198
243
|
|
|
244
|
+
## `orpc-fn/cli`
|
|
245
|
+
|
|
246
|
+
Optional peer: `hanzio` ^3.1.0 (`hanzio/cli`).
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import { defineCli } from 'hanzio/cli'
|
|
250
|
+
import { procedureCommands } from 'orpc-fn/cli'
|
|
251
|
+
|
|
252
|
+
const updateDeal = fn({
|
|
253
|
+
name: 'deal.update',
|
|
254
|
+
summary: 'Move a deal to another stage', // the command's help
|
|
255
|
+
meta: { cli: true },
|
|
256
|
+
input: z.object({ id: z.string().meta({ positional: true }), stage: z.string() }),
|
|
257
|
+
handler: async ({ input, context }) => { /* ... */ }
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
await defineCli({
|
|
261
|
+
name: 'app',
|
|
262
|
+
globals: z.object({ as: z.string().optional() }),
|
|
263
|
+
context: async ({ as }) => ({ user: as ? await loadUser(as) : undefined }),
|
|
264
|
+
commands: procedureCommands(router)
|
|
265
|
+
}).run() // app deal update d_1 --stage won --as ada@example.com
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`procedureCommands(router)` turns the routes declared with `meta: { cli: true }` into commands nested like the router, kebab-cased (`dealRoom.update` is `deal-room update`); add `cli?: boolean` to your meta type, or select routes with `filter`. Flags and positionals come from the route's `z.object()` input. A command calls the procedure through oRPC with the CLI's context, so middleware, guards and tracing run as over HTTP; `context: (cliContext, meta) => ...` maps that context per procedure and can refuse with a `CliError`. A 4xx `ORPCError` prints as `CODE: message`; anything else keeps its stack. Streams and non-object inputs throw when the commands are built. The procedure parses the already-validated flags again, so transforms must accept their own output.
|
|
269
|
+
|
|
199
270
|
## `orpc-fn/hono`
|
|
200
271
|
|
|
201
272
|
Optional peers: `hono`, `@orpc/openapi`, `@orpc/zod`, `@orpc/json-schema`.
|
|
@@ -221,6 +292,7 @@ Behaviour:
|
|
|
221
292
|
- Scalar docs are served at the OpenAPI prefix.
|
|
222
293
|
- `onError` sees only unexpected errors.
|
|
223
294
|
- `openapi.filter`, `openapi.smartCoercion` and `openapi.spec` (for security schemes) cover an external API with its own auth.
|
|
295
|
+
- `markRequestArrival(request)` at the front door (`Bun.serve({ fetch })`, before routing) makes `queue_ms` the time until the procedure runs: in-process queueing no handler timer sees. Pass `queueMs` to measure it another way.
|
|
224
296
|
- `context` builds the router's context and is checked against it: it is required when `{ headers, timing }` alone does not satisfy the router. It may return a `Response`, for example a 401.
|
|
225
297
|
|
|
226
298
|
## `orpc-fn/client`
|
|
@@ -242,8 +314,11 @@ export const client: RouterClient<typeof router> = createORPCClient(link)
|
|
|
242
314
|
export const orpc = createTanstackQueryUtils(client) // Vue Query or React Query
|
|
243
315
|
|
|
244
316
|
if (hasOrpcErrorCode(error, 'NOT_FOUND')) { /* … */ }
|
|
317
|
+
toast(userFacingErrorMessage(error, t('errors.generic'))) // server text only when it opts in
|
|
245
318
|
```
|
|
246
319
|
|
|
320
|
+
Route error messages are developer text, so `userFacingErrorMessage` shows your localized fallback unless the server opted in with `new ORPCError('BAD_REQUEST', { message, data: { userMessage } })`. `queryCacheSerializer` is a `serialize`/`deserialize` pair for TanStack Query persisters that round-trips `Date`s and the other types oRPC sends.
|
|
321
|
+
|
|
247
322
|
`createRpcLink` takes every `RPCLink` option. It also batches parallel calls into one request, matching `mountOrpc`'s server-side batching (`batch: { maxSize, exclude, groups }`, or `false` to turn it off). A batch is one request with one client context, so by default only calls without a client context are batched; pass `groups` to batch calls that share one. A streaming response cannot be batched, and the request doesn't say whether the response will stream, so pass `streamPaths` generated from the actual router with `createStreamManifest` (or `createStreamManifestAsync` for lazy routers). Serialize it to a frontend module; importing that data needs no server runtime. The `orpc-fn` CLI does that, resolving lazy routers, sorting paths and writing only on change:
|
|
248
323
|
|
|
249
324
|
```sh
|
|
@@ -272,7 +347,74 @@ const link = createBetterAuthExpoLink({
|
|
|
272
347
|
})
|
|
273
348
|
```
|
|
274
349
|
|
|
275
|
-
On native, calls go through `expo/fetch`, the only fetch that streams there. The bridge forwards the request body and the abort signal. Without the signal, cancelled subscriptions keep their sockets open, the device's HTTP pool runs out, and later requests hang. Cookies are sent in a header (`credentials: 'omit'`), together with `expo-origin` and `x-skip-oauth-proxy`, the same headers `@better-auth/expo` sends. On the server, `mountOrpc({ normalizeHeaders: normalizeExpoOrigin })` copies `expo-origin` to `origin`. The generic `createExpoLink` forwards upstream headers (including async/context-aware resolvers) and adds no provider-specific headers. `createBetterAuthExpoLink` supplies the cookie/origin preset above. On web, the link uses the platform fetch with cookies, or your explicit `webFetch` override. `createExpoFetch` is exported for a custom link.
|
|
350
|
+
On native, calls go through `expo/fetch`, the only fetch that streams there. In Expo SDK 55, cancelling a stream makes `expo/fetch` close its body twice and throw `Invalid state: Controller is already closed`; patch `src/winter/fetch/FetchResponse.ts` so its `didComplete` and `didFailWithError` listeners return when `isControllerClosed` is already set (with `bun patch expo` or `patch-package`). The bridge forwards the request body and the abort signal. Without the signal, cancelled subscriptions keep their sockets open, the device's HTTP pool runs out, and later requests hang. Cookies are sent in a header (`credentials: 'omit'`), together with `expo-origin` and `x-skip-oauth-proxy`, the same headers `@better-auth/expo` sends. On the server, `mountOrpc({ normalizeHeaders: normalizeExpoOrigin })` copies `expo-origin` to `origin`. The generic `createExpoLink` forwards upstream headers (including async/context-aware resolvers) and adds no provider-specific headers. `createBetterAuthExpoLink` supplies the cookie/origin preset above. On web, the link uses the platform fetch with cookies, or your explicit `webFetch` override. `createExpoFetch` is exported for a custom link.
|
|
351
|
+
|
|
352
|
+
## `orpc-fn/vue`
|
|
353
|
+
|
|
354
|
+
Peers: `vue`, `@tanstack/vue-query`.
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
// main.ts
|
|
358
|
+
app.use(VueQueryPlugin, { queryClient })
|
|
359
|
+
provideOrpc(app, { client, utils: orpc })
|
|
360
|
+
|
|
361
|
+
declare module 'orpc-fn/vue' {
|
|
362
|
+
interface Register { client: typeof client; utils: typeof orpc }
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
```ts
|
|
367
|
+
const { useQuery, useMutation, invalidate } = useApiClient()
|
|
368
|
+
const orders = useQuery((o) => o.order.list.queryOptions({ input: { search: search.value } }))
|
|
369
|
+
const save = useMutation((o) => o.order.update.mutationOptions({ onSuccess: () => invalidate((o) => o.order.key()) }))
|
|
370
|
+
|
|
371
|
+
// The client half of `fnLive`: HTTP seeds the cache, the stream keeps it current.
|
|
372
|
+
const order = useLiveQuery(
|
|
373
|
+
() => ({ id: props.id }),
|
|
374
|
+
(input, o) => o.order.get.queryOptions({ input }),
|
|
375
|
+
(o) => o.order.watch.call // the composable passes the input and an abort signal
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
// Once, in the signed-in shell: one stream of `{ domain }` events invalidates list queries.
|
|
379
|
+
useInvalidationStream({}, (o) => o.realtime.subscribeChanges.call, {
|
|
380
|
+
domains: { order: { debounceMs: 100, queryKeys: [orpc.order.key()] } },
|
|
381
|
+
logger
|
|
382
|
+
})
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
`useOrpcSubscription` (also `useApiClient().useSubscription`) reconnects with jittered backoff and closes while the page is hidden (`respectVisibility: false` keeps it). `useLiveQuery` writes each stream event under the key it was opened for, so an event in flight from a previous input is dropped. A stream whose events are not the cached type (an `fnLive` patch route, or a `select`ed cache) does not compile without `applyEvent`, and the stream's input must match the query's unless you pass `subscriptionInput`. Use `mergeSeed` when the seed can resolve after stream events. For large live payloads such as chat timelines, pass vue-query's `shallow: true` in the query options so the data is not made deeply reactive; mutate it only through `setQueryData`. Live queries carry `meta.live`, so invalidation streams skip them. Leave `refetchType` at TanStack's `'active'`: `'all'` refetches every cached query of a domain on each event, including screens nobody has open, which refetch on their next visit anyway. `useSubscriptionInvalidates` treats a stream as a "something changed" ping, and `useQueryErrorMessage` is `userFacingErrorMessage` as a computed. A surface that talks to another API passes `orpc` to each composable instead of using `provideOrpc`.
|
|
386
|
+
|
|
387
|
+
`orpc-fn/vue/testing` runs composables in a real app without a DOM: `withOrpcApp(setup, { utils })`, `createTestStream()` for a subscription the test drives (`await stream.push(event)` resolves once it was handled), and `createOrpcMock({ fn: mock })` for a deep stand-in of the utils.
|
|
388
|
+
|
|
389
|
+
## `orpc-fn/react`
|
|
390
|
+
|
|
391
|
+
Peers: `react`, `@tanstack/react-query`. Works on React Native: pausing follows TanStack's `focusManager`, so wire it to `AppState` once, as TanStack recommends:
|
|
392
|
+
|
|
393
|
+
```ts
|
|
394
|
+
focusManager.setEventListener((setFocused) => {
|
|
395
|
+
const subscription = AppState.addEventListener('change', (state) => setFocused(state === 'active'))
|
|
396
|
+
return () => subscription.remove()
|
|
397
|
+
})
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
const { status } = useOrpcSubscription({ id }, client.order.watch, { onEvent: (order) => setOrder(order) })
|
|
402
|
+
|
|
403
|
+
// Same contract as the Vue `useLiveQuery`, with the client procedure passed as is.
|
|
404
|
+
// For a large cache your `applyEvent` keeps immutable, pass `structuralSharing: false` in the query options.
|
|
405
|
+
const order = useLiveQuery({ id }, (input) => orpc.order.get.queryOptions({ input }), client.order.watch)
|
|
406
|
+
|
|
407
|
+
useInvalidationStream({}, client.realtime.subscribeChanges, {
|
|
408
|
+
enabled: signedIn,
|
|
409
|
+
domains: { order: { debounceMs: 500, queryKeys: [orpc.order.list.key()] } }
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
// Persist the cache per user: the buster drops someone else's saved cache, the hook clears memory.
|
|
413
|
+
const owner = session ? `${session.user.id}:${session.activeOrganizationId ?? ''}` : null
|
|
414
|
+
useQueryCacheOwner(owner)
|
|
415
|
+
const persister = createAsyncStoragePersister({ storage: AsyncStorage, ...queryCacheSerializer })
|
|
416
|
+
<PersistQueryClientProvider client={queryClient} persistOptions={{ persister, buster: owner ?? '' }} />
|
|
417
|
+
```
|
|
276
418
|
|
|
277
419
|
## Docs
|
|
278
420
|
|
package/dist/client.d.ts
CHANGED
|
@@ -42,5 +42,34 @@ export declare function createRpcLink<T extends ClientContext = ClientContext>(o
|
|
|
42
42
|
* route errors as `ORPCError`, so `instanceof` plus `code` is the contract.
|
|
43
43
|
*/
|
|
44
44
|
export declare function hasOrpcErrorCode<TCode extends ORPCErrorCode>(error: unknown, code: TCode): error is ORPCError<TCode, unknown>;
|
|
45
|
+
/**
|
|
46
|
+
* The server's message, only when the backend marked it user-safe by putting
|
|
47
|
+
* a `userMessage` string on the error's `data`. Route error messages are
|
|
48
|
+
* developer text (English, internal model names), so they are not shown by
|
|
49
|
+
* default; they stay on the error for logs and error tracking.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* throw new ORPCError('BAD_REQUEST', {
|
|
53
|
+
* message: 'Deal has no pipeline stage', // logs, telemetry
|
|
54
|
+
* data: { userMessage: 'Choose a stage first.' } // the user reads this
|
|
55
|
+
* })
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function userSafeServerMessage(error: unknown): string | null;
|
|
59
|
+
/** User-facing text for a caught error: the opted-in server message, else your localized fallback. */
|
|
60
|
+
export declare function userFacingErrorMessage(error: unknown, fallback: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* `serialize`/`deserialize` for a TanStack Query persister. API payloads carry
|
|
63
|
+
* `Date`s (and maybe `Map`s, `Set`s, `BigInt`s) that plain JSON returns as
|
|
64
|
+
* strings; oRPC's own serializer round-trips them.
|
|
65
|
+
*
|
|
66
|
+
* ```ts
|
|
67
|
+
* createAsyncStoragePersister({ storage: AsyncStorage, ...queryCacheSerializer })
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const queryCacheSerializer: {
|
|
71
|
+
serialize(value: unknown): string;
|
|
72
|
+
deserialize<T>(text: string): T;
|
|
73
|
+
};
|
|
45
74
|
export {};
|
|
46
75
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAChF,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAGtD,KAAK,YAAY,CAAC,CAAC,SAAS,aAAa,IAAI,qBAAqB,CACjE,OAAO,eAAe,CAAC,CAAC,CAAC,CACzB,CAAC,CAAC,CAAC,CAAA;AAEJ,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,aAAa,IACvD,cAAc,CAAC,CAAC,CAAC,GAAG;IACnB;;;;;;;OAOG;IACH,sEAAsE;IACtE,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;IAC5C,KAAK,CAAC,EACH,OAAO,GACP;QACA,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,2EAA2E;QAC3E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAA;QAC9C,MAAM,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;KACjC,CAAA;CACJ,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,SAAU,SAAS,MAAM,EAAE,YACU,CAAA;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACpE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC9B,OAAO,CAAC,CAAC,CAAC,CA2BZ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS,aAAa,EAC3D,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,KAAK,GACT,KAAK,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAEpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQnE;AAED,sGAAsG;AACtG,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACd,MAAM,CAER;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;IAChC,SAAS,QAAQ,OAAO,GAAG,MAAM;IAIjC,WAAW,CAAC,CAAC,QAAQ,MAAM,GAAG,CAAC;CAO/B,CAAA"}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ORPCError } from '@orpc/client';
|
|
2
2
|
import { RPCLink } from '@orpc/client/fetch';
|
|
3
3
|
import { BatchLinkPlugin } from '@orpc/client/plugins';
|
|
4
|
+
import { StandardRPCJsonSerializer } from '@orpc/client/standard';
|
|
4
5
|
/**
|
|
5
6
|
* Streaming responses cannot be batched, and the request does not say a
|
|
6
7
|
* response will stream - so streaming routes are recognised by name. The
|
|
@@ -48,4 +49,52 @@ export function createRpcLink(options) {
|
|
|
48
49
|
export function hasOrpcErrorCode(error, code) {
|
|
49
50
|
return error instanceof ORPCError && error.code === code;
|
|
50
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* The server's message, only when the backend marked it user-safe by putting
|
|
54
|
+
* a `userMessage` string on the error's `data`. Route error messages are
|
|
55
|
+
* developer text (English, internal model names), so they are not shown by
|
|
56
|
+
* default; they stay on the error for logs and error tracking.
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* throw new ORPCError('BAD_REQUEST', {
|
|
60
|
+
* message: 'Deal has no pipeline stage', // logs, telemetry
|
|
61
|
+
* data: { userMessage: 'Choose a stage first.' } // the user reads this
|
|
62
|
+
* })
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function userSafeServerMessage(error) {
|
|
66
|
+
if (!(error instanceof ORPCError))
|
|
67
|
+
return null;
|
|
68
|
+
const data = error.data;
|
|
69
|
+
if (typeof data !== 'object' || data === null)
|
|
70
|
+
return null;
|
|
71
|
+
const userMessage = data.userMessage;
|
|
72
|
+
return typeof userMessage === 'string' && userMessage.trim().length > 0
|
|
73
|
+
? userMessage
|
|
74
|
+
: null;
|
|
75
|
+
}
|
|
76
|
+
/** User-facing text for a caught error: the opted-in server message, else your localized fallback. */
|
|
77
|
+
export function userFacingErrorMessage(error, fallback) {
|
|
78
|
+
return userSafeServerMessage(error) ?? fallback;
|
|
79
|
+
}
|
|
80
|
+
const cacheSerializer = new StandardRPCJsonSerializer();
|
|
81
|
+
/**
|
|
82
|
+
* `serialize`/`deserialize` for a TanStack Query persister. API payloads carry
|
|
83
|
+
* `Date`s (and maybe `Map`s, `Set`s, `BigInt`s) that plain JSON returns as
|
|
84
|
+
* strings; oRPC's own serializer round-trips them.
|
|
85
|
+
*
|
|
86
|
+
* ```ts
|
|
87
|
+
* createAsyncStoragePersister({ storage: AsyncStorage, ...queryCacheSerializer })
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export const queryCacheSerializer = {
|
|
91
|
+
serialize(value) {
|
|
92
|
+
const [json, meta] = cacheSerializer.serialize(value);
|
|
93
|
+
return JSON.stringify({ json, meta });
|
|
94
|
+
},
|
|
95
|
+
deserialize(text) {
|
|
96
|
+
const { json, meta } = JSON.parse(text);
|
|
97
|
+
return cacheSerializer.deserialize(json, meta);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
51
100
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,SAAS,EAAsB,MAAM,cAAc,CAAA;AAChF,OAAO,EAAE,OAAO,EAAuB,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ClientContext, ORPCError, type ORPCErrorCode } from '@orpc/client'\nimport { RPCLink, type RPCLinkOptions } from '@orpc/client/fetch'\nimport { BatchLinkPlugin } from '@orpc/client/plugins'\nimport { StandardRPCJsonSerializer } from '@orpc/client/standard'\n\ntype BatchOptions<T extends ClientContext> = ConstructorParameters<\n\ttypeof BatchLinkPlugin<T>\n>[0]\n\nexport type CreateRpcLinkOptions<T extends ClientContext> =\n\tRPCLinkOptions<T> & {\n\t\t/**\n\t\t * Collapse parallel calls into one HTTP request, matching `mountOrpc`'s\n\t\t * server-side batching. Default: true (25 calls). Pass false to turn off.\n\t\t *\n\t\t * A batch is one HTTP request, so it carries one client context. By\n\t\t * default only calls without a client context are batched; pass\n\t\t * `groups` to batch calls that share a context (e.g. a token).\n\t\t */\n\t\t/** Client-safe manifest generated by createStreamManifest(router). */\n\t\tstreamPaths?: readonly (readonly string[])[]\n\t\tbatch?:\n\t\t\t| boolean\n\t\t\t| {\n\t\t\t\t\tmaxSize?: number\n\t\t\t\t\t/** Calls that must not be batched. Default: {@link isSubscriptionPath}. */\n\t\t\t\t\texclude?: (path: readonly string[]) => boolean\n\t\t\t\t\tgroups?: BatchOptions<T>['groups']\n\t\t\t }\n\t}\n\n/**\n * Streaming responses cannot be batched, and the request does not say a\n * response will stream - so streaming routes are recognised by name. The\n * default treats any path segment containing `subscribe` as one (the\n * convention `fnLive` routers use: `{ list, subscribe }`).\n */\nexport const isSubscriptionPath = (path: readonly string[]) =>\n\tpath.some((segment) => segment.toLowerCase().includes('subscribe'))\n\n/**\n * `RPCLink` with request batching: a page-load burst becomes one request\n * instead of many queued on the server's event loop.\n *\n * ```ts\n * const client: RouterClient<typeof router> = createORPCClient(createRpcLink({ url }))\n * export const orpc = createTanstackQueryUtils(client)\n * ```\n */\nexport function createRpcLink<T extends ClientContext = ClientContext>(\n\toptions: CreateRpcLinkOptions<T>\n): RPCLink<T> {\n\tconst { batch = true, plugins = [], streamPaths, ...rest } = options\n\tconst streams = new Set(streamPaths?.map((path) => JSON.stringify(path)))\n\tif (batch === false) return new RPCLink<T>({ ...rest, plugins })\n\tconst {\n\t\tmaxSize = 25,\n\t\texclude = isSubscriptionPath,\n\t\tgroups\n\t} = batch === true ? {} : batch\n\treturn new RPCLink<T>({\n\t\t...rest,\n\t\tplugins: [\n\t\t\tnew BatchLinkPlugin<T>({\n\t\t\t\tmaxSize,\n\t\t\t\tgroups: groups ?? [\n\t\t\t\t\t// Only context-free calls reach this group (see `exclude` below),\n\t\t\t\t\t// so the batch's empty context is exactly theirs.\n\t\t\t\t\t{ condition: () => true, context: {} as T }\n\t\t\t\t],\n\t\t\t\texclude: ({ path, context }) =>\n\t\t\t\t\tstreams.has(JSON.stringify(path)) ||\n\t\t\t\t\texclude(path) ||\n\t\t\t\t\t(groups === undefined && Object.keys(context).length > 0)\n\t\t\t}),\n\t\t\t...plugins\n\t\t]\n\t})\n}\n\n/**\n * Typed check for a route error on the client. The RPC link rebuilds thrown\n * route errors as `ORPCError`, so `instanceof` plus `code` is the contract.\n */\nexport function hasOrpcErrorCode<TCode extends ORPCErrorCode>(\n\terror: unknown,\n\tcode: TCode\n): error is ORPCError<TCode, unknown> {\n\treturn error instanceof ORPCError && error.code === code\n}\n\n/**\n * The server's message, only when the backend marked it user-safe by putting\n * a `userMessage` string on the error's `data`. Route error messages are\n * developer text (English, internal model names), so they are not shown by\n * default; they stay on the error for logs and error tracking.\n *\n * ```ts\n * throw new ORPCError('BAD_REQUEST', {\n * message: 'Deal has no pipeline stage', // logs, telemetry\n * data: { userMessage: 'Choose a stage first.' } // the user reads this\n * })\n * ```\n */\nexport function userSafeServerMessage(error: unknown): string | null {\n\tif (!(error instanceof ORPCError)) return null\n\tconst data: unknown = error.data\n\tif (typeof data !== 'object' || data === null) return null\n\tconst userMessage = (data as { userMessage?: unknown }).userMessage\n\treturn typeof userMessage === 'string' && userMessage.trim().length > 0\n\t\t? userMessage\n\t\t: null\n}\n\n/** User-facing text for a caught error: the opted-in server message, else your localized fallback. */\nexport function userFacingErrorMessage(\n\terror: unknown,\n\tfallback: string\n): string {\n\treturn userSafeServerMessage(error) ?? fallback\n}\n\nconst cacheSerializer = new StandardRPCJsonSerializer()\n\n/**\n * `serialize`/`deserialize` for a TanStack Query persister. API payloads carry\n * `Date`s (and maybe `Map`s, `Set`s, `BigInt`s) that plain JSON returns as\n * strings; oRPC's own serializer round-trips them.\n *\n * ```ts\n * createAsyncStoragePersister({ storage: AsyncStorage, ...queryCacheSerializer })\n * ```\n */\nexport const queryCacheSerializer = {\n\tserialize(value: unknown): string {\n\t\tconst [json, meta] = cacheSerializer.serialize(value)\n\t\treturn JSON.stringify({ json, meta })\n\t},\n\tdeserialize<T>(text: string): T {\n\t\tconst { json, meta } = JSON.parse(text) as {\n\t\t\tjson: unknown\n\t\t\tmeta: Parameters<typeof cacheSerializer.deserialize>[1]\n\t\t}\n\t\treturn cacheSerializer.deserialize(json, meta) as T\n\t}\n}\n"]}
|
package/dist/create-fn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-fn.d.ts","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"create-fn.d.ts","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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"}
|
package/dist/create-fn.js
CHANGED
package/dist/create-fn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-fn.js","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype BuilderChain,\n\tcreateProcedureAssembler\n} from './assemble-procedure.js'\nimport { isAsyncIteratorObject } from './stream.js'\nimport { normalizeRoute } from './route-options.js'\nimport { type AnyProcedure, ORPCError, os } from '@orpc/server'\nimport { procedureDefinition } from './compatibility.js'\nimport { type BoundCall, createBoundCall } from './bound-call.js'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport { createFnLive, type FnLive } from './live/fn-live.js'\nimport {\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateLiveRuntime,\n\ttype PubSubRuntimeOptions\n} from './live/pub-sub.js'\nimport {\n\tcreateDefaultLogger,\n\tprotectLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nimport { readFnMeta } from './meta.js'\nimport {\n\ttype AttributeValue,\n\tcreateTracing,\n\terrorAttributes,\n\terrorMessageOf,\n\ttype OtelApiLike,\n\ttype SpanLike,\n\ttype SpanOf\n} from './otel.js'\nimport { RAW_INPUT, REQUEST_TIMING, type InvocationTiming } from './timing.js'\nimport { createRouter } from './router.js'\nimport {\n\ttype ProcedureHookParams,\n\ttype CompletedHookEvent,\n\ttype CurrentContextOf,\n\ttype BuilderLike,\n\ttype FiniteExtras,\n\ttype ScopedExtrasGuard,\n\ttype Fn,\n\ttype FnCompletedEvent,\n\ttype FnDefinition,\n\ttype Guard,\n\ttype GuardParams,\n\ttype MaybePromise,\n\ttype RejectKeys,\n\tRESERVED_OPTION_KEYS,\n\ttype ReservedOptionKey\n} from './types.js'\n\n/** `CreateFnOptions` with the generics erased: what the implementation reads. */\ntype RuntimeOptions = {\n\tprocedures: Record<string, BuilderChain>\n\tdefault?: string\n\textras?: (params: Record<string, unknown>) => unknown\n\textrasByProcedure?: Record<\n\t\tstring,\n\t\t(params: Record<string, unknown>) => unknown\n\t>\n\tguards?: Record<\n\t\tstring,\n\t\t(value: unknown, params: GuardParams<unknown, unknown>) => unknown\n\t>\n\totel?: OtelApiLike\n\tlogger?: (scope: string, span: SpanLike | undefined) => FnLogger\n\tspanAttributes?: (params: {\n\t\tcontext: unknown\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Record<string, unknown>\n\t}) => Record<string, AttributeValue | undefined>\n\tonCompleted?: (event: FnCompletedEvent) => LogAttributes | undefined\n\tisExpectedError?: (error: unknown) => boolean\n\tpubsub?: PubSubRuntimeOptions\n}\n\nexport type CreateFnOptions<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel extends OtelApiLike | undefined,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\t/** Named oRPC builders, e.g. `{ public: os.$context<Ctx>(), protected: authed }`. */\n\tprocedures: TProcedures\n\t/**\n\t * Builder used when a route omits `procedure`. Leave it out to make every\n\t * route name its procedure, so none gets one by accident.\n\t */\n\tdefault?: TDefault\n\t/** Per-call values merged into every handler's params; may be async. */\n\textras?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{\n\t\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\t\tsignal: AbortSignal | undefined\n\t\t\t\tname: string\n\t\t\t}\n\t\t>\n\t) => MaybePromise<TExtras>\n\textrasByProcedure?: {\n\t\t[K in keyof TScoped & keyof TProcedures]: (params: {\n\t\t\tcontext: CurrentContextOf<TProcedures[K]>\n\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\tsignal: AbortSignal | undefined\n\t\t\tname: string\n\t\t\tprocedure: K\n\t\t}) => MaybePromise<TScoped[K] & ScopedExtrasGuard<NoInfer<TScoped[K]>>>\n\t}\n\t/**\n\t * Checks run before the handler; each key becomes a typed `fn()` option.\n\t * Keys must not reuse route options. False denies, true or void allows.\n\t */\n\tguards?: TGuards &\n\t\tRecord<\n\t\t\tstring,\n\t\t\tGuard<\n\t\t\t\tnever,\n\t\t\t\tProcedureHookParams<\n\t\t\t\t\tTProcedures,\n\t\t\t\t\tOmit<GuardParams<unknown, TMeta>, 'context' | 'procedure'>\n\t\t\t\t>\n\t\t\t>\n\t\t> &\n\t\tRejectKeys<\n\t\t\tNoInfer<TGuards>,\n\t\t\tReservedOptionKey,\n\t\t\t'orpc-fn: this guard name is a route option'\n\t\t>\n\t/**\n\t * Typed route metadata contract: `meta: defineMeta<AppMeta>()`.\n\t * Route declarations place values inside their own `meta` object.\n\t */\n\tmeta?: TMeta\n\t/** Allowed route tags: `tags: ['internal', 'external']`. */\n\ttags?: readonly TTag[]\n\t/** `import * as otel from '@opentelemetry/api'`. Omit for no tracing. */\n\totel?: TOtel\n\tlogger?: (scope: string, span: SpanOf<TOtel> | undefined) => TLogger\n\t/** Extra span attributes per call; undefined values are skipped. */\n\tspanAttributes?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{ name: string; meta: Partial<TMeta> }\n\t\t>\n\t) => Record<string, AttributeValue | undefined>\n\t/** Called after the procedure (or stream) settles; returned attributes join the `fn.completed` log. */\n\tonCompleted?: (\n\t\tevent: CompletedHookEvent<TProcedures, SpanOf<TOtel>>\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: lets hooks that return nothing type-check\n\t) => LogAttributes | undefined | void\n\t/** Errors that are the caller's fault, logged at `warn`. Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n\t/** Needed for `fnLive` and `createPubSub`. */\n\tpubsub?: PubSubRuntimeOptions\n}\n\ntype Definition<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\tprocedures: TProcedures\n\tdefault: TDefault\n\textras: TExtras\n\textrasByProcedure: TScoped\n\tguards: TGuards\n\tmeta: TMeta\n\ttag: TTag\n\tspan: SpanOf<TOtel>\n\tlogger: TLogger\n}\n\nexport type FnFactory<TDef extends FnDefinition> = {\n\tfn: Fn<TDef>\n\tfnLive: FnLive<TDef>\n\tcreatePubSub: CreatePubSub<TDef>\n\tcreatePublisher: CreatePublisher\n\tcreateRouter: typeof createRouter\n\treadMeta: typeof readFnMeta\n\t/**\n\t * A `call` outside any handler (seeders, scripts, tests), traced with this\n\t * instance's OpenTelemetry.\n\t */\n\tcreateCall: <TContext>(\n\t\tcontext: TContext,\n\t\tsignal?: AbortSignal\n\t) => BoundCall<TContext>\n\t/** Terminal, idempotent shutdown: close streams and await owned resources. */\n\tshutdown: () => Promise<void>\n\tdrainPubSubSubscribers: () => number\n\tactivePubSubSubscriberCount: () => number\n}\n\n/**\n * Builds the app's `fn` and friends once. Everything app-specific (auth,\n * context, database, queues, i18n, permissions) is injected here.\n */\nexport function createFn<\n\tconst TProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string = never,\n\tTExtras extends object = Record<never, never>,\n\tTGuards extends object = Record<never, never>,\n\tTMeta extends object = Record<never, never>,\n\tconst TTag extends string = string,\n\tTOtel extends OtelApiLike | undefined = undefined,\n\tTLogger extends FnLogger = FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n>(\n\toptions: CreateFnOptions<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t> &\n\t\tFiniteExtras<NoInfer<TExtras>>\n): FnFactory<\n\tDefinition<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t>\n> {\n\tconst runtime = options as unknown as RuntimeOptions\n\tconst tracing = createTracing(runtime.otel)\n\tconst defaultLogger = protectLogger(createDefaultLogger('fn'))\n\tconst createLogger = (\n\t\tscope: string,\n\t\tspan: SpanLike | undefined\n\t): FnLogger => {\n\t\ttry {\n\t\t\treturn protectLogger(\n\t\t\t\truntime.logger?.(scope, span) ??\n\t\t\t\t\t(scope === 'fn' ? defaultLogger : createDefaultLogger(scope))\n\t\t\t)\n\t\t} catch {\n\t\t\treturn defaultLogger\n\t\t}\n\t}\n\tconst isExpectedError = runtime.isExpectedError ?? isExpectedClientError\n\tconst guards = runtime.guards ?? {}\n\tconst isGuard = (option: string) => Object.hasOwn(guards, option)\n\tfor (const guard of Object.keys(guards)) {\n\t\tif (typeof guards[guard] !== 'function')\n\t\t\tthrow new TypeError(`orpc-fn: guard ${guard} must be a function`)\n\t\tif ((RESERVED_OPTION_KEYS as readonly string[]).includes(guard)) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: guard \"${guard}\" reuses a route option name; rename it`\n\t\t\t)\n\t\t}\n\t}\n\tif (runtime.default && !Object.hasOwn(runtime.procedures, runtime.default))\n\t\tthrow new TypeError(`orpc-fn: unknown default procedure ${runtime.default}`)\n\tfor (const [key, builder] of Object.entries(runtime.procedures)) {\n\t\tconst def = procedureDefinition(builder)\n\t\tif (def?.inputSchema !== undefined || def?.outputSchema !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: procedure \"${key}\" sets an input or output schema; set schemas on routes instead`\n\t\t\t)\n\t\t}\n\t}\n\n\tconst resolveKey = (procedure: string | undefined, name: string) => {\n\t\tconst key = procedure ?? runtime.default\n\t\tif (key === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: \"${name}\" needs a procedure; createFn has no default`\n\t\t\t)\n\t\t}\n\t\treturn key\n\t}\n\n\tconst buildProcedure = createProcedureAssembler(\n\t\truntime.procedures,\n\t\tresolveKey\n\t)\n\n\tconst invocation = Symbol('orpc-fn.invocation')\n\ttype Invocation = {\n\t\tspan: SpanLike | undefined\n\t\tlogger: FnLogger\n\t\tinput: unknown\n\t\tcontext: unknown\n\t\thandlerStarted: boolean\n\t\trawInput: unknown\n\t}\n\t// The overload-to-runtime boundary is adapted once at the returned factory.\n\tconst fn = (routeOptions: Record<string, unknown>): AnyProcedure => {\n\t\tconst {\n\t\t\thandler,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tname,\n\t\t\tprocedure,\n\t\t\tmeta,\n\t\t\tstream,\n\t\t\terrors,\n\t\t\tguardResolvers,\n\t\t\troute,\n\t\t\tguardChecks\n\t\t} = normalizeRoute(routeOptions, isGuard)\n\t\tconst key = resolveKey(procedure, name)\n\t\tconst built = buildProcedure({\n\t\t\tname,\n\t\t\tprocedure: key,\n\t\t\troute,\n\t\t\tmeta,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tstream,\n\t\t\t...(errors ? { errors } : {}),\n\t\t\thandler: async (params) => {\n\t\t\t\tconst { context, signal } = params\n\t\t\t\tconst state = context[invocation] as Invocation\n\t\t\t\tconst { [invocation]: _invocation, ...observedContext } = context\n\t\t\t\tstate.context = observedContext\n\t\t\t\tstate.input = params.input\n\t\t\t\tstate.handlerStarted = true\n\t\t\t\ttry {\n\t\t\t\t\tconst attributes = runtime.spanAttributes?.({\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta\n\t\t\t\t\t})\n\t\t\t\t\tfor (const [attribute, value] of Object.entries(attributes ?? {}))\n\t\t\t\t\t\tif (value !== undefined) state.span?.setAttribute(attribute, value)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.logger.warn('spanAttributes hook failed', {\n\t\t\t\t\t\terror: errorMessageOf(error)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tconst resolvedChecks = [...guardChecks]\n\t\t\t\tfor (const [guard, resolver] of Object.entries(guardResolvers)) {\n\t\t\t\t\tconst value = await resolver({ input: params.input, context, signal })\n\t\t\t\t\tif (value !== undefined) resolvedChecks.push([guard, value])\n\t\t\t\t}\n\t\t\t\tfor (const [guard, value] of resolvedChecks) {\n\t\t\t\t\tconst result = await guards[guard]?.(value, {\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tsignal\n\t\t\t\t\t})\n\t\t\t\t\tif (result === false)\n\t\t\t\t\t\tthrow new ORPCError('FORBIDDEN', {\n\t\t\t\t\t\t\tmessage: `Guard \"${guard}\" denied this call`\n\t\t\t\t\t\t})\n\t\t\t\t\tif (result !== undefined && result !== true)\n\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t`orpc-fn: guard \"${guard}\" must return void or boolean`\n\t\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst extraParams = {\n\t\t\t\t\tcontext,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tsignal,\n\t\t\t\t\tname,\n\t\t\t\t\tprocedure: key\n\t\t\t\t}\n\t\t\t\tconst shared = await runtime.extras?.(extraParams)\n\t\t\t\tconst scoped = await runtime.extrasByProcedure?.[key]?.(extraParams)\n\t\t\t\tconst extras = {\n\t\t\t\t\t...(shared as object | undefined),\n\t\t\t\t\t...(scoped as object | undefined)\n\t\t\t\t}\n\t\t\t\tif (extras && typeof extras === 'object') {\n\t\t\t\t\tfor (const reserved of [\n\t\t\t\t\t\t'input',\n\t\t\t\t\t\t'context',\n\t\t\t\t\t\t'call',\n\t\t\t\t\t\t'signal',\n\t\t\t\t\t\t'span',\n\t\t\t\t\t\t'logger',\n\t\t\t\t\t\t'errors',\n\t\t\t\t\t\t'lastEventId'\n\t\t\t\t\t]) {\n\t\t\t\t\t\tif (Object.hasOwn(extras, reserved))\n\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t`orpc-fn: extra \"${reserved}\" shadows a handler parameter`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn handler({\n\t\t\t\t\t...(extras as object | undefined),\n\t\t\t\t\tinput: params.input,\n\t\t\t\t\tcontext,\n\t\t\t\t\tcall: createBoundCall(context, signal, tracing),\n\t\t\t\t\tsignal,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tlogger: state.logger,\n\t\t\t\t\terrors: params.errors,\n\t\t\t\t\tlastEventId: params.lastEventId,\n\t\t\t\t\t[RAW_INPUT]: state.rawInput\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t\t// Prepending middleware shifts oRPC's validation indexes, covering auth,\n\t\t// input validation, output validation, and the final stream lifetime.\n\t\treturn os\n\t\t\t.use(async ({ context, next }, rawInput) => {\n\t\t\t\tconst started = performance.now()\n\t\t\t\tconst state: Invocation = {\n\t\t\t\t\tspan: undefined,\n\t\t\t\t\tlogger: defaultLogger,\n\t\t\t\t\tinput: undefined,\n\t\t\t\t\tcontext,\n\t\t\t\t\thandlerStarted: false,\n\t\t\t\t\trawInput\n\t\t\t\t}\n\t\t\t\tconst result = await tracing.inSpan(\n\t\t\t\t\tname,\n\t\t\t\t\t'SERVER',\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\tstate.span = span\n\t\t\t\t\t\tstate.logger = createLogger('fn', span)\n\t\t\t\t\t\tspan?.setAttribute('fn.operation', name)\n\t\t\t\t\t\tspan?.setAttribute('fn.procedure', key)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await next({ context: { [invocation]: state } })\n\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output) !== stream) {\n\t\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output)) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait result.output.return?.()\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t/* Release the unexpected stream. */\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t\t`orpc-fn: ${name} returned a result inconsistent with stream; declare stream: true for iterators`\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn result.output\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tconst timing = (context as Record<symbol, unknown>)[\n\t\t\t\t\t\t\t\tREQUEST_TIMING\n\t\t\t\t\t\t\t] as InvocationTiming | undefined\n\t\t\t\t\t\t\tif (timing && !(context as Record<symbol, unknown>)[invocation]) {\n\t\t\t\t\t\t\t\ttiming.procedureMs += performance.now() - started\n\t\t\t\t\t\t\t\ttiming.calls++\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(span, ...error) => {\n\t\t\t\t\t\tconst durationMs =\n\t\t\t\t\t\t\tMath.round((performance.now() - started) * 100) / 100\n\t\t\t\t\t\tspan?.setAttribute('fn.duration_ms', durationMs)\n\t\t\t\t\t\tlogCompleted(state.logger, {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\t\tsuccess: error.length === 0,\n\t\t\t\t\t\t\terror: error[0],\n\t\t\t\t\t\t\tinput: state.input,\n\t\t\t\t\t\t\tcontext: state.context,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\thandlerStarted: state.handlerStarted\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\treturn { output: result, context }\n\t\t\t})\n\t\t\t.router({ route: built }).route\n\t}\n\n\tconst logCompleted = (logger: FnLogger, event: FnCompletedEvent) => {\n\t\tconst { error, success } = event\n\t\tlet extra: LogAttributes | undefined\n\t\ttry {\n\t\t\textra = runtime.onCompleted?.(event)\n\t\t} catch (hookError) {\n\t\t\tlogger.warn('onCompleted hook failed', {\n\t\t\t\terror: errorMessageOf(hookError)\n\t\t\t})\n\t\t}\n\t\tlet expected = false\n\t\ttry {\n\t\t\texpected = isExpectedError(error)\n\t\t} catch {\n\t\t\texpected = isExpectedClientError(error)\n\t\t}\n\t\tconst level = success ? 'info' : expected ? 'warn' : 'error'\n\t\tlogger[level]('fn.completed', {\n\t\t\t...extra,\n\t\t\tevent: 'fn.completed',\n\t\t\toperation: event.name,\n\t\t\tprocedure: event.procedure,\n\t\t\tduration_ms: event.durationMs,\n\t\t\tstatus: success ? 'success' : 'failed',\n\t\t\t...(error === undefined ? {} : errorAttributes(error))\n\t\t})\n\t}\n\n\tconst live = createLiveRuntime({\n\t\tfn,\n\t\ttracing,\n\t\tcreateLogger,\n\t\tpubsub: runtime.pubsub\n\t})\n\n\t// The runtimes are untyped; `Fn`, `FnLive`, `CreatePubSub` and\n\t// `CreatePublisher` are their typed surface.\n\treturn {\n\t\tfn,\n\t\tfnLive: createFnLive({\n\t\t\tfn,\n\t\t\tcreateChannel: live.createChannel,\n\t\t\tcreateLogger,\n\t\t\tisGuard\n\t\t}),\n\t\tcreatePubSub: live.createPubSub,\n\t\tcreatePublisher: live.createPublisher,\n\t\tcreateRouter,\n\t\treadMeta: readFnMeta,\n\t\tcreateCall: <TContext>(context: TContext, signal?: AbortSignal) =>\n\t\t\tcreateBoundCall(context, signal, tracing),\n\t\tshutdown: live.shutdown,\n\t\tdrainPubSubSubscribers: live.drainPubSubSubscribers,\n\t\tactivePubSubSubscriberCount: live.activePubSubSubscriberCount\n\t} as unknown as FnFactory<\n\t\tDefinition<\n\t\t\tTProcedures,\n\t\t\tTDefault,\n\t\t\tTExtras,\n\t\t\tTGuards,\n\t\t\tTMeta,\n\t\t\tTTag,\n\t\t\tTOtel,\n\t\t\tTLogger,\n\t\t\tTScoped\n\t\t>\n\t>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-fn.js","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype BuilderChain,\n\tcreateProcedureAssembler\n} from './assemble-procedure.js'\nimport { isAsyncIteratorObject } from './stream.js'\nimport { normalizeRoute } from './route-options.js'\nimport { type AnyProcedure, ORPCError, os } from '@orpc/server'\nimport { procedureDefinition } from './compatibility.js'\nimport { type BoundCall, createBoundCall } from './bound-call.js'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport { createFnLive, type FnLive } from './live/fn-live.js'\nimport {\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateLiveRuntime,\n\ttype PubSubRuntimeOptions\n} from './live/pub-sub.js'\nimport {\n\tcreateDefaultLogger,\n\tprotectLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nimport { readFnMeta } from './meta.js'\nimport {\n\ttype AttributeValue,\n\tcreateTracing,\n\terrorAttributes,\n\terrorMessageOf,\n\ttype OtelApiLike,\n\ttype SpanLike,\n\ttype SpanOf\n} from './otel.js'\nimport { RAW_INPUT, REQUEST_TIMING, type InvocationTiming } from './timing.js'\nimport { createRouter } from './router.js'\nimport {\n\ttype ProcedureHookParams,\n\ttype CompletedHookEvent,\n\ttype CurrentContextOf,\n\ttype BuilderLike,\n\ttype FiniteExtras,\n\ttype ScopedExtrasGuard,\n\ttype Fn,\n\ttype FnCompletedEvent,\n\ttype FnDefinition,\n\ttype Guard,\n\ttype GuardParams,\n\ttype MaybePromise,\n\ttype RejectKeys,\n\tRESERVED_OPTION_KEYS,\n\ttype ReservedOptionKey\n} from './types.js'\n\n/** `CreateFnOptions` with the generics erased: what the implementation reads. */\ntype RuntimeOptions = {\n\tprocedures: Record<string, BuilderChain>\n\tdefault?: string\n\textras?: (params: Record<string, unknown>) => unknown\n\textrasByProcedure?: Record<\n\t\tstring,\n\t\t(params: Record<string, unknown>) => unknown\n\t>\n\tguards?: Record<\n\t\tstring,\n\t\t(value: unknown, params: GuardParams<unknown, unknown>) => unknown\n\t>\n\totel?: OtelApiLike\n\tlogger?: (scope: string, span: SpanLike | undefined) => FnLogger\n\tspanAttributes?: (params: {\n\t\tcontext: unknown\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Record<string, unknown>\n\t}) => Record<string, AttributeValue | undefined>\n\tonCompleted?: (event: FnCompletedEvent) => LogAttributes | undefined\n\tisExpectedError?: (error: unknown) => boolean\n\tpubsub?: PubSubRuntimeOptions\n}\n\nexport type CreateFnOptions<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel extends OtelApiLike | undefined,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\t/** Named oRPC builders, e.g. `{ public: os.$context<Ctx>(), protected: authed }`. */\n\tprocedures: TProcedures\n\t/**\n\t * Builder used when a route omits `procedure`. Leave it out to make every\n\t * route name its procedure, so none gets one by accident.\n\t */\n\tdefault?: TDefault\n\t/** Per-call values merged into every handler's params; may be async. */\n\textras?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{\n\t\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\t\tsignal: AbortSignal | undefined\n\t\t\t\tname: string\n\t\t\t}\n\t\t>\n\t) => MaybePromise<TExtras>\n\textrasByProcedure?: {\n\t\t[K in keyof TScoped & keyof TProcedures]: (params: {\n\t\t\tcontext: CurrentContextOf<TProcedures[K]>\n\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\tsignal: AbortSignal | undefined\n\t\t\tname: string\n\t\t\tprocedure: K\n\t\t}) => MaybePromise<TScoped[K] & ScopedExtrasGuard<NoInfer<TScoped[K]>>>\n\t}\n\t/**\n\t * Checks run before the handler; each key becomes a typed `fn()` option.\n\t * Keys must not reuse route options. False denies, true or void allows.\n\t */\n\tguards?: TGuards &\n\t\tRecord<\n\t\t\tstring,\n\t\t\tGuard<\n\t\t\t\tnever,\n\t\t\t\tProcedureHookParams<\n\t\t\t\t\tTProcedures,\n\t\t\t\t\tOmit<GuardParams<unknown, TMeta>, 'context' | 'procedure'>\n\t\t\t\t>\n\t\t\t>\n\t\t> &\n\t\tRejectKeys<\n\t\t\tNoInfer<TGuards>,\n\t\t\tReservedOptionKey,\n\t\t\t'orpc-fn: this guard name is a route option'\n\t\t>\n\t/**\n\t * Typed route metadata contract: `meta: defineMeta<AppMeta>()`.\n\t * Route declarations place values inside their own `meta` object.\n\t */\n\tmeta?: TMeta\n\t/** Allowed route tags: `tags: ['internal', 'external']`. */\n\ttags?: readonly TTag[]\n\t/** `import * as otel from '@opentelemetry/api'`. Omit for no tracing. */\n\totel?: TOtel\n\tlogger?: (scope: string, span: SpanOf<TOtel> | undefined) => TLogger\n\t/** Extra span attributes per call; undefined values are skipped. */\n\tspanAttributes?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{ name: string; meta: Partial<TMeta> }\n\t\t>\n\t) => Record<string, AttributeValue | undefined>\n\t/** Called after the procedure (or stream) settles; returned attributes join the `fn.completed` log. */\n\tonCompleted?: (\n\t\tevent: CompletedHookEvent<TProcedures, SpanOf<TOtel>>\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: lets hooks that return nothing type-check\n\t) => LogAttributes | undefined | void\n\t/** Errors that are the caller's fault, logged at `warn`. Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n\t/** Needed for `fnLive` and `createPubSub`. */\n\tpubsub?: PubSubRuntimeOptions\n}\n\ntype Definition<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\tprocedures: TProcedures\n\tdefault: TDefault\n\textras: TExtras\n\textrasByProcedure: TScoped\n\tguards: TGuards\n\tmeta: TMeta\n\ttag: TTag\n\tspan: SpanOf<TOtel>\n\tlogger: TLogger\n}\n\nexport type FnFactory<TDef extends FnDefinition> = {\n\tfn: Fn<TDef>\n\tfnLive: FnLive<TDef>\n\tcreatePubSub: CreatePubSub<TDef>\n\tcreatePublisher: CreatePublisher\n\tcreateRouter: typeof createRouter\n\treadMeta: typeof readFnMeta\n\t/**\n\t * A `call` outside any handler (seeders, scripts, tests), traced with this\n\t * instance's OpenTelemetry.\n\t */\n\tcreateCall: <TContext>(\n\t\tcontext: TContext,\n\t\tsignal?: AbortSignal\n\t) => BoundCall<TContext>\n\t/** Terminal, idempotent shutdown: close streams and await owned resources. */\n\tshutdown: () => Promise<void>\n\tdrainPubSubSubscribers: () => number\n\tactivePubSubSubscriberCount: () => number\n}\n\n/**\n * Builds the app's `fn` and friends once. Everything app-specific (auth,\n * context, database, queues, i18n, permissions) is injected here.\n */\nexport function createFn<\n\tconst TProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string = never,\n\tTExtras extends object = Record<never, never>,\n\tTGuards extends object = Record<never, never>,\n\tTMeta extends object = Record<never, never>,\n\tconst TTag extends string = string,\n\tTOtel extends OtelApiLike | undefined = undefined,\n\tTLogger extends FnLogger = FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n>(\n\toptions: CreateFnOptions<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t> &\n\t\tFiniteExtras<NoInfer<TExtras>>\n): FnFactory<\n\tDefinition<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t>\n> {\n\tconst runtime = options as unknown as RuntimeOptions\n\tconst tracing = createTracing(runtime.otel)\n\tconst defaultLogger = protectLogger(createDefaultLogger('fn'))\n\tconst createLogger = (\n\t\tscope: string,\n\t\tspan: SpanLike | undefined\n\t): FnLogger => {\n\t\ttry {\n\t\t\treturn protectLogger(\n\t\t\t\truntime.logger?.(scope, span) ??\n\t\t\t\t\t(scope === 'fn' ? defaultLogger : createDefaultLogger(scope))\n\t\t\t)\n\t\t} catch {\n\t\t\treturn defaultLogger\n\t\t}\n\t}\n\tconst isExpectedError = runtime.isExpectedError ?? isExpectedClientError\n\tconst guards = runtime.guards ?? {}\n\tconst isGuard = (option: string) => Object.hasOwn(guards, option)\n\tfor (const guard of Object.keys(guards)) {\n\t\tif (typeof guards[guard] !== 'function')\n\t\t\tthrow new TypeError(`orpc-fn: guard ${guard} must be a function`)\n\t\tif ((RESERVED_OPTION_KEYS as readonly string[]).includes(guard)) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: guard \"${guard}\" reuses a route option name; rename it`\n\t\t\t)\n\t\t}\n\t}\n\tif (runtime.default && !Object.hasOwn(runtime.procedures, runtime.default))\n\t\tthrow new TypeError(`orpc-fn: unknown default procedure ${runtime.default}`)\n\tfor (const [key, builder] of Object.entries(runtime.procedures)) {\n\t\tconst def = procedureDefinition(builder)\n\t\tif (def?.inputSchema !== undefined || def?.outputSchema !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: procedure \"${key}\" sets an input or output schema; set schemas on routes instead`\n\t\t\t)\n\t\t}\n\t}\n\n\tconst resolveKey = (procedure: string | undefined, name: string) => {\n\t\tconst key = procedure ?? runtime.default\n\t\tif (key === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: \"${name}\" needs a procedure; createFn has no default`\n\t\t\t)\n\t\t}\n\t\treturn key\n\t}\n\n\tconst buildProcedure = createProcedureAssembler(\n\t\truntime.procedures,\n\t\tresolveKey\n\t)\n\n\tconst invocation = Symbol('orpc-fn.invocation')\n\ttype Invocation = {\n\t\tspan: SpanLike | undefined\n\t\tlogger: FnLogger\n\t\tinput: unknown\n\t\tcontext: unknown\n\t\thandlerStarted: boolean\n\t\trawInput: unknown\n\t}\n\t// The overload-to-runtime boundary is adapted once at the returned factory.\n\tconst fn = (routeOptions: Record<string, unknown>): AnyProcedure => {\n\t\tconst {\n\t\t\thandler,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tname,\n\t\t\tprocedure,\n\t\t\tmeta,\n\t\t\tstream,\n\t\t\terrors,\n\t\t\tguardResolvers,\n\t\t\troute,\n\t\t\tguardChecks\n\t\t} = normalizeRoute(routeOptions, isGuard)\n\t\tconst key = resolveKey(procedure, name)\n\t\tconst built = buildProcedure({\n\t\t\tname,\n\t\t\tprocedure: key,\n\t\t\troute,\n\t\t\tmeta,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tstream,\n\t\t\t...(errors ? { errors } : {}),\n\t\t\thandler: async (params) => {\n\t\t\t\tconst { context, signal } = params\n\t\t\t\tconst state = context[invocation] as Invocation\n\t\t\t\tconst { [invocation]: _invocation, ...observedContext } = context\n\t\t\t\tstate.context = observedContext\n\t\t\t\tstate.input = params.input\n\t\t\t\tstate.handlerStarted = true\n\t\t\t\ttry {\n\t\t\t\t\tconst attributes = runtime.spanAttributes?.({\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta\n\t\t\t\t\t})\n\t\t\t\t\tfor (const [attribute, value] of Object.entries(attributes ?? {}))\n\t\t\t\t\t\tif (value !== undefined) state.span?.setAttribute(attribute, value)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.logger.warn('spanAttributes hook failed', {\n\t\t\t\t\t\terror: errorMessageOf(error)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tconst resolvedChecks = [...guardChecks]\n\t\t\t\tfor (const [guard, resolver] of Object.entries(guardResolvers)) {\n\t\t\t\t\tconst value = await resolver({ input: params.input, context, signal })\n\t\t\t\t\tif (value !== undefined) resolvedChecks.push([guard, value])\n\t\t\t\t}\n\t\t\t\tfor (const [guard, value] of resolvedChecks) {\n\t\t\t\t\tconst result = await guards[guard]?.(value, {\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tsignal\n\t\t\t\t\t})\n\t\t\t\t\tif (result === false)\n\t\t\t\t\t\tthrow new ORPCError('FORBIDDEN', {\n\t\t\t\t\t\t\tmessage: `Guard \"${guard}\" denied this call`\n\t\t\t\t\t\t})\n\t\t\t\t\tif (result !== undefined && result !== true)\n\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t`orpc-fn: guard \"${guard}\" must return void or boolean`\n\t\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst extraParams = {\n\t\t\t\t\tcontext,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tsignal,\n\t\t\t\t\tname,\n\t\t\t\t\tprocedure: key\n\t\t\t\t}\n\t\t\t\tconst shared = await runtime.extras?.(extraParams)\n\t\t\t\tconst scoped = await runtime.extrasByProcedure?.[key]?.(extraParams)\n\t\t\t\tconst extras = {\n\t\t\t\t\t...(shared as object | undefined),\n\t\t\t\t\t...(scoped as object | undefined)\n\t\t\t\t}\n\t\t\t\tif (extras && typeof extras === 'object') {\n\t\t\t\t\tfor (const reserved of [\n\t\t\t\t\t\t'input',\n\t\t\t\t\t\t'context',\n\t\t\t\t\t\t'call',\n\t\t\t\t\t\t'signal',\n\t\t\t\t\t\t'span',\n\t\t\t\t\t\t'logger',\n\t\t\t\t\t\t'errors',\n\t\t\t\t\t\t'lastEventId'\n\t\t\t\t\t]) {\n\t\t\t\t\t\tif (Object.hasOwn(extras, reserved))\n\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t`orpc-fn: extra \"${reserved}\" shadows a handler parameter`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn handler({\n\t\t\t\t\t...(extras as object | undefined),\n\t\t\t\t\tinput: params.input,\n\t\t\t\t\tcontext,\n\t\t\t\t\tcall: createBoundCall(context, signal, tracing),\n\t\t\t\t\tsignal,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tlogger: state.logger,\n\t\t\t\t\terrors: params.errors,\n\t\t\t\t\tlastEventId: params.lastEventId,\n\t\t\t\t\t[RAW_INPUT]: state.rawInput\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t\t// Prepending middleware shifts oRPC's validation indexes, covering auth,\n\t\t// input validation, output validation, and the final stream lifetime.\n\t\treturn os\n\t\t\t.use(async ({ context, next }, rawInput) => {\n\t\t\t\tconst started = performance.now()\n\t\t\t\tconst state: Invocation = {\n\t\t\t\t\tspan: undefined,\n\t\t\t\t\tlogger: defaultLogger,\n\t\t\t\t\tinput: undefined,\n\t\t\t\t\tcontext,\n\t\t\t\t\thandlerStarted: false,\n\t\t\t\t\trawInput\n\t\t\t\t}\n\t\t\t\tconst result = await tracing.inSpan(\n\t\t\t\t\tname,\n\t\t\t\t\t'SERVER',\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\tstate.span = span\n\t\t\t\t\t\tstate.logger = createLogger('fn', span)\n\t\t\t\t\t\tspan?.setAttribute('fn.operation', name)\n\t\t\t\t\t\tspan?.setAttribute('fn.procedure', key)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await next({ context: { [invocation]: state } })\n\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output) !== stream) {\n\t\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output)) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait result.output.return?.()\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t/* Release the unexpected stream. */\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t\t`orpc-fn: ${name} returned a result inconsistent with stream; declare stream: true for iterators`\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn result.output\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tconst timing = (context as Record<symbol, unknown>)[\n\t\t\t\t\t\t\t\tREQUEST_TIMING\n\t\t\t\t\t\t\t] as InvocationTiming | undefined\n\t\t\t\t\t\t\tif (timing && !(context as Record<symbol, unknown>)[invocation]) {\n\t\t\t\t\t\t\t\ttiming.procedureMs += performance.now() - started\n\t\t\t\t\t\t\t\ttiming.calls++\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(span, ...error) => {\n\t\t\t\t\t\tconst durationMs =\n\t\t\t\t\t\t\tMath.round((performance.now() - started) * 100) / 100\n\t\t\t\t\t\tspan?.setAttribute('fn.duration_ms', durationMs)\n\t\t\t\t\t\tlogCompleted(state.logger, {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\t\tsuccess: error.length === 0,\n\t\t\t\t\t\t\terror: error[0],\n\t\t\t\t\t\t\tinput: state.input,\n\t\t\t\t\t\t\tcontext: state.context,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\thandlerStarted: state.handlerStarted\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\treturn { output: result, context }\n\t\t\t})\n\t\t\t.router({ route: built }).route\n\t}\n\n\tconst logCompleted = (logger: FnLogger, event: FnCompletedEvent) => {\n\t\tconst { error, success } = event\n\t\tlet extra: LogAttributes | undefined\n\t\ttry {\n\t\t\textra = runtime.onCompleted?.(event)\n\t\t} catch (hookError) {\n\t\t\tlogger.warn('onCompleted hook failed', {\n\t\t\t\terror: errorMessageOf(hookError)\n\t\t\t})\n\t\t}\n\t\tlet expected = false\n\t\ttry {\n\t\t\texpected = isExpectedError(error)\n\t\t} catch {\n\t\t\texpected = isExpectedClientError(error)\n\t\t}\n\t\tconst level = success ? 'info' : expected ? 'warn' : 'error'\n\t\tlogger[level]('fn.completed', {\n\t\t\t...extra,\n\t\t\tevent: 'fn.completed',\n\t\t\toperation: event.name,\n\t\t\tprocedure: event.procedure,\n\t\t\tduration_ms: event.durationMs,\n\t\t\tstatus: success ? 'success' : 'failed',\n\t\t\t...(error === undefined ? {} : errorAttributes(error))\n\t\t})\n\t}\n\n\tconst live = createLiveRuntime({\n\t\tfn,\n\t\ttracing,\n\t\tcreateLogger,\n\t\tpubsub: runtime.pubsub\n\t})\n\n\t// The runtimes are untyped; `Fn`, `FnLive`, `CreatePubSub` and\n\t// `CreatePublisher` are their typed surface.\n\treturn {\n\t\tfn,\n\t\tfnLive: createFnLive({\n\t\t\tfn,\n\t\t\tcreateChannel: live.createChannel,\n\t\t\tisGuard\n\t\t}),\n\t\tcreatePubSub: live.createPubSub,\n\t\tcreatePublisher: live.createPublisher,\n\t\tcreateRouter,\n\t\treadMeta: readFnMeta,\n\t\tcreateCall: <TContext>(context: TContext, signal?: AbortSignal) =>\n\t\t\tcreateBoundCall(context, signal, tracing),\n\t\tshutdown: live.shutdown,\n\t\tdrainPubSubSubscribers: live.drainPubSubSubscribers,\n\t\tactivePubSubSubscriberCount: live.activePubSubSubscriberCount\n\t} as unknown as FnFactory<\n\t\tDefinition<\n\t\t\tTProcedures,\n\t\t\tTDefault,\n\t\t\tTExtras,\n\t\t\tTGuards,\n\t\t\tTMeta,\n\t\t\tTTag,\n\t\t\tTOtel,\n\t\t\tTLogger,\n\t\t\tTScoped\n\t\t>\n\t>\n}\n"]}
|
package/dist/hono.d.ts
CHANGED
|
@@ -57,7 +57,10 @@ export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption
|
|
|
57
57
|
plugins?: Plugin<InferRouterInitialContext<R>>[];
|
|
58
58
|
/** Rewrite request headers before they reach the context (see `normalizeExpoOrigin`). */
|
|
59
59
|
normalizeHeaders?: (headers: Headers) => Headers;
|
|
60
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Time spent before the handler ran, reported as `queue`. Default: time
|
|
62
|
+
* since {@link markRequestArrival}, when the server marked the request.
|
|
63
|
+
*/
|
|
61
64
|
queueMs?: (request: Request) => number | undefined;
|
|
62
65
|
/**
|
|
63
66
|
* Unexpected procedure errors (oRPC turns thrown errors into responses, so
|
|
@@ -70,6 +73,14 @@ export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption
|
|
|
70
73
|
/** Default: 4xx `ORPCError` or `AbortError`. */
|
|
71
74
|
isExpectedError?: (error: unknown) => boolean;
|
|
72
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* Marks a request at the server's front door (`Bun.serve({ fetch })`), before
|
|
78
|
+
* routing and middleware. `mountOrpc` reports the time until the procedure
|
|
79
|
+
* runs as `queue_ms`: in-process queueing no handler timer can see.
|
|
80
|
+
*/
|
|
81
|
+
export declare function markRequestArrival(request: Request): void;
|
|
82
|
+
/** Milliseconds since {@link markRequestArrival}, or undefined when unmarked. */
|
|
83
|
+
export declare function msSinceRequestArrival(request: Request): number | undefined;
|
|
73
84
|
/**
|
|
74
85
|
* Expo native sends `expo-origin` but not `origin`; copy it so cookie-based
|
|
75
86
|
* auth (e.g. Better Auth) sees the origin.
|
package/dist/hono.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAA;AAGpE,OAAO,EACN,KAAK,SAAS,EACd,KAAK,yBAAyB,EAE9B,MAAM,cAAc,CAAA;AAGrB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAElE,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAI7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAElD,qFAAqF;AACrF,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAA;AAErE;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,SAAS,IAAI,CAChE,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACjB,IAAI,EAAE,WAAW,KAEf,yBAAyB,CAAC,CAAC,CAAC,GAC5B,QAAQ,GACR,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAA;AAEnD,qFAAqF;AACrF,KAAK,aAAa,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,SAAS,IACpD,WAAW,SAAS,yBAAyB,CAAC,CAAC,CAAC,GAC7C;IAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CAAE,GAClC;IAAE,OAAO,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CAAE,CAAA;AAErC,KAAK,IAAI,GAAG,IAAI,MAAM,EAAE,CAAA;AACxB,KAAK,MAAM,CAAC,CAAC,SAAS,MAAM,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAA;AAExD,MAAM,MAAM,gBAAgB,CAC3B,CAAC,SAAS,GAAG,EACb,CAAC,SAAS,SAAS,IAChB,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IACzB,MAAM,EAAE,CAAC,CAAA;IACT,sEAAsE;IACtE,SAAS,CAAC,EAAE,IAAI,CAAA;IAChB,iEAAiE;IACjE,OAAO,CAAC,EAAE;QACT,MAAM,EAAE,IAAI,CAAA;QACZ,IAAI,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC/D,kFAAkF;QAClF,QAAQ,CAAC,EAAE,IAAI,CAAA;QACf,+DAA+D;QAC/D,MAAM,CAAC,EAAE,eAAe,CAAA;QACxB,sEAAsE;QACtE,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,2EAA2E;QAC3E,IAAI,CAAC,EAAE,IAAI,CAAC,+BAA+B,EAAE,QAAQ,CAAC,CAAA;QACtD,OAAO,CAAC,EAAE,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;KAChD,CAAA;IACD,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IACrC,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAC/B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAChD,yFAAyF;IACzF,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAA;IAChD
|
|
1
|
+
{"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"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"}
|
package/dist/hono.js
CHANGED
|
@@ -7,6 +7,20 @@ import { BatchHandlerPlugin } from '@orpc/server/plugins';
|
|
|
7
7
|
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4';
|
|
8
8
|
import { REQUEST_TIMING } from './timing.js';
|
|
9
9
|
import { isExpectedClientError } from './expected-client-error.js';
|
|
10
|
+
const arrivals = new WeakMap();
|
|
11
|
+
/**
|
|
12
|
+
* Marks a request at the server's front door (`Bun.serve({ fetch })`), before
|
|
13
|
+
* routing and middleware. `mountOrpc` reports the time until the procedure
|
|
14
|
+
* runs as `queue_ms`: in-process queueing no handler timer can see.
|
|
15
|
+
*/
|
|
16
|
+
export function markRequestArrival(request) {
|
|
17
|
+
arrivals.set(request, performance.now());
|
|
18
|
+
}
|
|
19
|
+
/** Milliseconds since {@link markRequestArrival}, or undefined when unmarked. */
|
|
20
|
+
export function msSinceRequestArrival(request) {
|
|
21
|
+
const arrivedAt = arrivals.get(request);
|
|
22
|
+
return arrivedAt === undefined ? undefined : performance.now() - arrivedAt;
|
|
23
|
+
}
|
|
10
24
|
/**
|
|
11
25
|
* Expo native sends `expo-origin` but not `origin`; copy it so cookie-based
|
|
12
26
|
* auth (e.g. Better Auth) sees the origin.
|
|
@@ -73,7 +87,7 @@ export function mountOrpc(app, options) {
|
|
|
73
87
|
const mount = (prefix, handler) => {
|
|
74
88
|
app.use(`${prefix}/*`, async (c, next) => {
|
|
75
89
|
const timing = {};
|
|
76
|
-
const queueMs = options.queueMs
|
|
90
|
+
const queueMs = (options.queueMs ?? msSinceRequestArrival)(c.req.raw);
|
|
77
91
|
if (queueMs !== undefined)
|
|
78
92
|
timing.queue_ms = Math.round(queueMs * 100) / 100;
|
|
79
93
|
const started = performance.now();
|