orpc-fn 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +70 -33
  2. package/dist/assemble-procedure.d.ts +13 -0
  3. package/dist/assemble-procedure.d.ts.map +1 -0
  4. package/dist/assemble-procedure.js +29 -0
  5. package/dist/assemble-procedure.js.map +1 -0
  6. package/dist/bound-call.d.ts +1 -1
  7. package/dist/bound-call.d.ts.map +1 -1
  8. package/dist/bound-call.js.map +1 -1
  9. package/dist/cli.d.ts +3 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +56 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/client.d.ts +4 -2
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +4 -2
  16. package/dist/client.js.map +1 -1
  17. package/dist/compatibility.d.ts +16 -0
  18. package/dist/compatibility.d.ts.map +1 -0
  19. package/dist/compatibility.js +4 -0
  20. package/dist/compatibility.js.map +1 -0
  21. package/dist/create-fn.d.ts +30 -34
  22. package/dist/create-fn.d.ts.map +1 -1
  23. package/dist/create-fn.js +177 -121
  24. package/dist/create-fn.js.map +1 -1
  25. package/dist/expo.d.ts +11 -25
  26. package/dist/expo.d.ts.map +1 -1
  27. package/dist/expo.js +25 -30
  28. package/dist/expo.js.map +1 -1
  29. package/dist/hono.d.ts +12 -4
  30. package/dist/hono.d.ts.map +1 -1
  31. package/dist/hono.js +29 -12
  32. package/dist/hono.js.map +1 -1
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/json-schema.d.ts +2 -0
  38. package/dist/json-schema.d.ts.map +1 -1
  39. package/dist/json-schema.js +11 -0
  40. package/dist/json-schema.js.map +1 -1
  41. package/dist/live/codec.d.ts +6 -1
  42. package/dist/live/codec.d.ts.map +1 -1
  43. package/dist/live/codec.js +14 -3
  44. package/dist/live/codec.js.map +1 -1
  45. package/dist/live/fn-live.d.ts +67 -22
  46. package/dist/live/fn-live.d.ts.map +1 -1
  47. package/dist/live/fn-live.js +98 -16
  48. package/dist/live/fn-live.js.map +1 -1
  49. package/dist/live/index.d.ts +1 -1
  50. package/dist/live/index.d.ts.map +1 -1
  51. package/dist/live/index.js.map +1 -1
  52. package/dist/live/ioredis.d.ts +4 -1
  53. package/dist/live/ioredis.d.ts.map +1 -1
  54. package/dist/live/ioredis.js +21 -2
  55. package/dist/live/ioredis.js.map +1 -1
  56. package/dist/live/lifecycle.d.ts +7 -0
  57. package/dist/live/lifecycle.d.ts.map +1 -0
  58. package/dist/live/lifecycle.js +36 -0
  59. package/dist/live/lifecycle.js.map +1 -0
  60. package/dist/live/memory.d.ts.map +1 -1
  61. package/dist/live/memory.js +4 -0
  62. package/dist/live/memory.js.map +1 -1
  63. package/dist/live/pub-sub.d.ts +81 -13
  64. package/dist/live/pub-sub.d.ts.map +1 -1
  65. package/dist/live/pub-sub.js +437 -126
  66. package/dist/live/pub-sub.js.map +1 -1
  67. package/dist/live/redis-bun.d.ts +1 -1
  68. package/dist/live/redis-bun.d.ts.map +1 -1
  69. package/dist/live/redis-bun.js +3 -5
  70. package/dist/live/redis-bun.js.map +1 -1
  71. package/dist/live/redis.d.ts +2 -2
  72. package/dist/live/redis.d.ts.map +1 -1
  73. package/dist/live/redis.js +36 -9
  74. package/dist/live/redis.js.map +1 -1
  75. package/dist/live/transport.d.ts +5 -1
  76. package/dist/live/transport.d.ts.map +1 -1
  77. package/dist/live/transport.js.map +1 -1
  78. package/dist/logger.d.ts +2 -0
  79. package/dist/logger.d.ts.map +1 -1
  80. package/dist/logger.js +21 -0
  81. package/dist/logger.js.map +1 -1
  82. package/dist/mastra.d.ts.map +1 -1
  83. package/dist/mastra.js +16 -7
  84. package/dist/mastra.js.map +1 -1
  85. package/dist/mcp/core.d.ts +41 -0
  86. package/dist/mcp/core.d.ts.map +1 -0
  87. package/dist/mcp/core.js +61 -0
  88. package/dist/mcp/core.js.map +1 -0
  89. package/dist/mcp/sdk.d.ts +12 -0
  90. package/dist/mcp/sdk.d.ts.map +1 -0
  91. package/dist/mcp/sdk.js +14 -0
  92. package/dist/mcp/sdk.js.map +1 -0
  93. package/dist/mcp/server.d.ts +11 -0
  94. package/dist/mcp/server.d.ts.map +1 -0
  95. package/dist/mcp/server.js +13 -0
  96. package/dist/mcp/server.js.map +1 -0
  97. package/dist/mcp.d.ts +3 -2
  98. package/dist/mcp.d.ts.map +1 -1
  99. package/dist/mcp.js +22 -7
  100. package/dist/mcp.js.map +1 -1
  101. package/dist/meta.d.ts +15 -7
  102. package/dist/meta.d.ts.map +1 -1
  103. package/dist/meta.js +9 -2
  104. package/dist/meta.js.map +1 -1
  105. package/dist/otel.d.ts.map +1 -1
  106. package/dist/otel.js +77 -6
  107. package/dist/otel.js.map +1 -1
  108. package/dist/route-options.d.ts +22 -0
  109. package/dist/route-options.d.ts.map +1 -0
  110. package/dist/route-options.js +67 -0
  111. package/dist/route-options.js.map +1 -0
  112. package/dist/router.d.ts +13 -1
  113. package/dist/router.d.ts.map +1 -1
  114. package/dist/router.js +35 -0
  115. package/dist/router.js.map +1 -1
  116. package/dist/timing.d.ts +8 -0
  117. package/dist/timing.d.ts.map +1 -0
  118. package/dist/timing.js +4 -0
  119. package/dist/timing.js.map +1 -0
  120. package/dist/types.d.ts +96 -41
  121. package/dist/types.d.ts.map +1 -1
  122. package/dist/types.js +6 -2
  123. package/dist/types.js.map +1 -1
  124. package/package.json +28 -3
  125. package/src/assemble-procedure.ts +42 -0
  126. package/src/bound-call.ts +4 -3
  127. package/src/cli.ts +68 -0
  128. package/src/client.ts +9 -2
  129. package/src/compatibility.ts +39 -0
  130. package/src/create-fn.ts +295 -182
  131. package/src/expo.ts +49 -44
  132. package/src/hono.ts +36 -17
  133. package/src/index.ts +7 -2
  134. package/src/json-schema.ts +16 -0
  135. package/src/live/codec.ts +22 -3
  136. package/src/live/fn-live.ts +248 -69
  137. package/src/live/index.ts +2 -0
  138. package/src/live/ioredis.ts +22 -2
  139. package/src/live/lifecycle.ts +44 -0
  140. package/src/live/memory.ts +4 -0
  141. package/src/live/pub-sub.ts +619 -168
  142. package/src/live/redis-bun.ts +7 -5
  143. package/src/live/redis.ts +37 -11
  144. package/src/live/transport.ts +4 -1
  145. package/src/logger.ts +20 -0
  146. package/src/mastra.ts +15 -7
  147. package/src/mcp/core.ts +102 -0
  148. package/src/mcp/sdk.ts +36 -0
  149. package/src/mcp/server.ts +35 -0
  150. package/src/mcp.ts +48 -20
  151. package/src/meta.ts +40 -24
  152. package/src/otel.ts +77 -10
  153. package/src/route-options.ts +100 -0
  154. package/src/router.ts +58 -1
  155. package/src/timing.ts +5 -0
  156. package/src/types.ts +186 -62
@@ -1 +1 @@
1
- {"version":3,"file":"create-fn.js","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnySchema } from '@orpc/contract'\nimport type { AnyProcedure } from '@orpc/server'\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\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nimport {\n\tFN_META_KEY,\n\ttype FnMeta,\n\treadFnMeta,\n\ttype StoredFnMeta\n} from './meta.js'\nimport {\n\ttype AttributeValue,\n\tcreateTracing,\n\terrorMessageOf,\n\ttype OtelApiLike,\n\ttype SpanLike,\n\ttype SpanOf\n} from './otel.js'\nimport { createRouter } from './router.js'\nimport {\n\ttype AnyFnContext,\n\ttype BuilderLike,\n\ttype BuildProcedure,\n\ttype FiniteExtras,\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\tROUTE_OPTION_KEYS,\n\ttype ReservedOptionKey\n} from './types.js'\n\n/** Builder methods `createFn` calls; `BuilderLike` is the public constraint. */\ntype BuilderChain = {\n\troute(route: Record<string, unknown>): BuilderChain\n\tmeta(meta: Record<string, unknown>): BuilderChain\n\tinput(schema: AnySchema): BuilderChain\n\toutput(schema: AnySchema): BuilderChain\n\thandler(handler: Parameters<BuildProcedure>[0]['handler']): AnyProcedure\n}\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\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\ntype UnionContext<TProcedures extends Record<string, BuilderLike>> =\n\tAnyFnContext<{\n\t\tprocedures: TProcedures\n\t\tdefault: string\n\t\textras: object\n\t\tguards: object\n\t\tmeta: object\n\t\ttag: string\n\t\tspan: SpanLike\n\t\tlogger: FnLogger\n\t}>\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> = {\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?: (params: {\n\t\tcontext: UnionContext<TProcedures>\n\t\tspan: SpanOf<TOtel> | undefined\n\t\tsignal: AbortSignal | undefined\n\t\tname: string\n\t\tprocedure: string\n\t}) => MaybePromise<TExtras>\n\t/**\n\t * Checks run before the handler; each key becomes a typed `fn()` option.\n\t * Keys must not reuse route options or meta keys.\n\t */\n\tguards?: TGuards &\n\t\tRecord<\n\t\t\tstring,\n\t\t\tGuard<never, GuardParams<UnionContext<TProcedures>, TMeta>>\n\t\t> &\n\t\tRejectKeys<\n\t\t\tNoInfer<TGuards>,\n\t\t\tReservedOptionKey | keyof NoInfer<TMeta>,\n\t\t\t'orpc-fn: this guard name is a route option or meta key'\n\t\t>\n\t/**\n\t * Typed route metadata: `meta: {} as { readOnly?: boolean }`. Keys become\n\t * `fn()` options and must not reuse route options.\n\t */\n\tmeta?: TMeta &\n\t\tRejectKeys<\n\t\t\tNoInfer<TMeta>,\n\t\t\tReservedOptionKey,\n\t\t\t'orpc-fn: this meta key is a route option'\n\t\t>\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?: (params: {\n\t\tcontext: UnionContext<TProcedures>\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Partial<TMeta>\n\t}) => Record<string, AttributeValue | undefined>\n\t/** Called after every handler; returned attributes join the `fn.completed` log. */\n\tonCompleted?: (\n\t\tevent: FnCompletedEvent<UnionContext<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> = {\n\tprocedures: TProcedures\n\tdefault: TDefault\n\textras: TExtras\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: (procedure: AnyProcedure) => FnMeta<TDef['meta']>\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/** End every open subscription of this instance; returns how many closed. */\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>(\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> &\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>\n> {\n\tconst runtime = options as unknown as RuntimeOptions\n\tconst tracing = createTracing(runtime.otel)\n\tconst defaultLogger = createDefaultLogger('fn')\n\tconst createLogger =\n\t\truntime.logger ??\n\t\t((scope: string) =>\n\t\t\tscope === 'fn' ? defaultLogger : createDefaultLogger(scope))\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 ((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\tfor (const [key, builder] of Object.entries(runtime.procedures)) {\n\t\tconst def = (builder as { '~orpc'?: Record<string, unknown> })['~orpc']\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: BuildProcedure = (route) => {\n\t\tconst key = resolveKey(route.procedure, route.name)\n\t\tlet builder = runtime.procedures[key]\n\t\tif (!builder) throw new Error(`orpc-fn: unknown procedure \"${key}\"`)\n\t\tconst stored: StoredFnMeta = {\n\t\t\tname: route.name,\n\t\t\tprocedure: key,\n\t\t\tmeta: route.meta\n\t\t}\n\t\tbuilder = builder\n\t\t\t.route({\n\t\t\t\toperationId: route.name,\n\t\t\t\t...Object.fromEntries(\n\t\t\t\t\tObject.entries(route.route).filter(([, value]) => value !== undefined)\n\t\t\t\t)\n\t\t\t})\n\t\t\t.meta({ [FN_META_KEY]: stored })\n\t\tif (route.input) builder = builder.input(route.input)\n\t\tif (route.output) builder = builder.output(route.output)\n\t\treturn builder.handler(route.handler)\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: the overloads in `Fn` carry the types\n\tconst fn = (routeOptions: any): AnyProcedure => {\n\t\tconst { handler, input, output, name, procedure, ...rest } = routeOptions\n\t\tconst key = resolveKey(procedure, name)\n\t\tconst route: Record<string, unknown> = {}\n\t\tconst guardChecks: Array<[string, unknown]> = []\n\t\tconst meta: Record<string, unknown> = {}\n\t\tfor (const [option, value] of Object.entries(rest)) {\n\t\t\tif (value === undefined) continue\n\t\t\tif ((ROUTE_OPTION_KEYS as readonly string[]).includes(option))\n\t\t\t\troute[option] = value\n\t\t\telse if (isGuard(option)) guardChecks.push([option, value])\n\t\t\telse meta[option] = value\n\t\t}\n\n\t\treturn 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\thandler: (params) => {\n\t\t\t\tconst { context, signal } = params\n\t\t\t\tconst startTime = performance.now()\n\t\t\t\tconst elapsedMs = () =>\n\t\t\t\t\tMath.round((performance.now() - startTime) * 100) / 100\n\t\t\t\tlet logger: FnLogger = defaultLogger\n\t\t\t\treturn 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\tlogger = 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\tconst attributes = runtime.spanAttributes?.({\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t})\n\t\t\t\t\t\tfor (const [attribute, value] of Object.entries(attributes ?? {})) {\n\t\t\t\t\t\t\tif (value !== undefined) span?.setAttribute(attribute, value)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfor (const [guard, value] of guardChecks) {\n\t\t\t\t\t\t\t\tawait guards[guard]?.(value, {\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t\t\tsignal\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst extras = await runtime.extras?.({\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tprocedure: key\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn await handler({\n\t\t\t\t\t\t\t\t...(extras as object | undefined),\n\t\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tcall: createBoundCall(context, signal, tracing),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tlogger\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t// Server-Timing reports the time until the result (or stream) exists.\n\t\t\t\t\t\t\tconst timing = context.timing\n\t\t\t\t\t\t\tif (typeof timing === 'object' && timing !== null) {\n\t\t\t\t\t\t\t\t;(timing as Record<string, unknown>).handler_ms = elapsedMs()\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// After the result, or after a returned stream ends; before the span ends.\n\t\t\t\t\t(span, ...error) => {\n\t\t\t\t\t\tconst durationMs = elapsedMs()\n\t\t\t\t\t\tspan?.setAttribute('fn.duration_ms', durationMs)\n\t\t\t\t\t\tlogCompleted(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: params.input,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\tconst logCompleted = (logger: FnLogger, event: FnCompletedEvent) => {\n\t\tconst { error, success } = event\n\t\tconst timing = (event.context as { timing?: unknown }).timing\n\t\tconst timingFields: LogAttributes = {}\n\t\tif (typeof timing === 'object' && timing !== null) {\n\t\t\tfor (const [field, value] of Object.entries(timing)) {\n\t\t\t\tif (field !== 'handler_ms' && typeof value === 'number') {\n\t\t\t\t\ttimingFields[field] = value\n\t\t\t\t}\n\t\t\t}\n\t\t}\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\tconst level = success ? 'info' : isExpectedError(error) ? 'warn' : 'error'\n\t\tlogger[level]('fn.completed', {\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...timingFields,\n\t\t\t...(error === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror_type: error instanceof Error ? error.name : typeof error,\n\t\t\t\t\t\terror_message: errorMessageOf(error)\n\t\t\t\t\t}),\n\t\t\t...extra\n\t\t})\n\t}\n\n\tconst live = createLiveRuntime({\n\t\tbuildProcedure,\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: fn as never,\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}) as never,\n\t\tcreatePubSub: live.createPubSub as never,\n\t\tcreatePublisher: live.createPublisher as never,\n\t\tcreateRouter,\n\t\treadMeta: (procedure) => readFnMeta(procedure),\n\t\tcreateCall: (context, signal) => createBoundCall(context, signal, tracing),\n\t\tdrainPubSubSubscribers: live.drainPubSubSubscribers,\n\t\tactivePubSubSubscriberCount: live.activePubSubSubscriberCount\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\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\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror_type: error instanceof Error ? error.name : typeof error,\n\t\t\t\t\t\terror_message: errorMessageOf(error)\n\t\t\t\t\t})\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"]}
package/dist/expo.d.ts CHANGED
@@ -31,36 +31,22 @@ export declare function createExpoFetch(options: {
31
31
  fetch: ExpoFetch;
32
32
  /** `Platform.OS !== 'web'`. */
33
33
  native: boolean;
34
+ webFetch?: (request: Request, init?: RequestInit) => Promise<Response>;
34
35
  }): (request: Request, init?: {
35
36
  redirect?: NonNullable<RequestInit['redirect']>;
36
37
  }) => Promise<Response>;
37
- export type CreateExpoLinkOptions<T extends ClientContext> = Omit<CreateRpcLinkOptions<T>, 'fetch' | 'headers'> & {
38
+ export type CreateExpoLinkOptions<T extends ClientContext> = Omit<CreateRpcLinkOptions<T>, 'fetch'> & {
38
39
  fetch: ExpoFetch;
39
40
  native: boolean;
40
- /** Session cookie, e.g. Better Auth's `authClient.getCookie()`. */
41
- getCookie?: () => string | null | undefined;
42
- /** `expo-origin` header; the server copies it to `origin` (`normalizeExpoOrigin`). */
43
- getExpoOrigin?: () => string | null | undefined;
44
- /** Extra headers on every request. */
45
- headers?: () => Record<string, string>;
41
+ /** Explicit browser fetch override; native always uses expo/fetch. */
42
+ webFetch?: (request: Request, init?: RequestInit) => Promise<Response>;
46
43
  };
47
- /**
48
- * `createRpcLink` for Expo: batching, the `expo/fetch` bridge and the headers
49
- * a Better Auth Expo client sends, so the API sees the same session and
50
- * origin as `/api/auth` requests.
51
- *
52
- * ```ts
53
- * import { fetch } from 'expo/fetch'
54
- * import { Platform } from 'react-native'
55
- *
56
- * const link = createExpoLink({
57
- * url: `${baseUrl}/api/rpc`,
58
- * fetch,
59
- * native: Platform.OS !== 'web',
60
- * getCookie: () => authClient.getCookie(),
61
- * getExpoOrigin
62
- * })
63
- * ```
64
- */
44
+ /** Generic streaming bridge with upstream async/context-aware headers. */
65
45
  export declare function createExpoLink<T extends ClientContext = ClientContext>(options: CreateExpoLinkOptions<T>): RPCLink<T>;
46
+ export type CreateBetterAuthExpoLinkOptions<T extends ClientContext> = CreateExpoLinkOptions<T> & {
47
+ getCookie?: () => string | null | undefined | Promise<string | null | undefined>;
48
+ getExpoOrigin?: () => string | null | undefined | Promise<string | null | undefined>;
49
+ };
50
+ /** Better Auth's native cookie/origin headers, kept behind an explicit preset. */
51
+ export declare function createBetterAuthExpoLink<T extends ClientContext = ClientContext>(options: CreateBetterAuthExpoLinkOptions<T>): RPCLink<T>;
66
52
  //# sourceMappingURL=expo.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAEtE,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAC/C,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,QAAQ,EACR,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAC5D,CAAA;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,KACf,OAAO,CAAC,YAAY,CAAC,CAAA;AAE1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAA;CACf,aAEU,OAAO,SACT;IAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAAE,KACxD,OAAO,CAAC,QAAQ,CAAC,CAkBpB;AAED,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,aAAa,IAAI,IAAI,CAChE,oBAAoB,CAAC,CAAC,CAAC,EACvB,OAAO,GAAG,SAAS,CACnB,GAAG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAC3C,sFAAsF;IACtF,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAC/C,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACrE,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CAyBZ"}
1
+ {"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAEtE,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAC/C,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,QAAQ,EACR,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAC5D,CAAA;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,KACf,OAAO,CAAC,YAAY,CAAC,CAAA;AAE1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtE,aAEU,OAAO,SACT;IAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAAE,KACxD,OAAO,CAAC,QAAQ,CAAC,CAqBpB;AAED,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,aAAa,IAAI,IAAI,CAChE,oBAAoB,CAAC,CAAC,CAAC,EACvB,OAAO,CACP,GAAG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtE,CAAA;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACrE,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CAMZ;AAED,MAAM,MAAM,+BAA+B,CAAC,CAAC,SAAS,aAAa,IAClE,qBAAqB,CAAC,CAAC,CAAC,GAAG;IAC1B,SAAS,CAAC,EAAE,MACT,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACrC,aAAa,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CACrC,CAAA;AAEF,kFAAkF;AAClF,wBAAgB,wBAAwB,CACvC,CAAC,SAAS,aAAa,GAAG,aAAa,EACtC,OAAO,EAAE,+BAA+B,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBzD"}
package/dist/expo.js CHANGED
@@ -15,7 +15,10 @@ import { createRpcLink } from './client.js';
15
15
  export function createExpoFetch(options) {
16
16
  return async (request, init) => {
17
17
  if (!options.native) {
18
- return globalThis.fetch(request, { ...init, credentials: 'include' });
18
+ return (options.webFetch ?? globalThis.fetch)(request, {
19
+ ...init,
20
+ credentials: 'include'
21
+ });
19
22
  }
20
23
  const hasBody = request.method !== 'GET' && request.method !== 'HEAD';
21
24
  const body = hasBody ? await request.arrayBuffer() : undefined;
@@ -32,40 +35,32 @@ export function createExpoFetch(options) {
32
35
  return response;
33
36
  };
34
37
  }
35
- /**
36
- * `createRpcLink` for Expo: batching, the `expo/fetch` bridge and the headers
37
- * a Better Auth Expo client sends, so the API sees the same session and
38
- * origin as `/api/auth` requests.
39
- *
40
- * ```ts
41
- * import { fetch } from 'expo/fetch'
42
- * import { Platform } from 'react-native'
43
- *
44
- * const link = createExpoLink({
45
- * url: `${baseUrl}/api/rpc`,
46
- * fetch,
47
- * native: Platform.OS !== 'web',
48
- * getCookie: () => authClient.getCookie(),
49
- * getExpoOrigin
50
- * })
51
- * ```
52
- */
38
+ /** Generic streaming bridge with upstream async/context-aware headers. */
53
39
  export function createExpoLink(options) {
54
- const { fetch, native, getCookie, getExpoOrigin, headers: extraHeaders, ...rest } = options;
40
+ const { fetch, native, webFetch, ...rest } = options;
55
41
  return createRpcLink({
56
42
  ...rest,
57
- fetch: createExpoFetch({ fetch, native }),
58
- headers: () => {
59
- const headers = { ...extraHeaders?.() };
60
- const cookie = getCookie?.();
43
+ fetch: createExpoFetch({ fetch, native, ...(webFetch ? { webFetch } : {}) })
44
+ });
45
+ }
46
+ /** Better Auth's native cookie/origin headers, kept behind an explicit preset. */
47
+ export function createBetterAuthExpoLink(options) {
48
+ const { getCookie, getExpoOrigin, headers: extraHeaders, ...rest } = options;
49
+ return createExpoLink({
50
+ ...rest,
51
+ headers: async (...args) => {
52
+ const supplied = typeof extraHeaders === 'function'
53
+ ? await extraHeaders(...args)
54
+ : await extraHeaders;
55
+ const headers = new Headers(supplied);
56
+ const cookie = await getCookie?.();
61
57
  if (cookie)
62
- headers.Cookie = cookie;
63
- if (native) {
64
- // What @better-auth/expo sends from native, for session and CORS parity.
65
- headers['x-skip-oauth-proxy'] = 'true';
66
- const origin = getExpoOrigin?.();
58
+ headers.set('Cookie', cookie);
59
+ if (options.native) {
60
+ headers.set('x-skip-oauth-proxy', 'true');
61
+ const origin = await getExpoOrigin?.();
67
62
  if (origin)
68
- headers['expo-origin'] = origin;
63
+ headers.set('expo-origin', origin);
69
64
  }
70
65
  return headers;
71
66
  }
package/dist/expo.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"expo.js","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,aAAa,EAAE,MAAM,aAAa,CAAA;AAwBtE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,OAI/B;IACA,OAAO,KAAK,EACX,OAAgB,EAChB,IAA0D,EACtC,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAA;QACtE,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAA;QACrE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QAC9D,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACjD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACtD,GAAG,IAAI;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,MAAM;SACnB,CAAC,CAAA;QACF,yEAAyE;QACzE,oEAAoE;QACpE,OAAO,QAAoB,CAAA;IAC5B,CAAC,CAAA;AACF,CAAC;AAgBD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,cAAc,CAC7B,OAAiC;IAEjC,MAAM,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,aAAa,EACb,OAAO,EAAE,YAAY,EACrB,GAAG,IAAI,EACP,GAAG,OAAO,CAAA;IACX,OAAO,aAAa,CAAI;QACvB,GAAG,IAAI;QACP,KAAK,EAAE,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACzC,OAAO,EAAE,GAAG,EAAE;YACb,MAAM,OAAO,GAA2B,EAAE,GAAG,YAAY,EAAE,EAAE,EAAE,CAAA;YAC/D,MAAM,MAAM,GAAG,SAAS,EAAE,EAAE,CAAA;YAC5B,IAAI,MAAM;gBAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA;YACnC,IAAI,MAAM,EAAE,CAAC;gBACZ,yEAAyE;gBACzE,OAAO,CAAC,oBAAoB,CAAC,GAAG,MAAM,CAAA;gBACtC,MAAM,MAAM,GAAG,aAAa,EAAE,EAAE,CAAA;gBAChC,IAAI,MAAM;oBAAE,OAAO,CAAC,aAAa,CAAC,GAAG,MAAM,CAAA;YAC5C,CAAC;YACD,OAAO,OAAO,CAAA;QACf,CAAC;KACD,CAAC,CAAA;AACH,CAAC","sourcesContent":["import type { ClientContext } from '@orpc/client'\nimport type { RPCLink } from '@orpc/client/fetch'\nimport { type CreateRpcLinkOptions, createRpcLink } from './client.js'\n\n/** What `fetch` from `expo/fetch` accepts from this bridge. */\nexport type ExpoFetchInit = {\n\tmethod: string\n\theaders: Record<string, string>\n\tbody?: ArrayBuffer\n\tsignal: AbortSignal\n\tcredentials: 'omit'\n\tredirect?: NonNullable<RequestInit['redirect']>\n}\n\n/** The response members oRPC reads; `expo/fetch`'s `FetchResponse` has them. */\nexport type ExpoResponse = Pick<\n\tResponse,\n\t'status' | 'headers' | 'body' | 'text' | 'blob' | 'formData'\n>\n\n/** `fetch` from `expo/fetch` (the only fetch that streams on native). */\nexport type ExpoFetch = (\n\turl: string,\n\tinit: ExpoFetchInit\n) => Promise<ExpoResponse>\n\n/**\n * oRPC's link `fetch` for React Native, built on `expo/fetch`.\n *\n * oRPC carries the input and the abort signal on the `Request`, not in\n * `init`, and the call is rebuilt for `expo/fetch`, so both are forwarded\n * explicitly: the body so the server receives the input, and the signal so a\n * cancelled subscription closes its socket. Without the signal, connections\n * leak and exhaust the device's HTTP pool after a few navigations, and every\n * later request hangs.\n *\n * Native sends cookies by header (see `createExpoLink`), so it omits the\n * credentialed cookie jar. On web it uses the platform `fetch` with cookies.\n */\nexport function createExpoFetch(options: {\n\tfetch: ExpoFetch\n\t/** `Platform.OS !== 'web'`. */\n\tnative: boolean\n}) {\n\treturn async (\n\t\trequest: Request,\n\t\tinit?: { redirect?: NonNullable<RequestInit['redirect']> }\n\t): Promise<Response> => {\n\t\tif (!options.native) {\n\t\t\treturn globalThis.fetch(request, { ...init, credentials: 'include' })\n\t\t}\n\t\tconst hasBody = request.method !== 'GET' && request.method !== 'HEAD'\n\t\tconst body = hasBody ? await request.arrayBuffer() : undefined\n\t\tconst response = await options.fetch(request.url, {\n\t\t\tmethod: request.method,\n\t\t\theaders: Object.fromEntries(request.headers.entries()),\n\t\t\t...init,\n\t\t\t...(body === undefined ? {} : { body }),\n\t\t\tsignal: request.signal,\n\t\t\tcredentials: 'omit'\n\t\t})\n\t\t// Not rebuilt with `new Response(...)`: React Native's Response polyfill\n\t\t// cannot stream a body. oRPC reads only the `ExpoResponse` members.\n\t\treturn response as Response\n\t}\n}\n\nexport type CreateExpoLinkOptions<T extends ClientContext> = Omit<\n\tCreateRpcLinkOptions<T>,\n\t'fetch' | 'headers'\n> & {\n\tfetch: ExpoFetch\n\tnative: boolean\n\t/** Session cookie, e.g. Better Auth's `authClient.getCookie()`. */\n\tgetCookie?: () => string | null | undefined\n\t/** `expo-origin` header; the server copies it to `origin` (`normalizeExpoOrigin`). */\n\tgetExpoOrigin?: () => string | null | undefined\n\t/** Extra headers on every request. */\n\theaders?: () => Record<string, string>\n}\n\n/**\n * `createRpcLink` for Expo: batching, the `expo/fetch` bridge and the headers\n * a Better Auth Expo client sends, so the API sees the same session and\n * origin as `/api/auth` requests.\n *\n * ```ts\n * import { fetch } from 'expo/fetch'\n * import { Platform } from 'react-native'\n *\n * const link = createExpoLink({\n * url: `${baseUrl}/api/rpc`,\n * fetch,\n * native: Platform.OS !== 'web',\n * getCookie: () => authClient.getCookie(),\n * getExpoOrigin\n * })\n * ```\n */\nexport function createExpoLink<T extends ClientContext = ClientContext>(\n\toptions: CreateExpoLinkOptions<T>\n): RPCLink<T> {\n\tconst {\n\t\tfetch,\n\t\tnative,\n\t\tgetCookie,\n\t\tgetExpoOrigin,\n\t\theaders: extraHeaders,\n\t\t...rest\n\t} = options\n\treturn createRpcLink<T>({\n\t\t...rest,\n\t\tfetch: createExpoFetch({ fetch, native }),\n\t\theaders: () => {\n\t\t\tconst headers: Record<string, string> = { ...extraHeaders?.() }\n\t\t\tconst cookie = getCookie?.()\n\t\t\tif (cookie) headers.Cookie = cookie\n\t\t\tif (native) {\n\t\t\t\t// What @better-auth/expo sends from native, for session and CORS parity.\n\t\t\t\theaders['x-skip-oauth-proxy'] = 'true'\n\t\t\t\tconst origin = getExpoOrigin?.()\n\t\t\t\tif (origin) headers['expo-origin'] = origin\n\t\t\t}\n\t\t\treturn headers\n\t\t}\n\t})\n}\n"]}
1
+ {"version":3,"file":"expo.js","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,aAAa,EAAE,MAAM,aAAa,CAAA;AAwBtE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,OAK/B;IACA,OAAO,KAAK,EACX,OAAgB,EAChB,IAA0D,EACtC,EAAE;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACrB,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE;gBACtD,GAAG,IAAI;gBACP,WAAW,EAAE,SAAS;aACtB,CAAC,CAAA;QACH,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAA;QACrE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;QAC9D,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACjD,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACtD,GAAG,IAAI;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,MAAM;SACnB,CAAC,CAAA;QACF,yEAAyE;QACzE,oEAAoE;QACpE,OAAO,QAAoB,CAAA;IAC5B,CAAC,CAAA;AACF,CAAC;AAYD,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAC7B,OAAiC;IAEjC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAA;IACpD,OAAO,aAAa,CAAI;QACvB,GAAG,IAAI;QACP,KAAK,EAAE,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;KAC5E,CAAC,CAAA;AACH,CAAC;AAgBD,kFAAkF;AAClF,MAAM,UAAU,wBAAwB,CAEtC,OAA2C;IAC5C,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAA;IAC5E,OAAO,cAAc,CAAI;QACxB,GAAG,IAAI;QACP,OAAO,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;YAC1B,MAAM,QAAQ,GACb,OAAO,YAAY,KAAK,UAAU;gBACjC,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,IAAI,CAAC;gBAC7B,CAAC,CAAC,MAAM,YAAY,CAAA;YACtB,MAAM,OAAO,GAAG,IAAI,OAAO,CAC1B,QAAoD,CACpD,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,EAAE,CAAA;YAClC,IAAI,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YACzC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAA;gBACzC,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,EAAE,CAAA;gBACtC,IAAI,MAAM;oBAAE,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;YAC/C,CAAC;YACD,OAAO,OAAO,CAAA;QACf,CAAC;KACD,CAAC,CAAA;AACH,CAAC","sourcesContent":["import type { ClientContext } from '@orpc/client'\nimport type { RPCLink } from '@orpc/client/fetch'\nimport { type CreateRpcLinkOptions, createRpcLink } from './client.js'\n\n/** What `fetch` from `expo/fetch` accepts from this bridge. */\nexport type ExpoFetchInit = {\n\tmethod: string\n\theaders: Record<string, string>\n\tbody?: ArrayBuffer\n\tsignal: AbortSignal\n\tcredentials: 'omit'\n\tredirect?: NonNullable<RequestInit['redirect']>\n}\n\n/** The response members oRPC reads; `expo/fetch`'s `FetchResponse` has them. */\nexport type ExpoResponse = Pick<\n\tResponse,\n\t'status' | 'headers' | 'body' | 'text' | 'blob' | 'formData'\n>\n\n/** `fetch` from `expo/fetch` (the only fetch that streams on native). */\nexport type ExpoFetch = (\n\turl: string,\n\tinit: ExpoFetchInit\n) => Promise<ExpoResponse>\n\n/**\n * oRPC's link `fetch` for React Native, built on `expo/fetch`.\n *\n * oRPC carries the input and the abort signal on the `Request`, not in\n * `init`, and the call is rebuilt for `expo/fetch`, so both are forwarded\n * explicitly: the body so the server receives the input, and the signal so a\n * cancelled subscription closes its socket. Without the signal, connections\n * leak and exhaust the device's HTTP pool after a few navigations, and every\n * later request hangs.\n *\n * Native sends cookies by header (see `createExpoLink`), so it omits the\n * credentialed cookie jar. On web it uses the platform `fetch` with cookies.\n */\nexport function createExpoFetch(options: {\n\tfetch: ExpoFetch\n\t/** `Platform.OS !== 'web'`. */\n\tnative: boolean\n\twebFetch?: (request: Request, init?: RequestInit) => Promise<Response>\n}) {\n\treturn async (\n\t\trequest: Request,\n\t\tinit?: { redirect?: NonNullable<RequestInit['redirect']> }\n\t): Promise<Response> => {\n\t\tif (!options.native) {\n\t\t\treturn (options.webFetch ?? globalThis.fetch)(request, {\n\t\t\t\t...init,\n\t\t\t\tcredentials: 'include'\n\t\t\t})\n\t\t}\n\t\tconst hasBody = request.method !== 'GET' && request.method !== 'HEAD'\n\t\tconst body = hasBody ? await request.arrayBuffer() : undefined\n\t\tconst response = await options.fetch(request.url, {\n\t\t\tmethod: request.method,\n\t\t\theaders: Object.fromEntries(request.headers.entries()),\n\t\t\t...init,\n\t\t\t...(body === undefined ? {} : { body }),\n\t\t\tsignal: request.signal,\n\t\t\tcredentials: 'omit'\n\t\t})\n\t\t// Not rebuilt with `new Response(...)`: React Native's Response polyfill\n\t\t// cannot stream a body. oRPC reads only the `ExpoResponse` members.\n\t\treturn response as Response\n\t}\n}\n\nexport type CreateExpoLinkOptions<T extends ClientContext> = Omit<\n\tCreateRpcLinkOptions<T>,\n\t'fetch'\n> & {\n\tfetch: ExpoFetch\n\tnative: boolean\n\t/** Explicit browser fetch override; native always uses expo/fetch. */\n\twebFetch?: (request: Request, init?: RequestInit) => Promise<Response>\n}\n\n/** Generic streaming bridge with upstream async/context-aware headers. */\nexport function createExpoLink<T extends ClientContext = ClientContext>(\n\toptions: CreateExpoLinkOptions<T>\n): RPCLink<T> {\n\tconst { fetch, native, webFetch, ...rest } = options\n\treturn createRpcLink<T>({\n\t\t...rest,\n\t\tfetch: createExpoFetch({ fetch, native, ...(webFetch ? { webFetch } : {}) })\n\t})\n}\n\nexport type CreateBetterAuthExpoLinkOptions<T extends ClientContext> =\n\tCreateExpoLinkOptions<T> & {\n\t\tgetCookie?: () =>\n\t\t\t| string\n\t\t\t| null\n\t\t\t| undefined\n\t\t\t| Promise<string | null | undefined>\n\t\tgetExpoOrigin?: () =>\n\t\t\t| string\n\t\t\t| null\n\t\t\t| undefined\n\t\t\t| Promise<string | null | undefined>\n\t}\n\n/** Better Auth's native cookie/origin headers, kept behind an explicit preset. */\nexport function createBetterAuthExpoLink<\n\tT extends ClientContext = ClientContext\n>(options: CreateBetterAuthExpoLinkOptions<T>): RPCLink<T> {\n\tconst { getCookie, getExpoOrigin, headers: extraHeaders, ...rest } = options\n\treturn createExpoLink<T>({\n\t\t...rest,\n\t\theaders: async (...args) => {\n\t\t\tconst supplied =\n\t\t\t\ttypeof extraHeaders === 'function'\n\t\t\t\t\t? await extraHeaders(...args)\n\t\t\t\t\t: await extraHeaders\n\t\t\tconst headers = new Headers(\n\t\t\t\tsupplied as ConstructorParameters<typeof Headers>[0]\n\t\t\t)\n\t\t\tconst cookie = await getCookie?.()\n\t\t\tif (cookie) headers.set('Cookie', cookie)\n\t\t\tif (options.native) {\n\t\t\t\theaders.set('x-skip-oauth-proxy', 'true')\n\t\t\t\tconst origin = await getExpoOrigin?.()\n\t\t\t\tif (origin) headers.set('expo-origin', origin)\n\t\t\t}\n\t\t\treturn headers\n\t\t}\n\t})\n}\n"]}
package/dist/hono.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { OpenAPIGeneratorGenerateOptions } from '@orpc/openapi';
1
2
  import { type AnyRouter, type InferRouterInitialContext } from '@orpc/server';
2
3
  import type { StandardHandlerPlugin } from '@orpc/server/standard';
3
4
  import type { Context as HonoContext, Env, Hono } from 'hono';
@@ -21,7 +22,7 @@ type ContextOption<E extends Env, R extends AnyRouter> = BaseContext extends Inf
21
22
  context: ContextFactory<E, R>;
22
23
  };
23
24
  type Path = `/${string}`;
24
- type Plugin = StandardHandlerPlugin<any>;
25
+ type Plugin<T extends object> = StandardHandlerPlugin<T>;
25
26
  export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption<E, R> & {
26
27
  router: R;
27
28
  /** Mount the RPC handler (oRPC's `RPCLink`) here. Omit to skip it. */
@@ -41,8 +42,8 @@ export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption
41
42
  /** Turn JSON strings back into `Date`s etc. for `z.date()` inputs. */
42
43
  smartCoercion?: boolean;
43
44
  /** Extra spec fields, e.g. `components.securitySchemes` and `security`. */
44
- spec?: Record<string, unknown>;
45
- plugins?: Plugin[];
45
+ spec?: Omit<OpenAPIGeneratorGenerateOptions, 'filter'>;
46
+ plugins?: Plugin<InferRouterInitialContext<R>>[];
46
47
  };
47
48
  /** Collapse parallel RPC calls into one HTTP request. Default: true (25 calls). */
48
49
  batch?: boolean | {
@@ -53,7 +54,7 @@ export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption
53
54
  /** SSE keep-alive comments every N ms (default 15000), or false. */
54
55
  sseKeepAlive?: boolean | number;
55
56
  /** Extra RPC plugins (e.g. `CORSPlugin`). */
56
- plugins?: Plugin[];
57
+ plugins?: Plugin<InferRouterInitialContext<R>>[];
57
58
  /** Rewrite request headers before they reach the context (see `normalizeExpoOrigin`). */
58
59
  normalizeHeaders?: (headers: Headers) => Headers;
59
60
  /** Time spent before the handler ran, reported as `queue`. */
@@ -75,6 +76,13 @@ export type MountOrpcOptions<E extends Env, R extends AnyRouter> = ContextOption
75
76
  */
76
77
  export declare function normalizeExpoOrigin(raw: Headers): Headers;
77
78
  export declare function formatServerTiming(totalMs: number, timing: Record<string, number | undefined>): string;
79
+ /**
80
+ * Response headers plus Server-Timing. For SSE, also disable proxy buffering
81
+ * so keep-alive comments reach the edge (empty `:` lines are otherwise easy
82
+ * for nginx/Fastly to hold until an idle kill). A copy: some responses (e.g.
83
+ * redirects) have immutable headers.
84
+ */
85
+ export declare function finishOrpcHeaders(response: Response, serverTiming: string | undefined): Headers;
78
86
  /** Mount oRPC's RPC and OpenAPI handlers on a Hono app. */
79
87
  export declare function mountOrpc<E extends Env, R extends AnyRouter>(app: Hono<E>, options: MountOrpcOptions<E, R>): void;
80
88
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hono.d.ts","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"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"}
package/dist/hono.js CHANGED
@@ -5,6 +5,7 @@ import { onError as orpcOnError } from '@orpc/server';
5
5
  import { RPCHandler } from '@orpc/server/fetch';
6
6
  import { BatchHandlerPlugin } from '@orpc/server/plugins';
7
7
  import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4';
8
+ import { REQUEST_TIMING } from './timing.js';
8
9
  import { isExpectedClientError } from './expected-client-error.js';
9
10
  /**
10
11
  * Expo native sends `expo-origin` but not `origin`; copy it so cookie-based
@@ -33,7 +34,7 @@ export function formatServerTiming(totalMs, timing) {
33
34
  * for nginx/Fastly to hold until an idle kill). A copy: some responses (e.g.
34
35
  * redirects) have immutable headers.
35
36
  */
36
- function finishHeaders(response, serverTiming) {
37
+ export function finishOrpcHeaders(response, serverTiming) {
37
38
  const headers = new Headers(response.headers);
38
39
  if (serverTiming) {
39
40
  headers.set('Server-Timing', serverTiming);
@@ -57,12 +58,17 @@ export function mountOrpc(app, options) {
57
58
  eventIteratorKeepAliveInterval: sseKeepAlive === true ? 15_000 : sseKeepAlive
58
59
  };
59
60
  const report = (error, { request }) => {
60
- if (isExpectedError(error))
61
- return;
62
- options.onError?.(error, {
63
- url: request.url.pathname,
64
- method: request.method
65
- });
61
+ try {
62
+ if (isExpectedError(error))
63
+ return;
64
+ options.onError?.(error, {
65
+ url: request.url.pathname,
66
+ method: request.method
67
+ });
68
+ }
69
+ catch {
70
+ /* Error reporting cannot replace transport outcomes. */
71
+ }
66
72
  };
67
73
  const mount = (prefix, handler) => {
68
74
  app.use(`${prefix}/*`, async (c, next) => {
@@ -79,24 +85,33 @@ export function mountOrpc(app, options) {
79
85
  : { headers, timing };
80
86
  if (context instanceof Response)
81
87
  return context;
88
+ const invocationTiming = { procedureMs: 0, calls: 0 };
82
89
  const { matched, response } = await handler.handle(c.req.raw, {
83
90
  prefix,
84
- context: context
91
+ context: {
92
+ ...context,
93
+ [REQUEST_TIMING]: invocationTiming
94
+ }
85
95
  });
86
96
  if (!matched)
87
97
  return next();
88
98
  const timed = serverTiming
89
- ? formatServerTiming(performance.now() - started, timing)
99
+ ? formatServerTiming(performance.now() - started, {
100
+ ...timing,
101
+ handler_ms: invocationTiming.procedureMs
102
+ })
90
103
  : undefined;
91
104
  return c.newResponse(response.body, {
92
105
  // oRPC only produces valid HTTP status codes.
93
106
  status: response.status,
94
- headers: finishHeaders(response, timed)
107
+ headers: finishOrpcHeaders(response, timed)
95
108
  });
96
109
  });
97
110
  };
98
111
  if (options.rpcPrefix) {
99
- const plugins = [...(options.plugins ?? [])];
112
+ const plugins = [
113
+ ...(options.plugins ?? [])
114
+ ];
100
115
  if (batch) {
101
116
  plugins.push(new BatchHandlerPlugin({
102
117
  maxSize: batch === true ? 25 : batch.maxSize
@@ -112,7 +127,9 @@ export function mountOrpc(app, options) {
112
127
  const { openapi } = options;
113
128
  const filter = openapi.filter ? { filter: openapi.filter } : {};
114
129
  const converters = [new ZodToJsonSchemaConverter()];
115
- const plugins = [...(openapi.plugins ?? [])];
130
+ const plugins = [
131
+ ...(openapi.plugins ?? [])
132
+ ];
116
133
  if (openapi.smartCoercion) {
117
134
  plugins.push(new SmartCoercionPlugin({ schemaConverters: converters }));
118
135
  }
package/dist/hono.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"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","sourcesContent":["import { SmartCoercionPlugin } from '@orpc/json-schema'\nimport { OpenAPIHandler } from '@orpc/openapi/fetch'\nimport { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'\nimport {\n\ttype AnyRouter,\n\ttype InferRouterInitialContext,\n\tonError as orpcOnError\n} from '@orpc/server'\nimport { RPCHandler } from '@orpc/server/fetch'\nimport { BatchHandlerPlugin } from '@orpc/server/plugins'\nimport type { StandardHandlerPlugin } from '@orpc/server/standard'\nimport { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'\nimport type { Context as HonoContext, Env, Hono } from 'hono'\nimport type { StatusCode } from 'hono/utils/http-status'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport type { ProcedureFilter } from './mcp.js'\n\n/** Per-request timings in ms; `fn()` adds `handler_ms`. Sent as Server-Timing. */\nexport type RequestTiming = Record<string, number>\n\n/** What every request starts with; the default context when `context` is omitted. */\nexport type BaseContext = { headers: Headers; timing: RequestTiming }\n\n/**\n * Builds the router's initial context from the request. Return a `Response`\n * to answer (e.g. 401) instead.\n */\nexport type ContextFactory<E extends Env, R extends AnyRouter> = (\n\tc: HonoContext<E>,\n\tbase: BaseContext\n) =>\n\t| InferRouterInitialContext<R>\n\t| Response\n\t| Promise<InferRouterInitialContext<R> | Response>\n\n/** `context` is optional only when the base context already satisfies the router. */\ntype ContextOption<E extends Env, R extends AnyRouter> =\n\tBaseContext extends InferRouterInitialContext<R>\n\t\t? { context?: ContextFactory<E, R> }\n\t\t: { context: ContextFactory<E, R> }\n\ntype Path = `/${string}`\n// biome-ignore lint/suspicious/noExplicitAny: plugins are context-agnostic here\ntype Plugin = StandardHandlerPlugin<any>\n\nexport type MountOrpcOptions<\n\tE extends Env,\n\tR extends AnyRouter\n> = ContextOption<E, R> & {\n\trouter: R\n\t/** Mount the RPC handler (oRPC's `RPCLink`) here. Omit to skip it. */\n\trpcPrefix?: Path\n\t/** Mount the OpenAPI (REST) handler and its Scalar docs here. */\n\topenapi?: {\n\t\tprefix: Path\n\t\tinfo?: { title: string; version: string; description?: string }\n\t\t/** Docs page, relative to `prefix` (default '/'); the spec is at `/spec.json`. */\n\t\tdocsPath?: Path\n\t\t/** Only expose matching procedures (also filters the spec). */\n\t\tfilter?: ProcedureFilter\n\t\t/** Turn JSON strings back into `Date`s etc. for `z.date()` inputs. */\n\t\tsmartCoercion?: boolean\n\t\t/** Extra spec fields, e.g. `components.securitySchemes` and `security`. */\n\t\tspec?: Record<string, unknown>\n\t\tplugins?: Plugin[]\n\t}\n\t/** Collapse parallel RPC calls into one HTTP request. Default: true (25 calls). */\n\tbatch?: boolean | { maxSize: number }\n\t/** Add a Server-Timing header from the request timing. Default: true */\n\tserverTiming?: boolean\n\t/** SSE keep-alive comments every N ms (default 15000), or false. */\n\tsseKeepAlive?: boolean | number\n\t/** Extra RPC plugins (e.g. `CORSPlugin`). */\n\tplugins?: Plugin[]\n\t/** Rewrite request headers before they reach the context (see `normalizeExpoOrigin`). */\n\tnormalizeHeaders?: (headers: Headers) => Headers\n\t/** Time spent before the handler ran, reported as `queue`. */\n\tqueueMs?: (request: Request) => number | undefined\n\t/**\n\t * Unexpected procedure errors (oRPC turns thrown errors into responses, so\n\t * Hono's `onError` never sees them). Expected client errors are skipped.\n\t */\n\tonError?: (error: unknown, request: { url: string; method: string }) => void\n\t/** Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n}\n\n/**\n * Expo native sends `expo-origin` but not `origin`; copy it so cookie-based\n * auth (e.g. Better Auth) sees the origin.\n */\nexport function normalizeExpoOrigin(raw: Headers): Headers {\n\tconst expo = raw.get('expo-origin')\n\tif (!expo || raw.get('origin')) return raw\n\tconst headers = new Headers(raw)\n\theaders.set('origin', expo)\n\treturn headers\n}\n\nexport function formatServerTiming(\n\ttotalMs: number,\n\ttiming: Record<string, number | undefined>\n): string {\n\tconst parts = [`total;dur=${totalMs.toFixed(2)}`]\n\tfor (const [key, value] of Object.entries(timing)) {\n\t\tif (value !== undefined) {\n\t\t\tparts.push(`${key.replace(/_ms$/, '')};dur=${value.toFixed(2)}`)\n\t\t}\n\t}\n\treturn parts.join(', ')\n}\n\n/**\n * Response headers plus Server-Timing. For SSE, also disable proxy buffering\n * so keep-alive comments reach the edge (empty `:` lines are otherwise easy\n * for nginx/Fastly to hold until an idle kill). A copy: some responses (e.g.\n * redirects) have immutable headers.\n */\nfunction finishHeaders(\n\tresponse: Response,\n\tserverTiming: string | undefined\n): Headers {\n\tconst headers = new Headers(response.headers)\n\tif (serverTiming) {\n\t\theaders.set('Server-Timing', serverTiming)\n\t\theaders.append('Access-Control-Expose-Headers', 'Server-Timing')\n\t}\n\tif ((headers.get('content-type') ?? '').includes('text/event-stream')) {\n\t\theaders.set('Cache-Control', 'no-cache')\n\t\theaders.set('X-Accel-Buffering', 'no')\n\t}\n\treturn headers\n}\n\n/** Mount oRPC's RPC and OpenAPI handlers on a Hono app. */\nexport function mountOrpc<E extends Env, R extends AnyRouter>(\n\tapp: Hono<E>,\n\toptions: MountOrpcOptions<E, R>\n): void {\n\tconst {\n\t\trouter,\n\t\tbatch = true,\n\t\tserverTiming = true,\n\t\tsseKeepAlive = true\n\t} = options\n\tconst isExpectedError = options.isExpectedError ?? isExpectedClientError\n\tconst keepAlive =\n\t\tsseKeepAlive === false\n\t\t\t? { eventIteratorKeepAliveEnabled: false }\n\t\t\t: {\n\t\t\t\t\teventIteratorKeepAliveEnabled: true,\n\t\t\t\t\t// Explicit keep-alive under proxy idle timers (~30s); oRPC's default is 5s.\n\t\t\t\t\teventIteratorKeepAliveInterval:\n\t\t\t\t\t\tsseKeepAlive === true ? 15_000 : sseKeepAlive\n\t\t\t\t}\n\tconst report = (\n\t\terror: unknown,\n\t\t{ request }: { request: { url: URL; method: string } }\n\t) => {\n\t\tif (isExpectedError(error)) return\n\t\toptions.onError?.(error, {\n\t\t\turl: request.url.pathname,\n\t\t\tmethod: request.method\n\t\t})\n\t}\n\n\tconst mount = (prefix: Path, handler: Pick<RPCHandler<object>, 'handle'>) => {\n\t\tapp.use(`${prefix}/*`, async (c, next) => {\n\t\t\tconst timing: RequestTiming = {}\n\t\t\tconst queueMs = options.queueMs?.(c.req.raw)\n\t\t\tif (queueMs !== undefined)\n\t\t\t\ttiming.queue_ms = Math.round(queueMs * 100) / 100\n\t\t\tconst started = performance.now()\n\t\t\tconst headers = options.normalizeHeaders\n\t\t\t\t? options.normalizeHeaders(c.req.raw.headers)\n\t\t\t\t: c.req.raw.headers\n\t\t\tconst context = options.context\n\t\t\t\t? await options.context(c, { headers, timing })\n\t\t\t\t: { headers, timing }\n\t\t\tif (context instanceof Response) return context\n\t\t\tconst { matched, response } = await handler.handle(c.req.raw, {\n\t\t\t\tprefix,\n\t\t\t\tcontext: context as object\n\t\t\t})\n\t\t\tif (!matched) return next()\n\t\t\tconst timed = serverTiming\n\t\t\t\t? formatServerTiming(performance.now() - started, timing)\n\t\t\t\t: undefined\n\t\t\treturn c.newResponse(response.body, {\n\t\t\t\t// oRPC only produces valid HTTP status codes.\n\t\t\t\tstatus: response.status as StatusCode,\n\t\t\t\theaders: finishHeaders(response, timed)\n\t\t\t})\n\t\t})\n\t}\n\n\tif (options.rpcPrefix) {\n\t\tconst plugins: Plugin[] = [...(options.plugins ?? [])]\n\t\tif (batch) {\n\t\t\tplugins.push(\n\t\t\t\tnew BatchHandlerPlugin({\n\t\t\t\t\tmaxSize: batch === true ? 25 : batch.maxSize\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t\tmount(\n\t\t\toptions.rpcPrefix,\n\t\t\tnew RPCHandler(router, {\n\t\t\t\t...keepAlive,\n\t\t\t\tplugins,\n\t\t\t\tinterceptors: options.onError ? [orpcOnError(report)] : []\n\t\t\t})\n\t\t)\n\t}\n\n\tif (options.openapi) {\n\t\tconst { openapi } = options\n\t\tconst filter = openapi.filter ? { filter: openapi.filter } : {}\n\t\tconst converters = [new ZodToJsonSchemaConverter()]\n\t\tconst plugins: Plugin[] = [...(openapi.plugins ?? [])]\n\t\tif (openapi.smartCoercion) {\n\t\t\tplugins.push(new SmartCoercionPlugin({ schemaConverters: converters }))\n\t\t}\n\t\tplugins.push(\n\t\t\tnew OpenAPIReferencePlugin({\n\t\t\t\tdocsProvider: 'scalar',\n\t\t\t\t...(openapi.docsPath ? { docsPath: openapi.docsPath } : {}),\n\t\t\t\tschemaConverters: converters,\n\t\t\t\tspecGenerateOptions: {\n\t\t\t\t\tinfo: openapi.info ?? { title: 'API', version: '0.0.0' },\n\t\t\t\t\tservers: [{ url: openapi.prefix }],\n\t\t\t\t\t...filter,\n\t\t\t\t\t...openapi.spec\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\tmount(\n\t\t\topenapi.prefix,\n\t\t\tnew OpenAPIHandler(router, {\n\t\t\t\t...keepAlive,\n\t\t\t\t...filter,\n\t\t\t\tplugins,\n\t\t\t\tinterceptors: options.onError ? [orpcOnError(report)] : []\n\t\t\t})\n\t\t)\n\t}\n}\n"]}
1
+ {"version":3,"file":"hono.js","sourceRoot":"","sources":["../src/hono.ts"],"names":[],"mappings":"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","sourcesContent":["import { SmartCoercionPlugin } from '@orpc/json-schema'\nimport type { OpenAPIGeneratorGenerateOptions } from '@orpc/openapi'\nimport { OpenAPIHandler } from '@orpc/openapi/fetch'\nimport { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'\nimport {\n\ttype AnyRouter,\n\ttype InferRouterInitialContext,\n\tonError as orpcOnError\n} from '@orpc/server'\nimport { RPCHandler } from '@orpc/server/fetch'\nimport { BatchHandlerPlugin } from '@orpc/server/plugins'\nimport type { StandardHandlerPlugin } from '@orpc/server/standard'\nimport { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'\nimport type { Context as HonoContext, Env, Hono } from 'hono'\nimport type { StatusCode } from 'hono/utils/http-status'\nimport { REQUEST_TIMING, type InvocationTiming } from './timing.js'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport type { ProcedureFilter } from './mcp.js'\n\n/** Per-request timings in ms; `fn()` adds `handler_ms`. Sent as Server-Timing. */\nexport type RequestTiming = Record<string, number>\n\n/** What every request starts with; the default context when `context` is omitted. */\nexport type BaseContext = { headers: Headers; timing: RequestTiming }\n\n/**\n * Builds the router's initial context from the request. Return a `Response`\n * to answer (e.g. 401) instead.\n */\nexport type ContextFactory<E extends Env, R extends AnyRouter> = (\n\tc: HonoContext<E>,\n\tbase: BaseContext\n) =>\n\t| InferRouterInitialContext<R>\n\t| Response\n\t| Promise<InferRouterInitialContext<R> | Response>\n\n/** `context` is optional only when the base context already satisfies the router. */\ntype ContextOption<E extends Env, R extends AnyRouter> =\n\tBaseContext extends InferRouterInitialContext<R>\n\t\t? { context?: ContextFactory<E, R> }\n\t\t: { context: ContextFactory<E, R> }\n\ntype Path = `/${string}`\ntype Plugin<T extends object> = StandardHandlerPlugin<T>\n\nexport type MountOrpcOptions<\n\tE extends Env,\n\tR extends AnyRouter\n> = ContextOption<E, R> & {\n\trouter: R\n\t/** Mount the RPC handler (oRPC's `RPCLink`) here. Omit to skip it. */\n\trpcPrefix?: Path\n\t/** Mount the OpenAPI (REST) handler and its Scalar docs here. */\n\topenapi?: {\n\t\tprefix: Path\n\t\tinfo?: { title: string; version: string; description?: string }\n\t\t/** Docs page, relative to `prefix` (default '/'); the spec is at `/spec.json`. */\n\t\tdocsPath?: Path\n\t\t/** Only expose matching procedures (also filters the spec). */\n\t\tfilter?: ProcedureFilter\n\t\t/** Turn JSON strings back into `Date`s etc. for `z.date()` inputs. */\n\t\tsmartCoercion?: boolean\n\t\t/** Extra spec fields, e.g. `components.securitySchemes` and `security`. */\n\t\tspec?: Omit<OpenAPIGeneratorGenerateOptions, 'filter'>\n\t\tplugins?: Plugin<InferRouterInitialContext<R>>[]\n\t}\n\t/** Collapse parallel RPC calls into one HTTP request. Default: true (25 calls). */\n\tbatch?: boolean | { maxSize: number }\n\t/** Add a Server-Timing header from the request timing. Default: true */\n\tserverTiming?: boolean\n\t/** SSE keep-alive comments every N ms (default 15000), or false. */\n\tsseKeepAlive?: boolean | number\n\t/** Extra RPC plugins (e.g. `CORSPlugin`). */\n\tplugins?: Plugin<InferRouterInitialContext<R>>[]\n\t/** Rewrite request headers before they reach the context (see `normalizeExpoOrigin`). */\n\tnormalizeHeaders?: (headers: Headers) => Headers\n\t/** Time spent before the handler ran, reported as `queue`. */\n\tqueueMs?: (request: Request) => number | undefined\n\t/**\n\t * Unexpected procedure errors (oRPC turns thrown errors into responses, so\n\t * Hono's `onError` never sees them). Expected client errors are skipped.\n\t */\n\tonError?: (error: unknown, request: { url: string; method: string }) => void\n\t/** Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n}\n\n/**\n * Expo native sends `expo-origin` but not `origin`; copy it so cookie-based\n * auth (e.g. Better Auth) sees the origin.\n */\nexport function normalizeExpoOrigin(raw: Headers): Headers {\n\tconst expo = raw.get('expo-origin')\n\tif (!expo || raw.get('origin')) return raw\n\tconst headers = new Headers(raw)\n\theaders.set('origin', expo)\n\treturn headers\n}\n\nexport function formatServerTiming(\n\ttotalMs: number,\n\ttiming: Record<string, number | undefined>\n): string {\n\tconst parts = [`total;dur=${totalMs.toFixed(2)}`]\n\tfor (const [key, value] of Object.entries(timing)) {\n\t\tif (value !== undefined) {\n\t\t\tparts.push(`${key.replace(/_ms$/, '')};dur=${value.toFixed(2)}`)\n\t\t}\n\t}\n\treturn parts.join(', ')\n}\n\n/**\n * Response headers plus Server-Timing. For SSE, also disable proxy buffering\n * so keep-alive comments reach the edge (empty `:` lines are otherwise easy\n * for nginx/Fastly to hold until an idle kill). A copy: some responses (e.g.\n * redirects) have immutable headers.\n */\nexport function finishOrpcHeaders(\n\tresponse: Response,\n\tserverTiming: string | undefined\n): Headers {\n\tconst headers = new Headers(response.headers)\n\tif (serverTiming) {\n\t\theaders.set('Server-Timing', serverTiming)\n\t\theaders.append('Access-Control-Expose-Headers', 'Server-Timing')\n\t}\n\tif ((headers.get('content-type') ?? '').includes('text/event-stream')) {\n\t\theaders.set('Cache-Control', 'no-cache')\n\t\theaders.set('X-Accel-Buffering', 'no')\n\t}\n\treturn headers\n}\n\n/** Mount oRPC's RPC and OpenAPI handlers on a Hono app. */\nexport function mountOrpc<E extends Env, R extends AnyRouter>(\n\tapp: Hono<E>,\n\toptions: MountOrpcOptions<E, R>\n): void {\n\tconst {\n\t\trouter,\n\t\tbatch = true,\n\t\tserverTiming = true,\n\t\tsseKeepAlive = true\n\t} = options\n\tconst isExpectedError = options.isExpectedError ?? isExpectedClientError\n\tconst keepAlive =\n\t\tsseKeepAlive === false\n\t\t\t? { eventIteratorKeepAliveEnabled: false }\n\t\t\t: {\n\t\t\t\t\teventIteratorKeepAliveEnabled: true,\n\t\t\t\t\t// Explicit keep-alive under proxy idle timers (~30s); oRPC's default is 5s.\n\t\t\t\t\teventIteratorKeepAliveInterval:\n\t\t\t\t\t\tsseKeepAlive === true ? 15_000 : sseKeepAlive\n\t\t\t\t}\n\tconst report = (\n\t\terror: unknown,\n\t\t{ request }: { request: { url: URL; method: string } }\n\t) => {\n\t\ttry {\n\t\t\tif (isExpectedError(error)) return\n\t\t\toptions.onError?.(error, {\n\t\t\t\turl: request.url.pathname,\n\t\t\t\tmethod: request.method\n\t\t\t})\n\t\t} catch {\n\t\t\t/* Error reporting cannot replace transport outcomes. */\n\t\t}\n\t}\n\n\tconst mount = (\n\t\tprefix: Path,\n\t\thandler: Pick<RPCHandler<InferRouterInitialContext<R>>, 'handle'>\n\t) => {\n\t\tapp.use(`${prefix}/*`, async (c, next) => {\n\t\t\tconst timing: RequestTiming = {}\n\t\t\tconst queueMs = options.queueMs?.(c.req.raw)\n\t\t\tif (queueMs !== undefined)\n\t\t\t\ttiming.queue_ms = Math.round(queueMs * 100) / 100\n\t\t\tconst started = performance.now()\n\t\t\tconst headers = options.normalizeHeaders\n\t\t\t\t? options.normalizeHeaders(c.req.raw.headers)\n\t\t\t\t: c.req.raw.headers\n\t\t\tconst context = options.context\n\t\t\t\t? await options.context(c, { headers, timing })\n\t\t\t\t: { headers, timing }\n\t\t\tif (context instanceof Response) return context\n\t\t\tconst invocationTiming: InvocationTiming = { procedureMs: 0, calls: 0 }\n\t\t\tconst { matched, response } = await handler.handle(c.req.raw, {\n\t\t\t\tprefix,\n\t\t\t\tcontext: {\n\t\t\t\t\t...context,\n\t\t\t\t\t[REQUEST_TIMING]: invocationTiming\n\t\t\t\t} as InferRouterInitialContext<R>\n\t\t\t})\n\t\t\tif (!matched) return next()\n\t\t\tconst timed = serverTiming\n\t\t\t\t? formatServerTiming(performance.now() - started, {\n\t\t\t\t\t\t...timing,\n\t\t\t\t\t\thandler_ms: invocationTiming.procedureMs\n\t\t\t\t\t})\n\t\t\t\t: undefined\n\t\t\treturn c.newResponse(response.body, {\n\t\t\t\t// oRPC only produces valid HTTP status codes.\n\t\t\t\tstatus: response.status as StatusCode,\n\t\t\t\theaders: finishOrpcHeaders(response, timed)\n\t\t\t})\n\t\t})\n\t}\n\n\tif (options.rpcPrefix) {\n\t\tconst plugins: Plugin<InferRouterInitialContext<R>>[] = [\n\t\t\t...(options.plugins ?? [])\n\t\t]\n\t\tif (batch) {\n\t\t\tplugins.push(\n\t\t\t\tnew BatchHandlerPlugin({\n\t\t\t\t\tmaxSize: batch === true ? 25 : batch.maxSize\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t\tmount(\n\t\t\toptions.rpcPrefix,\n\t\t\tnew RPCHandler(router, {\n\t\t\t\t...keepAlive,\n\t\t\t\tplugins,\n\t\t\t\tinterceptors: options.onError ? [orpcOnError(report)] : []\n\t\t\t})\n\t\t)\n\t}\n\n\tif (options.openapi) {\n\t\tconst { openapi } = options\n\t\tconst filter = openapi.filter ? { filter: openapi.filter } : {}\n\t\tconst converters = [new ZodToJsonSchemaConverter()]\n\t\tconst plugins: Plugin<InferRouterInitialContext<R>>[] = [\n\t\t\t...(openapi.plugins ?? [])\n\t\t]\n\t\tif (openapi.smartCoercion) {\n\t\t\tplugins.push(new SmartCoercionPlugin({ schemaConverters: converters }))\n\t\t}\n\t\tplugins.push(\n\t\t\tnew OpenAPIReferencePlugin({\n\t\t\t\tdocsProvider: 'scalar',\n\t\t\t\t...(openapi.docsPath ? { docsPath: openapi.docsPath } : {}),\n\t\t\t\tschemaConverters: converters,\n\t\t\t\tspecGenerateOptions: {\n\t\t\t\t\tinfo: openapi.info ?? { title: 'API', version: '0.0.0' },\n\t\t\t\t\tservers: [{ url: openapi.prefix }],\n\t\t\t\t\t...filter,\n\t\t\t\t\t...openapi.spec\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t\tmount(\n\t\t\topenapi.prefix,\n\t\t\tnew OpenAPIHandler(router, {\n\t\t\t\t...keepAlive,\n\t\t\t\t...filter,\n\t\t\t\tplugins,\n\t\t\t\tinterceptors: options.onError ? [orpcOnError(report)] : []\n\t\t\t})\n\t\t)\n\t}\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@ export { type CreateFnOptions, createFn, type FnFactory } from './create-fn.js';
3
3
  export { isExpectedClientError } from './expected-client-error.js';
4
4
  export { createBoundedEventQueue } from './live/pub-sub.js';
5
5
  export { createDefaultLogger, type FnLogger, type LogAttributes } from './logger.js';
6
- export { FN_META_KEY, type FnMeta, readFnMeta } from './meta.js';
6
+ export { defineMeta, FN_META_KEY, type FnMeta, readFnMeta } from './meta.js';
7
7
  export type { AttributeValue, OtelApiLike, SpanLike, SpanOf, Tracing } from './otel.js';
8
- export { createRouter } from './router.js';
8
+ export { createRouter, createStreamManifest, createStreamManifestAsync, renderStreamManifest } from './router.js';
9
9
  export type { AnyFnContext, BuilderLike, CurrentContextOf, Fn, FnCompletedEvent, FnContext, FnDefinition, FnProcedure, FnRouteOptions, Guard, GuardOptions, GuardParams, HandlerParams, InitialContextOf, ProcedureContext, ProcedureInput, ProcedureKey, ProcedureOption, ProcedureOutput, ReservedOptionKey, RouteConfig } from './types.js';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EACN,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,SAAS,EACd,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,mBAAmB,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAChE,YAAY,EACX,cAAc,EACd,WAAW,EACX,QAAQ,EACR,MAAM,EACN,OAAO,EACP,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,EAAE,EACF,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,cAAc,EACd,KAAK,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EACN,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,SAAS,EACd,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,mBAAmB,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC5E,YAAY,EACX,cAAc,EACd,WAAW,EACX,QAAQ,EACR,MAAM,EACN,OAAO,EACP,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,YAAY,EACZ,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,MAAM,aAAa,CAAA;AACpB,YAAY,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,EAAE,EACF,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,cAAc,EACd,KAAK,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -3,6 +3,6 @@ export { createFn } from './create-fn.js';
3
3
  export { isExpectedClientError } from './expected-client-error.js';
4
4
  export { createBoundedEventQueue } from './live/pub-sub.js';
5
5
  export { createDefaultLogger } from './logger.js';
6
- export { FN_META_KEY, readFnMeta } from './meta.js';
7
- export { createRouter } from './router.js';
6
+ export { defineMeta, FN_META_KEY, readFnMeta } from './meta.js';
7
+ export { createRouter, createStreamManifest, createStreamManifestAsync, renderStreamManifest } from './router.js';
8
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAEN,QAAQ,EAER,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,mBAAmB,EAGnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,WAAW,EAAe,UAAU,EAAE,MAAM,WAAW,CAAA;AAQhE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA","sourcesContent":["export { type BoundCall, createBoundCall } from './bound-call.js'\nexport {\n\ttype CreateFnOptions,\n\tcreateFn,\n\ttype FnFactory\n} from './create-fn.js'\nexport { isExpectedClientError } from './expected-client-error.js'\nexport { createBoundedEventQueue } from './live/pub-sub.js'\nexport {\n\tcreateDefaultLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nexport { FN_META_KEY, type FnMeta, readFnMeta } from './meta.js'\nexport type {\n\tAttributeValue,\n\tOtelApiLike,\n\tSpanLike,\n\tSpanOf,\n\tTracing\n} from './otel.js'\nexport { createRouter } from './router.js'\nexport type {\n\tAnyFnContext,\n\tBuilderLike,\n\tCurrentContextOf,\n\tFn,\n\tFnCompletedEvent,\n\tFnContext,\n\tFnDefinition,\n\tFnProcedure,\n\tFnRouteOptions,\n\tGuard,\n\tGuardOptions,\n\tGuardParams,\n\tHandlerParams,\n\tInitialContextOf,\n\tProcedureContext,\n\tProcedureInput,\n\tProcedureKey,\n\tProcedureOption,\n\tProcedureOutput,\n\tReservedOptionKey,\n\tRouteConfig\n} from './types.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAEN,QAAQ,EAER,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EACN,mBAAmB,EAGnB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAe,UAAU,EAAE,MAAM,WAAW,CAAA;AAQ5E,OAAO,EACN,YAAY,EACZ,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,MAAM,aAAa,CAAA","sourcesContent":["export { type BoundCall, createBoundCall } from './bound-call.js'\nexport {\n\ttype CreateFnOptions,\n\tcreateFn,\n\ttype FnFactory\n} from './create-fn.js'\nexport { isExpectedClientError } from './expected-client-error.js'\nexport { createBoundedEventQueue } from './live/pub-sub.js'\nexport {\n\tcreateDefaultLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nexport { defineMeta, FN_META_KEY, type FnMeta, readFnMeta } from './meta.js'\nexport type {\n\tAttributeValue,\n\tOtelApiLike,\n\tSpanLike,\n\tSpanOf,\n\tTracing\n} from './otel.js'\nexport {\n\tcreateRouter,\n\tcreateStreamManifest,\n\tcreateStreamManifestAsync,\n\trenderStreamManifest\n} from './router.js'\nexport type {\n\tAnyFnContext,\n\tBuilderLike,\n\tCurrentContextOf,\n\tFn,\n\tFnCompletedEvent,\n\tFnContext,\n\tFnDefinition,\n\tFnProcedure,\n\tFnRouteOptions,\n\tGuard,\n\tGuardOptions,\n\tGuardParams,\n\tHandlerParams,\n\tInitialContextOf,\n\tProcedureContext,\n\tProcedureInput,\n\tProcedureKey,\n\tProcedureOption,\n\tProcedureOutput,\n\tReservedOptionKey,\n\tRouteConfig\n} from './types.js'\n"]}
@@ -44,4 +44,6 @@ export type ToolSchema<TIn = unknown, TOut = TIn> = {
44
44
  export declare function rawInputSchema<TIn>(schema: AnySchema): ToolSchema<TIn>;
45
45
  /** Tool output the procedure already validated: described, passed through. */
46
46
  export declare function passThroughOutputSchema<TOut>(schema: AnySchema): ToolSchema<TOut>;
47
+ /** Tool protocols permit unions only when every branch accepts an object. */
48
+ export declare function isObjectJsonSchema(schema: JsonSchema): boolean;
47
49
  //# sourceMappingURL=json-schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI/C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,GAAG,IAAI;IACnD,WAAW,EAAE;QACZ,OAAO,EAAE,CAAC,CAAA;QACV,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CACT,KAAK,EAAE,OAAO,KAEZ;YAAE,KAAK,EAAE,IAAI,CAAC;YAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACnC;YAAE,MAAM,EAAE,aAAa,CAAC;gBAAE,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GAC9C,OAAO,CACL;YAAE,KAAK,EAAE,IAAI,CAAC;YAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACnC;YAAE,MAAM,EAAE,aAAa,CAAC;gBAAE,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAC/C,CAAA;QACJ,KAAK,CAAC,EAAE;YAAE,KAAK,EAAE,GAAG,CAAC;YAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAA;QACpC,UAAU,EAAE;YACX,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,UAAU,CAAA;YACxC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,UAAU,CAAA;SACzC,CAAA;KACD,CAAA;CACD,CAAA;AAYD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAiBtE;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,IAAI,EAC3C,MAAM,EAAE,SAAS,GACf,UAAU,CAAC,IAAI,CAAC,CAUlB"}
1
+ {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI/C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,GAAG,IAAI;IACnD,WAAW,EAAE;QACZ,OAAO,EAAE,CAAC,CAAA;QACV,MAAM,EAAE,MAAM,CAAA;QACd,QAAQ,EAAE,CACT,KAAK,EAAE,OAAO,KAEZ;YAAE,KAAK,EAAE,IAAI,CAAC;YAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACnC;YAAE,MAAM,EAAE,aAAa,CAAC;gBAAE,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GAC9C,OAAO,CACL;YAAE,KAAK,EAAE,IAAI,CAAC;YAAC,MAAM,CAAC,EAAE,SAAS,CAAA;SAAE,GACnC;YAAE,MAAM,EAAE,aAAa,CAAC;gBAAE,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,CAC/C,CAAA;QACJ,KAAK,CAAC,EAAE;YAAE,KAAK,EAAE,GAAG,CAAC;YAAC,MAAM,EAAE,IAAI,CAAA;SAAE,CAAA;QACpC,UAAU,EAAE;YACX,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,UAAU,CAAA;YACxC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,UAAU,CAAA;SACzC,CAAA;KACD,CAAA;CACD,CAAA;AAYD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAiBtE;AAED,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,IAAI,EAC3C,MAAM,EAAE,SAAS,GACf,UAAU,CAAC,IAAI,CAAC,CAUlB;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAa9D"}
@@ -41,4 +41,15 @@ export function passThroughOutputSchema(schema) {
41
41
  }
42
42
  };
43
43
  }
44
+ /** Tool protocols permit unions only when every branch accepts an object. */
45
+ export function isObjectJsonSchema(schema) {
46
+ if (schema.type === 'object')
47
+ return true;
48
+ const union = schema.anyOf ?? schema.oneOf;
49
+ return (Array.isArray(union) &&
50
+ union.length > 0 &&
51
+ union.every((branch) => typeof branch === 'object' &&
52
+ branch !== null &&
53
+ isObjectJsonSchema(branch)));
54
+ }
44
55
  //# sourceMappingURL=json-schema.js.map