@standardserver/shared
Advanced tools
+40
-30
@@ -1,5 +0,5 @@ | ||
| declare function toArray<T>(value: T): T extends readonly any[] ? T : Exclude<T, undefined | null>[]; | ||
| declare function toArray<T>(value: T): T extends readonly any[] ? T : (T extends undefined | null ? never : T[]); | ||
| declare const PACKAGE_NAME = "@standardserver/shared"; | ||
| declare const PACKAGE_VERSION = "0.0.7"; | ||
| declare const PACKAGE_VERSION = "0.0.8"; | ||
| /** | ||
@@ -22,2 +22,7 @@ * Generates a unique symbol for the specified name within the package scope. | ||
| } | ||
| /** | ||
| * Forwards an error to the global unhandled rejection handler via a rejected Promise. | ||
| * Useful for routing errors from sync contexts into async error pipelines. | ||
| */ | ||
| declare function emitUnhandledRejection(error: unknown): void; | ||
@@ -35,3 +40,6 @@ /** | ||
| interface AsyncCleanupFn { | ||
| (isCompleted: boolean): Promise<void>; | ||
| (state: { | ||
| isCancelled: boolean; | ||
| error?: unknown; | ||
| }): Promise<void>; | ||
| } | ||
@@ -54,3 +62,3 @@ | ||
| return(value?: any): Promise<IteratorResult<T, TReturn>>; | ||
| throw(err: any): Promise<IteratorResult<T, TReturn>>; | ||
| throw(error: any): Promise<IteratorResult<T, TReturn>>; | ||
| /** | ||
@@ -72,2 +80,6 @@ * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose') | ||
| declare function isTypescriptObject(maybeObject: unknown): maybeObject is object & Record<PropertyKey, unknown>; | ||
| /** | ||
| * Creates a new object with the specified keys omitted. | ||
| */ | ||
| declare function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>; | ||
@@ -84,30 +96,28 @@ interface GetOrBindOptions { | ||
| interface AsyncIdQueueCloseOptions { | ||
| id?: string; | ||
| reason?: unknown; | ||
| } | ||
| interface AsyncIdQueueOptions { | ||
| declare class Queue<T> { | ||
| private readonly items; | ||
| private readonly pendingPulls; | ||
| private closed; | ||
| /** | ||
| * Maximum number of buffered items per queue. | ||
| * Pushes an item into the queue. | ||
| * @throws when the queue is closed or aborted | ||
| */ | ||
| push(item: T): void; | ||
| /** | ||
| * Pulls the next item from the queue. | ||
| * | ||
| * @default Infinity | ||
| * @throws when the queue is closed or aborted. Note that buffered items can still be pulled after close until the buffer is drained. | ||
| */ | ||
| maxBufferedSize?: number; | ||
| pull(): Promise<T>; | ||
| /** | ||
| * Closes the queue and rejects any pending pulls. | ||
| * Buffered items remain available to be pulled. Repeated calls are ignored. | ||
| */ | ||
| close(reason?: unknown): void; | ||
| /** | ||
| * Aborts the queue. | ||
| * Unlike `close()`, this also discards any buffered items before closing. | ||
| */ | ||
| abort(reason?: unknown): void; | ||
| } | ||
| declare class AsyncIdQueue<T> { | ||
| private readonly maxBufferedSize; | ||
| private readonly openIds; | ||
| private readonly queues; | ||
| private readonly waiters; | ||
| constructor(options?: AsyncIdQueueOptions); | ||
| get length(): number; | ||
| 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: string): void; | ||
| } | ||
@@ -124,3 +134,3 @@ interface SleepOptions { | ||
| export { AbortError, AsyncIdQueue, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, SequentialIdGenerator, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; | ||
| export type { AsyncCleanupFn, AsyncIdQueueCloseOptions, AsyncIdQueueOptions, AsyncIteratorClassNextFn, GetOrBindOptions, SleepOptions }; | ||
| export { AbortError, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, Queue, SequentialIdGenerator, emitUnhandledRejection, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, omit, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; | ||
| export type { AsyncCleanupFn, AsyncIteratorClassNextFn, GetOrBindOptions, SleepOptions }; |
+40
-30
@@ -1,5 +0,5 @@ | ||
| declare function toArray<T>(value: T): T extends readonly any[] ? T : Exclude<T, undefined | null>[]; | ||
| declare function toArray<T>(value: T): T extends readonly any[] ? T : (T extends undefined | null ? never : T[]); | ||
| declare const PACKAGE_NAME = "@standardserver/shared"; | ||
| declare const PACKAGE_VERSION = "0.0.7"; | ||
| declare const PACKAGE_VERSION = "0.0.8"; | ||
| /** | ||
@@ -22,2 +22,7 @@ * Generates a unique symbol for the specified name within the package scope. | ||
| } | ||
| /** | ||
| * Forwards an error to the global unhandled rejection handler via a rejected Promise. | ||
| * Useful for routing errors from sync contexts into async error pipelines. | ||
| */ | ||
| declare function emitUnhandledRejection(error: unknown): void; | ||
@@ -35,3 +40,6 @@ /** | ||
| interface AsyncCleanupFn { | ||
| (isCompleted: boolean): Promise<void>; | ||
| (state: { | ||
| isCancelled: boolean; | ||
| error?: unknown; | ||
| }): Promise<void>; | ||
| } | ||
@@ -54,3 +62,3 @@ | ||
| return(value?: any): Promise<IteratorResult<T, TReturn>>; | ||
| throw(err: any): Promise<IteratorResult<T, TReturn>>; | ||
| throw(error: any): Promise<IteratorResult<T, TReturn>>; | ||
| /** | ||
@@ -72,2 +80,6 @@ * asyncDispose symbol only available in esnext, we should fallback to Symbol.for('asyncDispose') | ||
| declare function isTypescriptObject(maybeObject: unknown): maybeObject is object & Record<PropertyKey, unknown>; | ||
| /** | ||
| * Creates a new object with the specified keys omitted. | ||
| */ | ||
| declare function omit<T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>; | ||
@@ -84,30 +96,28 @@ interface GetOrBindOptions { | ||
| interface AsyncIdQueueCloseOptions { | ||
| id?: string; | ||
| reason?: unknown; | ||
| } | ||
| interface AsyncIdQueueOptions { | ||
| declare class Queue<T> { | ||
| private readonly items; | ||
| private readonly pendingPulls; | ||
| private closed; | ||
| /** | ||
| * Maximum number of buffered items per queue. | ||
| * Pushes an item into the queue. | ||
| * @throws when the queue is closed or aborted | ||
| */ | ||
| push(item: T): void; | ||
| /** | ||
| * Pulls the next item from the queue. | ||
| * | ||
| * @default Infinity | ||
| * @throws when the queue is closed or aborted. Note that buffered items can still be pulled after close until the buffer is drained. | ||
| */ | ||
| maxBufferedSize?: number; | ||
| pull(): Promise<T>; | ||
| /** | ||
| * Closes the queue and rejects any pending pulls. | ||
| * Buffered items remain available to be pulled. Repeated calls are ignored. | ||
| */ | ||
| close(reason?: unknown): void; | ||
| /** | ||
| * Aborts the queue. | ||
| * Unlike `close()`, this also discards any buffered items before closing. | ||
| */ | ||
| abort(reason?: unknown): void; | ||
| } | ||
| declare class AsyncIdQueue<T> { | ||
| private readonly maxBufferedSize; | ||
| private readonly openIds; | ||
| private readonly queues; | ||
| private readonly waiters; | ||
| constructor(options?: AsyncIdQueueOptions); | ||
| get length(): number; | ||
| 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: string): void; | ||
| } | ||
@@ -124,3 +134,3 @@ interface SleepOptions { | ||
| export { AbortError, AsyncIdQueue, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, SequentialIdGenerator, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; | ||
| export type { AsyncCleanupFn, AsyncIdQueueCloseOptions, AsyncIdQueueOptions, AsyncIteratorClassNextFn, GetOrBindOptions, SleepOptions }; | ||
| export { AbortError, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, Queue, SequentialIdGenerator, emitUnhandledRejection, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, omit, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; | ||
| export type { AsyncCleanupFn, AsyncIteratorClassNextFn, GetOrBindOptions, SleepOptions }; |
+70
-86
@@ -6,3 +6,3 @@ function toArray(value) { | ||
| const PACKAGE_NAME = "@standardserver/shared"; | ||
| const PACKAGE_VERSION = "0.0.7"; | ||
| const PACKAGE_VERSION = "0.0.8"; | ||
| function getPackageSymbol(name) { | ||
@@ -18,2 +18,7 @@ return Symbol.for(`${PACKAGE_NAME}@${PACKAGE_VERSION}/${name}`); | ||
| } | ||
| function emitUnhandledRejection(error) { | ||
| Promise.reject(error).catch(() => { | ||
| throw error; | ||
| }); | ||
| } | ||
@@ -58,2 +63,3 @@ function sequential(fn) { | ||
| } | ||
| let errorRef; | ||
| try { | ||
@@ -65,9 +71,10 @@ const result = await next(); | ||
| return result; | ||
| } catch (err) { | ||
| } catch (error) { | ||
| errorRef = { value: error }; | ||
| this.isDone = true; | ||
| throw err; | ||
| throw error; | ||
| } finally { | ||
| if (this.isDone && !this.isExecuteComplete) { | ||
| this.isExecuteComplete = true; | ||
| await this.cleanup(true); | ||
| await this.cleanup(errorRef ? { isCancelled: false, error: errorRef.value } : { isCancelled: false }); | ||
| } | ||
@@ -81,13 +88,13 @@ } | ||
| this.isExecuteComplete = true; | ||
| await this.cleanup(false); | ||
| await this.cleanup({ isCancelled: true }); | ||
| } | ||
| return { done: true, value }; | ||
| } | ||
| async throw(err) { | ||
| async throw(error) { | ||
| this.isDone = true; | ||
| if (!this.isExecuteComplete) { | ||
| this.isExecuteComplete = true; | ||
| await this.cleanup(false); | ||
| await this.cleanup({ isCancelled: true, error }); | ||
| } | ||
| throw err; | ||
| throw error; | ||
| } | ||
@@ -101,3 +108,3 @@ /** | ||
| this.isExecuteComplete = true; | ||
| await this.cleanup(false); | ||
| await this.cleanup({ isCancelled: true }); | ||
| } | ||
@@ -127,2 +134,9 @@ } | ||
| } | ||
| function omit(obj, keys) { | ||
| const result = { ...obj }; | ||
| for (const key of keys) { | ||
| delete result[key]; | ||
| } | ||
| return result; | ||
| } | ||
@@ -146,89 +160,59 @@ const GET_OR_BIND_CACHE = /* @__PURE__ */ new WeakMap(); | ||
| class AsyncIdQueue { | ||
| maxBufferedSize; | ||
| openIds = /* @__PURE__ */ new Set(); | ||
| queues = /* @__PURE__ */ new Map(); | ||
| waiters = /* @__PURE__ */ new Map(); | ||
| constructor(options = {}) { | ||
| this.maxBufferedSize = options.maxBufferedSize ?? Infinity; | ||
| } | ||
| 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); | ||
| } | ||
| class Queue { | ||
| items = []; | ||
| pendingPulls = []; | ||
| closed; | ||
| /** | ||
| * Pushes an item into the queue. | ||
| * @throws when the queue is closed or aborted | ||
| */ | ||
| push(item) { | ||
| if (this.closed) { | ||
| throw this.closed.reason; | ||
| } | ||
| const pendingPull = this.pendingPulls.shift(); | ||
| if (pendingPull) { | ||
| pendingPull[0](item); | ||
| } else { | ||
| let items = this.queues.get(id); | ||
| if (!items) { | ||
| items = []; | ||
| this.queues.set(id, items); | ||
| } | ||
| items.push(item); | ||
| if (items.length > this.maxBufferedSize) { | ||
| items.shift(); | ||
| } | ||
| if (items.length === 0) { | ||
| this.queues.delete(id); | ||
| } | ||
| this.items.push(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); | ||
| } | ||
| /** | ||
| * Pulls the next item from the queue. | ||
| * | ||
| * @throws when the queue is closed or aborted. Note that buffered items can still be pulled after close until the buffer is drained. | ||
| */ | ||
| async pull() { | ||
| const item = this.items.shift(); | ||
| if (item !== void 0) { | ||
| return item; | ||
| } | ||
| if (this.closed) { | ||
| throw this.closed.reason; | ||
| } | ||
| 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]); | ||
| } | ||
| this.pendingPulls.push([resolve, reject]); | ||
| }); | ||
| } | ||
| 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(); | ||
| /** | ||
| * Closes the queue and rejects any pending pulls. | ||
| * Buffered items remain available to be pulled. Repeated calls are ignored. | ||
| */ | ||
| close(reason) { | ||
| if (this.closed) { | ||
| 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); | ||
| reason ??= new AbortError("Queue was closed."); | ||
| this.closed = { reason }; | ||
| this.pendingPulls.forEach(([, reject]) => reject(reason)); | ||
| this.pendingPulls.length = 0; | ||
| } | ||
| assertOpen(id) { | ||
| if (!this.isOpen(id)) { | ||
| throw new Error(`[AsyncIdQueue] Cannot access queue[${id}] because it is not open or aborted.`); | ||
| } | ||
| /** | ||
| * Aborts the queue. | ||
| * Unlike `close()`, this also discards any buffered items before closing. | ||
| */ | ||
| abort(reason) { | ||
| reason ??= new AbortError("Queue was aborted."); | ||
| this.items.length = 0; | ||
| this.close(reason); | ||
| } | ||
@@ -267,2 +251,2 @@ } | ||
| export { AbortError, AsyncIdQueue, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, SequentialIdGenerator, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; | ||
| export { AbortError, AsyncIteratorClass, PACKAGE_NAME, PACKAGE_VERSION, Queue, SequentialIdGenerator, emitUnhandledRejection, getOrBind, getPackageSymbol, isAsyncIteratorObject, isTypescriptObject, omit, parseEmptyableJSON, sequential, sleep, stringifyJSON, toArray, tryDecodeURIComponent }; |
+1
-1
| { | ||
| "name": "@standardserver/shared", | ||
| "type": "module", | ||
| "version": "0.0.7", | ||
| "version": "0.0.8", | ||
| "license": "MIT", | ||
@@ -6,0 +6,0 @@ "homepage": "https://standardserver.dev", |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
17920
2.34%350
-1.13%1
Infinity%