@orpc/shared 0.0.0-next.f9e0a4c → 0.0.0-next.f9e5dec

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,6 +17,9 @@
17
17
  <a href="https://discord.gg/TXEbwRBvQn">
18
18
  <img alt="Discord" src="https://img.shields.io/discord/1308966753044398161?color=7389D8&label&logo=discord&logoColor=ffffff" />
19
19
  </a>
20
+ <a href="https://deepwiki.com/unnoq/orpc">
21
+ <img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki">
22
+ </a>
20
23
  </div>
21
24
 
22
25
  <h3 align="center">Typesafe APIs Made Simple 🪄</h3>
@@ -31,7 +34,7 @@
31
34
  - **📘 First-Class OpenAPI**: Built-in support that fully adheres to the OpenAPI standard.
32
35
  - **📝 Contract-First Development**: Optionally define your API contract before implementation.
33
36
  - **🔍 First-Class OpenTelemetry**: Seamlessly integrate with OpenTelemetry for observability.
34
- - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), Pinia Colada, and more.
37
+ - **⚙️ Framework Integrations**: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, Pinia Colada, and more.
35
38
  - **🚀 Server Actions**: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
36
39
  - **🔠 Standard Schema Support**: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
37
40
  - **🗃️ Native Types**: Supports native types like Date, File, Blob, BigInt, URL, and more.
@@ -54,6 +57,7 @@ You can find the full documentation [here](https://orpc.unnoq.com).
54
57
  - [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Deeply integrate oRPC with [NestJS](https://nestjs.com/).
55
58
  - [@orpc/react](https://www.npmjs.com/package/@orpc/react): Utilities for integrating oRPC with React and React Server Actions.
56
59
  - [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): [TanStack Query](https://tanstack.com/query/latest) integration.
60
+ - [@orpc/experimental-react-swr](https://www.npmjs.com/package/@orpc/experimental-react-swr): [SWR](https://swr.vercel.app/) integration.
57
61
  - [@orpc/vue-colada](https://www.npmjs.com/package/@orpc/vue-colada): Integration with [Pinia Colada](https://pinia-colada.esm.dev/).
58
62
  - [@orpc/hey-api](https://www.npmjs.com/package/@orpc/hey-api): [Hey API](https://heyapi.dev/) integration.
59
63
  - [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): More schemas that [Zod](https://zod.dev/) doesn't support yet.
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Promisable } from 'type-fest';
2
2
  export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest';
3
3
  import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api';
4
- export { group, guard, mapEntries, mapValues, omit } from 'radash';
4
+ export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';
5
5
 
6
6
  type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions];
7
7
  declare function resolveMaybeOptionalOptions<T>(rest: MaybeOptionalOptions<T>): T;
@@ -30,7 +30,7 @@ type OmitChainMethodDeep<T extends object, K extends keyof any> = {
30
30
 
31
31
  declare const ORPC_NAME = "orpc";
32
32
  declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
33
- declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e0a4c";
33
+ declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e5dec";
34
34
 
35
35
  /**
36
36
  * Error thrown when an operation is aborted.
@@ -60,7 +60,7 @@ interface EventPublisherSubscribeIteratorOptions extends EventPublisherOptions {
60
60
  /**
61
61
  * Aborts the async iterator. Throws if aborted before or during pulling.
62
62
  */
63
- signal?: AbortSignal;
63
+ signal?: AbortSignal | undefined;
64
64
  }
65
65
  declare class EventPublisher<T extends Record<PropertyKey, any>> {
66
66
  #private;
@@ -103,6 +103,14 @@ declare class SequentialIdGenerator {
103
103
  private index;
104
104
  generate(): string;
105
105
  }
106
+ /**
107
+ * Compares two sequential IDs.
108
+ * Returns:
109
+ * - negative if `a` < `b`
110
+ * - positive if `a` > `b`
111
+ * - 0 if equal
112
+ */
113
+ declare function compareSequentialIds(a: string, b: string): number;
106
114
 
107
115
  type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
108
116
  type IntersectPick<T, U> = Pick<T, keyof T & keyof U>;
@@ -121,6 +129,7 @@ interface Registry {
121
129
  type ThrowableError = Registry extends {
122
130
  throwableError: infer T;
123
131
  } ? T : Error;
132
+ type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never;
124
133
 
125
134
  type InterceptableOptions = Record<string, any>;
126
135
  type InterceptorOptions<TOptions extends InterceptableOptions, TResult> = Omit<TOptions, 'next'> & {
@@ -262,6 +271,11 @@ declare function findDeepMatches(check: (value: unknown) => boolean, payload: un
262
271
  maps: Segment[][];
263
272
  values: unknown[];
264
273
  };
274
+ /**
275
+ * Get constructor of the value
276
+ *
277
+ */
278
+ declare function getConstructor(value: unknown): Function | null | undefined;
265
279
  /**
266
280
  * Check if the value is an object even it created by `Object.create(null)` or more tricky way.
267
281
  */
@@ -271,21 +285,47 @@ declare function isObject(value: unknown): value is Record<PropertyKey, unknown>
271
285
  */
272
286
  declare function isTypescriptObject(value: unknown): value is object & Record<PropertyKey, unknown>;
273
287
  declare function clone<T>(value: T): T;
274
- declare function get(object: unknown, path: readonly string[]): unknown;
288
+ declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
275
289
  declare function isPropertyKey(value: unknown): value is PropertyKey;
276
290
  declare const NullProtoObj: ({
277
291
  new <T extends Record<PropertyKey, unknown>>(): T;
278
292
  });
279
293
 
294
+ type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
295
+ declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
296
+ /**
297
+ * Returns the value if it is defined, otherwise returns the fallback
298
+ */
299
+ declare function fallback<T>(value: T | undefined, fallback: T): T;
300
+
301
+ /**
302
+ * Prevents objects from being awaitable by intercepting the `then` method
303
+ * when called by the native await mechanism. This is useful for preventing
304
+ * accidental awaiting of objects that aren't meant to be promises.
305
+ */
306
+ declare function preventNativeAwait<T extends object>(target: T): T;
307
+ /**
308
+ * Create a proxy that overlays one object (`overlay`) on top of another (`target`).
309
+ *
310
+ * - Properties from `overlay` take precedence.
311
+ * - Properties not in `overlay` fall back to `target`.
312
+ * - Methods from either object are bound to `overlay` so `this` is consistent.
313
+ *
314
+ * Useful when you want to override or extend behavior without fully copying/merging objects.
315
+ */
316
+ declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;
317
+
280
318
  interface AsyncIdQueueCloseOptions {
281
319
  id?: string;
282
320
  reason?: unknown;
283
321
  }
284
322
  declare class AsyncIdQueue<T> {
285
323
  private readonly openIds;
286
- private readonly items;
287
- private readonly pendingPulls;
324
+ private readonly queues;
325
+ private readonly waiters;
288
326
  get length(): number;
327
+ get waiterIds(): string[];
328
+ hasBufferedItems(id: string): boolean;
289
329
  open(id: string): void;
290
330
  isOpen(id: string): boolean;
291
331
  push(id: string, item: T): void;
@@ -294,13 +334,21 @@ declare class AsyncIdQueue<T> {
294
334
  assertOpen(id: string): void;
295
335
  }
296
336
 
337
+ /**
338
+ * Converts a `ReadableStream` into an `AsyncIteratorClass`.
339
+ */
297
340
  declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>;
341
+ /**
342
+ * Converts an `AsyncIterator` into a `ReadableStream`.
343
+ */
298
344
  declare function asyncIteratorToStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>;
345
+ /**
346
+ * Converts an `AsyncIterator` into a `ReadableStream`, ensuring that
347
+ * all emitted object values are *unproxied* before enqueuing.
348
+ */
349
+ declare function asyncIteratorToUnproxiedDataStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>;
299
350
 
300
351
  declare function tryDecodeURIComponent(value: string): string;
301
352
 
302
- type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
303
- declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
304
-
305
- export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorWithSpan, clone, defer, findDeepMatches, get, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
306
- export type { AnyFunction, AsyncIdQueueCloseOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClassNextFn, AsyncIteratorWithSpanOptions, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, OtelConfig, PromiseWithError, Registry, RunWithSpanOptions, Segment, SetOptional, SetSpanErrorOptions, ThrowableError, Value };
353
+ 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 };
354
+ 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 };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Promisable } from 'type-fest';
2
2
  export { IsEqual, IsNever, JsonValue, PartialDeep, Promisable } from 'type-fest';
3
3
  import { Tracer, TraceAPI, ContextAPI, PropagationAPI, SpanOptions, Context, Span, AttributeValue, Exception } from '@opentelemetry/api';
4
- export { group, guard, mapEntries, mapValues, omit } from 'radash';
4
+ export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';
5
5
 
6
6
  type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions];
7
7
  declare function resolveMaybeOptionalOptions<T>(rest: MaybeOptionalOptions<T>): T;
@@ -30,7 +30,7 @@ type OmitChainMethodDeep<T extends object, K extends keyof any> = {
30
30
 
31
31
  declare const ORPC_NAME = "orpc";
32
32
  declare const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
33
- declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e0a4c";
33
+ declare const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e5dec";
34
34
 
35
35
  /**
36
36
  * Error thrown when an operation is aborted.
@@ -60,7 +60,7 @@ interface EventPublisherSubscribeIteratorOptions extends EventPublisherOptions {
60
60
  /**
61
61
  * Aborts the async iterator. Throws if aborted before or during pulling.
62
62
  */
63
- signal?: AbortSignal;
63
+ signal?: AbortSignal | undefined;
64
64
  }
65
65
  declare class EventPublisher<T extends Record<PropertyKey, any>> {
66
66
  #private;
@@ -103,6 +103,14 @@ declare class SequentialIdGenerator {
103
103
  private index;
104
104
  generate(): string;
105
105
  }
106
+ /**
107
+ * Compares two sequential IDs.
108
+ * Returns:
109
+ * - negative if `a` < `b`
110
+ * - positive if `a` > `b`
111
+ * - 0 if equal
112
+ */
113
+ declare function compareSequentialIds(a: string, b: string): number;
106
114
 
107
115
  type SetOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
108
116
  type IntersectPick<T, U> = Pick<T, keyof T & keyof U>;
@@ -121,6 +129,7 @@ interface Registry {
121
129
  type ThrowableError = Registry extends {
122
130
  throwableError: infer T;
123
131
  } ? T : Error;
132
+ type InferAsyncIterableYield<T> = T extends AsyncIterable<infer U> ? U : never;
124
133
 
125
134
  type InterceptableOptions = Record<string, any>;
126
135
  type InterceptorOptions<TOptions extends InterceptableOptions, TResult> = Omit<TOptions, 'next'> & {
@@ -262,6 +271,11 @@ declare function findDeepMatches(check: (value: unknown) => boolean, payload: un
262
271
  maps: Segment[][];
263
272
  values: unknown[];
264
273
  };
274
+ /**
275
+ * Get constructor of the value
276
+ *
277
+ */
278
+ declare function getConstructor(value: unknown): Function | null | undefined;
265
279
  /**
266
280
  * Check if the value is an object even it created by `Object.create(null)` or more tricky way.
267
281
  */
@@ -271,21 +285,47 @@ declare function isObject(value: unknown): value is Record<PropertyKey, unknown>
271
285
  */
272
286
  declare function isTypescriptObject(value: unknown): value is object & Record<PropertyKey, unknown>;
273
287
  declare function clone<T>(value: T): T;
274
- declare function get(object: unknown, path: readonly string[]): unknown;
288
+ declare function get(object: unknown, path: readonly PropertyKey[]): unknown;
275
289
  declare function isPropertyKey(value: unknown): value is PropertyKey;
276
290
  declare const NullProtoObj: ({
277
291
  new <T extends Record<PropertyKey, unknown>>(): T;
278
292
  });
279
293
 
294
+ type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
295
+ declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
296
+ /**
297
+ * Returns the value if it is defined, otherwise returns the fallback
298
+ */
299
+ declare function fallback<T>(value: T | undefined, fallback: T): T;
300
+
301
+ /**
302
+ * Prevents objects from being awaitable by intercepting the `then` method
303
+ * when called by the native await mechanism. This is useful for preventing
304
+ * accidental awaiting of objects that aren't meant to be promises.
305
+ */
306
+ declare function preventNativeAwait<T extends object>(target: T): T;
307
+ /**
308
+ * Create a proxy that overlays one object (`overlay`) on top of another (`target`).
309
+ *
310
+ * - Properties from `overlay` take precedence.
311
+ * - Properties not in `overlay` fall back to `target`.
312
+ * - Methods from either object are bound to `overlay` so `this` is consistent.
313
+ *
314
+ * Useful when you want to override or extend behavior without fully copying/merging objects.
315
+ */
316
+ declare function overlayProxy<T extends object, U extends object>(target: Value<T>, partial: U): U & Omit<T, keyof U>;
317
+
280
318
  interface AsyncIdQueueCloseOptions {
281
319
  id?: string;
282
320
  reason?: unknown;
283
321
  }
284
322
  declare class AsyncIdQueue<T> {
285
323
  private readonly openIds;
286
- private readonly items;
287
- private readonly pendingPulls;
324
+ private readonly queues;
325
+ private readonly waiters;
288
326
  get length(): number;
327
+ get waiterIds(): string[];
328
+ hasBufferedItems(id: string): boolean;
289
329
  open(id: string): void;
290
330
  isOpen(id: string): boolean;
291
331
  push(id: string, item: T): void;
@@ -294,13 +334,21 @@ declare class AsyncIdQueue<T> {
294
334
  assertOpen(id: string): void;
295
335
  }
296
336
 
337
+ /**
338
+ * Converts a `ReadableStream` into an `AsyncIteratorClass`.
339
+ */
297
340
  declare function streamToAsyncIteratorClass<T>(stream: ReadableStream<T>): AsyncIteratorClass<T>;
341
+ /**
342
+ * Converts an `AsyncIterator` into a `ReadableStream`.
343
+ */
298
344
  declare function asyncIteratorToStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>;
345
+ /**
346
+ * Converts an `AsyncIterator` into a `ReadableStream`, ensuring that
347
+ * all emitted object values are *unproxied* before enqueuing.
348
+ */
349
+ declare function asyncIteratorToUnproxiedDataStream<T>(iterator: AsyncIterator<T>): ReadableStream<T>;
299
350
 
300
351
  declare function tryDecodeURIComponent(value: string): string;
301
352
 
302
- type Value<T, TArgs extends any[] = []> = T | ((...args: TArgs) => T);
303
- declare function value<T, TArgs extends any[]>(value: Value<T, TArgs>, ...args: NoInfer<TArgs>): T extends Value<infer U, any> ? U : never;
304
-
305
- export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorWithSpan, clone, defer, findDeepMatches, get, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
306
- export type { AnyFunction, AsyncIdQueueCloseOptions, AsyncIteratorClassCleanupFn, AsyncIteratorClassNextFn, AsyncIteratorWithSpanOptions, EventPublisherOptions, EventPublisherSubscribeIteratorOptions, InterceptableOptions, Interceptor, InterceptorOptions, IntersectPick, MaybeOptionalOptions, OmitChainMethodDeep, OnFinishState, OtelConfig, PromiseWithError, Registry, RunWithSpanOptions, Segment, SetOptional, SetSpanErrorOptions, ThrowableError, Value };
353
+ 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 };
354
+ 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 };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { group, guard, mapEntries, mapValues, omit } from 'radash';
1
+ export { group, guard, mapEntries, mapValues, omit, retry, sleep } from 'radash';
2
2
 
3
3
  function resolveMaybeOptionalOptions(rest) {
4
4
  return rest[0] ?? {};
@@ -21,7 +21,7 @@ function readAsBuffer(source) {
21
21
 
22
22
  const ORPC_NAME = "orpc";
23
23
  const ORPC_SHARED_PACKAGE_NAME = "@orpc/shared";
24
- const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e0a4c";
24
+ const ORPC_SHARED_PACKAGE_VERSION = "0.0.0-next.f9e5dec";
25
25
 
26
26
  class AbortError extends Error {
27
27
  constructor(...rest) {
@@ -153,11 +153,17 @@ async function runInSpanContext(span, fn) {
153
153
 
154
154
  class AsyncIdQueue {
155
155
  openIds = /* @__PURE__ */ new Set();
156
- items = /* @__PURE__ */ new Map();
157
- pendingPulls = /* @__PURE__ */ new Map();
156
+ queues = /* @__PURE__ */ new Map();
157
+ waiters = /* @__PURE__ */ new Map();
158
158
  get length() {
159
159
  return this.openIds.size;
160
160
  }
161
+ get waiterIds() {
162
+ return Array.from(this.waiters.keys());
163
+ }
164
+ hasBufferedItems(id) {
165
+ return Boolean(this.queues.get(id)?.length);
166
+ }
161
167
  open(id) {
162
168
  this.openIds.add(id);
163
169
  }
@@ -166,59 +172,57 @@ class AsyncIdQueue {
166
172
  }
167
173
  push(id, item) {
168
174
  this.assertOpen(id);
169
- const pending = this.pendingPulls.get(id);
175
+ const pending = this.waiters.get(id);
170
176
  if (pending?.length) {
171
177
  pending.shift()[0](item);
172
178
  if (pending.length === 0) {
173
- this.pendingPulls.delete(id);
179
+ this.waiters.delete(id);
174
180
  }
175
181
  } else {
176
- const items = this.items.get(id);
182
+ const items = this.queues.get(id);
177
183
  if (items) {
178
184
  items.push(item);
179
185
  } else {
180
- this.items.set(id, [item]);
186
+ this.queues.set(id, [item]);
181
187
  }
182
188
  }
183
189
  }
184
190
  async pull(id) {
185
191
  this.assertOpen(id);
186
- const items = this.items.get(id);
192
+ const items = this.queues.get(id);
187
193
  if (items?.length) {
188
194
  const item = items.shift();
189
195
  if (items.length === 0) {
190
- this.items.delete(id);
196
+ this.queues.delete(id);
191
197
  }
192
198
  return item;
193
199
  }
194
200
  return new Promise((resolve, reject) => {
195
- const waitingPulls = this.pendingPulls.get(id);
201
+ const waitingPulls = this.waiters.get(id);
196
202
  const pending = [resolve, reject];
197
203
  if (waitingPulls) {
198
204
  waitingPulls.push(pending);
199
205
  } else {
200
- this.pendingPulls.set(id, [pending]);
206
+ this.waiters.set(id, [pending]);
201
207
  }
202
208
  });
203
209
  }
204
210
  close({ id, reason } = {}) {
205
211
  if (id === void 0) {
206
- this.pendingPulls.forEach((pendingPulls, id2) => {
207
- pendingPulls.forEach(([, reject]) => {
208
- reject(reason ?? new Error(`[AsyncIdQueue] Queue[${id2}] was closed or aborted while waiting for pulling.`));
209
- });
212
+ this.waiters.forEach((pendingPulls, id2) => {
213
+ const error2 = reason ?? new AbortError(`[AsyncIdQueue] Queue[${id2}] was closed or aborted while waiting for pulling.`);
214
+ pendingPulls.forEach(([, reject]) => reject(error2));
210
215
  });
211
- this.pendingPulls.clear();
216
+ this.waiters.clear();
212
217
  this.openIds.clear();
213
- this.items.clear();
218
+ this.queues.clear();
214
219
  return;
215
220
  }
216
- this.pendingPulls.get(id)?.forEach(([, reject]) => {
217
- reject(reason ?? new Error(`[AsyncIdQueue] Queue[${id}] was closed or aborted while waiting for pulling.`));
218
- });
219
- this.pendingPulls.delete(id);
221
+ const error = reason ?? new AbortError(`[AsyncIdQueue] Queue[${id}] was closed or aborted while waiting for pulling.`);
222
+ this.waiters.get(id)?.forEach(([, reject]) => reject(error));
223
+ this.waiters.delete(id);
220
224
  this.openIds.delete(id);
221
- this.items.delete(id);
225
+ this.queues.delete(id);
222
226
  }
223
227
  assertOpen(id) {
224
228
  if (!this.isOpen(id)) {
@@ -298,49 +302,51 @@ class AsyncIteratorClass {
298
302
  }
299
303
  function replicateAsyncIterator(source, count) {
300
304
  const queue = new AsyncIdQueue();
301
- const replicated = [];
302
- let error;
305
+ const ids = Array.from({ length: count }, (_, i) => i.toString());
306
+ let isSourceFinished = false;
303
307
  const start = once(async () => {
304
308
  try {
305
309
  while (true) {
306
310
  const item = await source.next();
307
- for (let id = 0; id < count; id++) {
308
- if (queue.isOpen(id.toString())) {
309
- queue.push(id.toString(), item);
311
+ ids.forEach((id) => {
312
+ if (queue.isOpen(id)) {
313
+ queue.push(id, { next: item });
310
314
  }
311
- }
315
+ });
312
316
  if (item.done) {
313
317
  break;
314
318
  }
315
319
  }
316
- } catch (e) {
317
- error = { value: e };
320
+ } catch (error) {
321
+ ids.forEach((id) => {
322
+ if (queue.isOpen(id)) {
323
+ queue.push(id, { error });
324
+ }
325
+ });
326
+ } finally {
327
+ isSourceFinished = true;
318
328
  }
319
329
  });
320
- for (let id = 0; id < count; id++) {
321
- queue.open(id.toString());
322
- replicated.push(new AsyncIteratorClass(
323
- () => {
330
+ const replicated = ids.map((id) => {
331
+ queue.open(id);
332
+ return new AsyncIteratorClass(
333
+ async () => {
324
334
  start();
325
- return new Promise((resolve, reject) => {
326
- queue.pull(id.toString()).then(resolve).catch(reject);
327
- defer(() => {
328
- if (error) {
329
- reject(error.value);
330
- }
331
- });
332
- });
335
+ const item = await queue.pull(id);
336
+ if (item.next) {
337
+ return item.next;
338
+ }
339
+ throw item.error;
333
340
  },
334
341
  async (reason) => {
335
- queue.close({ id: id.toString() });
336
- if (reason !== "next") {
337
- if (replicated.every((_, id2) => !queue.isOpen(id2.toString()))) {
338
- await source?.return?.();
339
- }
342
+ queue.close({ id });
343
+ if (reason !== "next" && !queue.length && !isSourceFinished) {
344
+ isSourceFinished = true;
345
+ await source?.return?.();
340
346
  }
341
347
  }
342
- ));
343
- }
348
+ );
349
+ });
344
350
  return replicated;
345
351
  }
346
352
  function asyncIteratorWithSpan({ name, ...options }, iterator) {
@@ -397,15 +403,15 @@ class EventPublisher {
397
403
  if (typeof listenerOrOptions === "function") {
398
404
  let listeners = this.#listenersMap.get(event);
399
405
  if (!listeners) {
400
- this.#listenersMap.set(event, listeners = /* @__PURE__ */ new Set());
406
+ this.#listenersMap.set(event, listeners = []);
401
407
  }
402
- listeners.add(listenerOrOptions);
403
- return () => {
404
- listeners.delete(listenerOrOptions);
405
- if (listeners.size === 0) {
408
+ listeners.push(listenerOrOptions);
409
+ return once(() => {
410
+ listeners.splice(listeners.indexOf(listenerOrOptions), 1);
411
+ if (listeners.length === 0) {
406
412
  this.#listenersMap.delete(event);
407
413
  }
408
- };
414
+ });
409
415
  }
410
416
  const signal = listenerOrOptions?.signal;
411
417
  const maxBufferedEvents = listenerOrOptions?.maxBufferedEvents ?? this.#maxBufferedEvents;
@@ -451,13 +457,19 @@ class EventPublisher {
451
457
  }
452
458
 
453
459
  class SequentialIdGenerator {
454
- index = BigInt(0);
460
+ index = BigInt(1);
455
461
  generate() {
456
- const id = this.index.toString(32);
462
+ const id = this.index.toString(36);
457
463
  this.index++;
458
464
  return id;
459
465
  }
460
466
  }
467
+ function compareSequentialIds(a, b) {
468
+ if (a.length !== b.length) {
469
+ return a.length - b.length;
470
+ }
471
+ return a < b ? -1 : a > b ? 1 : 0;
472
+ }
461
473
 
462
474
  function onStart(callback) {
463
475
  return async (options, ...rest) => {
@@ -536,6 +548,12 @@ function findDeepMatches(check, payload, segments = [], maps = [], values = [])
536
548
  }
537
549
  return { maps, values };
538
550
  }
551
+ function getConstructor(value) {
552
+ if (!isTypescriptObject(value)) {
553
+ return null;
554
+ }
555
+ return Object.getPrototypeOf(value)?.constructor;
556
+ }
539
557
  function isObject(value) {
540
558
  if (!value || typeof value !== "object") {
541
559
  return false;
@@ -581,6 +599,61 @@ const NullProtoObj = /* @__PURE__ */ (() => {
581
599
  return e;
582
600
  })();
583
601
 
602
+ function value(value2, ...args) {
603
+ if (typeof value2 === "function") {
604
+ return value2(...args);
605
+ }
606
+ return value2;
607
+ }
608
+ function fallback(value2, fallback2) {
609
+ return value2 === void 0 ? fallback2 : value2;
610
+ }
611
+
612
+ function preventNativeAwait(target) {
613
+ return new Proxy(target, {
614
+ get(target2, prop, receiver) {
615
+ const value2 = Reflect.get(target2, prop, receiver);
616
+ if (prop !== "then" || typeof value2 !== "function") {
617
+ return value2;
618
+ }
619
+ return new Proxy(value2, {
620
+ apply(targetFn, thisArg, args) {
621
+ if (args.length !== 2 || args.some((arg) => !isNativeFunction(arg))) {
622
+ return Reflect.apply(targetFn, thisArg, args);
623
+ }
624
+ let shouldOmit = true;
625
+ args[0].call(thisArg, preventNativeAwait(new Proxy(target2, {
626
+ get: (target3, prop2, receiver2) => {
627
+ if (shouldOmit && prop2 === "then") {
628
+ shouldOmit = false;
629
+ return void 0;
630
+ }
631
+ return Reflect.get(target3, prop2, receiver2);
632
+ }
633
+ })));
634
+ }
635
+ });
636
+ }
637
+ });
638
+ }
639
+ const NATIVE_FUNCTION_REGEX = /^\s*function\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/;
640
+ function isNativeFunction(fn) {
641
+ return typeof fn === "function" && NATIVE_FUNCTION_REGEX.test(fn.toString());
642
+ }
643
+ function overlayProxy(target, partial) {
644
+ const proxy = new Proxy(typeof target === "function" ? partial : target, {
645
+ get(_, prop) {
646
+ const targetValue = prop in partial ? partial : value(target);
647
+ const v = Reflect.get(targetValue, prop);
648
+ return typeof v === "function" ? v.bind(targetValue) : v;
649
+ },
650
+ has(_, prop) {
651
+ return Reflect.has(partial, prop) || Reflect.has(value(target), prop);
652
+ }
653
+ });
654
+ return proxy;
655
+ }
656
+
584
657
  function streamToAsyncIteratorClass(stream) {
585
658
  const reader = stream.getReader();
586
659
  return new AsyncIteratorClass(
@@ -607,6 +680,22 @@ function asyncIteratorToStream(iterator) {
607
680
  }
608
681
  });
609
682
  }
683
+ function asyncIteratorToUnproxiedDataStream(iterator) {
684
+ return new ReadableStream({
685
+ async pull(controller) {
686
+ const { done, value } = await iterator.next();
687
+ if (done) {
688
+ controller.close();
689
+ } else {
690
+ const unproxied = isObject(value) ? { ...value } : Array.isArray(value) ? value.map((i) => i) : value;
691
+ controller.enqueue(unproxied);
692
+ }
693
+ },
694
+ async cancel() {
695
+ await iterator.return?.();
696
+ }
697
+ });
698
+ }
610
699
 
611
700
  function tryDecodeURIComponent(value) {
612
701
  try {
@@ -616,11 +705,4 @@ function tryDecodeURIComponent(value) {
616
705
  }
617
706
  }
618
707
 
619
- function value(value2, ...args) {
620
- if (typeof value2 === "function") {
621
- return value2(...args);
622
- }
623
- return value2;
624
- }
625
-
626
- export { AbortError, AsyncIdQueue, AsyncIteratorClass, EventPublisher, NullProtoObj, ORPC_NAME, ORPC_SHARED_PACKAGE_NAME, ORPC_SHARED_PACKAGE_VERSION, SequentialIdGenerator, asyncIteratorToStream, asyncIteratorWithSpan, clone, defer, findDeepMatches, get, getGlobalOtelConfig, intercept, isAsyncIteratorObject, isObject, isPropertyKey, isTypescriptObject, onError, onFinish, onStart, onSuccess, once, parseEmptyableJSON, readAsBuffer, replicateAsyncIterator, resolveMaybeOptionalOptions, runInSpanContext, runWithSpan, sequential, setGlobalOtelConfig, setSpanAttribute, setSpanError, splitInHalf, startSpan, streamToAsyncIteratorClass, stringifyJSON, toArray, toOtelException, toSpanAttributeValue, tryDecodeURIComponent, value };
708
+ 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 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/shared",
3
3
  "type": "module",
4
- "version": "0.0.0-next.f9e0a4c",
4
+ "version": "0.0.0-next.f9e5dec",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -33,13 +33,13 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "radash": "^12.1.1",
36
- "type-fest": "^4.39.1"
36
+ "type-fest": "^5.2.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@opentelemetry/api": "^1.9.0",
40
- "arktype": "2.1.20",
40
+ "arktype": "2.1.27",
41
41
  "valibot": "^1.1.0",
42
- "zod": "^4.0.17"
42
+ "zod": "^4.1.12"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "unbuild",