@orpc/shared
Advanced tools
+61
-8
@@ -105,2 +105,26 @@ import { Arrayable, Promisable } from 'type-fest'; | ||
| }, 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; | ||
@@ -151,4 +175,4 @@ | ||
| mapResult?: (result: IteratorResult<TYield, TReturn>) => Promisable<IteratorResult<TMappedYield, TMappedReturn>>; | ||
| mapError?: (error: unknown) => Promisable<unknown>; | ||
| onError?: (error: unknown) => Promisable<void>; | ||
| mapError?: (error: ThrowableError) => Promisable<ThrowableError>; | ||
| onError?: (error: ThrowableError) => Promisable<void>; | ||
| /** | ||
@@ -162,2 +186,31 @@ * Execute after the stream finishes or is cancelled. | ||
| declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[]; | ||
| interface ConsumeAsyncIteratorOptions<T, TReturn, TError> { | ||
| /** | ||
| * Called on each event | ||
| */ | ||
| 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; | ||
| } | ||
| /** | ||
| * 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>; | ||
@@ -281,4 +334,4 @@ type Segment = string | number; | ||
| mapResult?: (result: ReadableStreamReadResult<T>) => Promisable<ReadableStreamReadResult<TMapped>>; | ||
| mapError?: (error: unknown) => Promisable<unknown>; | ||
| onError?: (error: unknown) => Promisable<void>; | ||
| mapError?: (error: ThrowableError) => Promisable<ThrowableError>; | ||
| onError?: (error: ThrowableError) => Promisable<void>; | ||
| /** | ||
@@ -292,5 +345,5 @@ * Guaranteed to execute exactly once after the stream finishes or is cancelled. | ||
| /** | ||
| * Converts a `ReadableStream` into an `AsyncIteratorClass`. | ||
| * Converts a {@link ReadableStream} into an {@link AsyncIteratorClass}. | ||
| */ | ||
| declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>, { signal }?: { | ||
| declare function streamToAsyncIteratorObject<T>(stream: ReadableStream<T>, { signal }?: { | ||
| signal?: undefined | AbortSignal; | ||
@@ -310,3 +363,3 @@ }): AsyncIteratorClass<T>; | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onError, onFinish, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorClass, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream }; | ||
| export type { AnyFunction, AsyncIdQueueCloseOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OnFinishState, OpenTelemetryConfig, OrderablePlugin, PromiseWithError, Public, ReadableStreamReadResult, Registry, RunWithSpanOptions, Segment, StartSpanOptions, ThrowableError, Value, WrapAsyncIteratorOptions, WrapReadableStreamOptions }; | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, 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 }; |
+61
-8
@@ -105,2 +105,26 @@ import { Arrayable, Promisable } from 'type-fest'; | ||
| }, 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; | ||
@@ -151,4 +175,4 @@ | ||
| mapResult?: (result: IteratorResult<TYield, TReturn>) => Promisable<IteratorResult<TMappedYield, TMappedReturn>>; | ||
| mapError?: (error: unknown) => Promisable<unknown>; | ||
| onError?: (error: unknown) => Promisable<void>; | ||
| mapError?: (error: ThrowableError) => Promisable<ThrowableError>; | ||
| onError?: (error: ThrowableError) => Promisable<void>; | ||
| /** | ||
@@ -162,2 +186,31 @@ * Execute after the stream finishes or is cancelled. | ||
| declare function replicateAsyncIterator<T, TReturn, TNext>(source: AsyncIterator<T, TReturn, TNext>, count: number): (AsyncIteratorClass<T, TReturn, TNext>)[]; | ||
| interface ConsumeAsyncIteratorOptions<T, TReturn, TError> { | ||
| /** | ||
| * Called on each event | ||
| */ | ||
| 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; | ||
| } | ||
| /** | ||
| * 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>; | ||
@@ -281,4 +334,4 @@ type Segment = string | number; | ||
| mapResult?: (result: ReadableStreamReadResult<T>) => Promisable<ReadableStreamReadResult<TMapped>>; | ||
| mapError?: (error: unknown) => Promisable<unknown>; | ||
| onError?: (error: unknown) => Promisable<void>; | ||
| mapError?: (error: ThrowableError) => Promisable<ThrowableError>; | ||
| onError?: (error: ThrowableError) => Promisable<void>; | ||
| /** | ||
@@ -292,5 +345,5 @@ * Guaranteed to execute exactly once after the stream finishes or is cancelled. | ||
| /** | ||
| * Converts a `ReadableStream` into an `AsyncIteratorClass`. | ||
| * Converts a {@link ReadableStream} into an {@link AsyncIteratorClass}. | ||
| */ | ||
| declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>, { signal }?: { | ||
| declare function streamToAsyncIteratorObject<T>(stream: ReadableStream<T>, { signal }?: { | ||
| signal?: undefined | AbortSignal; | ||
@@ -310,3 +363,3 @@ }): AsyncIteratorClass<T>; | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onError, onFinish, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorClass, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream }; | ||
| export type { AnyFunction, AsyncIdQueueCloseOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OnFinishState, OpenTelemetryConfig, OrderablePlugin, PromiseWithError, Public, ReadableStreamReadResult, Registry, RunWithSpanOptions, Segment, StartSpanOptions, ThrowableError, Value, WrapAsyncIteratorOptions, WrapReadableStreamOptions }; | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, 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 }; |
+250
-199
@@ -1,2 +0,2 @@ | ||
| import { AbortError, AsyncIteratorClass, isTypescriptObject, getOrBind } from '@standardserver/shared'; | ||
| import { AbortError, AsyncIteratorClass, getOrBind, isTypescriptObject, isAsyncIteratorObject } from '@standardserver/shared'; | ||
| export { AbortError, AsyncIteratorClass, SequentialIdGenerator, getOrBind, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray } from '@standardserver/shared'; | ||
@@ -187,57 +187,2 @@ | ||
| 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 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); | ||
| } | ||
| const SPAN_ERROR_STATUS = 2; | ||
@@ -515,3 +460,52 @@ const OPENTELEMETRY_CONFIG_SYMBOL = Symbol.for("ORPC_OPENTELEMETRY_CONFIG"); | ||
| } | ||
| 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; | ||
| } | ||
| options.onEvent(value); | ||
| } | ||
| } catch (error) { | ||
| onFinishState = [error, void 0, false]; | ||
| if (!options.onError && !options.onFinish) { | ||
| throw error; | ||
| } | ||
| options.onError?.(error); | ||
| } finally { | ||
| options.onFinish?.(onFinishState); | ||
| } | ||
| })(); | ||
| return async () => { | ||
| await (await iterator)?.return?.(); | ||
| }; | ||
| } | ||
| function value(value2, ...args) { | ||
| if (typeof value2 === "function") { | ||
| return value2(...args); | ||
| } | ||
| return value2; | ||
| } | ||
| 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 findDeepMatches(check, payload, segments = [], maps = [], values = []) { | ||
@@ -628,80 +622,2 @@ if (check(payload)) { | ||
| 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 promiseWithResolvers() { | ||
@@ -716,65 +632,2 @@ const result = {}; | ||
| function value(value2, ...args) { | ||
| if (typeof value2 === "function") { | ||
| return value2(...args); | ||
| } | ||
| return value2; | ||
| } | ||
| 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 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; | ||
| } | ||
| 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; | ||
| }); | ||
| try { | ||
| fn().then(resolve, reject); | ||
| return await promise; | ||
| } finally { | ||
| if (abortListener) { | ||
| signal.removeEventListener("abort", abortListener); | ||
| } | ||
| } | ||
| } | ||
| function replicateReadableStream(stream, count) { | ||
@@ -850,3 +703,3 @@ if (count <= 0) { | ||
| } | ||
| function streamToAsyncIteratorClass(stream, { signal } = {}) { | ||
| function streamToAsyncIteratorObject(stream, { signal } = {}) { | ||
| const reader = stream.getReader(); | ||
@@ -917,2 +770,200 @@ let cancelledBySignal = false; | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, isDeepEqual, isPlainObject, isPropertyKey, loadBytes, matchesHttpPath, matchesHttpPathPrefix, mergeHttpPath, normalizeHttpPath, omit, onError, onFinish, onStart, onSuccess, once, override, pathToHttpPath, promiseWithResolvers, recordSpanError, replicateAsyncIterator, replicateReadableStream, resolveMaybeOptionalOptions, runInSpanContext, runWithSignal, runWithSpan, set, setOpenTelemetryConfig, setSpanAttributeIfDefined, sortPlugins, splitInHalf, startSpan, streamToAsyncIteratorClass, toOtelException, toSpanAttributeValue, toStringOrBytes, traceAsyncIterator, traceReadableStream, tryDecodeURIComponent, tryOrUndefined, value, wrapAsyncIterator, wrapReadableStream }; | ||
| 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; | ||
| } | ||
| 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; | ||
| }); | ||
| try { | ||
| fn().then(resolve, reject); | ||
| return await promise; | ||
| } finally { | ||
| if (abortListener) { | ||
| signal.removeEventListener("abort", abortListener); | ||
| } | ||
| } | ||
| } | ||
| export { AsyncIdQueue, NullProtoObj, ORPC_NAME, allAbortSignal, asyncIteratorToStream, asyncIteratorToUnproxiedDataStream, bindMethods, clone, compareSequentialIds, consumeAsyncIterator, defer, findDeepMatches, get, getConstructor, getOpenTelemetryConfig, intercept, isAbortError, 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 }; |
+2
-2
| { | ||
| "name": "@orpc/shared", | ||
| "type": "module", | ||
| "version": "2.0.0-beta.14", | ||
| "version": "2.0.0-beta.15", | ||
| "license": "MIT", | ||
@@ -36,3 +36,3 @@ "homepage": "https://orpc.dev", | ||
| "dependencies": { | ||
| "@standardserver/shared": "^0.0.25", | ||
| "@standardserver/shared": "^0.0.32", | ||
| "radash": "^12.1.1", | ||
@@ -39,0 +39,0 @@ "type-fest": "^5.3.1" |
+1
-1
@@ -110,3 +110,2 @@ <h1 align="center">oRPC - Typesafe APIs Made Simple 🪄</h1> | ||
| <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/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/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> | ||
@@ -172,2 +171,3 @@ <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&v=4" width="139" alt="shota"/><br />shota</a></td> | ||
| <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/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="32" height="32" alt="Peter Adam" /></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> | ||
@@ -174,0 +174,0 @@ <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> |
87604
9.11%1288
8.97%+ Added
- Removed