UNPKG

@intlayer/chokidar

Version:

Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.

1 lines 7.93 kB
{"version":3,"file":"pLimit.mjs","names":["#head","#tail","#size"],"sources":["../../../src/utils/pLimit.ts"],"sourcesContent":["/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node<T> {\n value: T;\n next: Node<T> | undefined;\n\n constructor(value: T) {\n this.value = value;\n }\n}\n\nexport class Queue<T> {\n #head: Node<T> | undefined;\n #tail: Node<T> | undefined;\n #size!: number;\n\n constructor() {\n this.clear();\n }\n\n enqueue(value: T): void {\n const node = new Node(value);\n\n if (this.#head) {\n this.#tail!.next = node;\n this.#tail = node;\n } else {\n this.#head = node;\n this.#tail = node;\n }\n\n this.#size++;\n }\n\n dequeue(): T | undefined {\n const current = this.#head;\n if (!current) {\n return;\n }\n\n this.#head = current.next;\n this.#size--;\n return current.value;\n }\n\n peek(): T | undefined {\n if (!this.#head) {\n return;\n }\n\n return this.#head.value;\n\n // TODO: Node.js 18.\n // return this.#head?.value;\n }\n\n clear(): void {\n this.#head = undefined;\n this.#tail = undefined;\n this.#size = 0;\n }\n\n get size(): number {\n return this.#size;\n }\n\n *[Symbol.iterator](): Generator<T, void, unknown> {\n let current = this.#head;\n\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n\n *drain(): Generator<T | undefined, void, unknown> {\n while (this.#head) {\n yield this.dequeue();\n }\n }\n}\n\nexport const pLimit = (concurrency: number) => {\n validateConcurrency(concurrency);\n\n const queue = new Queue<() => void>();\n let activeCount = 0;\n\n const idleWaiters: Array<() => void> = [];\n const notifyIdleIfNeeded = (): void => {\n if (activeCount === 0 && queue.size === 0) {\n while (idleWaiters.length) idleWaiters.pop()?.();\n }\n };\n\n const resumeNext = (): void => {\n // Process the next queued function if we're under the concurrency limit\n if (activeCount < concurrency && queue.size > 0) {\n activeCount++;\n queue.dequeue()?.();\n }\n };\n\n const next = (): void => {\n activeCount--;\n resumeNext();\n };\n\n const run = async (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): Promise<void> => {\n // Execute the function and capture the result promise\n const result = (async () => fn(...arguments_))();\n\n // Resolve immediately with the promise (don't wait for completion)\n resolve(result);\n\n // Wait for the function to complete (success or failure)\n // We catch errors here to prevent unhandled rejections,\n // but the original promise rejection is preserved for the caller\n try {\n await result;\n } catch {}\n\n // Decrement active count and process next queued function\n next();\n };\n\n const enqueue = (\n fn: (...args: any[]) => Promise<any>,\n resolve: (value: Promise<any>) => void,\n arguments_: any[]\n ): void => {\n // Queue the internal resolve function instead of the run function\n // to preserve the asynchronous execution context.\n new Promise<void>((internalResolve) => {\n queue.enqueue(internalResolve);\n }).then(run.bind(undefined, fn, resolve, arguments_));\n\n // Start processing immediately if we haven't reached the concurrency limit\n if (activeCount < concurrency) {\n resumeNext();\n }\n };\n\n const generator = (\n fn: (...args: any[]) => Promise<any>,\n ...arguments_: any[]\n ): Promise<any> =>\n new Promise<any>((resolve) => {\n enqueue(fn, resolve, arguments_);\n });\n\n Object.defineProperties(generator, {\n activeCount: {\n get: () => activeCount,\n },\n pendingCount: {\n get: () => queue.size,\n },\n clearQueue: {\n value() {\n queue.clear();\n notifyIdleIfNeeded();\n },\n },\n concurrency: {\n get: () => concurrency,\n\n set(newConcurrency: number) {\n validateConcurrency(newConcurrency);\n concurrency = newConcurrency;\n\n queueMicrotask(() => {\n while (activeCount < concurrency && queue.size > 0) {\n resumeNext();\n }\n });\n },\n },\n map: {\n async value<T, R>(\n array: T[],\n fn: (value: T, index: number) => Promise<R>\n ): Promise<R[]> {\n const promises = array.map((value, index) => this(fn, value, index));\n return Promise.all(promises);\n },\n },\n onIdle: {\n /**\n * Resolves when `activeCount === 0` and the queue is empty.\n * Use this to wait for completion without holding a list of Promises.\n */\n value(): Promise<void> {\n if (activeCount === 0 && queue.size === 0) return Promise.resolve();\n return new Promise<void>((resolve) => idleWaiters.push(resolve));\n },\n },\n });\n\n return generator;\n};\n\nconst validateConcurrency = (concurrency: number): void => {\n if (\n !(\n (Number.isInteger(concurrency) ||\n concurrency === Number.POSITIVE_INFINITY) &&\n concurrency > 0\n )\n ) {\n throw new TypeError('Expected `concurrency` to be a number from 1 and up');\n }\n};\n"],"mappings":"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"}