@orpc/shared
Advanced tools
+258
-25
| import { Promisable } from 'type-fest'; | ||
| export { IsEqual, IsNever, PartialDeep, Promisable } from 'type-fest'; | ||
| export { group, guard, mapEntries, mapValues, omit } from 'radash'; | ||
| export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest'; | ||
| import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api'; | ||
| export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash'; | ||
@@ -11,5 +12,16 @@ type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions]; | ||
| /** | ||
| * 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 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>; | ||
| /** | ||
| * Executes the callback function after the current call stack has been cleared. | ||
| */ | ||
| declare function defer(callback: () => void): void; | ||
@@ -20,6 +32,85 @@ type OmitChainMethodDeep<T extends object, K extends keyof any> = { | ||
| declare const ORPC_NAME = "orpc"; | ||
| declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared"; | ||
| declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.b6b8746"; | ||
| /** | ||
| * Error thrown when an operation is aborted. | ||
| * Uses the standardized 'AbortError' name for consistency with JavaScript APIs. | ||
| */ | ||
| declare class AbortError extends Error { | ||
| constructor(...rest: ConstructorParameters<typeof Error>); | ||
| } | ||
| 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 nextId; | ||
| generate(): number; | ||
| private index; | ||
| generate(): string; | ||
| } | ||
| /** | ||
| * Compares two sequential IDs. | ||
| * Returns: | ||
| * - negative if `a` < `b` | ||
| * - positive if `a` > `b` | ||
| * - 0 if equal | ||
| */ | ||
| declare function compareSequentialIds(a: string, b: string): number; | ||
@@ -43,2 +134,3 @@ type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; | ||
| } ? T : Error; | ||
| type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never; | ||
@@ -51,3 +143,3 @@ type InterceptableOptions = Record<string, any>; | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -58,3 +150,3 @@ declare function onStart<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -65,3 +157,3 @@ declare function onSuccess<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -73,3 +165,3 @@ declare function onError<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -81,10 +173,104 @@ declare function onFinish<T, TOptions extends { | ||
| /** | ||
| * Only import types from @opentelemetry/api to avoid runtime dependencies. | ||
| */ | ||
| 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 { | ||
| /** | ||
| * Span error status is not set if error is due to cancellation by the signal. | ||
| */ | ||
| signal?: AbortSignal; | ||
| } | ||
| /** | ||
| * 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 { | ||
| /** | ||
| * The name of the span to create. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * Context to use for the span. | ||
| */ | ||
| context?: Context; | ||
| } | ||
| /** | ||
| * 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>; | ||
| declare function isAsyncIteratorObject(maybe: unknown): maybe is AsyncIteratorObject<any, any, any>; | ||
| interface CreateAsyncIteratorObjectCleanupFn { | ||
| interface AsyncIteratorClassNextFn<T, TReturn> { | ||
| (): Promise<IteratorResult<T, TReturn>>; | ||
| } | ||
| interface AsyncIteratorClassCleanupFn { | ||
| (reason: 'return' | 'throw' | 'next' | 'dispose'): Promise<void>; | ||
| } | ||
| declare function createAsyncIteratorObject<T, TReturn, TNext>(next: () => Promise<IteratorResult<T, TReturn>>, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncIteratorObject<T, TReturn, TNext> & AsyncGenerator<T, TReturn, TNext>; | ||
| 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>>; | ||
| /** | ||
| * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose') | ||
| */ | ||
| [asyncDisposeSymbol](): Promise<void>; | ||
| [Symbol.asyncIterator](): this; | ||
| } | ||
| declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[]; | ||
| interface AsyncIteratorWithSpanOptions extends SetSpanErrorOptions { | ||
| /** | ||
| * The name of the span to create. | ||
| */ | ||
| name: string; | ||
| } | ||
| 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): undefined extends T ? undefined | string : string; | ||
| declare function stringifyJSON<T>(value: T | { | ||
| toJSON(): T; | ||
| }): undefined extends T ? undefined | string : string; | ||
@@ -97,2 +283,7 @@ type Segment = string | number; | ||
| /** | ||
| * Get constructor of the value | ||
| * | ||
| */ | ||
| declare function getConstructor(value: unknown): Function | null | undefined; | ||
| /** | ||
| * Check if the value is an object even it created by `Object.create(null)` or more tricky way. | ||
@@ -106,26 +297,68 @@ */ | ||
| declare function clone<T>(value: T): T; | ||
| declare function get(object: object, path: readonly string[]): unknown; | ||
| declare function get(object: unknown, path: readonly PropertyKey[]): unknown; | ||
| declare function isPropertyKey(value: unknown): value is PropertyKey; | ||
| declare const NullProtoObj: ({ | ||
| new <T extends Record<PropertyKey, unknown>>(): T; | ||
| }); | ||
| 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; | ||
| /** | ||
| * Returns the value if it is defined, otherwise returns the fallback | ||
| */ | ||
| declare function fallback<T>(value: T | undefined, fallback: T): T; | ||
| /** | ||
| * 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 preventNativeAwait<T extends object>(target: T): T; | ||
| /** | ||
| * Create a proxy that overlays one object (`overlay`) on top of another (`target`). | ||
| * | ||
| * - 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 when you want to override or extend behavior without fully copying/merging objects. | ||
| */ | ||
| declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>; | ||
| interface AsyncIdQueueCloseOptions { | ||
| id?: number; | ||
| reason?: Error; | ||
| id?: string; | ||
| reason?: unknown; | ||
| } | ||
| declare class AsyncIdQueue<T> { | ||
| private readonly openIds; | ||
| private readonly items; | ||
| private readonly pendingPulls; | ||
| private readonly queues; | ||
| private readonly waiters; | ||
| get length(): number; | ||
| open(id: number): void; | ||
| isOpen(id: number): boolean; | ||
| push(id: number, item: T): void; | ||
| pull(id: number): Promise<T>; | ||
| get waiterIds(): string[]; | ||
| hasBufferedItems(id: string): boolean; | ||
| open(id: string): void; | ||
| isOpen(id: string): boolean; | ||
| push(id: string, item: T): void; | ||
| pull(id: string): Promise<T>; | ||
| close({ id, reason }?: AsyncIdQueueCloseOptions): void; | ||
| assertOpen(id: number): void; | ||
| assertOpen(id: string): 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; | ||
| /** | ||
| * Converts a `ReadableStream` into an `AsyncIteratorClass`. | ||
| */ | ||
| declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>; | ||
| /** | ||
| * Converts an `AsyncIterator` into a `ReadableStream`. | ||
| */ | ||
| declare function asyncIteratorToStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>; | ||
| /** | ||
| * Converts an `AsyncIterator` into a `ReadableStream`, ensuring that | ||
| * all emitted object values are *unproxied* before enqueuing. | ||
| */ | ||
| declare function asyncIteratorToUnproxiedDataStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>; | ||
| export { AsyncIdQueue, SequentialIdGenerator, clone, createAsyncIteratorObject, findDeepMatches, get, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, resolveMaybeOptionalOptions, sequential, splitInHalf, stringifyJSON, toArray, value }; | ||
| export type { AnyFunction, AsyncIdQueueCloseOptions, CreateAsyncIteratorObjectCleanupFn, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, PromiseWithError, Registry, Segment, SetOptional, ThrowableError, Value }; | ||
| declare function tryDecodeURIComponent(value: string): string; | ||
| 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, 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 }; |
+258
-25
| import { Promisable } from 'type-fest'; | ||
| export { IsEqual, IsNever, PartialDeep, Promisable } from 'type-fest'; | ||
| export { group, guard, mapEntries, mapValues, omit } from 'radash'; | ||
| export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest'; | ||
| import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api'; | ||
| export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash'; | ||
@@ -11,5 +12,16 @@ type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions]; | ||
| /** | ||
| * 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 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>; | ||
| /** | ||
| * Executes the callback function after the current call stack has been cleared. | ||
| */ | ||
| declare function defer(callback: () => void): void; | ||
@@ -20,6 +32,85 @@ type OmitChainMethodDeep<T extends object, K extends keyof any> = { | ||
| declare const ORPC_NAME = "orpc"; | ||
| declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared"; | ||
| declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.b6b8746"; | ||
| /** | ||
| * Error thrown when an operation is aborted. | ||
| * Uses the standardized 'AbortError' name for consistency with JavaScript APIs. | ||
| */ | ||
| declare class AbortError extends Error { | ||
| constructor(...rest: ConstructorParameters<typeof Error>); | ||
| } | ||
| 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 nextId; | ||
| generate(): number; | ||
| private index; | ||
| generate(): string; | ||
| } | ||
| /** | ||
| * Compares two sequential IDs. | ||
| * Returns: | ||
| * - negative if `a` < `b` | ||
| * - positive if `a` > `b` | ||
| * - 0 if equal | ||
| */ | ||
| declare function compareSequentialIds(a: string, b: string): number; | ||
@@ -43,2 +134,3 @@ type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; | ||
| } ? T : Error; | ||
| type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never; | ||
@@ -51,3 +143,3 @@ type InterceptableOptions = Record<string, any>; | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -58,3 +150,3 @@ declare function onStart<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -65,3 +157,3 @@ declare function onSuccess<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -73,3 +165,3 @@ declare function onError<T, TOptions extends { | ||
| /** | ||
| * Can used for interceptors or middlewares | ||
| * Can be used for interceptors or middlewares | ||
| */ | ||
@@ -81,10 +173,104 @@ declare function onFinish<T, TOptions extends { | ||
| /** | ||
| * Only import types from @opentelemetry/api to avoid runtime dependencies. | ||
| */ | ||
| 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 { | ||
| /** | ||
| * Span error status is not set if error is due to cancellation by the signal. | ||
| */ | ||
| signal?: AbortSignal; | ||
| } | ||
| /** | ||
| * 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 { | ||
| /** | ||
| * The name of the span to create. | ||
| */ | ||
| name: string; | ||
| /** | ||
| * Context to use for the span. | ||
| */ | ||
| context?: Context; | ||
| } | ||
| /** | ||
| * 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>; | ||
| declare function isAsyncIteratorObject(maybe: unknown): maybe is AsyncIteratorObject<any, any, any>; | ||
| interface CreateAsyncIteratorObjectCleanupFn { | ||
| interface AsyncIteratorClassNextFn<T, TReturn> { | ||
| (): Promise<IteratorResult<T, TReturn>>; | ||
| } | ||
| interface AsyncIteratorClassCleanupFn { | ||
| (reason: 'return' | 'throw' | 'next' | 'dispose'): Promise<void>; | ||
| } | ||
| declare function createAsyncIteratorObject<T, TReturn, TNext>(next: () => Promise<IteratorResult<T, TReturn>>, cleanup: CreateAsyncIteratorObjectCleanupFn): AsyncIteratorObject<T, TReturn, TNext> & AsyncGenerator<T, TReturn, TNext>; | ||
| 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>>; | ||
| /** | ||
| * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose') | ||
| */ | ||
| [asyncDisposeSymbol](): Promise<void>; | ||
| [Symbol.asyncIterator](): this; | ||
| } | ||
| declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[]; | ||
| interface AsyncIteratorWithSpanOptions extends SetSpanErrorOptions { | ||
| /** | ||
| * The name of the span to create. | ||
| */ | ||
| name: string; | ||
| } | ||
| 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): undefined extends T ? undefined | string : string; | ||
| declare function stringifyJSON<T>(value: T | { | ||
| toJSON(): T; | ||
| }): undefined extends T ? undefined | string : string; | ||
@@ -97,2 +283,7 @@ type Segment = string | number; | ||
| /** | ||
| * Get constructor of the value | ||
| * | ||
| */ | ||
| declare function getConstructor(value: unknown): Function | null | undefined; | ||
| /** | ||
| * Check if the value is an object even it created by `Object.create(null)` or more tricky way. | ||
@@ -106,26 +297,68 @@ */ | ||
| declare function clone<T>(value: T): T; | ||
| declare function get(object: object, path: readonly string[]): unknown; | ||
| declare function get(object: unknown, path: readonly PropertyKey[]): unknown; | ||
| declare function isPropertyKey(value: unknown): value is PropertyKey; | ||
| declare const NullProtoObj: ({ | ||
| new <T extends Record<PropertyKey, unknown>>(): T; | ||
| }); | ||
| 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; | ||
| /** | ||
| * Returns the value if it is defined, otherwise returns the fallback | ||
| */ | ||
| declare function fallback<T>(value: T | undefined, fallback: T): T; | ||
| /** | ||
| * 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 preventNativeAwait<T extends object>(target: T): T; | ||
| /** | ||
| * Create a proxy that overlays one object (`overlay`) on top of another (`target`). | ||
| * | ||
| * - 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 when you want to override or extend behavior without fully copying/merging objects. | ||
| */ | ||
| declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>; | ||
| interface AsyncIdQueueCloseOptions { | ||
| id?: number; | ||
| reason?: Error; | ||
| id?: string; | ||
| reason?: unknown; | ||
| } | ||
| declare class AsyncIdQueue<T> { | ||
| private readonly openIds; | ||
| private readonly items; | ||
| private readonly pendingPulls; | ||
| private readonly queues; | ||
| private readonly waiters; | ||
| get length(): number; | ||
| open(id: number): void; | ||
| isOpen(id: number): boolean; | ||
| push(id: number, item: T): void; | ||
| pull(id: number): Promise<T>; | ||
| get waiterIds(): string[]; | ||
| hasBufferedItems(id: string): boolean; | ||
| open(id: string): void; | ||
| isOpen(id: string): boolean; | ||
| push(id: string, item: T): void; | ||
| pull(id: string): Promise<T>; | ||
| close({ id, reason }?: AsyncIdQueueCloseOptions): void; | ||
| assertOpen(id: number): void; | ||
| assertOpen(id: string): 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; | ||
| /** | ||
| * Converts a `ReadableStream` into an `AsyncIteratorClass`. | ||
| */ | ||
| declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>; | ||
| /** | ||
| * Converts an `AsyncIterator` into a `ReadableStream`. | ||
| */ | ||
| declare function asyncIteratorToStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>; | ||
| /** | ||
| * Converts an `AsyncIterator` into a `ReadableStream`, ensuring that | ||
| * all emitted object values are *unproxied* before enqueuing. | ||
| */ | ||
| declare function asyncIteratorToUnproxiedDataStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>; | ||
| export { AsyncIdQueue, SequentialIdGenerator, clone, createAsyncIteratorObject, findDeepMatches, get, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, resolveMaybeOptionalOptions, sequential, splitInHalf, stringifyJSON, toArray, value }; | ||
| export type { AnyFunction, AsyncIdQueueCloseOptions, CreateAsyncIteratorObjectCleanupFn, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, PromiseWithError, Registry, Segment, SetOptional, ThrowableError, Value }; | ||
| declare function tryDecodeURIComponent(value: string): string; | ||
| 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, 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 }; |
+544
-141
@@ -1,2 +0,2 @@ | ||
| export { group, guard, mapEntries, mapValues, omit } from 'radash'; | ||
| export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash'; | ||
@@ -15,2 +15,20 @@ function resolveMaybeOptionalOptions(rest) { | ||
| function readAsBuffer(source) { | ||
| if (typeof source.bytes === "function") { | ||
| return source.bytes(); | ||
| } | ||
| return source.arrayBuffer(); | ||
| } | ||
| const ORPC_NAME = "orpc"; | ||
| const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared"; | ||
| const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.b6b8746"; | ||
| class AbortError extends Error { | ||
| constructor(...rest) { | ||
| super(...rest); | ||
| this.name = "AbortError"; | ||
| } | ||
| } | ||
| function once(fn) { | ||
@@ -36,13 +54,422 @@ let cached; | ||
| } | ||
| function defer(callback) { | ||
| if (typeof setTimeout === "function") { | ||
| setTimeout(callback, 0); | ||
| } else { | ||
| Promise.resolve().then(() => Promise.resolve().then(() => Promise.resolve().then(callback))); | ||
| } | ||
| } | ||
| const SPAN_ERROR_STATUS = 2; | ||
| 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 getGlobalOtelConfig() { | ||
| return globalThis[GLOBAL_OTEL_CONFIG_KEY]; | ||
| } | ||
| function startSpan(name, options = {}, context) { | ||
| const tracer = getGlobalOtelConfig()?.tracer; | ||
| return tracer?.startSpan(name, options, context); | ||
| } | ||
| function setSpanError(span, error, options = {}) { | ||
| if (!span) { | ||
| return; | ||
| } | ||
| const exception = toOtelException(error); | ||
| span.recordException(exception); | ||
| if (!options.signal?.aborted || options.signal.reason !== error) { | ||
| span.setStatus({ | ||
| code: SPAN_ERROR_STATUS, | ||
| message: exception.message | ||
| }); | ||
| } | ||
| } | ||
| function setSpanAttribute(span, key, value) { | ||
| if (!span || value === void 0) { | ||
| return; | ||
| } | ||
| span.setAttribute(key, value); | ||
| } | ||
| function toOtelException(error) { | ||
| if (error instanceof Error) { | ||
| const exception = { | ||
| message: error.message, | ||
| name: error.name, | ||
| stack: error.stack | ||
| }; | ||
| if ("code" in error && (typeof error.code === "string" || typeof error.code === "number")) { | ||
| exception.code = error.code; | ||
| } | ||
| return exception; | ||
| } | ||
| return { message: String(error) }; | ||
| } | ||
| function toSpanAttributeValue(data) { | ||
| if (data === void 0) { | ||
| return "undefined"; | ||
| } | ||
| try { | ||
| return JSON.stringify(data, (_, value) => { | ||
| if (typeof value === "bigint") { | ||
| return value.toString(); | ||
| } | ||
| if (value instanceof Map || value instanceof Set) { | ||
| return Array.from(value); | ||
| } | ||
| return value; | ||
| }); | ||
| } catch { | ||
| return String(data); | ||
| } | ||
| } | ||
| async function runWithSpan({ name, context, ...options }, fn) { | ||
| const tracer = getGlobalOtelConfig()?.tracer; | ||
| if (!tracer) { | ||
| return fn(); | ||
| } | ||
| const callback = async (span) => { | ||
| try { | ||
| return await fn(span); | ||
| } catch (e) { | ||
| setSpanError(span, e, options); | ||
| throw e; | ||
| } finally { | ||
| span.end(); | ||
| } | ||
| }; | ||
| if (context) { | ||
| return tracer.startActiveSpan(name, options, context, callback); | ||
| } else { | ||
| return tracer.startActiveSpan(name, options, callback); | ||
| } | ||
| } | ||
| async function runInSpanContext(span, fn) { | ||
| const otelConfig = getGlobalOtelConfig(); | ||
| if (!span || !otelConfig) { | ||
| return fn(); | ||
| } | ||
| const ctx = otelConfig.trace.setSpan(otelConfig.context.active(), span); | ||
| return otelConfig.context.with(ctx, fn); | ||
| } | ||
| class AsyncIdQueue { | ||
| openIds = /* @__PURE__ */ new Set(); | ||
| queues = /* @__PURE__ */ new Map(); | ||
| waiters = /* @__PURE__ */ new Map(); | ||
| 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) { | ||
| this.openIds.add(id); | ||
| } | ||
| isOpen(id) { | ||
| return this.openIds.has(id); | ||
| } | ||
| push(id, item) { | ||
| this.assertOpen(id); | ||
| const pending = this.waiters.get(id); | ||
| if (pending?.length) { | ||
| pending.shift()[0](item); | ||
| if (pending.length === 0) { | ||
| this.waiters.delete(id); | ||
| } | ||
| } else { | ||
| const items = this.queues.get(id); | ||
| if (items) { | ||
| items.push(item); | ||
| } else { | ||
| this.queues.set(id, [item]); | ||
| } | ||
| } | ||
| } | ||
| async pull(id) { | ||
| this.assertOpen(id); | ||
| const items = this.queues.get(id); | ||
| if (items?.length) { | ||
| const item = items.shift(); | ||
| if (items.length === 0) { | ||
| this.queues.delete(id); | ||
| } | ||
| return item; | ||
| } | ||
| return new Promise((resolve, reject) => { | ||
| const waitingPulls = this.waiters.get(id); | ||
| const pending = [resolve, reject]; | ||
| if (waitingPulls) { | ||
| waitingPulls.push(pending); | ||
| } else { | ||
| this.waiters.set(id, [pending]); | ||
| } | ||
| }); | ||
| } | ||
| close({ id, reason } = {}) { | ||
| if (id === void 0) { | ||
| this.waiters.forEach((pendingPulls, id2) => { | ||
| const error2 = reason ?? new AbortError(`[AsyncIdQueue] Queue[${id2}] was closed or aborted while waiting for pulling.`); | ||
| pendingPulls.forEach(([, reject]) => reject(error2)); | ||
| }); | ||
| this.waiters.clear(); | ||
| this.openIds.clear(); | ||
| this.queues.clear(); | ||
| return; | ||
| } | ||
| const error = reason ?? new AbortError(`[AsyncIdQueue] Queue[${id}] was closed or aborted while waiting for pulling.`); | ||
| this.waiters.get(id)?.forEach(([, reject]) => reject(error)); | ||
| this.waiters.delete(id); | ||
| this.openIds.delete(id); | ||
| this.queues.delete(id); | ||
| } | ||
| assertOpen(id) { | ||
| if (!this.isOpen(id)) { | ||
| throw new Error(`[AsyncIdQueue] Cannot access queue[${id}] because it is not open or aborted.`); | ||
| } | ||
| } | ||
| } | ||
| 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 { | ||
| 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"); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| next() { | ||
| return this.#next(); | ||
| } | ||
| async return(value) { | ||
| this.#isDone = true; | ||
| if (!this.#isExecuteComplete) { | ||
| this.#isExecuteComplete = true; | ||
| await this.#cleanup("return"); | ||
| } | ||
| 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; | ||
| } | ||
| } | ||
| function replicateAsyncIterator(source, count) { | ||
| const queue = new AsyncIdQueue(); | ||
| const ids = Array.from({ length: count }, (_, i) => i.toString()); | ||
| let isSourceFinished = false; | ||
| const start = once(async () => { | ||
| try { | ||
| while (true) { | ||
| const item = await source.next(); | ||
| ids.forEach((id) => { | ||
| if (queue.isOpen(id)) { | ||
| queue.push(id, { next: item }); | ||
| } | ||
| }); | ||
| if (item.done) { | ||
| break; | ||
| } | ||
| } | ||
| } catch (error) { | ||
| ids.forEach((id) => { | ||
| if (queue.isOpen(id)) { | ||
| queue.push(id, { error }); | ||
| } | ||
| }); | ||
| } finally { | ||
| isSourceFinished = true; | ||
| } | ||
| }); | ||
| const replicated = ids.map((id) => { | ||
| queue.open(id); | ||
| return new AsyncIteratorClass( | ||
| async () => { | ||
| start(); | ||
| const item = await queue.pull(id); | ||
| if (item.next) { | ||
| return item.next; | ||
| } | ||
| throw item.error; | ||
| }, | ||
| async (reason) => { | ||
| queue.close({ id }); | ||
| if (reason !== "next" && !queue.length && !isSourceFinished) { | ||
| isSourceFinished = true; | ||
| await source?.return?.(); | ||
| } | ||
| } | ||
| ); | ||
| }); | ||
| return replicated; | ||
| } | ||
| 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?.()); | ||
| } | ||
| } 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 { | ||
| nextId = 0; | ||
| index = BigInt(1); | ||
| generate() { | ||
| if (this.nextId === Number.MAX_SAFE_INTEGER) { | ||
| this.nextId = 0; | ||
| return Number.MAX_SAFE_INTEGER; | ||
| } | ||
| return this.nextId++; | ||
| 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; | ||
| } | ||
@@ -101,65 +528,2 @@ function onStart(callback) { | ||
| function isAsyncIteratorObject(maybe) { | ||
| if (!maybe || typeof maybe !== "object") { | ||
| return false; | ||
| } | ||
| return Symbol.asyncIterator in maybe && typeof maybe[Symbol.asyncIterator] === "function"; | ||
| } | ||
| function createAsyncIteratorObject(next, cleanup) { | ||
| let isExecuteComplete = false; | ||
| let isDone = false; | ||
| const iterator = { | ||
| next: sequential(async () => { | ||
| if (isDone) { | ||
| return { done: true, value: void 0 }; | ||
| } | ||
| try { | ||
| const result = await next(); | ||
| if (result.done) { | ||
| isDone = true; | ||
| } | ||
| return result; | ||
| } catch (err) { | ||
| isDone = true; | ||
| throw err; | ||
| } finally { | ||
| if (isDone && !isExecuteComplete) { | ||
| isExecuteComplete = true; | ||
| await cleanup("next"); | ||
| } | ||
| } | ||
| }), | ||
| async return(value) { | ||
| isDone = true; | ||
| if (!isExecuteComplete) { | ||
| isExecuteComplete = true; | ||
| await cleanup("return"); | ||
| } | ||
| return { done: true, value }; | ||
| }, | ||
| async throw(err) { | ||
| isDone = true; | ||
| if (!isExecuteComplete) { | ||
| isExecuteComplete = true; | ||
| await cleanup("throw"); | ||
| } | ||
| throw err; | ||
| }, | ||
| /** | ||
| * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose') | ||
| */ | ||
| async [Symbol.asyncDispose ?? Symbol.for("asyncDispose")]() { | ||
| isDone = true; | ||
| if (!isExecuteComplete) { | ||
| isExecuteComplete = true; | ||
| await cleanup("dispose"); | ||
| } | ||
| }, | ||
| [Symbol.asyncIterator]() { | ||
| return iterator; | ||
| } | ||
| }; | ||
| return iterator; | ||
| } | ||
| function parseEmptyableJSON(text) { | ||
@@ -190,2 +554,8 @@ if (!text) { | ||
| } | ||
| function getConstructor(value) { | ||
| if (!isTypescriptObject(value)) { | ||
| return null; | ||
| } | ||
| return Object.getPrototypeOf(value)?.constructor; | ||
| } | ||
| function isObject(value) { | ||
@@ -210,2 +580,5 @@ if (!value || typeof value !== "object") { | ||
| } | ||
| for (const sym of Object.getOwnPropertySymbols(value)) { | ||
| result[sym] = clone(value[sym]); | ||
| } | ||
| return result; | ||
@@ -229,86 +602,116 @@ } | ||
| } | ||
| const NullProtoObj = /* @__PURE__ */ (() => { | ||
| const e = function() { | ||
| }; | ||
| e.prototype = /* @__PURE__ */ Object.create(null); | ||
| Object.freeze(e.prototype); | ||
| return e; | ||
| })(); | ||
| class AsyncIdQueue { | ||
| openIds = /* @__PURE__ */ new Set(); | ||
| items = /* @__PURE__ */ new Map(); | ||
| pendingPulls = /* @__PURE__ */ new Map(); | ||
| get length() { | ||
| return this.openIds.size; | ||
| function value(value2, ...args) { | ||
| if (typeof value2 === "function") { | ||
| return value2(...args); | ||
| } | ||
| open(id) { | ||
| this.openIds.add(id); | ||
| } | ||
| isOpen(id) { | ||
| return this.openIds.has(id); | ||
| } | ||
| push(id, item) { | ||
| this.assertOpen(id); | ||
| const pending = this.pendingPulls.get(id); | ||
| if (pending?.length) { | ||
| pending.shift()[0](item); | ||
| if (pending.length === 0) { | ||
| this.pendingPulls.delete(id); | ||
| return value2; | ||
| } | ||
| function fallback(value2, fallback2) { | ||
| return value2 === void 0 ? fallback2 : value2; | ||
| } | ||
| 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; | ||
| } | ||
| } else { | ||
| const items = this.items.get(id); | ||
| if (items) { | ||
| items.push(item); | ||
| 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); | ||
| } | ||
| }))); | ||
| } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| 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; | ||
| }, | ||
| has(_, prop) { | ||
| return Reflect.has(partial, prop) || Reflect.has(value(target), prop); | ||
| } | ||
| }); | ||
| return proxy; | ||
| } | ||
| function streamToAsyncIteratorClass(stream) { | ||
| const reader = stream.getReader(); | ||
| return new AsyncIteratorClass( | ||
| async () => { | ||
| return reader.read(); | ||
| }, | ||
| async () => { | ||
| await reader.cancel(); | ||
| } | ||
| ); | ||
| } | ||
| function asyncIteratorToStream(iterator) { | ||
| return new ReadableStream({ | ||
| async pull(controller) { | ||
| const { done, value } = await iterator.next(); | ||
| if (done) { | ||
| controller.close(); | ||
| } else { | ||
| this.items.set(id, [item]); | ||
| controller.enqueue(value); | ||
| } | ||
| }, | ||
| async cancel() { | ||
| await iterator.return?.(); | ||
| } | ||
| } | ||
| async pull(id) { | ||
| this.assertOpen(id); | ||
| const items = this.items.get(id); | ||
| if (items?.length) { | ||
| const item = items.shift(); | ||
| if (items.length === 0) { | ||
| this.items.delete(id); | ||
| } | ||
| return item; | ||
| } | ||
| return new Promise((resolve, reject) => { | ||
| const waitingPulls = this.pendingPulls.get(id); | ||
| const pending = [resolve, reject]; | ||
| if (waitingPulls) { | ||
| waitingPulls.push(pending); | ||
| }); | ||
| } | ||
| function asyncIteratorToUnproxiedDataStream(iterator) { | ||
| return new ReadableStream({ | ||
| async pull(controller) { | ||
| const { done, value } = await iterator.next(); | ||
| if (done) { | ||
| controller.close(); | ||
| } else { | ||
| this.pendingPulls.set(id, [pending]); | ||
| const unproxied = isObject(value) ? { ...value } : Array.isArray(value) ? value.map((i) => i) : value; | ||
| controller.enqueue(unproxied); | ||
| } | ||
| }); | ||
| } | ||
| close({ id, reason } = {}) { | ||
| if (id === void 0) { | ||
| this.pendingPulls.forEach((pendingPulls, id2) => { | ||
| pendingPulls.forEach(([, reject]) => { | ||
| reject(reason ?? new Error(`[AsyncIdQueue] Queue[${id2}] was closed or aborted while waiting for pulling.`)); | ||
| }); | ||
| }); | ||
| this.pendingPulls.clear(); | ||
| this.openIds.clear(); | ||
| this.items.clear(); | ||
| return; | ||
| }, | ||
| async cancel() { | ||
| await iterator.return?.(); | ||
| } | ||
| this.pendingPulls.get(id)?.forEach(([, reject]) => { | ||
| reject(reason ?? new Error(`[AsyncIdQueue] Queue[${id}] was closed or aborted while waiting for pulling.`)); | ||
| }); | ||
| this.pendingPulls.delete(id); | ||
| this.openIds.delete(id); | ||
| this.items.delete(id); | ||
| } | ||
| assertOpen(id) { | ||
| if (!this.isOpen(id)) { | ||
| throw new Error(`[AsyncIdQueue] Cannot access queue[${id}] because it is not open or aborted.`); | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| function value(value2, ...args) { | ||
| if (typeof value2 === "function") { | ||
| return value2(...args); | ||
| function tryDecodeURIComponent(value) { | ||
| try { | ||
| return decodeURIComponent(value); | ||
| } catch { | ||
| return value; | ||
| } | ||
| return value2; | ||
| } | ||
| export { AsyncIdQueue, SequentialIdGenerator, clone, createAsyncIteratorObject, findDeepMatches, get, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, resolveMaybeOptionalOptions, sequential, splitInHalf, stringifyJSON, toArray, value }; | ||
| 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, 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 }; |
+19
-6
| { | ||
| "name": "@orpc/shared", | ||
| "type": "module", | ||
| "version": "0.0.0-next.b6b0cc3", | ||
| "version": "0.0.0-next.b6b8746", | ||
| "license": "MIT", | ||
| "homepage": "https://orpc.unnoq.com", | ||
| "homepage": "https://orpc.dev", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/unnoq/orpc.git", | ||
| "url": "git+https://github.com/middleapi/orpc.git", | ||
| "directory": "packages/shared" | ||
| }, | ||
| "keywords": [ | ||
| "unnoq", | ||
| "orpc" | ||
@@ -26,6 +25,20 @@ ], | ||
| ], | ||
| "peerDependencies": { | ||
| "@opentelemetry/api": ">=1.9.0" | ||
| }, | ||
| "peerDependenciesMeta": { | ||
| "@opentelemetry/api": { | ||
| "optional": true | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "radash": "^12.1.0", | ||
| "type-fest": "^4.39.1" | ||
| "radash": "^12.1.1", | ||
| "type-fest": "^5.4.4" | ||
| }, | ||
| "devDependencies": { | ||
| "@opentelemetry/api": "^1.9.0", | ||
| "arktype": "2.2.0", | ||
| "valibot": "^1.2.0", | ||
| "zod": "^4.3.6" | ||
| }, | ||
| "scripts": { | ||
@@ -32,0 +45,0 @@ "build": "unbuild", |
+126
-24
@@ -1,8 +0,3 @@ | ||
| > [!WARNING] | ||
| > | ||
| > `@orpc/shared` is an internal dependency of oRPC packages. It does not follow semver and may change at any time without notice. | ||
| > Please do not use it in your project. | ||
| <div align="center"> | ||
| <image align="center" src="https://orpc.unnoq.com/logo.webp" width=280 alt="oRPC logo" /> | ||
| <image align="center" src="https://orpc.dev/logo.webp" width=280 alt="oRPC logo" /> | ||
| </div> | ||
@@ -13,4 +8,4 @@ | ||
| <div align="center"> | ||
| <a href="https://codecov.io/gh/unnoq/orpc"> | ||
| <img alt="codecov" src="https://codecov.io/gh/unnoq/orpc/branch/main/graph/badge.svg"> | ||
| <a href="https://codecov.io/gh/middleapi/orpc"> | ||
| <img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg"> | ||
| </a> | ||
@@ -20,4 +15,4 @@ <a href="https://www.npmjs.com/package/@orpc/shared"> | ||
| </a> | ||
| <a href="https://github.com/unnoq/orpc/blob/main/LICENSE"> | ||
| <img alt="MIT License" src="https://img.shields.io/github/license/unnoq/orpc?logo=open-source-initiative" /> | ||
| <a href="https://github.com/middleapi/orpc/blob/main/LICENSE"> | ||
| <img alt="MIT License" src="https://img.shields.io/github/license/middleapi/orpc?logo=open-source-initiative" /> | ||
| </a> | ||
@@ -27,2 +22,5 @@ <a href="https://discord.gg/TXEbwRBvQn"> | ||
| </a> | ||
| <a href="https://deepwiki.com/middleapi/orpc"> | ||
| <img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"> | ||
| </a> | ||
| </div> | ||
@@ -41,3 +39,4 @@ | ||
| - **π Contract-First Development**: Optionally define your API contract before implementation. | ||
| - **βοΈ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte), Pinia Colada, and more. | ||
| - **π 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. | ||
@@ -50,7 +49,6 @@ - **π Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators. | ||
| - **π Extendability**: Easily extend functionality with plugins, middleware, and interceptors. | ||
| - **π‘οΈ Reliability**: Well-tested, TypeScript-based, production-ready, and MIT licensed. | ||
| ## Documentation | ||
| You can find the full documentation [here](https://orpc.unnoq.com). | ||
| You can find the full documentation [here](https://orpc.dev). | ||
@@ -62,10 +60,10 @@ ## Packages | ||
| - [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume your API on the client with type-safety. | ||
| - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with NestJS. | ||
| - [@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/react-query](https://www.npmjs.com/package/@orpc/react-query): Integration with [React Query](https://tanstack.com/query/latest/docs/framework/react/overview). | ||
| - [@orpc/vue-query](https://www.npmjs.com/package/@orpc/vue-query): Integration with [Vue Query](https://tanstack.com/query/latest/docs/framework/vue/overview). | ||
| - [@orpc/solid-query](https://www.npmjs.com/package/@orpc/solid-query): Integration with [Solid Query](https://tanstack.com/query/latest/docs/framework/solid/overview). | ||
| - [@orpc/svelte-query](https://www.npmjs.com/package/@orpc/svelte-query): Integration with [Svelte Query](https://tanstack.com/query/latest/docs/framework/svelte/overview). | ||
| - [@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/openapi](https://www.npmjs.com/package/@orpc/openapi): Generate OpenAPI specs and handle OpenAPI requests. | ||
| - [@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. | ||
@@ -81,6 +79,110 @@ - [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): OpenAPI spec generation from [Valibot](https://valibot.dev/). | ||
| <p align="center"> | ||
| <a href="https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg"> | ||
| <img src='https://cdn.jsdelivr.net/gh/unnoq/unnoq/sponsors.svg'/> | ||
| </a> | ||
| If you find oRPC valuable and would like to support its development, you can do so here: [GitHub Sponsors](https://github.com/sponsors/dinwwwh). | ||
| ### π Platinum Sponsor | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://screenshotone.com/?ref=orpc" target="_blank" rel="noopener" title="ScreenshotOne.com"><img src="https://avatars.githubusercontent.com/u/97035603?v=4" width="279" alt="ScreenshotOne.com"/><br />ScreenshotOne.com</a></td> | ||
| </tr> | ||
| </table> | ||
| ### π₯ Silver Sponsor | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://misskey.io/?ref=orpc" target="_blank" rel="noopener" title="ζδΈγγ"><img src="https://avatars.githubusercontent.com/u/37681609?u=0dd4c7e4ba937cbb52b068c55914b1d8164dc0c7&v=4" width="209" alt="ζδΈγγ"/><br />ζδΈγγ</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="209" alt="christ12938"/><br />christ12938</a></td> | ||
| </tr> | ||
| </table> | ||
| ### Generous Sponsors | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/ln-markets?ref=orpc" target="_blank" rel="noopener" title="LN Markets"><img src="https://avatars.githubusercontent.com/u/70597625?v=4" width="167" alt="LN Markets"/><br />LN Markets</a></td> | ||
| </tr> | ||
| </table> | ||
| ### Sponsors | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/hrmcdonald?ref=orpc" target="_blank" rel="noopener" title="Reece McDonald"><img src="https://avatars.githubusercontent.com/u/39349270?v=4" width="139" alt="Reece McDonald"/><br />Reece McDonald</a></td> | ||
| <td align="center"><a href="https://github.com/nicognaW?ref=orpc" target="_blank" rel="noopener" title="nk"><img src="https://avatars.githubusercontent.com/u/66731869?u=4699bda3a9092d3ec34fbd959450767bcc8b8b6d&v=4" width="139" alt="nk"/><br />nk</a></td> | ||
| <td align="center"><a href="https://github.com/supastarter?ref=orpc" target="_blank" rel="noopener" title="supastarter"><img src="https://avatars.githubusercontent.com/u/110960143?v=4" width="139" alt="supastarter"/><br />supastarter</a></td> | ||
| <td align="center"><a href="https://github.com/divmgl?ref=orpc" target="_blank" rel="noopener" title="Dexter Miguel"><img src="https://avatars.githubusercontent.com/u/5452298?u=645993204be8696c085ecf0d228c3062efe2ed65&v=4" width="139" alt="Dexter Miguel"/><br />Dexter Miguel</a></td> | ||
| <td align="center"><a href="https://github.com/herrfugbaum?ref=orpc" target="_blank" rel="noopener" title="herrfugbaum"><img src="https://avatars.githubusercontent.com/u/12859776?u=644dc1666d0220bc0468eb0de3c56b919f635b16&v=4" width="139" alt="herrfugbaum"/><br />herrfugbaum</a></td> | ||
| <td align="center"><a href="https://github.com/ryota-murakami?ref=orpc" target="_blank" rel="noopener" title="Ryota Murakami"><img src="https://avatars.githubusercontent.com/u/5501268?u=599389e03340734325726ca3f8f423c021d47d7f&v=4" width="139" alt="Ryota Murakami"/><br />Ryota Murakami</a></td> | ||
| </tr> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/dcramer?ref=orpc" target="_blank" rel="noopener" title="David Cramer"><img src="https://avatars.githubusercontent.com/u/23610?v=4" width="139" alt="David Cramer"/><br />David Cramer</a></td> | ||
| <td align="center"><a href="https://github.com/valerii15298?ref=orpc" target="_blank" rel="noopener" title="Valerii Petryniak"><img src="https://avatars.githubusercontent.com/u/44531564?u=88ac74d9bacd20401518441907acad21063cd397&v=4" width="139" alt="Valerii Petryniak"/><br />Valerii Petryniak</a></td> | ||
| <td align="center"><a href="https://github.com/happyboy2022?ref=orpc" target="_blank" rel="noopener" title="happyboy"><img src="https://avatars.githubusercontent.com/u/103669586?u=65b49c4b893ed3703909fbb3a7a22313f3f9c121&v=4" width="139" alt="happyboy"/><br />happyboy</a></td> | ||
| <td align="center"><a href="https://github.com/letstri?ref=orpc" target="_blank" rel="noopener" title="Valerii Strilets"><img src="https://avatars.githubusercontent.com/u/13253748?u=c7b10399ccc8f8081e24db94ec32cd9858e86ac3&v=4" width="139" alt="Valerii Strilets"/><br />Valerii Strilets</a></td> | ||
| <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&v=4" width="139" alt="Kyle Mistele"/><br />Kyle Mistele</a></td> | ||
| <td align="center"><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="139" alt="Andrew Peters"/><br />Andrew Peters</a></td> | ||
| </tr> | ||
| <tr> | ||
| <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&v=4" width="139" alt="Ryan Vogel"/><br />Ryan Vogel</a></td> | ||
| <td align="center"><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&v=4" width="139" alt="Peter Adam"/><br />Peter Adam</a></td> | ||
| <td align="center"><a href="https://github.com/yukimotochern?ref=orpc" target="_blank" rel="noopener" title="Chen, Zhi-Yuan"><img src="https://avatars.githubusercontent.com/u/20896173?u=945c33fc21725e4d566a0d02afc54b136ca1d67a&v=4" width="139" alt="Chen, Zhi-Yuan"/><br />Chen, Zhi-Yuan</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&v=4" width="139" alt="Ryan Soderberg"/><br />Ryan Soderberg</a></td> | ||
| </tr> | ||
| </table> | ||
| ### Backers | ||
| <table> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/rhinodavid?ref=orpc" target="_blank" rel="noopener" title="David Walsh"><img src="https://avatars.githubusercontent.com/u/5778036?u=b5521f07d2f88c3db2a0dae62b5f2f8357214af0&v=4" width="119" alt="David Walsh"/><br />David Walsh</a></td> | ||
| <td align="center"><a href="https://github.com/Robbe95?ref=orpc" target="_blank" rel="noopener" title="Robbe Vaes"><img src="https://avatars.githubusercontent.com/u/44748019?u=e0232402c045ad4eac7cbd217f1f47e083103b89&v=4" width="119" alt="Robbe Vaes"/><br />Robbe Vaes</a></td> | ||
| <td align="center"><a href="https://github.com/aidansunbury?ref=orpc" target="_blank" rel="noopener" title="Aidan Sunbury"><img src="https://avatars.githubusercontent.com/u/64103161?v=4" width="119" alt="Aidan Sunbury"/><br />Aidan Sunbury</a></td> | ||
| <td align="center"><a href="https://github.com/soonoo?ref=orpc" target="_blank" rel="noopener" title="soonoo"><img src="https://avatars.githubusercontent.com/u/5436405?u=5d0b4aa955c87e30e6bda7f0cccae5402da99528&v=4" width="119" alt="soonoo"/><br />soonoo</a></td> | ||
| <td align="center"><a href="https://github.com/kporten?ref=orpc" target="_blank" rel="noopener" title="Kevin Porten"><img src="https://avatars.githubusercontent.com/u/1839345?u=dc2263d5cfe0d927ce1a0be04a1d55dd6b55405c&v=4" width="119" alt="Kevin Porten"/><br />Kevin Porten</a></td> | ||
| <td align="center"><a href="https://github.com/pumpkinlink?ref=orpc" target="_blank" rel="noopener" title="Denis"><img src="https://avatars.githubusercontent.com/u/11864620?u=5f47bbe6c65d0f6f5cf011021490238e4b0593d0&v=4" width="119" alt="Denis"/><br />Denis</a></td> | ||
| <td align="center"><a href="https://github.com/christopher-kapic?ref=orpc" target="_blank" rel="noopener" title="Christopher Kapic"><img src="https://avatars.githubusercontent.com/u/59740769?u=e7ad4b72b5bf6c9eb1644c26dbf3332a8f987377&v=4" width="119" alt="Christopher Kapic"/><br />Christopher Kapic</a></td> | ||
| </tr> | ||
| <tr> | ||
| <td align="center"><a href="https://github.com/thomasballinger?ref=orpc" target="_blank" rel="noopener" title="Tom Ballinger"><img src="https://avatars.githubusercontent.com/u/458879?u=4b045ac75d721b6ac2b42a74d7d37f61f0414031&v=4" width="119" alt="Tom Ballinger"/><br />Tom Ballinger</a></td> | ||
| <td align="center"><a href="https://github.com/SSam0419?ref=orpc" target="_blank" rel="noopener" title="Sam"><img src="https://avatars.githubusercontent.com/u/102863520?u=3c89611f549d5070be232eb4532f690c8f2e7a65&v=4" width="119" alt="Sam"/><br />Sam</a></td> | ||
| <td align="center"><a href="https://github.com/Titoine?ref=orpc" target="_blank" rel="noopener" title="Titoine"><img src="https://avatars.githubusercontent.com/u/3514286?u=1bb1e86b0c99c8a1121372e56d51a177eea12191&v=4" width="119" alt="Titoine"/><br />Titoine</a></td> | ||
| <td align="center"><a href="https://github.com/Mnigos?ref=orpc" target="_blank" rel="noopener" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&v=4" width="119" alt="Igor Makowski"/><br />Igor Makowski</a></td> | ||
| <td align="center"><a href="https://github.com/steelbrain?ref=orpc" target="_blank" rel="noopener" title="Anees Iqbal"><img src="https://avatars.githubusercontent.com/u/4278113?u=22b80b5399eed68ac76cd58b02961b0481f1db11&v=4" width="119" alt="Anees Iqbal"/><br />Anees Iqbal</a></td> | ||
| <td align="center"><a href="https://github.com/hanayashiki?ref=orpc" target="_blank" rel="noopener" title="wang chenyu"><img src="https://avatars.githubusercontent.com/u/26056783?u=98c5ceda64b19874ed2a31515467332ea991e590&v=4" width="119" alt="wang chenyu"/><br />wang chenyu</a></td> | ||
| <td align="center"><a href="https://github.com/piscis?ref=orpc" target="_blank" rel="noopener" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&v=4" width="119" alt="Alex"/><br />Alex</a></td> | ||
| </tr> | ||
| </table> | ||
| ### Past Sponsors | ||
| <p> | ||
| <a href="https://github.com/MrMaxie?ref=orpc" target="_blank" rel="noopener" title="Maxie"><img src="https://avatars.githubusercontent.com/u/3857836?u=5e6b57973d4385d655663ffdd836e487856f2984&v=4" width="32" height="32" alt="Maxie" /></a> | ||
| <a href="https://github.com/Stijn-Timmer?ref=orpc" target="_blank" rel="noopener" title="Stijn Timmer"><img src="https://avatars.githubusercontent.com/u/100147665?u=106b2c18e9c98a61861b4ee7fc100f5b9906a6c9&v=4" width="32" height="32" alt="Stijn Timmer" /></a> | ||
| <a href="https://github.com/u1-liquid?ref=orpc" target="_blank" rel="noopener" title="γγγγγ¨γΌγ«γ "><img src="https://avatars.githubusercontent.com/u/17376330?u=de3353804be889f009f7e0a1582daf04d0ab292d&v=4" width="32" height="32" alt="γγγγγ¨γΌγ«γ " /></a> | ||
| <a href="https://github.com/zuplo?ref=orpc" target="_blank" rel="noopener" title="Zuplo"><img src="https://avatars.githubusercontent.com/u/85497839?v=4" width="32" height="32" alt="Zuplo" /></a> | ||
| <a href="https://github.com/motopods?ref=orpc" target="_blank" rel="noopener" title="motopods"><img src="https://avatars.githubusercontent.com/u/58200641?u=18833983d65b481ae90a4adec2373064ec58bcf3&v=4" width="32" height="32" alt="motopods" /></a> | ||
| <a href="https://github.com/franciscohermida?ref=orpc" target="_blank" rel="noopener" title="Francisco Hermida"><img src="https://avatars.githubusercontent.com/u/483242?u=bbcbc80eb9d8781ff401f7dafc3b59cd7bea0561&v=4" width="32" height="32" alt="Francisco Hermida" /></a> | ||
| <a href="https://github.com/theoludwig?ref=orpc" target="_blank" rel="noopener" title="ThΓ©o LUDWIG"><img src="https://avatars.githubusercontent.com/u/25207499?u=a6a9653725a2f574c07893748806668e0598cdbe&v=4" width="32" height="32" alt="ThΓ©o LUDWIG" /></a> | ||
| <a href="https://github.com/abhay-ramesh?ref=orpc" target="_blank" rel="noopener" title="Abhay Ramesh"><img src="https://avatars.githubusercontent.com/u/66196314?u=c5c2b0327b26606c2efcfaf17046ab18c3d25c57&v=4" width="32" height="32" alt="Abhay Ramesh" /></a> | ||
| <a href="https://github.com/shr-ink?ref=orpc" target="_blank" rel="noopener" title="shr.ink oΓΌ"><img src="https://avatars.githubusercontent.com/u/139700438?v=4" width="32" height="32" alt="shr.ink oΓΌ" /></a> | ||
| <a href="https://github.com/johngerome?ref=orpc" target="_blank" rel="noopener" title="0x4e32"><img src="https://avatars.githubusercontent.com/u/2002000?u=24e8dd943cfc862aa284d858a023532c75071ade&v=4" width="32" height="32" alt="0x4e32" /></a> | ||
| <a href="https://github.com/yzuyr?ref=orpc" target="_blank" rel="noopener" title="Ryuz"><img src="https://avatars.githubusercontent.com/u/196539378?u=d38374588d219b6748b16406982f6559411466d4&v=4" width="32" height="32" alt="Ryuz" /></a> | ||
| <a href="https://github.com/YiCChi?ref=orpc" target="_blank" rel="noopener" title="yicchi"><img src="https://avatars.githubusercontent.com/u/86967274?u=6c2756f09fe15dd94d572f560e979cd157982852&v=4" width="32" height="32" alt="yicchi" /></a> | ||
| <a href="https://github.com/cloudycotton?ref=orpc" target="_blank" rel="noopener" title="Saksham"><img src="https://avatars.githubusercontent.com/u/168998965?u=9b9634a5aed66a51c1b880663272725b00b92b14&v=4" width="32" height="32" alt="Saksham" /></a> | ||
| <a href="https://github.com/hrynevychroman?ref=orpc" target="_blank" rel="noopener" title="Roman Hrynevych"><img src="https://avatars.githubusercontent.com/u/82209198?u=1a1d111ab3d589855b9cc8a7fefb1b5c6a4fbbaf&v=4" width="32" height="32" alt="Roman Hrynevych" /></a> | ||
| <a href="https://github.com/rokitgg?ref=orpc" target="_blank" rel="noopener" title="rokitg"><img src="https://avatars.githubusercontent.com/u/125133357?u=06c74aefaa2236b06a2e5fba5a5c612339f45912&v=4" width="32" height="32" alt="rokitg" /></a> | ||
| <a href="https://github.com/omarkhatibgg?ref=orpc" target="_blank" rel="noopener" title="Omar Khatib"><img src="https://avatars.githubusercontent.com/u/9054278?u=afbba7331b85c51b8eee4130f5fd31b1017dc919&v=4" width="32" height="32" alt="Omar Khatib" /></a> | ||
| <a href="https://github.com/YuSabo90002?ref=orpc" target="_blank" rel="noopener" title="Yu-Sabo"><img src="https://avatars.githubusercontent.com/u/13120582?v=4" width="32" height="32" alt="Yu-Sabo" /></a> | ||
| <a href="https://github.com/bapspatil?ref=orpc" target="_blank" rel="noopener" title="Bapusaheb Patil"><img src="https://avatars.githubusercontent.com/u/16699418?v=4" width="32" height="32" alt="Bapusaheb Patil" /></a> | ||
| <a href="https://github.com/ripgrim?ref=orpc" target="_blank" rel="noopener" title="grim"><img src="https://avatars.githubusercontent.com/u/75869731?u=b17c42ec2309552fdb822a86b25a2f99146a4d72&v=4" width="32" height="32" alt="grim" /></a> | ||
| <a href="https://github.com/nelsonlaidev?ref=orpc" target="_blank" rel="noopener" title="Nelson Lai"><img src="https://avatars.githubusercontent.com/u/75498339?u=2fc0e0b95dd184c5ffb744df977cb15a18b60672&v=4" width="32" height="32" alt="Nelson Lai" /></a> | ||
| <a href="https://github.com/nguyenlc1993?ref=orpc" target="_blank" rel="noopener" title="LΓͺ Cao NguyΓͺn"><img src="https://avatars.githubusercontent.com/u/13871971?u=83c8b69d9e35b589c4e1f066cc113b1d9461386f&v=4" width="32" height="32" alt="LΓͺ Cao NguyΓͺn" /></a> | ||
| <a href="https://github.com/wobsoriano?ref=orpc" target="_blank" rel="noopener" title="Robert Soriano"><img src="https://avatars.githubusercontent.com/u/13049130?u=6d72104182e7c9ed25934815313fb69107332111&v=4" width="32" height="32" alt="Robert Soriano" /></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> | ||
| <a href="https://github.com/FabworksHQ?ref=orpc" target="_blank" rel="noopener" title="Fabworks"><img src="https://avatars.githubusercontent.com/u/160179500?v=4" width="32" height="32" alt="Fabworks" /></a> | ||
| <a href="https://github.com/NovakAnton?ref=orpc" target="_blank" rel="noopener" title="Novak Antonijevic"><img src="https://avatars.githubusercontent.com/u/157126729?u=ae49fa22292d55c0434ff0ca008206155b18663b&v=4" width="32" height="32" alt="Novak Antonijevic" /></a> | ||
| <a href="https://github.com/laduniestu?ref=orpc" target="_blank" rel="noopener" title="Laduni Estu Syalwa"><img src="https://avatars.githubusercontent.com/u/44757637?u=a2fc1ea8f7d827a96721176f79d30592d1c48059&v=4" width="32" height="32" alt="Laduni Estu Syalwa" /></a> | ||
| <a href="https://github.com/illarionvk?ref=orpc" target="_blank" rel="noopener" title="Illarion Koperski"><img src="https://avatars.githubusercontent.com/u/5012724?u=7cfa13652f7ac5fb3c56d880e3eb3fbe40c3ea34&v=4" width="32" height="32" alt="Illarion Koperski" /></a> | ||
| <a href="https://github.com/Scrumplex?ref=orpc" target="_blank" rel="noopener" title="Sefa Eyeoglu"><img src="https://avatars.githubusercontent.com/u/11587657?u=ab503582165c0bbff0cca47ce31c9450bb1553c9&v=4" width="32" height="32" alt="Sefa Eyeoglu" /></a> | ||
| </p> | ||
@@ -90,2 +192,2 @@ | ||
| Distributed under the MIT License. See [LICENSE](https://github.com/unnoq/orpc/blob/main/LICENSE) for more information. | ||
| Distributed under the MIT License. See [LICENSE](https://github.com/middleapi/orpc/blob/main/LICENSE) for more information. |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
74939
173.7%1033
151.95%186
121.43%3
50%4
Infinity%1
Infinity%+ Added
+ Added
+ Added
- Removed
Updated
Updated