🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP β†’
Sign In

@orpc/shared

Package Overview
Dependencies
Maintainers
1
Versions
1114
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@orpc/shared - npm Package Compare versions

Comparing version
1.14.11
to
1.14.12
+202
-211
dist/index.d.mts

@@ -1,46 +0,106 @@

import { Arrayable, Promisable } from 'type-fest';
export { Arrayable, IsEqual, PartialDeep, Promisable, Writable } from 'type-fest';
import { Promisable } from 'type-fest';
export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest';
import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api';
import { AsyncIteratorClass } from '@standardserver/shared';
export { AbortError, AsyncCleanupFn, AsyncIteratorClass, AsyncIteratorClassNextFn, SequentialIdGenerator, getOrBind, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray } from '@standardserver/shared';
export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';
type MaybeOptionalOptions<TOptions> = object extends TOptions ? [options?: TOptions] : [options: TOptions];
type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions];
declare function resolveMaybeOptionalOptions<T>(rest: MaybeOptionalOptions<T>): T;
declare function toArray<T>(value: T): T extends readonly any[] ? T : Exclude<T, undefined | null>[];
declare function splitInHalf<T>(arr: readonly T[]): [T[], T[]];
/**
* Load Request/Response/Blob/File/.. to a buffer (Uint8Array<ArrayBuffer>).
* Converts Request/Response/Blob/File/.. to a buffer (ArrayBuffer or Uint8Array).
*
* Prefers the newer `.bytes` method when available as it more efficient but not widely supported yet.
*/
declare function loadBytes(source: Pick<Blob, 'arrayBuffer' | 'bytes'>): ReturnType<Blob['bytes']>;
declare function readAsBuffer(source: Pick<Blob, 'arrayBuffer' | 'bytes'>): Promise<ArrayBuffer | Uint8Array>;
type AnyFunction = (...args: any[]) => any;
declare function once<T extends () => any>(fn: T): () => ReturnType<T>;
declare function sequential<A extends any[], R>(fn: (...args: A) => Promise<R>): (...args: A) => Promise<R>;
/**
* Normalize text or binary-like inputs to either:
* - the original string value, or
* - a Uint8Array view over the source bytes.
* Executes the callback function after the current call stack has been cleared.
*/
declare function toStringOrBytes(source: Arrayable<string | ArrayBuffer | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>>): string | Awaited<ReturnType<Blob['bytes']>>;
declare function defer(callback: () => void): void;
declare function isDeepEqual(a: unknown, b: unknown): boolean;
type OmitChainMethodDeep<T extends object, K extends keyof any> = {
[P in keyof Omit<T, K>]: T[P] extends AnyFunction ? ((...args: Parameters<T[P]>) => OmitChainMethodDeep<ReturnType<T[P]>, K>) : T[P];
};
declare const ORPC_NAME = "orpc";
declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
declare const ORPC_SHARED_PACKAGE_VERSION = "1.14.12";
declare function isAbortError(error: unknown): error is Error;
type AnyFunction = (...args: any[]) => any;
declare function once<T>(fn: () => T): () => T;
/**
* Executes the callback function after the current call stack has been cleared.
* Error thrown when an operation is aborted.
* Uses the standardized 'AbortError' name for consistency with JavaScript APIs.
*/
declare function defer(callback: () => void): void;
declare function tryOrUndefined<T>(fn: () => T): undefined | T;
declare class AbortError extends Error {
constructor(...rest: ConstructorParameters<typeof Error>);
}
declare function pathToHttpPath(path: readonly string[]): `/${string}`;
declare function normalizeHttpPath(path: string): `/${string}`;
declare function mergeHttpPath(a: `/${string}`, b: `/${string}`): `/${string}`;
declare function matchesHttpPathPrefix(url: `/${string}`, prefix: `/${string}`): boolean;
declare function matchesHttpPath(url: `/${string}`, path: `/${string}`): boolean;
declare function isCompressibleContentType(contentType: string | null | undefined): boolean;
interface EventPublisherOptions {
/**
* Maximum number of events to buffer for async iterator subscribers.
*
* If the buffer exceeds this limit, the oldest event is dropped.
* This prevents unbounded memory growth if consumers process events slowly.
*
* Set to:
* - `0`: Disable buffering. Events must be consumed before the next one arrives.
* - `1`: Only keep the latest event. Useful for real-time updates where only the most recent value matters.
* - `Infinity`: Keep all events. Ensures no data loss, but may lead to high memory usage.
*
* @default 100
*/
maxBufferedEvents?: number;
}
interface EventPublisherSubscribeIteratorOptions extends EventPublisherOptions {
/**
* Aborts the async iterator. Throws if aborted before or during pulling.
*/
signal?: AbortSignal | undefined;
}
declare class EventPublisher<T extends Record<PropertyKey, any>> {
#private;
constructor(options?: EventPublisherOptions);
get size(): number;
/**
* Emits an event and delivers the payload to all subscribed listeners.
*/
publish<K extends keyof T>(event: K, payload: T[K]): void;
/**
* Subscribes to a specific event using a callback function.
* Returns an unsubscribe function to remove the listener.
*
* @example
* ```ts
* const unsubscribe = publisher.subscribe('event', (payload) => {
* console.log(payload)
* })
*
* // Later
* unsubscribe()
* ```
*/
subscribe<K extends keyof T>(event: K, listener: (payload: T[K]) => void): () => void;
/**
* Subscribes to a specific event using an async iterator.
* Useful for `for await...of` loops with optional buffering and abort support.
*
* @example
* ```ts
* for await (const payload of publisher.subscribe('event', { signal })) {
* console.log(payload)
* }
* ```
*/
subscribe<K extends keyof T>(event: K, options?: EventPublisherSubscribeIteratorOptions): AsyncGenerator<T[K]> & AsyncIteratorObject<T[K]>;
}
declare class SequentialIdGenerator {
private index;
generate(): string;
}
/**

@@ -55,7 +115,4 @@ * Compares two sequential IDs.

type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type IntersectPick<T, U> = Pick<T, keyof T & keyof U>;
/**
* Remove protected/private properties/methods
*/
type Public<T> = Pick<T, keyof T>;
type PromiseWithError<T, TError> = Promise<T> & {

@@ -69,3 +126,3 @@ __error?: {

*
* - `ThrowableError` the error type that represent throwable errors should be `Error` or `null | undefined | {}` if you want more strict.
* - `throwableError` the error type that represent throwable errors should be `Error` or `null | undefined | {}` if you want more strict.
*/

@@ -75,4 +132,5 @@ interface Registry {

type ThrowableError = Registry extends {
ThrowableError: infer T;
throwableError: infer T;
} ? T : Error;
type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never;

@@ -85,51 +143,27 @@ type InterceptableOptions = Record<string, any>;

/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onStart<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onSuccess<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(result: Awaited<ReturnType<TOptions['next']>>, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onError<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(error: ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
type OnFinishState<TResult, TError> = [error: TError, data: undefined, isSuccess: false] | [error: null, data: TResult, isSuccess: true];
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onFinish<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(state: OnFinishState<Awaited<ReturnType<TOptions['next']>>, ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError>, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Creates a middleware or interceptor that invokes a callback when the returned async
* iterator object throws an error while being consumed.
*
* This does not replace the `onError`. `onError` only fires on the
* initial call (before the interceptor returns the iterator), whereas this
* callback only fires while consuming the iterator. Use both together to
* catch all possible errors.
*/
declare function onAsyncIteratorObjectError<T, TOptions extends {
next: () => any;
}, TRest extends any[]>(callback: NoInfer<(error: ThrowableError | (ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError), options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Creates an interceptor that invokes a callback when the returned readable
* stream errors while being consumed.
*
* This does not replace the `onError`. `onError` only fires on the
* initial call (before the interceptor returns the stream), whereas this
* callback only fires while consuming the stream. Use both together to catch
* all possible errors.
*/
declare function onReadableStreamError<T, TOptions extends {
next: () => any;
}, TRest extends any[]>(callback: NoInfer<(error: ThrowableError | (ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError), options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
declare function intercept<TOptions extends InterceptableOptions, TResult>(interceptors: undefined | Interceptor<TOptions, TResult>[], options: NoInfer<TOptions>, main: NoInfer<(options: TOptions) => TResult>): TResult;
declare function intercept<TOptions extends InterceptableOptions, TResult>(interceptors: Interceptor<TOptions, TResult>[], options: NoInfer<TOptions>, main: NoInfer<(options: TOptions) => TResult>): TResult;

@@ -140,14 +174,45 @@ /**

interface OpenTelemetryConfig {
interface OtelConfig {
tracer: Tracer;
trace: TraceAPI;
context: ContextAPI;
propagation: PropagationAPI;
}
/**
* Sets the global OpenTelemetry config.
* Call this once at app startup. Use `undefined` to disable tracing.
*/
declare function setGlobalOtelConfig(config: OtelConfig | undefined): void;
/**
* Gets the global OpenTelemetry config.
* Returns `undefined` if OpenTelemetry is not configured, initialized, or enabled.
*/
declare function getGlobalOtelConfig(): OtelConfig | undefined;
/**
* Starts a new OpenTelemetry span with the given name and options.
*
* @returns The new span, or `undefined` if no tracer is set.
*/
declare function startSpan(name: string, options?: SpanOptions, context?: Context): Span | undefined;
interface SetSpanErrorOptions {
/**
* propagation is optional, can reduce bundle size in some cases.
* Span error status is not set if error is due to cancellation by the signal.
*/
propagation?: PropagationAPI | undefined;
signal?: AbortSignal;
}
declare function setOpenTelemetryConfig(config: OpenTelemetryConfig | undefined): void;
declare function getOpenTelemetryConfig(): OpenTelemetryConfig | undefined;
interface StartSpanOptions extends SpanOptions {
/**
* Records and sets the error status on the given span.
* If the span is `undefined`, it does nothing.
*/
declare function setSpanError(span: Span | undefined, error: unknown, options?: SetSpanErrorOptions): void;
declare function setSpanAttribute(span: Span | undefined, key: string, value: AttributeValue | undefined): void;
/**
* Converts an error to an OpenTelemetry Exception.
*/
declare function toOtelException(error: unknown): Exclude<Exception, string>;
/**
* Converts a value to a string suitable for OpenTelemetry span attributes.
*/
declare function toSpanAttributeValue(data: unknown): string;
interface RunWithSpanOptions extends SpanOptions, SetSpanErrorOptions {
/**

@@ -158,64 +223,55 @@ * The name of the span to create.

/**
* Context to use for the created span.
* Context to use for the span.
*/
context?: Context;
}
declare function startSpan(options: StartSpanOptions | string): Span | undefined;
declare function recordSpanError(span: Span | undefined, error: unknown): void;
declare function setSpanAttributeIfDefined(span: Span | undefined, key: string, value: AttributeValue | undefined): void;
declare function toOtelException(error: unknown): Exclude<Exception, string>;
declare function toSpanAttributeValue(data: unknown): string;
interface RunWithSpanOptions extends StartSpanOptions {
}
declare function runWithSpan<T>(options: string | RunWithSpanOptions, fn: (span?: Span) => Promisable<T>): Promise<T>;
/**
* Runs a function within the context of a new OpenTelemetry span.
* The span is ended automatically, and errors are recorded to the span.
*/
declare function runWithSpan<T>({ name, context, ...options }: RunWithSpanOptions, fn: (span?: Span) => Promisable<T>): Promise<T>;
/**
* Runs a function within the context of an existing OpenTelemetry span.
*/
declare function runInSpanContext<T>(span: Span | undefined, fn: () => Promisable<T>): Promise<T>;
interface WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn> {
declare function isAsyncIteratorObject(maybe: unknown): maybe is AsyncIteratorObject<any, any, any>;
interface AsyncIteratorClassNextFn<T, TReturn> {
(): Promise<IteratorResult<T, TReturn>>;
}
interface AsyncIteratorClassCleanupFn {
(reason: 'return' | 'throw' | 'next' | 'dispose'): Promise<void>;
}
declare const fallbackAsyncDisposeSymbol: unique symbol;
declare const asyncDisposeSymbol: typeof Symbol extends {
asyncDispose: infer T;
} ? T : typeof fallbackAsyncDisposeSymbol;
declare class AsyncIteratorClass<T, TReturn = unknown, TNext = unknown> implements AsyncIteratorObject<T, TReturn, TNext>, AsyncGenerator<T, TReturn, TNext> {
#private;
constructor(next: AsyncIteratorClassNextFn<T, TReturn>, cleanup: AsyncIteratorClassCleanupFn);
next(): Promise<IteratorResult<T, TReturn>>;
return(value?: any): Promise<IteratorResult<T, TReturn>>;
throw(err: any): Promise<IteratorResult<T, TReturn>>;
/**
* Any call to the original iterator will be executed inside this function.
* Useful when you want execution to happen within a specific context,
* such as AsyncLocalStorage.
* asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
*/
runWith?: <T>(run: () => Promise<T>) => Promise<T>;
mapResult?: (result: IteratorResult<TYield, TReturn>) => Promisable<IteratorResult<TMappedYield, TMappedReturn>>;
mapError?: (error: ThrowableError) => Promisable<ThrowableError>;
onError?: (error: ThrowableError) => Promisable<void>;
/**
* Execute after the stream finishes or is cancelled.
*/
onFinish?: () => Promisable<void>;
[asyncDisposeSymbol](): Promise<void>;
[Symbol.asyncIterator](): this;
}
declare function wrapAsyncIterator<TYield, TReturn, TMappedYield = TYield, TMappedReturn = TReturn>(iterator: AsyncIterator<TYield, TReturn>, { runWith, mapResult, mapError, onError, onFinish }: WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn>): NoInfer<AsyncIteratorClass<TMappedYield, TMappedReturn>>;
declare function traceAsyncIterator<T, TReturn, TNext>(options: StartSpanOptions | string, iterator: AsyncIterator<T, TReturn, TNext>): AsyncIteratorClass<T, TReturn, TNext>;
declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[];
interface ConsumeAsyncIteratorOptions<T, TReturn, TError> {
interface AsyncIteratorWithSpanOptions extends SetSpanErrorOptions {
/**
* Called on each event
* The name of the span to create.
*/
onEvent: (event: T) => void;
/**
* Called once error happens
*/
onError?: (error: TError) => void;
/**
* Called once AsyncIteratorObject is done
*
* @info If iterator is canceled, `undefined` can be passed on success
*/
onSuccess?: (value: TReturn | undefined) => void;
/**
* Called once after onError or onSuccess
*
* @info If iterator is canceled, `undefined` can be passed on success
*/
onFinish?: (state: [error: TError, data: undefined, isSuccess: false] | [error: null, data: TReturn | undefined, isSuccess: true]) => void;
name: string;
}
/**
* Consumes an AsyncIteratorObject with lifecycle callbacks
*
* @warning If no `onError` or `onFinish` is provided, error will be thrown into unhandled rejection channel.
* @return unsubscribe callback
*/
declare function consumeAsyncIterator<T, TReturn, TError = ThrowableError>(iterator: AsyncIterator<T, TReturn> | PromiseWithError<AsyncIterator<T, TReturn>, TError>, options: ConsumeAsyncIteratorOptions<T, TReturn, TError | ThrowableError>): () => Promise<void>;
declare function asyncIteratorWithSpan<T, TReturn, TNext>({ name, ...options }: AsyncIteratorWithSpanOptions, iterator: AsyncIterator<T, TReturn, TNext>): AsyncIteratorClass<T, TReturn, TNext>;
declare function parseEmptyableJSON(text: string | null | undefined): unknown;
declare function stringifyJSON<T>(value: T | {
toJSON(): T;
}): undefined extends T ? undefined | string : string;
declare function logError(error: unknown): void;
type Segment = string | number;

@@ -232,13 +288,11 @@ declare function findDeepMatches(check: (value: unknown) => boolean, payload: unknown, segments?: Segment[], maps?: Segment[][], values?: unknown[]): {

/**
* Checks whether a value is a plain object, including objects created with
* `Object.create(null)`.
* Check if the value is an object even it created by `Object.create(null)` or more tricky way.
*/
declare function isPlainObject(value: unknown): value is Record<PropertyKey, unknown>;
declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
declare function isObject(value: unknown): value is Record<PropertyKey, unknown>;
/**
* Sets a value at the given path, creating plain objects for intermediate keys as needed.
* Check if the value satisfy a `object` type in typescript
*/
declare function set(root: object, path: [PropertyKey, ...PropertyKey[]] | [...PropertyKey[], PropertyKey], value: unknown): void;
declare function omit<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
declare function isTypescriptObject(value: unknown): value is object & Record<PropertyKey, unknown>;
declare function clone<T>(value: T): T;
declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
declare function isPropertyKey(value: unknown): value is PropertyKey;

@@ -248,53 +302,26 @@ declare const NullProtoObj: ({

});
/**
* Returns an object containing all methods of the given object, with each
* method bound to the original object instance.
*
* Methods are collected from both the object itself and its prototype chain
* (excluding `Object.prototype` and the `constructor` property).
*/
declare function bindMethods<T extends object>(obj: T): Pick<T, {
[K in keyof T]: T[K] extends AnyFunction ? K : never;
}[keyof T]>;
interface OrderablePlugin {
/** Unique name of the plugin, used for ordering and identification. */
name: string;
/** Plugins this plugin should execute before. */
before?: string[] | undefined;
/** Plugins this plugin should execute after. */
after?: string[] | undefined;
}
type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
/**
* Sorts plugins based on their `before` and `after` dependencies.
* Returns the value if it is defined, otherwise returns the fallback
*/
declare function sortPlugins<T extends OrderablePlugin>(plugins: T[]): T[];
declare function fallback<T>(value: T | undefined, fallback: T): T;
/**
* Creates a promise together with its associated `resolve` and `reject`
* functions.
*
* Equivalent to `Promise.withResolvers()`, but works in environments
* where that API is not yet available.
* Prevents objects from being awaitable by intercepting the `then` method
* when called by the native await mechanism. This is useful for preventing
* accidental awaiting of objects that aren't meant to be promises.
*/
declare function promiseWithResolvers<T>(): {
promise: Promise<T>;
resolve: (v: T) => void;
reject: (reason: unknown) => void;
};
type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
declare function preventNativeAwait<T extends object>(target: T): T;
/**
* Creates a proxy that overlays a `partial` object on top of a `target`.
* Create a proxy that overlays one object (`overlay`) on top of another (`target`).
*
* - Properties from `partial` take precedence.
* - Properties not present in `partial` fall back to the resolved `target`.
* - Methods are bound to the proxy to ensure a consistent `this` context.
* - Properties from `overlay` take precedence.
* - Properties not in `overlay` fall back to `target`.
* - Methods from either object are bound to `overlay` so `this` is consistent.
*
* Useful for overriding specific properties of an object while delegating
* all other access to the original target without needing to know its full structure.
* Useful when you want to override or extend behavior without fully copying/merging objects.
*/
declare function override<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;
declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;

@@ -309,3 +336,5 @@ interface AsyncIdQueueCloseOptions {

private readonly waiters;
get size(): number;
get length(): number;
get waiterIds(): string[];
hasBufferedItems(id: string): boolean;
open(id: string): void;

@@ -316,48 +345,10 @@ isOpen(id: string): boolean;

close({ id, reason }?: AsyncIdQueueCloseOptions): void;
private assertOpen;
assertOpen(id: string): void;
}
/**
* Returns a signal that aborts only after all provided signals are aborted.
* Converts a `ReadableStream` into an `AsyncIteratorClass`.
*/
declare function allAbortSignal(signals: readonly (AbortSignal | undefined)[]): AbortSignal | undefined;
declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>;
/**
* Returns a signal that aborts as soon as any of the provided signals aborts,
* with the same abort reason.
*/
declare function anyAbortSignal(signals: readonly (AbortSignal | undefined)[]): AbortSignal | undefined;
declare function runWithSignal<T>(signal: AbortSignal | undefined, fn: () => Promise<T>): Promise<T>;
declare function replicateReadableStream<T>(stream: ReadableStream<T>, count: number): ReadableStream<T>[];
type ReadableStreamReadResult<T> = {
done: false;
value: T;
} | {
done: true;
value?: undefined | T;
};
interface WrapReadableStreamOptions<T, TMapped> {
/**
* Any call to the original stream reader will be executed inside this function.
* Useful when you want execution to happen within a specific context,
* such as AsyncLocalStorage.
*/
runWith?: <T>(run: () => Promise<T>) => Promise<T>;
mapResult?: (result: ReadableStreamReadResult<T>) => Promisable<ReadableStreamReadResult<TMapped>>;
mapError?: (error: ThrowableError) => Promisable<ThrowableError>;
onError?: (error: ThrowableError) => Promisable<void>;
/**
* Guaranteed to execute exactly once after the stream finishes or is cancelled.
*/
onFinish?: () => Promisable<void>;
}
declare function wrapReadableStream<T, TMapped = T>(stream: ReadableStream<T>, { runWith, mapResult, mapError, onError, onFinish }: WrapReadableStreamOptions<T, TMapped>): NoInfer<ReadableStream<TMapped>>;
declare function traceReadableStream<T>(options: StartSpanOptions | string, stream: ReadableStream<T>): ReadableStream<T>;
/**
* Converts a {@link ReadableStream} into an {@link AsyncIteratorClass}.
*/
declare function streamToAsyncIteratorObject<T>(stream: ReadableStream<T>, { signal }?: {
signal?: undefined | AbortSignal;
}): AsyncIteratorClass<T>;
/**
* Converts an `AsyncIterator` into a `ReadableStream`.

@@ -374,3 +365,3 @@ */

export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, anyAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isCompressibleContentType, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorObject, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream };
export type { AnyFunction, AsyncIdQueueCloseOptions, ConsumeAsyncIteratorOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OnFinishState, OpenTelemetryConfig, OrderablePlugin, PromiseWithError, Public, ReadableStreamReadResult, Registry, RunWithSpanOptions, Segment, StartSpanOptions, ThrowableError, Value, WrapAsyncIteratorOptions, WrapReadableStreamOptions };
export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, asyncIteratorWithSpan, clone, compareSequentialIds, defer, fallback, findDeepMatches, get, getConstructor, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, logError, onError, onFinish, onStart, onSuccess, once, overlayProxy, parseEmptyableJSON, preventNativeAwait, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
export type { AnyFunction, AsyncIdQueueCloseOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClassNextFn, AsyncIteratorWithSpanOptions, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, InferAsyncIterableYield, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, OtelConfig, PromiseWithError, Registry, RunWithSpanOptions, Segment, SetOptional, SetSpanErrorOptions, ThrowableError, Value };

@@ -1,46 +0,106 @@

import { Arrayable, Promisable } from 'type-fest';
export { Arrayable, IsEqual, PartialDeep, Promisable, Writable } from 'type-fest';
import { Promisable } from 'type-fest';
export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest';
import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api';
import { AsyncIteratorClass } from '@standardserver/shared';
export { AbortError, AsyncCleanupFn, AsyncIteratorClass, AsyncIteratorClassNextFn, SequentialIdGenerator, getOrBind, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray } from '@standardserver/shared';
export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';
type MaybeOptionalOptions<TOptions> = object extends TOptions ? [options?: TOptions] : [options: TOptions];
type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions];
declare function resolveMaybeOptionalOptions<T>(rest: MaybeOptionalOptions<T>): T;
declare function toArray<T>(value: T): T extends readonly any[] ? T : Exclude<T, undefined | null>[];
declare function splitInHalf<T>(arr: readonly T[]): [T[], T[]];
/**
* Load Request/Response/Blob/File/.. to a buffer (Uint8Array<ArrayBuffer>).
* Converts Request/Response/Blob/File/.. to a buffer (ArrayBuffer or Uint8Array).
*
* Prefers the newer `.bytes` method when available as it more efficient but not widely supported yet.
*/
declare function loadBytes(source: Pick<Blob, 'arrayBuffer' | 'bytes'>): ReturnType<Blob['bytes']>;
declare function readAsBuffer(source: Pick<Blob, 'arrayBuffer' | 'bytes'>): Promise<ArrayBuffer | Uint8Array>;
type AnyFunction = (...args: any[]) => any;
declare function once<T extends () => any>(fn: T): () => ReturnType<T>;
declare function sequential<A extends any[], R>(fn: (...args: A) => Promise<R>): (...args: A) => Promise<R>;
/**
* Normalize text or binary-like inputs to either:
* - the original string value, or
* - a Uint8Array view over the source bytes.
* Executes the callback function after the current call stack has been cleared.
*/
declare function toStringOrBytes(source: Arrayable<string | ArrayBuffer | Pick<Uint8Array<ArrayBuffer>, 'buffer' | 'byteOffset' | 'byteLength'>>): string | Awaited<ReturnType<Blob['bytes']>>;
declare function defer(callback: () => void): void;
declare function isDeepEqual(a: unknown, b: unknown): boolean;
type OmitChainMethodDeep<T extends object, K extends keyof any> = {
[P in keyof Omit<T, K>]: T[P] extends AnyFunction ? ((...args: Parameters<T[P]>) => OmitChainMethodDeep<ReturnType<T[P]>, K>) : T[P];
};
declare const ORPC_NAME = "orpc";
declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
declare const ORPC_SHARED_PACKAGE_VERSION = "1.14.12";
declare function isAbortError(error: unknown): error is Error;
type AnyFunction = (...args: any[]) => any;
declare function once<T>(fn: () => T): () => T;
/**
* Executes the callback function after the current call stack has been cleared.
* Error thrown when an operation is aborted.
* Uses the standardized 'AbortError' name for consistency with JavaScript APIs.
*/
declare function defer(callback: () => void): void;
declare function tryOrUndefined<T>(fn: () => T): undefined | T;
declare class AbortError extends Error {
constructor(...rest: ConstructorParameters<typeof Error>);
}
declare function pathToHttpPath(path: readonly string[]): `/${string}`;
declare function normalizeHttpPath(path: string): `/${string}`;
declare function mergeHttpPath(a: `/${string}`, b: `/${string}`): `/${string}`;
declare function matchesHttpPathPrefix(url: `/${string}`, prefix: `/${string}`): boolean;
declare function matchesHttpPath(url: `/${string}`, path: `/${string}`): boolean;
declare function isCompressibleContentType(contentType: string | null | undefined): boolean;
interface EventPublisherOptions {
/**
* Maximum number of events to buffer for async iterator subscribers.
*
* If the buffer exceeds this limit, the oldest event is dropped.
* This prevents unbounded memory growth if consumers process events slowly.
*
* Set to:
* - `0`: Disable buffering. Events must be consumed before the next one arrives.
* - `1`: Only keep the latest event. Useful for real-time updates where only the most recent value matters.
* - `Infinity`: Keep all events. Ensures no data loss, but may lead to high memory usage.
*
* @default 100
*/
maxBufferedEvents?: number;
}
interface EventPublisherSubscribeIteratorOptions extends EventPublisherOptions {
/**
* Aborts the async iterator. Throws if aborted before or during pulling.
*/
signal?: AbortSignal | undefined;
}
declare class EventPublisher<T extends Record<PropertyKey, any>> {
#private;
constructor(options?: EventPublisherOptions);
get size(): number;
/**
* Emits an event and delivers the payload to all subscribed listeners.
*/
publish<K extends keyof T>(event: K, payload: T[K]): void;
/**
* Subscribes to a specific event using a callback function.
* Returns an unsubscribe function to remove the listener.
*
* @example
* ```ts
* const unsubscribe = publisher.subscribe('event', (payload) => {
* console.log(payload)
* })
*
* // Later
* unsubscribe()
* ```
*/
subscribe<K extends keyof T>(event: K, listener: (payload: T[K]) => void): () => void;
/**
* Subscribes to a specific event using an async iterator.
* Useful for `for await...of` loops with optional buffering and abort support.
*
* @example
* ```ts
* for await (const payload of publisher.subscribe('event', { signal })) {
* console.log(payload)
* }
* ```
*/
subscribe<K extends keyof T>(event: K, options?: EventPublisherSubscribeIteratorOptions): AsyncGenerator<T[K]> & AsyncIteratorObject<T[K]>;
}
declare class SequentialIdGenerator {
private index;
generate(): string;
}
/**

@@ -55,7 +115,4 @@ * Compares two sequential IDs.

type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type IntersectPick<T, U> = Pick<T, keyof T & keyof U>;
/**
* Remove protected/private properties/methods
*/
type Public<T> = Pick<T, keyof T>;
type PromiseWithError<T, TError> = Promise<T> & {

@@ -69,3 +126,3 @@ __error?: {

*
* - `ThrowableError` the error type that represent throwable errors should be `Error` or `null | undefined | {}` if you want more strict.
* - `throwableError` the error type that represent throwable errors should be `Error` or `null | undefined | {}` if you want more strict.
*/

@@ -75,4 +132,5 @@ interface Registry {

type ThrowableError = Registry extends {
ThrowableError: infer T;
throwableError: infer T;
} ? T : Error;
type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never;

@@ -85,51 +143,27 @@ type InterceptableOptions = Record<string, any>;

/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onStart<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onSuccess<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(result: Awaited<ReturnType<TOptions['next']>>, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onError<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(error: ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
type OnFinishState<TResult, TError> = [error: TError, data: undefined, isSuccess: false] | [error: null, data: TResult, isSuccess: true];
/**
* Can used for interceptors or middlewares
* Can be used for interceptors or middlewares
*/
declare function onFinish<T, TOptions extends {
next: () => any;
next(): any;
}, TRest extends any[]>(callback: NoInfer<(state: OnFinishState<Awaited<ReturnType<TOptions['next']>>, ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError>, options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Creates a middleware or interceptor that invokes a callback when the returned async
* iterator object throws an error while being consumed.
*
* This does not replace the `onError`. `onError` only fires on the
* initial call (before the interceptor returns the iterator), whereas this
* callback only fires while consuming the iterator. Use both together to
* catch all possible errors.
*/
declare function onAsyncIteratorObjectError<T, TOptions extends {
next: () => any;
}, TRest extends any[]>(callback: NoInfer<(error: ThrowableError | (ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError), options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
/**
* Creates an interceptor that invokes a callback when the returned readable
* stream errors while being consumed.
*
* This does not replace the `onError`. `onError` only fires on the
* initial call (before the interceptor returns the stream), whereas this
* callback only fires while consuming the stream. Use both together to catch
* all possible errors.
*/
declare function onReadableStreamError<T, TOptions extends {
next: () => any;
}, TRest extends any[]>(callback: NoInfer<(error: ThrowableError | (ReturnType<TOptions['next']> extends PromiseWithError<any, infer E> ? E : ThrowableError), options: TOptions, ...rest: TRest) => Promisable<void>>): (options: TOptions, ...rest: TRest) => T | Promise<Awaited<ReturnType<TOptions['next']>>>;
declare function intercept<TOptions extends InterceptableOptions, TResult>(interceptors: undefined | Interceptor<TOptions, TResult>[], options: NoInfer<TOptions>, main: NoInfer<(options: TOptions) => TResult>): TResult;
declare function intercept<TOptions extends InterceptableOptions, TResult>(interceptors: Interceptor<TOptions, TResult>[], options: NoInfer<TOptions>, main: NoInfer<(options: TOptions) => TResult>): TResult;

@@ -140,14 +174,45 @@ /**

interface OpenTelemetryConfig {
interface OtelConfig {
tracer: Tracer;
trace: TraceAPI;
context: ContextAPI;
propagation: PropagationAPI;
}
/**
* Sets the global OpenTelemetry config.
* Call this once at app startup. Use `undefined` to disable tracing.
*/
declare function setGlobalOtelConfig(config: OtelConfig | undefined): void;
/**
* Gets the global OpenTelemetry config.
* Returns `undefined` if OpenTelemetry is not configured, initialized, or enabled.
*/
declare function getGlobalOtelConfig(): OtelConfig | undefined;
/**
* Starts a new OpenTelemetry span with the given name and options.
*
* @returns The new span, or `undefined` if no tracer is set.
*/
declare function startSpan(name: string, options?: SpanOptions, context?: Context): Span | undefined;
interface SetSpanErrorOptions {
/**
* propagation is optional, can reduce bundle size in some cases.
* Span error status is not set if error is due to cancellation by the signal.
*/
propagation?: PropagationAPI | undefined;
signal?: AbortSignal;
}
declare function setOpenTelemetryConfig(config: OpenTelemetryConfig | undefined): void;
declare function getOpenTelemetryConfig(): OpenTelemetryConfig | undefined;
interface StartSpanOptions extends SpanOptions {
/**
* Records and sets the error status on the given span.
* If the span is `undefined`, it does nothing.
*/
declare function setSpanError(span: Span | undefined, error: unknown, options?: SetSpanErrorOptions): void;
declare function setSpanAttribute(span: Span | undefined, key: string, value: AttributeValue | undefined): void;
/**
* Converts an error to an OpenTelemetry Exception.
*/
declare function toOtelException(error: unknown): Exclude<Exception, string>;
/**
* Converts a value to a string suitable for OpenTelemetry span attributes.
*/
declare function toSpanAttributeValue(data: unknown): string;
interface RunWithSpanOptions extends SpanOptions, SetSpanErrorOptions {
/**

@@ -158,64 +223,55 @@ * The name of the span to create.

/**
* Context to use for the created span.
* Context to use for the span.
*/
context?: Context;
}
declare function startSpan(options: StartSpanOptions | string): Span | undefined;
declare function recordSpanError(span: Span | undefined, error: unknown): void;
declare function setSpanAttributeIfDefined(span: Span | undefined, key: string, value: AttributeValue | undefined): void;
declare function toOtelException(error: unknown): Exclude<Exception, string>;
declare function toSpanAttributeValue(data: unknown): string;
interface RunWithSpanOptions extends StartSpanOptions {
}
declare function runWithSpan<T>(options: string | RunWithSpanOptions, fn: (span?: Span) => Promisable<T>): Promise<T>;
/**
* Runs a function within the context of a new OpenTelemetry span.
* The span is ended automatically, and errors are recorded to the span.
*/
declare function runWithSpan<T>({ name, context, ...options }: RunWithSpanOptions, fn: (span?: Span) => Promisable<T>): Promise<T>;
/**
* Runs a function within the context of an existing OpenTelemetry span.
*/
declare function runInSpanContext<T>(span: Span | undefined, fn: () => Promisable<T>): Promise<T>;
interface WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn> {
declare function isAsyncIteratorObject(maybe: unknown): maybe is AsyncIteratorObject<any, any, any>;
interface AsyncIteratorClassNextFn<T, TReturn> {
(): Promise<IteratorResult<T, TReturn>>;
}
interface AsyncIteratorClassCleanupFn {
(reason: 'return' | 'throw' | 'next' | 'dispose'): Promise<void>;
}
declare const fallbackAsyncDisposeSymbol: unique symbol;
declare const asyncDisposeSymbol: typeof Symbol extends {
asyncDispose: infer T;
} ? T : typeof fallbackAsyncDisposeSymbol;
declare class AsyncIteratorClass<T, TReturn = unknown, TNext = unknown> implements AsyncIteratorObject<T, TReturn, TNext>, AsyncGenerator<T, TReturn, TNext> {
#private;
constructor(next: AsyncIteratorClassNextFn<T, TReturn>, cleanup: AsyncIteratorClassCleanupFn);
next(): Promise<IteratorResult<T, TReturn>>;
return(value?: any): Promise<IteratorResult<T, TReturn>>;
throw(err: any): Promise<IteratorResult<T, TReturn>>;
/**
* Any call to the original iterator will be executed inside this function.
* Useful when you want execution to happen within a specific context,
* such as AsyncLocalStorage.
* asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
*/
runWith?: <T>(run: () => Promise<T>) => Promise<T>;
mapResult?: (result: IteratorResult<TYield, TReturn>) => Promisable<IteratorResult<TMappedYield, TMappedReturn>>;
mapError?: (error: ThrowableError) => Promisable<ThrowableError>;
onError?: (error: ThrowableError) => Promisable<void>;
/**
* Execute after the stream finishes or is cancelled.
*/
onFinish?: () => Promisable<void>;
[asyncDisposeSymbol](): Promise<void>;
[Symbol.asyncIterator](): this;
}
declare function wrapAsyncIterator<TYield, TReturn, TMappedYield = TYield, TMappedReturn = TReturn>(iterator: AsyncIterator<TYield, TReturn>, { runWith, mapResult, mapError, onError, onFinish }: WrapAsyncIteratorOptions<TYield, TReturn, TMappedYield, TMappedReturn>): NoInfer<AsyncIteratorClass<TMappedYield, TMappedReturn>>;
declare function traceAsyncIterator<T, TReturn, TNext>(options: StartSpanOptions | string, iterator: AsyncIterator<T, TReturn, TNext>): AsyncIteratorClass<T, TReturn, TNext>;
declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[];
interface ConsumeAsyncIteratorOptions<T, TReturn, TError> {
interface AsyncIteratorWithSpanOptions extends SetSpanErrorOptions {
/**
* Called on each event
* The name of the span to create.
*/
onEvent: (event: T) => void;
/**
* Called once error happens
*/
onError?: (error: TError) => void;
/**
* Called once AsyncIteratorObject is done
*
* @info If iterator is canceled, `undefined` can be passed on success
*/
onSuccess?: (value: TReturn | undefined) => void;
/**
* Called once after onError or onSuccess
*
* @info If iterator is canceled, `undefined` can be passed on success
*/
onFinish?: (state: [error: TError, data: undefined, isSuccess: false] | [error: null, data: TReturn | undefined, isSuccess: true]) => void;
name: string;
}
/**
* Consumes an AsyncIteratorObject with lifecycle callbacks
*
* @warning If no `onError` or `onFinish` is provided, error will be thrown into unhandled rejection channel.
* @return unsubscribe callback
*/
declare function consumeAsyncIterator<T, TReturn, TError = ThrowableError>(iterator: AsyncIterator<T, TReturn> | PromiseWithError<AsyncIterator<T, TReturn>, TError>, options: ConsumeAsyncIteratorOptions<T, TReturn, TError | ThrowableError>): () => Promise<void>;
declare function asyncIteratorWithSpan<T, TReturn, TNext>({ name, ...options }: AsyncIteratorWithSpanOptions, iterator: AsyncIterator<T, TReturn, TNext>): AsyncIteratorClass<T, TReturn, TNext>;
declare function parseEmptyableJSON(text: string | null | undefined): unknown;
declare function stringifyJSON<T>(value: T | {
toJSON(): T;
}): undefined extends T ? undefined | string : string;
declare function logError(error: unknown): void;
type Segment = string | number;

@@ -232,13 +288,11 @@ declare function findDeepMatches(check: (value: unknown) => boolean, payload: unknown, segments?: Segment[], maps?: Segment[][], values?: unknown[]): {

/**
* Checks whether a value is a plain object, including objects created with
* `Object.create(null)`.
* Check if the value is an object even it created by `Object.create(null)` or more tricky way.
*/
declare function isPlainObject(value: unknown): value is Record<PropertyKey, unknown>;
declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
declare function isObject(value: unknown): value is Record<PropertyKey, unknown>;
/**
* Sets a value at the given path, creating plain objects for intermediate keys as needed.
* Check if the value satisfy a `object` type in typescript
*/
declare function set(root: object, path: [PropertyKey, ...PropertyKey[]] | [...PropertyKey[], PropertyKey], value: unknown): void;
declare function omit<T extends object, K extends keyof T>(obj: T, keys: readonly K[]): Omit<T, K>;
declare function isTypescriptObject(value: unknown): value is object & Record<PropertyKey, unknown>;
declare function clone<T>(value: T): T;
declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
declare function isPropertyKey(value: unknown): value is PropertyKey;

@@ -248,53 +302,26 @@ declare const NullProtoObj: ({

});
/**
* Returns an object containing all methods of the given object, with each
* method bound to the original object instance.
*
* Methods are collected from both the object itself and its prototype chain
* (excluding `Object.prototype` and the `constructor` property).
*/
declare function bindMethods<T extends object>(obj: T): Pick<T, {
[K in keyof T]: T[K] extends AnyFunction ? K : never;
}[keyof T]>;
interface OrderablePlugin {
/** Unique name of the plugin, used for ordering and identification. */
name: string;
/** Plugins this plugin should execute before. */
before?: string[] | undefined;
/** Plugins this plugin should execute after. */
after?: string[] | undefined;
}
type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
/**
* Sorts plugins based on their `before` and `after` dependencies.
* Returns the value if it is defined, otherwise returns the fallback
*/
declare function sortPlugins<T extends OrderablePlugin>(plugins: T[]): T[];
declare function fallback<T>(value: T | undefined, fallback: T): T;
/**
* Creates a promise together with its associated `resolve` and `reject`
* functions.
*
* Equivalent to `Promise.withResolvers()`, but works in environments
* where that API is not yet available.
* Prevents objects from being awaitable by intercepting the `then` method
* when called by the native await mechanism. This is useful for preventing
* accidental awaiting of objects that aren't meant to be promises.
*/
declare function promiseWithResolvers<T>(): {
promise: Promise<T>;
resolve: (v: T) => void;
reject: (reason: unknown) => void;
};
type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
declare function preventNativeAwait<T extends object>(target: T): T;
/**
* Creates a proxy that overlays a `partial` object on top of a `target`.
* Create a proxy that overlays one object (`overlay`) on top of another (`target`).
*
* - Properties from `partial` take precedence.
* - Properties not present in `partial` fall back to the resolved `target`.
* - Methods are bound to the proxy to ensure a consistent `this` context.
* - Properties from `overlay` take precedence.
* - Properties not in `overlay` fall back to `target`.
* - Methods from either object are bound to `overlay` so `this` is consistent.
*
* Useful for overriding specific properties of an object while delegating
* all other access to the original target without needing to know its full structure.
* Useful when you want to override or extend behavior without fully copying/merging objects.
*/
declare function override<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;
declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;

@@ -309,3 +336,5 @@ interface AsyncIdQueueCloseOptions {

private readonly waiters;
get size(): number;
get length(): number;
get waiterIds(): string[];
hasBufferedItems(id: string): boolean;
open(id: string): void;

@@ -316,48 +345,10 @@ isOpen(id: string): boolean;

close({ id, reason }?: AsyncIdQueueCloseOptions): void;
private assertOpen;
assertOpen(id: string): void;
}
/**
* Returns a signal that aborts only after all provided signals are aborted.
* Converts a `ReadableStream` into an `AsyncIteratorClass`.
*/
declare function allAbortSignal(signals: readonly (AbortSignal | undefined)[]): AbortSignal | undefined;
declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>;
/**
* Returns a signal that aborts as soon as any of the provided signals aborts,
* with the same abort reason.
*/
declare function anyAbortSignal(signals: readonly (AbortSignal | undefined)[]): AbortSignal | undefined;
declare function runWithSignal<T>(signal: AbortSignal | undefined, fn: () => Promise<T>): Promise<T>;
declare function replicateReadableStream<T>(stream: ReadableStream<T>, count: number): ReadableStream<T>[];
type ReadableStreamReadResult<T> = {
done: false;
value: T;
} | {
done: true;
value?: undefined | T;
};
interface WrapReadableStreamOptions<T, TMapped> {
/**
* Any call to the original stream reader will be executed inside this function.
* Useful when you want execution to happen within a specific context,
* such as AsyncLocalStorage.
*/
runWith?: <T>(run: () => Promise<T>) => Promise<T>;
mapResult?: (result: ReadableStreamReadResult<T>) => Promisable<ReadableStreamReadResult<TMapped>>;
mapError?: (error: ThrowableError) => Promisable<ThrowableError>;
onError?: (error: ThrowableError) => Promisable<void>;
/**
* Guaranteed to execute exactly once after the stream finishes or is cancelled.
*/
onFinish?: () => Promisable<void>;
}
declare function wrapReadableStream<T, TMapped = T>(stream: ReadableStream<T>, { runWith, mapResult, mapError, onError, onFinish }: WrapReadableStreamOptions<T, TMapped>): NoInfer<ReadableStream<TMapped>>;
declare function traceReadableStream<T>(options: StartSpanOptions | string, stream: ReadableStream<T>): ReadableStream<T>;
/**
* Converts a {@link ReadableStream} into an {@link AsyncIteratorClass}.
*/
declare function streamToAsyncIteratorObject<T>(stream: ReadableStream<T>, { signal }?: {
signal?: undefined | AbortSignal;
}): AsyncIteratorClass<T>;
/**
* Converts an `AsyncIterator` into a `ReadableStream`.

@@ -374,3 +365,3 @@ */

export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, anyAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isCompressibleContentType, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorObject, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream };
export type { AnyFunction, AsyncIdQueueCloseOptions, ConsumeAsyncIteratorOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OnFinishState, OpenTelemetryConfig, OrderablePlugin, PromiseWithError, Public, ReadableStreamReadResult, Registry, RunWithSpanOptions, Segment, StartSpanOptions, ThrowableError, Value, WrapAsyncIteratorOptions, WrapReadableStreamOptions };
export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, asyncIteratorWithSpan, clone, compareSequentialIds, defer, fallback, findDeepMatches, get, getConstructor, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, logError, onError, onFinish, onStart, onSuccess, once, overlayProxy, parseEmptyableJSON, preventNativeAwait, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
export type { AnyFunction, AsyncIdQueueCloseOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClassNextFn, AsyncIteratorWithSpanOptions, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, InferAsyncIterableYield, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, OtelConfig, PromiseWithError, Registry, RunWithSpanOptions, Segment, SetOptional, SetSpanErrorOptions, ThrowableError, Value };

@@ -1,3 +0,2 @@

import { AbortError, AsyncIteratorClass, getOrBind, isTypescriptObject, isAsyncIteratorObject } from '@standardserver/shared';
export { AbortError, AsyncIteratorClass, SequentialIdGenerator, getOrBind, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray } from '@standardserver/shared';
export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';

@@ -8,2 +7,5 @@ function resolveMaybeOptionalOptions(rest) {

function toArray(value) {
return Array.isArray(value) ? value : value === void 0 || value === null ? [] : [value];
}
function splitInHalf(arr) {

@@ -14,101 +16,18 @@ const half = Math.ceil(arr.length / 2);

async function loadBytes(source) {
function readAsBuffer(source) {
if (typeof source.bytes === "function") {
return source.bytes();
}
return new Uint8Array(await source.arrayBuffer());
return source.arrayBuffer();
}
function toStringOrBytes(source) {
if (typeof source === "string") {
return source;
}
if (source instanceof ArrayBuffer) {
return new Uint8Array(source);
}
if (Array.isArray(source)) {
return concatBytes(source);
}
if (source instanceof Uint8Array) {
return source;
}
return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
}
function toBytes(item) {
if (typeof item === "string") {
return new TextEncoder().encode(item);
}
if (item instanceof ArrayBuffer) {
return new Uint8Array(item);
}
if (item instanceof Uint8Array) {
return item;
}
return new Uint8Array(item.buffer, item.byteOffset, item.byteLength);
}
function concatBytes(items) {
const chunks = items.map(toBytes);
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
const result = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
result.set(chunk, offset);
offset += chunk.byteLength;
}
return result;
}
function isDeepEqual(a, b) {
return isDeepEqualInternal(a, b, /* @__PURE__ */ new WeakMap());
}
function isDeepEqualInternal(a, b, visited) {
if (Object.is(a, b)) {
return true;
}
if (typeof a !== typeof b) {
return false;
}
if (a === null || typeof a !== "object") {
return false;
}
if (b === null || typeof b !== "object") {
return false;
}
const isArray = Array.isArray(a);
if (isArray !== Array.isArray(b)) {
return false;
}
if (isArray && a.length !== b.length) {
return false;
}
const aRecord = a;
const bRecord = b;
const visitedMatches = visited.get(a);
if (visitedMatches?.has(b)) {
return true;
}
if (visitedMatches) {
visitedMatches.add(b);
} else {
visited.set(a, new WeakSet([b]));
}
const aKeys = Object.keys(aRecord).filter((k) => aRecord[k] !== void 0);
const bKeys = Object.keys(bRecord).filter((k) => bRecord[k] !== void 0);
if (aKeys.length !== bKeys.length) {
return false;
}
for (const key of aKeys) {
if (!Object.hasOwn(bRecord, key)) {
return false;
}
if (!isDeepEqualInternal(aRecord[key], bRecord[key], visited)) {
return false;
}
}
return true;
}
const ORPC_NAME = "orpc";
const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
const ORPC_SHARED_PACKAGE_VERSION = "1.14.12";
function isAbortError(error) {
return error instanceof Error && error.name.includes("Abort");
class AbortError extends Error {
constructor(...rest) {
super(...rest);
this.name = "AbortError";
}
}

@@ -127,2 +46,11 @@

}
function sequential(fn) {
let lastOperationPromise = Promise.resolve();
return (...args) => {
return lastOperationPromise = lastOperationPromise.catch(() => {
}).then(() => {
return fn(...args);
});
};
}
function defer(callback) {

@@ -135,85 +63,16 @@ if (typeof setTimeout === "function") {

}
function tryOrUndefined(fn) {
try {
return fn();
} catch {
return void 0;
}
}
function tryDecodeURIComponent(value) {
try {
return decodeURIComponent(value);
} catch {
return value;
}
}
function pathToHttpPath(path) {
return `/${path.map(encodeURIComponent).join("/")}`;
}
function normalizeHttpPath(path) {
const paths = path.split("/");
if (paths.at(0) === "") {
paths.shift();
}
return pathToHttpPath(paths.map(tryDecodeURIComponent));
}
function mergeHttpPath(a, b) {
return `${a.endsWith("/") ? a.slice(0, -1) : a}${b}`;
}
function matchesHttpPathPrefix(url, prefix) {
if (!url.startsWith(prefix)) {
return false;
}
const charAfterPrefix = url[prefix.length];
return charAfterPrefix === "/" || charAfterPrefix === "?" || charAfterPrefix === "#" || charAfterPrefix === void 0 || prefix[prefix.length - 1] === "/";
}
function matchesHttpPath(url, path) {
const pathWithoutEndSlash = path.endsWith("/") ? path.slice(0, path.length - 1) : path;
if (!url.startsWith(pathWithoutEndSlash)) {
return false;
}
let charAfterPrefix = url[pathWithoutEndSlash.length];
if (charAfterPrefix === "/") {
charAfterPrefix = url[pathWithoutEndSlash.length + 1];
}
return charAfterPrefix === void 0 || charAfterPrefix === "?" || charAfterPrefix === "#";
}
const COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/(?!event-stream(?:[;\s]|$))[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
const MAX_COMPRESSIBLE_CONTENT_TYPE_LENGTH = 1024;
function isCompressibleContentType(contentType) {
if (contentType === null || contentType === void 0) {
return false;
}
if (contentType.length > MAX_COMPRESSIBLE_CONTENT_TYPE_LENGTH) {
return false;
}
return COMPRESSIBLE_CONTENT_TYPE_REGEX.test(contentType);
}
function compareSequentialIds(a, b) {
if (a.length !== b.length) {
return a.length - b.length;
}
return a < b ? -1 : a > b ? 1 : 0;
}
const SPAN_ERROR_STATUS = 2;
const OPENTELEMETRY_CONFIG_SYMBOL = Symbol.for("ORPC_OPENTELEMETRY_CONFIG");
function setOpenTelemetryConfig(config) {
globalThis[OPENTELEMETRY_CONFIG_SYMBOL] = config;
const GLOBAL_OTEL_CONFIG_KEY = `__${ORPC_SHARED_PACKAGE_NAME}@${ORPC_SHARED_PACKAGE_VERSION}/otel/config__`;
function setGlobalOtelConfig(config) {
globalThis[GLOBAL_OTEL_CONFIG_KEY] = config;
}
function getOpenTelemetryConfig() {
return globalThis[OPENTELEMETRY_CONFIG_SYMBOL];
function getGlobalOtelConfig() {
return globalThis[GLOBAL_OTEL_CONFIG_KEY];
}
function startSpan(options) {
const tracer = getOpenTelemetryConfig()?.tracer;
if (!tracer) {
return void 0;
}
const { name, context, ...spanOptions } = typeof options === "string" ? { name: options } : options;
return tracer.startSpan(name, spanOptions, context);
function startSpan(name, options = {}, context) {
const tracer = getGlobalOtelConfig()?.tracer;
return tracer?.startSpan(name, options, context);
}
function recordSpanError(span, error) {
function setSpanError(span, error, options = {}) {
if (!span) {

@@ -224,3 +83,3 @@ return;

span.recordException(exception);
if (!isAbortError(error)) {
if (!options.signal?.aborted || options.signal.reason !== error) {
span.setStatus({

@@ -232,3 +91,3 @@ code: SPAN_ERROR_STATUS,

}
function setSpanAttributeIfDefined(span, key, value) {
function setSpanAttribute(span, key, value) {
if (!span || value === void 0) {

@@ -271,10 +130,7 @@ return;

}
async function runWithSpan(options, fn) {
const tracer = getOpenTelemetryConfig()?.tracer;
async function runWithSpan({ name, context, ...options }, fn) {
const tracer = getGlobalOtelConfig()?.tracer;
if (!tracer) {
return fn();
}
if (typeof options === "string") {
options = { name: options };
}
const callback = async (span) => {

@@ -284,3 +140,3 @@ try {

} catch (e) {
recordSpanError(span, e);
setSpanError(span, e, options);
throw e;

@@ -291,10 +147,10 @@ } finally {

};
if (options.context) {
return tracer.startActiveSpan(options.name, options, options.context, callback);
if (context) {
return tracer.startActiveSpan(name, options, context, callback);
} else {
return tracer.startActiveSpan(options.name, options, callback);
return tracer.startActiveSpan(name, options, callback);
}
}
async function runInSpanContext(span, fn) {
const otelConfig = getOpenTelemetryConfig();
const otelConfig = getGlobalOtelConfig();
if (!span || !otelConfig) {

@@ -311,5 +167,11 @@ return fn();

waiters = /* @__PURE__ */ new Map();
get size() {
get length() {
return this.openIds.size;
}
get waiterIds() {
return Array.from(this.waiters.keys());
}
hasBufferedItems(id) {
return Boolean(this.queues.get(id)?.length);
}
open(id) {

@@ -382,50 +244,70 @@ this.openIds.add(id);

function wrapAsyncIterator(iterator, { runWith, mapResult, mapError, onError, onFinish }) {
runWith ??= (run) => run();
let isDone;
return new AsyncIteratorClass(async () => {
try {
let result;
function isAsyncIteratorObject(maybe) {
if (!maybe || typeof maybe !== "object") {
return false;
}
return "next" in maybe && typeof maybe.next === "function" && Symbol.asyncIterator in maybe && typeof maybe[Symbol.asyncIterator] === "function";
}
const fallbackAsyncDisposeSymbol = Symbol.for("asyncDispose");
const asyncDisposeSymbol = Symbol.asyncDispose ?? fallbackAsyncDisposeSymbol;
class AsyncIteratorClass {
#isDone = false;
#isExecuteComplete = false;
#cleanup;
#next;
constructor(next, cleanup) {
this.#cleanup = cleanup;
this.#next = sequential(async () => {
if (this.#isDone) {
return { done: true, value: void 0 };
}
try {
result = await runWith(() => iterator.next());
isDone = result.done;
} catch (error) {
isDone = true;
throw error;
}
return mapResult ? await mapResult(result) : result;
} catch (error) {
await onError?.(error);
throw mapError ? await mapError(error) : error;
}
}, async (_state) => {
try {
if (!isDone) {
try {
await runWith(async () => iterator.return?.());
} catch (error) {
await onError?.(error);
throw error;
const result = await next();
if (result.done) {
this.#isDone = true;
}
return result;
} catch (err) {
this.#isDone = true;
throw err;
} finally {
if (this.#isDone && !this.#isExecuteComplete) {
this.#isExecuteComplete = true;
await this.#cleanup("next");
}
}
} finally {
await onFinish?.();
});
}
next() {
return this.#next();
}
async return(value) {
this.#isDone = true;
if (!this.#isExecuteComplete) {
this.#isExecuteComplete = true;
await this.#cleanup("return");
}
});
}
function traceAsyncIterator(options, iterator) {
const getSpan = once(() => startSpan(options));
return wrapAsyncIterator(iterator, {
runWith: (run) => runInSpanContext(getSpan(), run),
mapResult(result) {
getSpan()?.addEvent(result.done ? "completed" : "yielded");
return result;
},
onError(error) {
recordSpanError(getSpan(), error);
},
onFinish() {
getSpan()?.end();
return { done: true, value };
}
async throw(err) {
this.#isDone = true;
if (!this.#isExecuteComplete) {
this.#isExecuteComplete = true;
await this.#cleanup("throw");
}
});
throw err;
}
/**
* asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose')
*/
async [asyncDisposeSymbol]() {
this.#isDone = true;
if (!this.#isExecuteComplete) {
this.#isExecuteComplete = true;
await this.#cleanup("dispose");
}
}
[Symbol.asyncIterator]() {
return this;
}
}

@@ -470,5 +352,5 @@ function replicateAsyncIterator(source, count) {

},
async ({ kind, error }) => {
queue.close({ id, reason: error });
if (kind === "cancelled" && !queue.size && !isSourceFinished) {
async (reason) => {
queue.close({ id });
if (reason !== "next" && !queue.length && !isSourceFinished) {
isSourceFinished = true;

@@ -482,47 +364,190 @@ await source?.return?.();

}
function consumeAsyncIterator(iterator, options) {
void (async () => {
let onFinishState;
try {
const resolvedIterator = await iterator;
while (true) {
const { done, value } = await resolvedIterator.next();
if (done) {
const realValue = value;
onFinishState = [null, realValue, true];
options.onSuccess?.(realValue);
break;
function asyncIteratorWithSpan({ name, ...options }, iterator) {
let span;
return new AsyncIteratorClass(
async () => {
span ??= startSpan(name);
try {
const result = await runInSpanContext(span, () => iterator.next());
span?.addEvent(result.done ? "completed" : "yielded");
return result;
} catch (err) {
setSpanError(span, err, options);
throw err;
}
},
async (reason) => {
try {
if (reason !== "next") {
await runInSpanContext(span, () => iterator.return?.());
}
options.onEvent(value);
} catch (err) {
setSpanError(span, err, options);
throw err;
} finally {
span?.end();
}
}
);
}
class EventPublisher {
#listenersMap = /* @__PURE__ */ new Map();
#maxBufferedEvents;
constructor(options = {}) {
this.#maxBufferedEvents = options.maxBufferedEvents ?? 100;
}
get size() {
return this.#listenersMap.size;
}
/**
* Emits an event and delivers the payload to all subscribed listeners.
*/
publish(event, payload) {
const listeners = this.#listenersMap.get(event);
if (!listeners) {
return;
}
for (const listener of listeners) {
listener(payload);
}
}
subscribe(event, listenerOrOptions) {
if (typeof listenerOrOptions === "function") {
let listeners = this.#listenersMap.get(event);
if (!listeners) {
this.#listenersMap.set(event, listeners = []);
}
listeners.push(listenerOrOptions);
return once(() => {
listeners.splice(listeners.indexOf(listenerOrOptions), 1);
if (listeners.length === 0) {
this.#listenersMap.delete(event);
}
});
}
const signal = listenerOrOptions?.signal;
const maxBufferedEvents = listenerOrOptions?.maxBufferedEvents ?? this.#maxBufferedEvents;
signal?.throwIfAborted();
const bufferedEvents = [];
const pullResolvers = [];
const unsubscribe = this.subscribe(event, (payload) => {
const resolver = pullResolvers.shift();
if (resolver) {
resolver[0]({ done: false, value: payload });
} else {
bufferedEvents.push(payload);
if (bufferedEvents.length > maxBufferedEvents) {
bufferedEvents.shift();
}
}
});
const abortListener = (event2) => {
unsubscribe();
pullResolvers.forEach((resolver) => resolver[1](event2.target.reason));
pullResolvers.length = 0;
bufferedEvents.length = 0;
};
signal?.addEventListener("abort", abortListener, { once: true });
return new AsyncIteratorClass(async () => {
if (signal?.aborted) {
throw signal.reason;
}
if (bufferedEvents.length > 0) {
return { done: false, value: bufferedEvents.shift() };
}
return new Promise((resolve, reject) => {
pullResolvers.push([resolve, reject]);
});
}, async () => {
unsubscribe();
signal?.removeEventListener("abort", abortListener);
pullResolvers.forEach((resolver) => resolver[0]({ done: true, value: void 0 }));
pullResolvers.length = 0;
bufferedEvents.length = 0;
});
}
}
class SequentialIdGenerator {
index = BigInt(1);
generate() {
const id = this.index.toString(36);
this.index++;
return id;
}
}
function compareSequentialIds(a, b) {
if (a.length !== b.length) {
return a.length - b.length;
}
return a < b ? -1 : a > b ? 1 : 0;
}
function onStart(callback) {
return async (options, ...rest) => {
await callback(options, ...rest);
return await options.next();
};
}
function onSuccess(callback) {
return async (options, ...rest) => {
const result = await options.next();
await callback(result, options, ...rest);
return result;
};
}
function onError(callback) {
return async (options, ...rest) => {
try {
return await options.next();
} catch (error) {
onFinishState = [error, void 0, false];
options.onError?.(error);
await callback(error, options, ...rest);
throw error;
}
};
}
function onFinish(callback) {
let state;
return async (options, ...rest) => {
try {
const result = await options.next();
state = [null, result, true];
return result;
} catch (error) {
state = [error, void 0, false];
throw error;
} finally {
options.onFinish?.(onFinishState);
await callback(state, options, ...rest);
}
})();
return async () => {
await (await iterator)?.return?.();
};
}
function intercept(interceptors, options, main) {
const next = (options2, index) => {
const interceptor = interceptors[index];
if (!interceptor) {
return main(options2);
}
return interceptor({
...options2,
next: (newOptions = options2) => next(newOptions, index + 1)
});
};
return next(options, 0);
}
function value(value2, ...args) {
if (typeof value2 === "function") {
return value2(...args);
function parseEmptyableJSON(text) {
if (!text) {
return void 0;
}
return value2;
return JSON.parse(text);
}
function stringifyJSON(value) {
return JSON.stringify(value);
}
function override(target, partial) {
const proxy = new Proxy(typeof target === "function" ? partial : target, {
get(_, prop) {
const targetValue = prop in partial ? partial : value(target);
return getOrBind(targetValue, prop);
},
has(_, prop) {
return Reflect.has(partial, prop) || Reflect.has(value(target), prop);
}
});
return proxy;
function logError(error) {
if (typeof console === "object" && typeof console.error === "function") {
console.error(error);
}
}

@@ -538,3 +563,3 @@

});
} else if (isPlainObject(payload)) {
} else if (isObject(payload)) {
for (const key in payload) {

@@ -552,3 +577,3 @@ findDeepMatches(check, payload[key], [...segments, key], maps, values);

}
function isPlainObject(value) {
function isObject(value) {
if (!value || typeof value !== "object") {

@@ -560,31 +585,5 @@ return false;

}
function get(object, path) {
let current = object;
for (const key of path) {
if (!isTypescriptObject(current) || !Object.hasOwn(current, key)) {
return void 0;
}
current = current[key];
}
return current;
function isTypescriptObject(value) {
return !!value && (typeof value === "object" || typeof value === "function");
}
function set(root, path, value) {
let current = root;
for (let i = 0; i < path.length - 1; i++) {
const key = path[i];
const next = current[key];
if (!isTypescriptObject(next)) {
current[key] = {};
}
current = current[key];
}
current[path.at(-1)] = value;
}
function omit(obj, keys) {
const result = { ...obj };
for (const key of keys) {
delete result[key];
}
return result;
}
function clone(value) {

@@ -594,3 +593,3 @@ if (Array.isArray(value)) {

}
if (isPlainObject(value)) {
if (isObject(value)) {
const result = {};

@@ -607,2 +606,12 @@ for (const key in value) {

}
function get(object, path) {
let current = object;
for (const key of path) {
if (!isTypescriptObject(current)) {
return void 0;
}
current = current[key];
}
return current;
}
function isPropertyKey(value) {

@@ -619,139 +628,66 @@ const type = typeof value;

})();
function bindMethods(obj) {
const methods = new NullProtoObj();
let current = obj;
while (current && current !== Object.prototype) {
for (const key of Object.getOwnPropertyNames(current)) {
if (key === "constructor" || key in methods) {
continue;
}
const val = obj[key];
if (typeof val === "function") {
methods[key] = val.bind(obj);
}
}
for (const sym of Object.getOwnPropertySymbols(current)) {
if (sym in methods) {
continue;
}
const val = obj[sym];
if (typeof val === "function") {
methods[sym] = val.bind(obj);
}
}
current = Object.getPrototypeOf(current);
function value(value2, ...args) {
if (typeof value2 === "function") {
return value2(...args);
}
return methods;
return value2;
}
function promiseWithResolvers() {
const result = {};
result.promise = new Promise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
function fallback(value2, fallback2) {
return value2 === void 0 ? fallback2 : value2;
}
function replicateReadableStream(stream, count) {
if (count <= 0) {
return [];
}
const replicated = [];
let pending = stream;
for (let index = 0; index < count - 1; index++) {
const [replica, remainder] = pending.tee();
replicated.push(replica);
pending = remainder;
}
replicated.push(pending);
return replicated;
}
function wrapReadableStream(stream, { runWith, mapResult, mapError, onError, onFinish }) {
runWith ??= (run) => run();
const reader = once(() => stream.getReader());
const finish = once(async () => onFinish?.());
return new ReadableStream({
async pull(controller) {
let result;
try {
const readResult = await runWith(() => reader().read());
result = mapResult ? await mapResult(readResult) : readResult;
} catch (error) {
try {
await onError?.(error);
controller.error(mapError ? await mapError(error) : error);
} finally {
await finish();
}
return;
function preventNativeAwait(target) {
return new Proxy(target, {
get(target2, prop, receiver) {
const value2 = Reflect.get(target2, prop, receiver);
if (prop !== "then" || typeof value2 !== "function") {
return value2;
}
if (result.done) {
controller.close();
await finish();
} else {
controller.enqueue(result.value);
}
},
async cancel(reason) {
try {
try {
await runWith(() => reader().cancel(reason));
} catch (error) {
await onError?.(error);
throw error;
return new Proxy(value2, {
apply(targetFn, thisArg, args) {
if (args.length !== 2 || args.some((arg) => !isNativeFunction(arg))) {
return Reflect.apply(targetFn, thisArg, args);
}
let shouldOmit = true;
args[0].call(thisArg, preventNativeAwait(new Proxy(target2, {
get: (target3, prop2, receiver2) => {
if (shouldOmit && prop2 === "then") {
shouldOmit = false;
return void 0;
}
return Reflect.get(target3, prop2, receiver2);
}
})));
}
} finally {
await finish();
}
});
}
});
}
function traceReadableStream(options, stream) {
const getSpan = once(() => startSpan(options));
return wrapReadableStream(stream, {
runWith: (run) => runInSpanContext(getSpan(), run),
mapResult(result) {
getSpan()?.addEvent(result.done ? "closed" : "enqueued");
return result;
const NATIVE_FUNCTION_REGEX = /^\s*function\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/;
function isNativeFunction(fn) {
return typeof fn === "function" && NATIVE_FUNCTION_REGEX.test(fn.toString());
}
function overlayProxy(target, partial) {
const proxy = new Proxy(typeof target === "function" ? partial : target, {
get(_, prop) {
const targetValue = prop in partial ? partial : value(target);
const v = Reflect.get(targetValue, prop);
return typeof v === "function" ? v.bind(targetValue) : v;
},
onError(error) {
recordSpanError(getSpan(), error);
},
onFinish() {
getSpan()?.end();
has(_, prop) {
return Reflect.has(partial, prop) || Reflect.has(value(target), prop);
}
});
return proxy;
}
function streamToAsyncIteratorObject(stream, { signal } = {}) {
function streamToAsyncIteratorClass(stream) {
const reader = stream.getReader();
let cancelledBySignal = false;
return new AsyncIteratorClass(
async () => {
if (signal?.aborted) {
cancelledBySignal = true;
throw signal.reason;
}
if (!signal) {
return reader.read();
}
const { promise, reject } = promiseWithResolvers();
const onAbort = () => reject(signal.reason);
signal.addEventListener("abort", onAbort, { once: true });
try {
return await Promise.race([
reader.read(),
promise.catch(async (reason) => {
cancelledBySignal = true;
throw reason;
})
]);
} finally {
signal.removeEventListener("abort", onAbort);
}
return reader.read();
},
async ({ kind, error }) => {
if (kind === "cancelled" || kind === "error" && cancelledBySignal) {
await reader.cancel(error);
}
async () => {
await reader.cancel();
}

@@ -782,3 +718,3 @@ );

} else {
const unproxied = isPlainObject(value) ? { ...value } : Array.isArray(value) ? value.map((i) => i) : value;
const unproxied = isObject(value) ? { ...value } : Array.isArray(value) ? value.map((i) => i) : value;
controller.enqueue(unproxied);

@@ -793,226 +729,10 @@ }

function onStart(callback) {
return async (options, ...rest) => {
await callback(options, ...rest);
return await options.next();
};
}
function onSuccess(callback) {
return async (options, ...rest) => {
const result = await options.next();
await callback(result, options, ...rest);
return result;
};
}
function onError(callback) {
return async (options, ...rest) => {
try {
return await options.next();
} catch (error) {
await callback(error, options, ...rest);
throw error;
}
};
}
function onFinish(callback) {
let state;
return async (options, ...rest) => {
try {
const result = await options.next();
state = [null, result, true];
return result;
} catch (error) {
state = [error, void 0, false];
throw error;
} finally {
await callback(state, options, ...rest);
}
};
}
function onAsyncIteratorObjectError(callback) {
return async (options, ...rest) => {
const output = await options.next();
if (!isAsyncIteratorObject(output)) {
return output;
}
return override(output, wrapAsyncIterator(output, {
onError: (error) => callback(error, options, ...rest)
}));
};
}
function onReadableStreamError(callback) {
return async (options, ...rest) => {
const output = await options.next();
if (!(output instanceof ReadableStream)) {
return output;
}
return override(output, wrapReadableStream(output, {
onError: (error) => callback(error, options, ...rest)
}));
};
}
function intercept(interceptors, options, main) {
if (!interceptors?.length) {
return main(options);
}
const next = (options2, index) => {
const interceptor = interceptors[index];
if (!interceptor) {
return main(options2);
}
return interceptor({
...options2,
next: (newOptions = options2) => next(newOptions, index + 1)
});
};
return next(options, 0);
}
function sortPlugins(plugins) {
const pluginCount = plugins.length;
const pluginIdToIndices = /* @__PURE__ */ new Map();
for (let i = 0; i < pluginCount; i++) {
const plugin = plugins[i];
const indices = pluginIdToIndices.get(plugin.name);
if (indices === void 0) {
pluginIdToIndices.set(plugin.name, [i]);
} else {
indices.push(i);
}
}
const graph = Array.from(
{ length: pluginCount },
() => /* @__PURE__ */ new Set()
);
for (let i = 0; i < pluginCount; i++) {
const plugin = plugins[i];
const beforeList = plugin.before;
if (beforeList !== void 0) {
for (const beforeId of beforeList) {
const beforeIndices = pluginIdToIndices.get(beforeId);
if (beforeIndices === void 0)
continue;
for (const beforeIndex of beforeIndices) {
const beforeGraph = graph[beforeIndex];
if (beforeGraph !== void 0) {
beforeGraph.add(i);
}
}
}
}
const afterList = plugin.after;
if (afterList !== void 0) {
const currentGraph = graph[i];
if (currentGraph !== void 0) {
for (const afterId of afterList) {
const afterIndices = pluginIdToIndices.get(afterId);
if (afterIndices === void 0)
continue;
for (const afterIndex of afterIndices) {
currentGraph.add(afterIndex);
}
}
}
}
}
const sorted = [];
const visiting = /* @__PURE__ */ new Set();
const visited = /* @__PURE__ */ new Set();
function visit(index) {
if (visited.has(index))
return;
if (visiting.has(index)) {
const plugin2 = plugins[index];
const pluginId = plugin2 !== void 0 ? plugin2.name : "unknown";
throw new Error(`Circular dependency detected involving plugin "${pluginId}"`);
}
visiting.add(index);
const deps = graph[index];
if (deps !== void 0) {
for (const depIndex of deps) {
visit(depIndex);
}
}
visiting.delete(index);
visited.add(index);
const plugin = plugins[index];
if (plugin !== void 0) {
sorted.push(plugin);
}
}
for (let i = 0; i < pluginCount; i++) {
visit(i);
}
return sorted;
}
function allAbortSignal(signals) {
const realSignals = signals.filter((signal) => signal !== void 0);
if (realSignals.length === 0 || realSignals.length !== signals.length) {
return void 0;
}
const controller = new AbortController();
const abortIfAllAborted = () => {
if (realSignals.every((signal) => signal.aborted)) {
controller.abort();
}
};
abortIfAllAborted();
for (const signal of realSignals) {
signal.addEventListener("abort", () => {
abortIfAllAborted();
}, {
once: true,
signal: controller.signal
});
}
return controller.signal;
}
function anyAbortSignal(signals) {
const realSignals = signals.filter((signal) => signal !== void 0);
if (realSignals.length === 0) {
return void 0;
}
if (realSignals.length === 1) {
return realSignals[0];
}
if (typeof AbortSignal.any === "function") {
return AbortSignal.any(realSignals);
}
const controller = new AbortController();
for (const signal of realSignals) {
if (signal.aborted) {
controller.abort(signal.reason);
break;
}
signal.addEventListener("abort", () => {
controller.abort(signal.reason);
}, {
once: true,
signal: controller.signal
});
}
return controller.signal;
}
async function runWithSignal(signal, fn) {
if (!signal) {
return fn();
}
signal.throwIfAborted();
const { promise, reject, resolve } = promiseWithResolvers();
let abortListener;
signal.addEventListener("abort", abortListener = () => {
reject(signal.reason);
abortListener = void 0;
});
function tryDecodeURIComponent(value) {
try {
fn().then(resolve, reject);
return await promise;
} finally {
if (abortListener) {
signal.removeEventListener("abort", abortListener);
}
return decodeURIComponent(value);
} catch {
return value;
}
}
export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, anyAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isCompressibleContentType, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onAsyncIteratorObjectError, onError, onFinish, onReadableStreamError, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorObject, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream };
export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, asyncIteratorWithSpan, clone, compareSequentialIds, defer, fallback, findDeepMatches, get, getConstructor, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, logError, onError, onFinish, onStart, onSuccess, once, overlayProxy, parseEmptyableJSON, preventNativeAwait, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
{
"name": "@orpc/shared",
"type": "module",
"version": "1.14.11",
"version": "1.14.12",
"license": "MIT",

@@ -17,3 +17,2 @@ "homepage": "https://orpc.dev",

"exports": {
"./package.json": "./package.json",
".": {

@@ -37,16 +36,16 @@ "types": "./dist/index.d.mts",

"dependencies": {
"@standardserver/shared": "^0.5.0",
"radash": "^12.1.1",
"type-fest": "^5.3.1"
"type-fest": "^5.4.4"
},
"devDependencies": {
"@opentelemetry/api": "^1.9.1",
"arktype": "^2.2.1",
"valibot": "^1.4.1",
"zod": "^4.4.3"
"@opentelemetry/api": "^1.9.0",
"arktype": "2.2.0",
"valibot": "^1.2.0",
"zod": "^4.3.6"
},
"scripts": {
"build": "unbuild",
"build:watch": "pnpm run build --watch",
"type:check": "tsc -b"
}
}
+46
-50

@@ -1,6 +0,10 @@

<h1 align="center">oRPC - Typesafe APIs Made Simple πŸͺ„</h1>
<div align="center">
<image align="center" src="https://orpc.dev/logo.webp" width=280 alt="oRPC logo" />
</div>
<h1></h1>
<div align="center">
<a href="https://codecov.io/gh/middleapi/orpc">
<img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg">
<img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/1.x/graph/badge.svg">
</a>

@@ -10,6 +14,3 @@ <a href="https://www.npmjs.com/package/@orpc/shared">

</a>
<a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
<img alt="CodSpeed" src="https://img.shields.io/endpoint?url=https://codspeed.io/badge.json" />
</a>
<a href="https://github.com/middleapi/orpc/blob/main/LICENSE">
<a href="https://github.com/middleapi/orpc/blob/1.x/LICENSE">
<img alt="MIT License" src="https://img.shields.io/github/license/middleapi/orpc?logo=open-source-initiative" />

@@ -25,49 +26,51 @@ </a>

## Documentation
<h3 align="center">Typesafe APIs Made Simple πŸͺ„</h3>
You can read the documentation [here](https://orpc.dev).
**oRPC is a powerful combination of RPC and OpenAPI**, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards
## Packages
---
**Core**
## Highlights
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Define API contract as the single source of truth.
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build APIs or implement contracts.
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume APIs with end-to-end type safety.
- [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Add OpenAPI compatibility to APIs.
- **πŸ”— End-to-End Type Safety**: Ensure type-safe inputs, outputs, and errors from client to server.
- **πŸ“˜ First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
- **πŸ“ Contract-First Development**: Optionally define your API contract before implementation.
- **πŸ” First-Class OpenTelemetry**: Seamlessly integrate with OpenTelemetry for observability.
- **βš™οΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, Pinia Colada, and more.
- **πŸš€ Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
- **πŸ”  Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
- **πŸ—ƒοΈ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
- **⏱️ Lazy Router**: Enhance cold start times with our lazy routing feature.
- **πŸ“‘ SSE & Streaming**: Enjoy full type-safe support for SSE and streaming.
- **🌍 Multi-Runtime Support**: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
- **πŸ”Œ Extendability**: Easily extend functionality with plugins, middleware, and interceptors.
**Schema validation**
## Documentation
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): Integrate with [Zod](https://zod.dev/).
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): Integrate with [Valibot](https://valibot.dev/).
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): Integrate with [ArkType](https://arktype.io/).
You can find the full documentation [here](https://orpc.dev).
**Built-in features**
## Packages
- [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher): Pub/Sub with memory, Redis, and Upstash adapters.
- [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit): Rate limiting with memory, Redis, and Upstash adapters.
- [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema): Smart coercion for OpenAPI requests.
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Build your API contract.
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build your API or implement API contract.
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety.
- [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests.
- [@orpc/otel](https://www.npmjs.com/package/@orpc/otel): [OpenTelemetry](https://opentelemetry.io/) integration for observability.
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
- [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
- [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): [TanStack Query](https://tanstack.com/query/latest) integration.
- [@orpc/experimental-react-swr](https://www.npmjs.com/package/@orpc/experimental-react-swr): [SWR](https://swr.vercel.app/) integration.
- [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
- [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/).
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): OpenAPI spec generation from [ArkType](https://arktype.io/).
**Framework & ecosystem integrations**
## `@orpc/shared`
- [@orpc/next](https://www.npmjs.com/package/@orpc/next): Integrate with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data).
- [@orpc/ai-sdk](https://www.npmjs.com/package/@orpc/ai-sdk): Turn contracts and procedures into [AI SDK](https://ai-sdk.dev/) tools.
- [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): Integrate with [TanStack Query](https://tanstack.com/query/latest).
- [@orpc/pinia-colada](https://www.npmjs.com/package/@orpc/pinia-colada): Integrate with [Pinia Colada](https://pinia-colada.esm.dev/).
- [@orpc/swr](https://www.npmjs.com/package/@orpc/swr): Integrate with [SWR](https://swr.vercel.app/).
- [@orpc/experimental-effect](https://www.npmjs.com/package/@orpc/experimental-effect): Integrate with [Effect](https://effect.website/).
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Implement your contract with [NestJS](https://nestjs.com/).
- [@orpc/bun](https://www.npmjs.com/package/@orpc/bun): Adapters for [Bun's Redis](https://bun.sh/).
- [@orpc/cloudflare](https://www.npmjs.com/package/@orpc/cloudflare): Adapters for [Cloudflare's RateLimit and Durable Objects](https://developers.cloudflare.com/workers/).
- [@orpc/trpc](https://www.npmjs.com/package/@orpc/trpc): Reuse existing [tRPC](https://trpc.io/) routers within oRPC.
Provides shared utilities for oRPC packages.
**Observability**
- [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry): Integrate with [OpenTelemetry](https://opentelemetry.io/) for distributed tracing.
- [@orpc/pino](https://www.npmjs.com/package/@orpc/pino): Integrate with [Pino](https://getpino.io/) for logging.
- [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog): Integrate with [Evlog](https://evlog.dev/) for logging.
## Sponsors
Like what we build over at [middleapi](https://github.com/middleapi)? You can help keep it going here: [GitHub Sponsors](https://github.com/sponsors/dinwwwh). Every bit helps! πŸš€
If you find oRPC valuable and would like to support its development, you can do so here: [GitHub Sponsors](https://github.com/sponsors/dinwwwh).

@@ -114,6 +117,7 @@ ### πŸ† Platinum Sponsor

<td align="center"><a href="https://github.com/K-Mistele?ref=orpc" target="_blank" rel="noopener" title="Kyle Mistele"><img src="https://avatars.githubusercontent.com/u/18430555?u=3afebeb81de666e35aaac3ed46f14159d7603ffb&amp;v=4" width="139" alt="Kyle Mistele"/><br />Kyle Mistele</a></td>
<td align="center"><a href="https://github.com/R44VC0RP?ref=orpc" target="_blank" rel="noopener" title="Ryan Vogel"><img src="https://avatars.githubusercontent.com/u/89211796?u=1857347b9787d8d8a7ea5bfc333f96be92d5a683&amp;v=4" width="139" alt="Ryan Vogel"/><br />Ryan Vogel</a></td>
<td align="center"><a href="https://github.com/christ12938?ref=orpc" target="_blank" rel="noopener" title="christ12938"><img src="https://avatars.githubusercontent.com/u/25758598?v=4" width="139" alt="christ12938"/><br />christ12938</a></td>
<td align="center"><a href="https://github.com/Ryanjso?ref=orpc" target="_blank" rel="noopener" title="Ryan Soderberg"><img src="https://avatars.githubusercontent.com/u/39172778?u=5ed913c31d57e7221b75784abcad48c7ebddde27&amp;v=4" width="139" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/Ryanjso?ref=orpc" target="_blank" rel="noopener" title="Ryan Soderberg"><img src="https://avatars.githubusercontent.com/u/39172778?u=5ed913c31d57e7221b75784abcad48c7ebddde27&amp;v=4" width="139" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td>
<td align="center"><a href="https://github.com/itigoore01?ref=orpc" target="_blank" rel="noopener" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&amp;v=4" width="139" alt="shota"/><br />shota</a></td>

@@ -178,3 +182,2 @@ </tr>

<a href="https://github.com/andrewpeters9?ref=orpc" target="_blank" rel="noopener" title="Andrew Peters"><img src="https://avatars.githubusercontent.com/u/36251325?v=4" width="32" height="32" alt="Andrew Peters" /></a>
<a href="https://github.com/R44VC0RP?ref=orpc" target="_blank" rel="noopener" title="Ryan Vogel"><img src="https://avatars.githubusercontent.com/u/89211796?u=1857347b9787d8d8a7ea5bfc333f96be92d5a683&amp;v=4" width="32" height="32" alt="Ryan Vogel" /></a>
<a href="https://github.com/SKostyukovich?ref=orpc" target="_blank" rel="noopener" title="SKostyukovich"><img src="https://avatars.githubusercontent.com/u/10700067?v=4" width="32" height="32" alt="SKostyukovich" /></a>

@@ -194,11 +197,4 @@ <a href="https://github.com/peter-adam-dy?ref=orpc" target="_blank" rel="noopener" title="Peter Adam"><img src="https://avatars.githubusercontent.com/u/132129459?u=4f3dbbb3b443990b56acb7d6a5d11ed2c555f6db&amp;v=4" width="32" height="32" alt="Peter Adam" /></a>

## References
oRPC is inspired by existing solutions that prioritize type safety and developer experience. Special acknowledgments to:
- [tRPC](https://trpc.io): For pioneering the concept of end-to-end type-safe RPC and influencing the development of type-safe APIs.
- [ts-rest](https://ts-rest.com): For its emphasis on contract-first development and OpenAPI integration, which have greatly inspired oRPC's feature set.
## License
Distributed under the MIT License. See [LICENSE](https://github.com/middleapi/orpc/blob/main/LICENSE) for more information.
Distributed under the MIT License. See [LICENSE](https://github.com/middleapi/orpc/blob/1.x/LICENSE) for more information.