orpc-fn 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -32
- package/dist/assemble-procedure.d.ts +13 -0
- package/dist/assemble-procedure.d.ts.map +1 -0
- package/dist/assemble-procedure.js +29 -0
- package/dist/assemble-procedure.js.map +1 -0
- package/dist/bound-call.d.ts +1 -1
- package/dist/bound-call.d.ts.map +1 -1
- package/dist/bound-call.js.map +1 -1
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -2
- package/dist/client.js.map +1 -1
- package/dist/compatibility.d.ts +16 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +4 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/create-fn.d.ts +30 -34
- package/dist/create-fn.d.ts.map +1 -1
- package/dist/create-fn.js +177 -121
- package/dist/create-fn.js.map +1 -1
- package/dist/expo.d.ts +11 -25
- package/dist/expo.d.ts.map +1 -1
- package/dist/expo.js +25 -30
- package/dist/expo.js.map +1 -1
- package/dist/hono.d.ts +12 -4
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +29 -12
- package/dist/hono.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/json-schema.d.ts +2 -0
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/json-schema.js +11 -0
- package/dist/json-schema.js.map +1 -1
- package/dist/live/codec.d.ts +6 -1
- package/dist/live/codec.d.ts.map +1 -1
- package/dist/live/codec.js +14 -3
- package/dist/live/codec.js.map +1 -1
- package/dist/live/fn-live.d.ts +63 -22
- package/dist/live/fn-live.d.ts.map +1 -1
- package/dist/live/fn-live.js +98 -16
- package/dist/live/fn-live.js.map +1 -1
- package/dist/live/index.d.ts +1 -1
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js.map +1 -1
- package/dist/live/ioredis.d.ts +4 -1
- package/dist/live/ioredis.d.ts.map +1 -1
- package/dist/live/ioredis.js +21 -2
- package/dist/live/ioredis.js.map +1 -1
- package/dist/live/lifecycle.d.ts +7 -0
- package/dist/live/lifecycle.d.ts.map +1 -0
- package/dist/live/lifecycle.js +36 -0
- package/dist/live/lifecycle.js.map +1 -0
- package/dist/live/memory.d.ts.map +1 -1
- package/dist/live/memory.js +4 -0
- package/dist/live/memory.js.map +1 -1
- package/dist/live/pub-sub.d.ts +76 -12
- package/dist/live/pub-sub.d.ts.map +1 -1
- package/dist/live/pub-sub.js +429 -125
- package/dist/live/pub-sub.js.map +1 -1
- package/dist/live/redis-bun.d.ts +1 -1
- package/dist/live/redis-bun.d.ts.map +1 -1
- package/dist/live/redis-bun.js +3 -5
- package/dist/live/redis-bun.js.map +1 -1
- package/dist/live/redis.d.ts +2 -2
- package/dist/live/redis.d.ts.map +1 -1
- package/dist/live/redis.js +36 -9
- package/dist/live/redis.js.map +1 -1
- package/dist/live/transport.d.ts +5 -1
- package/dist/live/transport.d.ts.map +1 -1
- package/dist/live/transport.js.map +1 -1
- package/dist/logger.d.ts +2 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +21 -0
- package/dist/logger.js.map +1 -1
- package/dist/mastra.d.ts.map +1 -1
- package/dist/mastra.js +16 -7
- package/dist/mastra.js.map +1 -1
- package/dist/mcp/sdk.d.ts +20 -0
- package/dist/mcp/sdk.d.ts.map +1 -0
- package/dist/mcp/sdk.js +82 -0
- package/dist/mcp/sdk.js.map +1 -0
- package/dist/mcp.d.ts +3 -2
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +22 -7
- package/dist/mcp.js.map +1 -1
- package/dist/meta.d.ts +15 -7
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +9 -2
- package/dist/meta.js.map +1 -1
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +77 -6
- package/dist/otel.js.map +1 -1
- package/dist/route-options.d.ts +22 -0
- package/dist/route-options.d.ts.map +1 -0
- package/dist/route-options.js +67 -0
- package/dist/route-options.js.map +1 -0
- package/dist/router.d.ts +5 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +22 -0
- package/dist/router.js.map +1 -1
- package/dist/timing.d.ts +8 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +4 -0
- package/dist/timing.js.map +1 -0
- package/dist/types.d.ts +86 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -2
- package/dist/types.js.map +1 -1
- package/package.json +15 -3
- package/src/assemble-procedure.ts +42 -0
- package/src/bound-call.ts +4 -3
- package/src/client.ts +9 -2
- package/src/compatibility.ts +39 -0
- package/src/create-fn.ts +297 -183
- package/src/expo.ts +49 -44
- package/src/hono.ts +36 -17
- package/src/index.ts +6 -2
- package/src/json-schema.ts +16 -0
- package/src/live/codec.ts +22 -3
- package/src/live/fn-live.ts +244 -69
- package/src/live/index.ts +2 -0
- package/src/live/ioredis.ts +22 -2
- package/src/live/lifecycle.ts +44 -0
- package/src/live/memory.ts +4 -0
- package/src/live/pub-sub.ts +608 -166
- package/src/live/redis-bun.ts +7 -5
- package/src/live/redis.ts +37 -11
- package/src/live/transport.ts +4 -1
- package/src/logger.ts +20 -0
- package/src/mastra.ts +15 -7
- package/src/mcp/sdk.ts +118 -0
- package/src/mcp.ts +48 -20
- package/src/meta.ts +40 -24
- package/src/otel.ts +77 -10
- package/src/route-options.ts +100 -0
- package/src/router.ts +39 -1
- package/src/timing.ts +5 -0
- package/src/types.ts +204 -62
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgFA,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,MAAM;IACN,QAAQ;IACR,SAAS;IACT,aAAa;IACb,YAAY;IACZ,eAAe;IACf,oBAAoB;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,MAAM;CACsC,CAAA;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IACnC,GAAG,iBAAiB;IACpB,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;IACN,aAAa;CACJ,CAAA","sourcesContent":["import type {\n\tAnySchema,\n\tErrorMap,\n\tInferSchemaInput,\n\tInferSchemaOutput,\n\tMeta,\n\tSchema\n} from '@orpc/contract'\nimport type {\n\tAnyProcedure,\n\tDecoratedProcedure,\n\tProcedure,\n\tRoute\n} from '@orpc/server'\nimport type { ZodType, z } from 'zod'\nimport type { BoundCall } from './bound-call.js'\nimport type { FnLogger } from './logger.js'\nimport type { SpanLike } from './otel.js'\n\nexport type MaybePromise<T> = T | Promise<T>\n\n/**\n * An oRPC builder without input or output schema: `os`, `os.$context<T>()`,\n * `os.use(...)`. A schema set on the builder is rejected by `createFn`; set it\n * on the route instead.\n */\n/* biome-ignore-start lint/suspicious/noExplicitAny: matches every builder's generic methods */\nexport type BuilderLike = {\n\troute(route: any): unknown\n\tmeta(meta: any): unknown\n\tinput(schema: any): unknown\n\toutput(schema: any): unknown\n\thandler(handler: any): Procedure<any, any, any, any, any, any>\n}\n/* biome-ignore-end lint/suspicious/noExplicitAny: matches every builder's generic methods */\n\n/** Input a procedure is called with (before its input schema runs). */\nexport type ProcedureInput<T> =\n\tT extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer _TCurrent,\n\t\tinfer TInputSchema extends AnySchema,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? InferSchemaInput<TInputSchema>\n\t\t: unknown\n\n/** What a procedure resolves to (after its output schema runs). */\nexport type ProcedureOutput<T> =\n\tT extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer _TCurrent,\n\t\tinfer _TIn,\n\t\tinfer TOutputSchema extends AnySchema,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? InferSchemaOutput<TOutputSchema>\n\t\t: unknown\n\n/** Context a procedure must be called with. */\nexport type ProcedureContext<T> =\n\tT extends Procedure<\n\t\tinfer TContext,\n\t\tinfer _TCurrent,\n\t\tinfer _TIn,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? TContext\n\t\t: never\n\n/** `Omit` that keeps each member of a union (handler params narrow by discriminant). */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown\n\t? Omit<T, K>\n\t: never\n\n/** `fn()` options passed to oRPC's `.route()`; `RouteConfig` is derived from it. */\nexport const ROUTE_OPTION_KEYS = [\n\t'path',\n\t'method',\n\t'summary',\n\t'description',\n\t'deprecated',\n\t'successStatus',\n\t'successDescription',\n\t'inputStructure',\n\t'outputStructure',\n\t'tags'\n] as const satisfies readonly (keyof Route)[]\n\n/**\n * `fn()` option names owned by the route itself. Guard and meta keys must not\n * reuse them: such an option would be read as the route option and the guard\n * would never run.\n */\nexport const RESERVED_OPTION_KEYS = [\n\t...ROUTE_OPTION_KEYS,\n\t'name',\n\t'procedure',\n\t'input',\n\t'output',\n\t'handler',\n\t'live',\n\t'operationId'\n] as const\n\nexport type ReservedOptionKey = (typeof RESERVED_OPTION_KEYS)[number]\n\n/** @internal Builds one route from a `procedures` builder; shared by `fn` and `createPubSub`. */\nexport type BuildProcedure = (options: {\n\tname: string\n\tprocedure: string | undefined\n\troute: Record<string, unknown>\n\tmeta: Record<string, unknown>\n\tinput?: AnySchema | undefined\n\toutput?: AnySchema | undefined\n\thandler: (options: {\n\t\tinput: unknown\n\t\tcontext: Record<string, unknown>\n\t\tsignal?: AbortSignal\n\t}) => unknown\n}) => AnyProcedure\n\n/** Turns every key of `T` found in `K` into a readable type error. */\nexport type RejectKeys<T, K extends PropertyKey, TMessage extends string> = {\n\t[P in Extract<keyof T, K>]: TMessage\n}\n\n/**\n * Handler extras must have known keys: an index signature would claim every\n * handler param. Intersected into `createFn`'s options to reject it.\n */\nexport type FiniteExtras<T> = string extends keyof T\n\t? { extras: 'orpc-fn: extras need known keys, not an index signature' }\n\t: number extends keyof T\n\t\t? { extras: 'orpc-fn: extras need known keys, not an index signature' }\n\t\t: unknown\n\ntype ProcedureOf<TBuilder> = TBuilder extends {\n\thandler(handler: never): infer TProcedure\n}\n\t? TProcedure\n\t: never\n\n/** Context a route built from this builder is called with. */\nexport type InitialContextOf<TBuilder> = ProcedureContext<ProcedureOf<TBuilder>>\n\n/** Context the handler sees, after the builder's middleware. */\nexport type CurrentContextOf<TBuilder> =\n\tProcedureOf<TBuilder> extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer TContext,\n\t\tinfer _TIn,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? TContext\n\t\t: never\n\ntype ErrorMapOf<TBuilder> =\n\tProcedureOf<TBuilder> extends {\n\t\t'~orpc': { errorMap: infer T extends ErrorMap }\n\t}\n\t\t? T\n\t\t: ErrorMap\ntype MetaOf<TBuilder> =\n\tProcedureOf<TBuilder> extends { '~orpc': { meta: infer T extends Meta } }\n\t\t? T\n\t\t: Meta\n\n/**\n * Everything `createFn` inferred from its options. Route types read from it;\n * apps rarely spell it out.\n */\nexport type FnDefinition = {\n\tprocedures: Record<string, BuilderLike>\n\tdefault: string\n\textras: object\n\tguards: object\n\tmeta: object\n\ttag: string\n\tspan: SpanLike\n\tlogger: FnLogger\n}\n\nexport type ProcedureKey<TDef extends FnDefinition> = keyof TDef['procedures'] &\n\tstring\n\n/** Context the handler of a `procedure: TKey` route receives. */\nexport type FnContext<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>\n> = CurrentContextOf<TDef['procedures'][TKey]>\n\n/** Union of every procedure's handler context: what guards and extras see. */\nexport type AnyFnContext<TDef extends FnDefinition> = {\n\t[K in ProcedureKey<TDef>]: FnContext<TDef, K>\n}[ProcedureKey<TDef>]\n\nexport type GuardParams<TContext, TMeta> = {\n\tcontext: TContext\n\tinput: unknown\n\t/** Route name (operationId). */\n\tname: string\n\t/** Procedures key the route was built from. */\n\tprocedure: string\n\tmeta: Partial<TMeta>\n\tsignal: AbortSignal | undefined\n}\n\n/**\n * A check run before the handler. Its first parameter becomes an option on\n * `fn({...})`; the guard runs only on routes that set it. Throw (usually an\n * `ORPCError`) to refuse the call.\n */\nexport type Guard<TValue, TParams> = (value: TValue, params: TParams) => unknown\n\nexport type GuardOptions<TGuards> = {\n\t[K in keyof TGuards]?: TGuards[K] extends (\n\t\tvalue: infer TValue,\n\t\tparams: never\n\t) => unknown\n\t\t? TValue\n\t\t: never\n}\n\nexport type HandlerParams<\n\tTDef extends FnDefinition,\n\tTInput,\n\tTKey extends ProcedureKey<TDef>\n> = DistributiveOmit<\n\tTDef['extras'],\n\t'input' | 'context' | 'call' | 'signal' | 'span' | 'logger'\n> & {\n\tinput: TInput\n\tcontext: FnContext<TDef, TKey>\n\t/** Calls another procedure with this context and signal, in a child span. */\n\tcall: BoundCall<FnContext<TDef, TKey>>\n\t/** Cancellation is inherited by nested calls; pass to interruptible I/O. */\n\tsignal: AbortSignal | undefined\n\t/** Active OpenTelemetry span, undefined when `createFn({ otel })` is not set. */\n\tspan: TDef['span'] | undefined\n\tlogger: TDef['logger']\n}\n\n/** Route options shared by every `fn()` overload. */\nexport type RouteConfig<TTag extends string = string> = Pick<\n\tRoute,\n\tExclude<(typeof ROUTE_OPTION_KEYS)[number], 'tags'>\n> & {\n\t/** Required. Becomes the OpenAPI operationId and the span name (e.g. 'user.create'). */\n\tname: string\n\ttags?: TTag[]\n}\n\nexport type FnRouteOptions<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>\n> = RouteConfig<TDef['tag']> &\n\tGuardOptions<TDef['guards']> &\n\tTDef['meta'] &\n\tProcedureOption<TDef, TKey>\n\n/**\n * Which `createFn({ procedures })` builder a route uses. Optional when\n * `createFn` has a `default`; required on every route when it has none.\n */\nexport type ProcedureOption<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>\n> = [TDef['default']] extends [never]\n\t? { procedure: TKey }\n\t: { procedure?: TKey }\n\nexport type FnProcedure<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>,\n\tTInputSchema extends Schema<unknown, unknown>,\n\tTOutputSchema extends Schema<unknown, unknown>\n> = DecoratedProcedure<\n\tInitialContextOf<TDef['procedures'][TKey]>,\n\tFnContext<TDef, TKey>,\n\tTInputSchema,\n\tTOutputSchema,\n\tErrorMapOf<TDef['procedures'][TKey]>,\n\tMetaOf<TDef['procedures'][TKey]>\n>\n\ntype InputOf<T> = [T] extends [ZodType] ? z.output<T> : unknown\ntype ReturnOf<TOut, TReturn> = [TOut] extends [ZodType]\n\t? z.input<TOut>\n\t: TReturn\n\n/** `fn()`: four overloads for input/output schema × inferred. */\nexport interface Fn<TDef extends FnDefinition> {\n\t// 1. With input + output schema\n\t<\n\t\tTInput extends ZodType,\n\t\tTOut extends ZodType,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default']\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput: TOut\n\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, z.output<TInput>, NoInfer<TKey>>\n\t\t\t) => MaybePromise<z.input<TOut>>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnProcedure<TDef, TKey, TInput, TOut>\n\n\t// 2. With input, inferred output\n\t<\n\t\tTInput extends ZodType,\n\t\tTReturn,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default']\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, z.output<TInput>, NoInfer<TKey>>\n\t\t\t) => MaybePromise<TReturn>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnProcedure<TDef, TKey, TInput, Schema<TReturn, TReturn>>\n\n\t// 3. No input, with output schema\n\t<TOut extends ZodType, TKey extends ProcedureKey<TDef> = TDef['default']>(\n\t\toptions: {\n\t\t\tinput?: undefined\n\t\t\toutput: TOut\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, unknown, NoInfer<TKey>>\n\t\t\t) => MaybePromise<z.input<TOut>>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnProcedure<TDef, TKey, Schema<unknown, unknown>, TOut>\n\n\t// 4. No input, inferred output\n\t<TReturn, TKey extends ProcedureKey<TDef> = TDef['default']>(\n\t\toptions: {\n\t\t\tinput?: undefined\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, unknown, NoInfer<TKey>>\n\t\t\t) => MaybePromise<TReturn>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnProcedure<TDef, TKey, Schema<unknown, unknown>, Schema<TReturn, TReturn>>\n\n\t// 5. Never matches valid code first; it only words the type errors, which\n\t// TypeScript reports against the last overload.\n\t<\n\t\tTReturn,\n\t\tTInput extends ZodType | undefined = undefined,\n\t\tTOut extends ZodType | undefined = undefined,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default']\n\t>(\n\t\toptions: {\n\t\t\tinput?: TInput\n\t\t\toutput?: TOut\n\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, InputOf<TInput>, NoInfer<TKey>>\n\t\t\t) => MaybePromise<ReturnOf<TOut, TReturn>>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnProcedure<\n\t\tTDef,\n\t\tTKey,\n\t\t[TInput] extends [ZodType] ? TInput : Schema<unknown, unknown>,\n\t\t[TOut] extends [ZodType] ? TOut : Schema<TReturn, TReturn>\n\t>\n}\n\n/** What `fn.completed` reports, and what `onCompleted` receives. */\nexport type FnCompletedEvent<TContext = unknown, TSpan = SpanLike> = {\n\tname: string\n\tprocedure: string\n\tdurationMs: number\n\tsuccess: boolean\n\terror: unknown\n\tinput: unknown\n\tcontext: TContext\n\tspan: TSpan | undefined\n\tmeta: Record<string, unknown>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAkFA,oFAAoF;AACpF,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC,MAAM;IACN,QAAQ;IACR,SAAS;IACT,aAAa;IACb,YAAY;IACZ,eAAe;IACf,oBAAoB;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,MAAM;CACsC,CAAA;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IACnC,GAAG,iBAAiB;IACpB,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,SAAS;IACT,MAAM;IACN,aAAa;IACb,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,gBAAgB;CACP,CAAA","sourcesContent":["import type {\n\tAnySchema,\n\tErrorMap,\n\tInferSchemaInput,\n\tInferSchemaOutput,\n\tMergedErrorMap,\n\tSchema\n} from '@orpc/contract'\nimport type {\n\tAnyProcedure,\n\tDecoratedProcedure,\n\tProcedure,\n\tRoute\n} from '@orpc/server'\nimport type { createORPCErrorConstructorMap } from '@orpc/server'\nimport type { StoredFnMeta } from './meta.js'\nimport type { NativeErrors, NativeMeta } from './compatibility.js'\nimport type { BoundCall } from './bound-call.js'\nimport type { FnLogger } from './logger.js'\nimport type { SpanLike } from './otel.js'\n\nexport type MaybePromise<T> = T | Promise<T>\n\n/**\n * An oRPC builder without input or output schema: `os`, `os.$context<T>()`,\n * `os.use(...)`. A schema set on the builder is rejected by `createFn`; set it\n * on the route instead.\n */\n/* biome-ignore-start lint/suspicious/noExplicitAny: matches every builder's generic methods */\nexport type BuilderLike = {\n\troute(route: any): unknown\n\tmeta(meta: any): unknown\n\tinput(schema: any): unknown\n\toutput(schema: any): unknown\n\thandler(handler: any): Procedure<any, any, any, any, any, any>\n}\n/* biome-ignore-end lint/suspicious/noExplicitAny: matches every builder's generic methods */\n\n/** Input a procedure is called with (before its input schema runs). */\nexport type ProcedureInput<T> =\n\tT extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer _TCurrent,\n\t\tinfer TInputSchema extends AnySchema,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? InferSchemaInput<TInputSchema>\n\t\t: unknown\n\n/** What a procedure resolves to (after its output schema runs). */\nexport type ProcedureOutput<T> =\n\tT extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer _TCurrent,\n\t\tinfer _TIn,\n\t\tinfer TOutputSchema extends AnySchema,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? InferSchemaOutput<TOutputSchema>\n\t\t: unknown\n\n/** Context a procedure must be called with. */\nexport type ProcedureContext<T> =\n\tT extends Procedure<\n\t\tinfer TContext,\n\t\tinfer _TCurrent,\n\t\tinfer _TIn,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? TContext\n\t\t: never\n\n/** `Omit` that keeps each member of a union (handler params narrow by discriminant). */\nexport type DistributiveOmit<T, K extends PropertyKey> = T extends unknown\n\t? Omit<T, K>\n\t: never\n\n/** `fn()` options passed to oRPC's `.route()`; `RouteConfig` is derived from it. */\nexport const ROUTE_OPTION_KEYS = [\n\t'path',\n\t'method',\n\t'summary',\n\t'description',\n\t'deprecated',\n\t'successStatus',\n\t'successDescription',\n\t'inputStructure',\n\t'outputStructure',\n\t'tags'\n] as const satisfies readonly (keyof Route)[]\n\n/**\n * `fn()` option names owned by the route itself. Guard keys must not\n * reuse them: such an option would be read as the route option and the guard\n * would never run.\n */\nexport const RESERVED_OPTION_KEYS = [\n\t...ROUTE_OPTION_KEYS,\n\t'name',\n\t'procedure',\n\t'input',\n\t'output',\n\t'handler',\n\t'live',\n\t'operationId',\n\t'meta',\n\t'stream',\n\t'errors',\n\t'guardResolvers'\n] as const\n\nexport type ReservedOptionKey = (typeof RESERVED_OPTION_KEYS)[number]\n\n/** @internal Builds one route from a selected native procedure builder. */\nexport type BuildProcedure = (options: {\n\tname: string\n\tprocedure: string | undefined\n\troute: Record<string, unknown>\n\tmeta: Record<string, unknown>\n\tinput?: AnySchema | undefined\n\toutput?: AnySchema | undefined\n\tstream?: boolean\n\terrors?: ErrorMap\n\thandler: (options: {\n\t\tinput: unknown\n\t\tcontext: Record<string | symbol, unknown>\n\t\tsignal?: AbortSignal\n\t\tlastEventId?: string\n\t\terrors: ReturnType<typeof createORPCErrorConstructorMap>\n\t}) => unknown\n}) => AnyProcedure\n\n/** Turns every key of `T` found in `K` into a readable type error. */\nexport type RejectKeys<T, K extends PropertyKey, TMessage extends string> = {\n\t[P in Extract<keyof T, K>]: TMessage\n}\n\n/**\n * Handler extras must have known keys: an index signature would claim every\n * handler param. Intersected into `createFn`'s options to reject it.\n */\nexport type FiniteExtras<T> = T extends unknown\n\t? string extends keyof T\n\t\t? { extras: 'orpc-fn: extras need known keys, not an index signature' }\n\t\t: number extends keyof T\n\t\t\t? { extras: 'orpc-fn: extras need known keys, not an index signature' }\n\t\t\t: Extract<\n\t\t\t\t\t\tkeyof T,\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> extends never\n\t\t\t\t? unknown\n\t\t\t\t: { extras: 'orpc-fn: extras cannot shadow handler parameters' }\n\t: never\n\ntype ProcedureOf<TBuilder> = TBuilder extends {\n\thandler(handler: never): infer TProcedure\n}\n\t? TProcedure\n\t: never\n\n/** Context a route built from this builder is called with. */\nexport type InitialContextOf<TBuilder> = ProcedureContext<ProcedureOf<TBuilder>>\n\n/** Context the handler sees, after the builder's middleware. */\nexport type CurrentContextOf<TBuilder> =\n\tProcedureOf<TBuilder> extends Procedure<\n\t\tinfer _TInitial,\n\t\tinfer TContext,\n\t\tinfer _TIn,\n\t\tinfer _TOut,\n\t\tinfer _TErrors,\n\t\tinfer _TMeta\n\t>\n\t\t? TContext\n\t\t: never\n\nexport type ErrorMapOf<TBuilder> = NativeErrors<ProcedureOf<TBuilder>>\ntype MetaOf<TBuilder> = NativeMeta<ProcedureOf<TBuilder>>\n\n/**\n * Everything `createFn` inferred from its options. Route types read from it;\n * apps rarely spell it out.\n */\nexport type FnDefinition = {\n\tprocedures: Record<string, BuilderLike>\n\tdefault: string\n\textras: object\n\textrasByProcedure?: Partial<Record<string, object>>\n\tguards: object\n\tmeta: object\n\ttag: string\n\tspan: SpanLike\n\tlogger: FnLogger\n}\n\nexport type ProcedureKey<TDef extends FnDefinition> = keyof TDef['procedures'] &\n\tstring\n\n/** Context the handler of a `procedure: TKey` route receives. */\nexport type FnContext<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>\n> = CurrentContextOf<TDef['procedures'][TKey]>\n\n/** Union of every procedure's handler context: what guards and extras see. */\nexport type AnyFnContext<TDef extends FnDefinition> = {\n\t[K in ProcedureKey<TDef>]: FnContext<TDef, K>\n}[ProcedureKey<TDef>]\n\nexport type GuardParams<TContext, TMeta> = {\n\tcontext: TContext\n\tinput: unknown\n\t/** Route name (operationId). */\n\tname: string\n\t/** Procedures key the route was built from. */\n\tprocedure: string\n\tmeta: Partial<TMeta>\n\tsignal: AbortSignal | undefined\n}\n\n/**\n * A check run before the handler. Its first parameter becomes an option on\n * `fn({...})`; the guard runs only on routes that set it. Throw (usually an\n * `ORPCError`) to refuse the call.\n */\n/* biome-ignore-start lint/suspicious/noConfusingVoidType: union prevents accidental value returns while accepting assertion-style guards */\nexport type Guard<TValue, TParams> = (\n\tvalue: TValue,\n\tparams: TParams\n) => MaybePromise<void | boolean>\n/* biome-ignore-end lint/suspicious/noConfusingVoidType: assertion-style guards */\n\nexport type GuardOptions<TGuards> = {\n\t[K in keyof TGuards]?: TGuards[K] extends (\n\t\tvalue: infer TValue,\n\t\tparams: never\n\t) => unknown\n\t\t? TValue\n\t\t: never\n}\n\n/** Match object spread: scoped extras replace shared keys, preserving unions. */\ntype MergeExtras<TShared, TScoped> = TShared extends unknown\n\t? TScoped extends unknown\n\t\t? Omit<TShared, keyof TScoped> & TScoped\n\t\t: never\n\t: never\n\nexport type HandlerParams<\n\tTDef extends FnDefinition,\n\tTInput,\n\tTKey extends ProcedureKey<TDef>,\n\tTErrors extends ErrorMap = Record<never, never>\n> = DistributiveOmit<\n\tMergeExtras<\n\t\tTDef['extras'],\n\t\tTDef extends { extrasByProcedure: infer E }\n\t\t\t? TKey extends keyof E\n\t\t\t\t? E[TKey]\n\t\t\t\t: object\n\t\t\t: object\n\t>,\n\t| 'input'\n\t| 'context'\n\t| 'call'\n\t| 'signal'\n\t| 'span'\n\t| 'logger'\n\t| 'errors'\n\t| 'lastEventId'\n> & {\n\tinput: TInput\n\tcontext: FnContext<TDef, TKey>\n\t/** Calls another procedure with this context and signal, in a child span. */\n\tcall: BoundCall<FnContext<TDef, TKey>>\n\t/** Cancellation is inherited by nested calls; pass to interruptible I/O. */\n\tsignal: AbortSignal | undefined\n\t/** Active OpenTelemetry span, undefined when `createFn({ otel })` is not set. */\n\tspan: TDef['span'] | undefined\n\tlogger: TDef['logger']\n\tlastEventId: string | undefined\n\terrors: ReturnType<\n\t\ttypeof createORPCErrorConstructorMap<\n\t\t\tMergedErrorMap<ErrorMapOf<TDef['procedures'][TKey]>, TErrors>\n\t\t>\n\t>\n}\n\n/** Route options shared by every `fn()` overload. */\nexport type RouteConfig<TTag extends string = string> = Pick<\n\tRoute,\n\tExclude<(typeof ROUTE_OPTION_KEYS)[number], 'tags'>\n> & {\n\t/** Required. Becomes the OpenAPI operationId and the span name (e.g. 'user.create'). */\n\tname: string\n\ttags?: TTag[]\n}\n\nexport type FnRouteOptions<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>,\n\tTInput = unknown,\n\tTErrors extends ErrorMap = Record<never, never>\n> = RouteConfig<TDef['tag']> &\n\tGuardOptions<TDef['guards']> & {\n\t\tmeta?: TDef['meta']\n\t\tstream?: boolean\n\t\terrors?: TErrors\n\t\tguardResolvers?: {\n\t\t\t[K in keyof TDef['guards']]?: (params: {\n\t\t\t\tinput: TInput\n\t\t\t\tcontext: FnContext<TDef, TKey>\n\t\t\t\tsignal: AbortSignal | undefined\n\t\t\t}) => MaybePromise<GuardOptions<TDef['guards']>[K]>\n\t\t}\n\t} & ProcedureOption<TDef, TKey>\n\n/**\n * Which `createFn({ procedures })` builder a route uses. Optional when\n * `createFn` has a `default`; required on every route when it has none.\n */\nexport type ProcedureOption<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>\n> = [TDef['default']] extends [never]\n\t? { procedure: TKey }\n\t: { procedure?: TKey }\n\nexport type FnProcedure<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>,\n\tTInputSchema extends Schema<unknown, unknown>,\n\tTOutputSchema extends Schema<unknown, unknown>,\n\tTErrors extends ErrorMap = Record<never, never>\n> = DecoratedProcedure<\n\tInitialContextOf<TDef['procedures'][TKey]>,\n\tFnContext<TDef, TKey>,\n\tTInputSchema,\n\tTOutputSchema,\n\tMergedErrorMap<ErrorMapOf<TDef['procedures'][TKey]>, TErrors>,\n\tMetaOf<TDef['procedures'][TKey]> & {\n\t\t'orpc-fn': StoredFnMeta<TDef['meta'], TKey>\n\t}\n>\n\ntype InputOf<T> = [T] extends [AnySchema] ? InferSchemaOutput<T> : unknown\ntype ReturnOf<TOut, TReturn> = [TOut] extends [AnySchema]\n\t? InferSchemaInput<TOut>\n\t: TReturn\n\n/** `fn()`: four overloads for input/output schema × inferred. */\nexport interface Fn<TDef extends FnDefinition> {\n\t// 1. With input + output schema\n\t<\n\t\tTInput extends AnySchema,\n\t\tTOut extends AnySchema,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput: TOut\n\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<\n\t\t\t\t\tTDef,\n\t\t\t\t\tInferSchemaOutput<TInput>,\n\t\t\t\t\tNoInfer<TKey>,\n\t\t\t\t\tTErrors\n\t\t\t\t>\n\t\t\t) => MaybePromise<InferSchemaInput<TOut>>\n\t\t} & FnRouteOptions<TDef, TKey, InferSchemaOutput<TInput>, TErrors>\n\t): FnProcedure<TDef, TKey, TInput, TOut, TErrors>\n\n\t// 2. With input, inferred output\n\t<\n\t\tTInput extends AnySchema,\n\t\tTReturn,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<\n\t\t\t\t\tTDef,\n\t\t\t\t\tInferSchemaOutput<TInput>,\n\t\t\t\t\tNoInfer<TKey>,\n\t\t\t\t\tTErrors\n\t\t\t\t>\n\t\t\t) => MaybePromise<TReturn>\n\t\t} & FnRouteOptions<TDef, TKey, InferSchemaOutput<TInput>, TErrors>\n\t): FnProcedure<TDef, TKey, TInput, Schema<TReturn, TReturn>, TErrors>\n\n\t// 3. No input, with output schema\n\t<\n\t\tTOut extends AnySchema,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput?: undefined\n\t\t\toutput: TOut\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, unknown, NoInfer<TKey>, TErrors>\n\t\t\t) => MaybePromise<InferSchemaInput<TOut>>\n\t\t} & FnRouteOptions<TDef, TKey, unknown, TErrors>\n\t): FnProcedure<TDef, TKey, Schema<unknown, unknown>, TOut, TErrors>\n\n\t// 4. No input, inferred output\n\t<\n\t\tTReturn,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput?: undefined\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, unknown, NoInfer<TKey>, TErrors>\n\t\t\t) => MaybePromise<TReturn>\n\t\t} & FnRouteOptions<TDef, TKey, unknown, TErrors>\n\t): FnProcedure<\n\t\tTDef,\n\t\tTKey,\n\t\tSchema<unknown, unknown>,\n\t\tSchema<TReturn, TReturn>,\n\t\tTErrors\n\t>\n\n\t// 5. Never matches valid code first; it only words the type errors, which\n\t// TypeScript reports against the last overload.\n\t<\n\t\tTReturn,\n\t\tTInput extends AnySchema | undefined = undefined,\n\t\tTOut extends AnySchema | undefined = undefined,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput?: TInput\n\t\t\toutput?: TOut\n\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, InputOf<TInput>, NoInfer<TKey>, TErrors>\n\t\t\t) => MaybePromise<ReturnOf<TOut, TReturn>>\n\t\t} & FnRouteOptions<TDef, TKey, InputOf<TInput>, TErrors>\n\t): FnProcedure<\n\t\tTDef,\n\t\tTKey,\n\t\t[TInput] extends [AnySchema] ? TInput : Schema<unknown, unknown>,\n\t\t[TOut] extends [AnySchema] ? TOut : Schema<TReturn, TReturn>,\n\t\tTErrors\n\t>\n}\n\n/** What `fn.completed` reports, and what `onCompleted` receives. */\nexport type FnCompletedEvent<TContext = unknown, TSpan = SpanLike> = {\n\tname: string\n\tprocedure: string\n\tdurationMs: number\n\tsuccess: boolean\n\t/** False when authentication or input validation prevented handler execution. */\n\thandlerStarted: boolean\n\terror: unknown\n\tinput: unknown\n\tcontext: TContext\n\tspan: TSpan | undefined\n\tmeta: Record<string, unknown>\n}\n\n/** Factory hooks retain the builder key/context relationship. */\nexport type ProcedureHookParams<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTExtra = object\n> = {\n\t[K in keyof TProcedures & string]: TExtra & {\n\t\tprocedure: K\n\t\tcontext: CurrentContextOf<TProcedures[K]>\n\t}\n}[keyof TProcedures & string]\n\nexport type CompletedHookEvent<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTSpan\n> = {\n\t[K in keyof TProcedures & string]: Omit<\n\t\tFnCompletedEvent<unknown, TSpan>,\n\t\t'context' | 'procedure' | 'handlerStarted'\n\t> & { procedure: K } & (\n\t\t\t| { handlerStarted: true; context: CurrentContextOf<TProcedures[K]> }\n\t\t\t| { handlerStarted: false; context: InitialContextOf<TProcedures[K]> }\n\t\t)\n}[keyof TProcedures & string]\n\nexport type FiniteScopedExtras<T> = {\n\t[K in keyof T]: string extends keyof T[K]\n\t\t? K\n\t\t: number extends keyof T[K]\n\t\t\t? K\n\t\t\t: Extract<\n\t\t\t\t\t\tkeyof T[K],\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> extends never\n\t\t\t\t? never\n\t\t\t\t: K\n}[keyof T] extends never\n\t? unknown\n\t: {\n\t\t\textrasByProcedure: 'orpc-fn: scoped extras need finite keys and cannot shadow handler parameters'\n\t\t}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orpc-fn",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Define a backend function once: a typed oRPC procedure with tracing, logging, guards, injected handler extras, nested calls and live queries over Redis.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -70,6 +70,10 @@
|
|
|
70
70
|
"./expo": {
|
|
71
71
|
"types": "./dist/expo.d.ts",
|
|
72
72
|
"import": "./dist/expo.js"
|
|
73
|
+
},
|
|
74
|
+
"./mcp/sdk": {
|
|
75
|
+
"types": "./dist/mcp/sdk.d.ts",
|
|
76
|
+
"import": "./dist/mcp/sdk.js"
|
|
73
77
|
}
|
|
74
78
|
},
|
|
75
79
|
"types": "./dist/index.d.ts",
|
|
@@ -93,7 +97,9 @@
|
|
|
93
97
|
"attw": "attw --pack . --profile esm-only",
|
|
94
98
|
"publint": "publint",
|
|
95
99
|
"test:consumers": "bun scripts/check-consumers.ts",
|
|
96
|
-
"verify:package": "node scripts/verify-package.mjs"
|
|
100
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
101
|
+
"test:types-performance": "bun scripts/check-types-performance.ts",
|
|
102
|
+
"test:client-bundle": "bun scripts/check-client-bundle.ts"
|
|
97
103
|
},
|
|
98
104
|
"peerDependencies": {
|
|
99
105
|
"@mastra/core": "^1.51.0",
|
|
@@ -106,7 +112,8 @@
|
|
|
106
112
|
"@orpc/zod": "^1.14.0",
|
|
107
113
|
"hono": "^4.0.0",
|
|
108
114
|
"ioredis": "^5.0.0",
|
|
109
|
-
"zod": "^4.0.0"
|
|
115
|
+
"zod": "^4.0.0",
|
|
116
|
+
"@modelcontextprotocol/sdk": "^1.32.0"
|
|
110
117
|
},
|
|
111
118
|
"peerDependenciesMeta": {
|
|
112
119
|
"@mastra/core": {
|
|
@@ -129,12 +136,16 @@
|
|
|
129
136
|
},
|
|
130
137
|
"ioredis": {
|
|
131
138
|
"optional": true
|
|
139
|
+
},
|
|
140
|
+
"@modelcontextprotocol/sdk": {
|
|
141
|
+
"optional": true
|
|
132
142
|
}
|
|
133
143
|
},
|
|
134
144
|
"devDependencies": {
|
|
135
145
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
136
146
|
"@biomejs/biome": "^2.2.4",
|
|
137
147
|
"@mastra/core": "1.51.0",
|
|
148
|
+
"@modelcontextprotocol/sdk": "1.32.0",
|
|
138
149
|
"@opentelemetry/api": "^1.9.0",
|
|
139
150
|
"@orpc/client": "1.14.8",
|
|
140
151
|
"@orpc/contract": "1.14.8",
|
|
@@ -148,6 +159,7 @@
|
|
|
148
159
|
"ioredis": "5.8.2",
|
|
149
160
|
"publint": "^0.3.12",
|
|
150
161
|
"typescript": "^7.0.2",
|
|
162
|
+
"typescript-ast": "npm:typescript@5.7.3",
|
|
151
163
|
"zod": "4.4.3"
|
|
152
164
|
},
|
|
153
165
|
"bugs": {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { AnySchema } from '@orpc/contract'
|
|
2
|
+
import type { AnyProcedure } from '@orpc/server'
|
|
3
|
+
import { FN_META_KEY, type StoredFnMeta } from './meta.js'
|
|
4
|
+
import type { BuildProcedure } from './types.js'
|
|
5
|
+
|
|
6
|
+
export type BuilderChain = {
|
|
7
|
+
route(route: Record<string, unknown>): BuilderChain
|
|
8
|
+
meta(meta: Record<string, unknown>): BuilderChain
|
|
9
|
+
input(schema: AnySchema): BuilderChain
|
|
10
|
+
output(schema: AnySchema): BuilderChain
|
|
11
|
+
errors(errors: import('@orpc/contract').ErrorMap): BuilderChain
|
|
12
|
+
handler(handler: Parameters<BuildProcedure>[0]['handler']): AnyProcedure
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createProcedureAssembler(
|
|
16
|
+
procedures: Record<string, BuilderChain>,
|
|
17
|
+
resolveKey: (key: string | undefined, name: string) => string
|
|
18
|
+
): BuildProcedure {
|
|
19
|
+
return (route) => {
|
|
20
|
+
const key = resolveKey(route.procedure, route.name)
|
|
21
|
+
let builder = procedures[key]
|
|
22
|
+
if (!builder) throw new Error(`orpc-fn: unknown procedure "${key}"`)
|
|
23
|
+
const stored: StoredFnMeta = {
|
|
24
|
+
name: route.name,
|
|
25
|
+
procedure: key,
|
|
26
|
+
meta: route.meta,
|
|
27
|
+
stream: route.stream ?? false
|
|
28
|
+
}
|
|
29
|
+
builder = builder
|
|
30
|
+
.route({
|
|
31
|
+
operationId: route.name,
|
|
32
|
+
...Object.fromEntries(
|
|
33
|
+
Object.entries(route.route).filter(([, value]) => value !== undefined)
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
.meta({ [FN_META_KEY]: stored })
|
|
37
|
+
if (route.errors) builder = builder.errors(route.errors)
|
|
38
|
+
if (route.input) builder = builder.input(route.input)
|
|
39
|
+
if (route.output) builder = builder.output(route.output)
|
|
40
|
+
return builder.handler(route.handler)
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/bound-call.ts
CHANGED
|
@@ -18,10 +18,11 @@ type ContextCheck<TContext, T> = [TContext] extends [ProcedureContext<T>]
|
|
|
18
18
|
* Calls another procedure with the caller's context and signal. `TContext` is
|
|
19
19
|
* the caller's context; the callee must accept it.
|
|
20
20
|
*/
|
|
21
|
-
|
|
22
|
-
export type BoundCall<TContext = any> = <T extends AnyProcedure>(
|
|
21
|
+
export type BoundCall<TContext> = <T extends AnyProcedure>(
|
|
23
22
|
procedure: T & ContextCheck<TContext, T>,
|
|
24
|
-
|
|
23
|
+
...args: undefined extends ProcedureInput<T>
|
|
24
|
+
? [input?: ProcedureInput<T>]
|
|
25
|
+
: [input: ProcedureInput<T>]
|
|
25
26
|
) => Promise<ProcedureOutput<T>>
|
|
26
27
|
|
|
27
28
|
const noTracing = createTracing(undefined)
|
package/src/client.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type CreateRpcLinkOptions<T extends ClientContext> =
|
|
|
16
16
|
* default only calls without a client context are batched; pass
|
|
17
17
|
* `groups` to batch calls that share a context (e.g. a token).
|
|
18
18
|
*/
|
|
19
|
+
/** Client-safe manifest generated by createStreamManifest(router). */
|
|
20
|
+
streamPaths?: readonly (readonly string[])[]
|
|
19
21
|
batch?:
|
|
20
22
|
| boolean
|
|
21
23
|
| {
|
|
@@ -47,7 +49,8 @@ export const isSubscriptionPath = (path: readonly string[]) =>
|
|
|
47
49
|
export function createRpcLink<T extends ClientContext = ClientContext>(
|
|
48
50
|
options: CreateRpcLinkOptions<T>
|
|
49
51
|
): RPCLink<T> {
|
|
50
|
-
const { batch = true, plugins = [], ...rest } = options
|
|
52
|
+
const { batch = true, plugins = [], streamPaths, ...rest } = options
|
|
53
|
+
const streams = new Set(streamPaths?.map((path) => JSON.stringify(path)))
|
|
51
54
|
if (batch === false) return new RPCLink<T>({ ...rest, plugins })
|
|
52
55
|
const {
|
|
53
56
|
maxSize = 25,
|
|
@@ -65,6 +68,7 @@ export function createRpcLink<T extends ClientContext = ClientContext>(
|
|
|
65
68
|
{ condition: () => true, context: {} as T }
|
|
66
69
|
],
|
|
67
70
|
exclude: ({ path, context }) =>
|
|
71
|
+
streams.has(JSON.stringify(path)) ||
|
|
68
72
|
exclude(path) ||
|
|
69
73
|
(groups === undefined && Object.keys(context).length > 0)
|
|
70
74
|
}),
|
|
@@ -77,6 +81,9 @@ export function createRpcLink<T extends ClientContext = ClientContext>(
|
|
|
77
81
|
* Typed check for a route error on the client. The RPC link rebuilds thrown
|
|
78
82
|
* route errors as `ORPCError`, so `instanceof` plus `code` is the contract.
|
|
79
83
|
*/
|
|
80
|
-
export function hasOrpcErrorCode
|
|
84
|
+
export function hasOrpcErrorCode<TCode extends ORPCErrorCode>(
|
|
85
|
+
error: unknown,
|
|
86
|
+
code: TCode
|
|
87
|
+
): error is ORPCError<TCode, unknown> {
|
|
81
88
|
return error instanceof ORPCError && error.code === code
|
|
82
89
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AnySchema, ErrorMap, Meta } from '@orpc/contract'
|
|
2
|
+
import type { Procedure, Route } from '@orpc/server'
|
|
3
|
+
|
|
4
|
+
/** All runtime access to oRPC's implementation namespace is audited here. */
|
|
5
|
+
export type ProcedureDefinition = {
|
|
6
|
+
meta?: Record<string, unknown>
|
|
7
|
+
route?: Route
|
|
8
|
+
inputSchema?: AnySchema
|
|
9
|
+
outputSchema?: AnySchema
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function procedureDefinition(procedure: object): ProcedureDefinition {
|
|
13
|
+
return (procedure as { '~orpc'?: ProcedureDefinition })['~orpc'] ?? {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type NativeMeta<T> =
|
|
17
|
+
T extends Procedure<
|
|
18
|
+
infer _I,
|
|
19
|
+
infer _C,
|
|
20
|
+
infer _In,
|
|
21
|
+
infer _Out,
|
|
22
|
+
infer _E,
|
|
23
|
+
infer M extends Meta
|
|
24
|
+
>
|
|
25
|
+
? M
|
|
26
|
+
: Meta
|
|
27
|
+
export type NativeErrors<T> =
|
|
28
|
+
T extends Procedure<
|
|
29
|
+
infer _I,
|
|
30
|
+
infer _C,
|
|
31
|
+
infer _In,
|
|
32
|
+
infer _Out,
|
|
33
|
+
infer E extends ErrorMap,
|
|
34
|
+
infer _M
|
|
35
|
+
>
|
|
36
|
+
? E
|
|
37
|
+
: ErrorMap
|
|
38
|
+
export type LibraryMeta<T> =
|
|
39
|
+
NativeMeta<T> extends { 'orpc-fn': infer M } ? M : never
|