UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

1 lines 8.96 kB
{"version":3,"sources":["../src/async.ts"],"sourcesContent":["/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// NOTE: This file is pulled into client code and cannot have any Node-only\n// dependencies.\n\n/**\n * A handle to a promise and its resolvers.\n */\nexport interface Task<T> {\n resolve: (result: T) => void;\n reject: (err: unknown) => void;\n promise: Promise<T>;\n}\n\n/** Utility for creating Tasks. */\nexport function createTask<T>(): Task<T> {\n let resolve: unknown, reject: unknown;\n const promise = new Promise<T>(\n (res, rej) => ([resolve, reject] = [res, rej])\n );\n return {\n resolve: resolve as Task<T>['resolve'],\n reject: reject as Task<T>['reject'],\n promise,\n };\n}\n\n/**\n * Unique sentinel used internally to mark the end of a {@link Channel}'s\n * stream. Using a private Symbol (instead of `null`) ensures that legitimate\n * falsy values sent by callers (including `null`) are never confused with the\n * close signal.\n */\nconst DONE = Symbol('channel-done');\n\n/**\n * A class designed to help turn repeated callbacks into async iterators.\n * Based loosely on a combination of Go channels and Promises.\n */\nexport class Channel<T> implements AsyncIterable<T> {\n private ready: Task<void> = createTask<void>();\n private buffer: (T | typeof DONE)[] = [];\n private err: unknown = null;\n private done: boolean = false;\n\n send(value: T): void {\n this.buffer.push(value);\n this.ready.resolve();\n }\n\n close(): void {\n this.buffer.push(DONE);\n this.ready.resolve();\n }\n\n error(err: unknown): void {\n this.err = err;\n // Note: we must call this.ready.reject here in case we get an error even before the stream is initiated,\n // however we cannot rely on this.ready.reject because it will be ignored if ready.resolved has already\n // been called, so this.err will be checked in the iterator as well.\n this.ready.reject(err);\n }\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return {\n next: async (): Promise<IteratorResult<T>> => {\n if (this.done) {\n return { value: undefined as unknown as T, done: true };\n }\n if (this.err) {\n throw this.err;\n }\n\n if (!this.buffer.length) {\n await this.ready.promise;\n }\n const value = this.buffer.shift()!;\n if (!this.buffer.length) {\n this.ready = createTask<void>();\n }\n if (value === DONE) {\n // Mark the channel as done so that any further calls to next()\n // (e.g. manual iteration after the stream has ended) return\n // {done: true} immediately instead of awaiting a readiness promise\n // that will never resolve.\n this.done = true;\n return {\n value: undefined,\n done: true,\n };\n }\n\n return {\n value,\n done: false,\n };\n },\n };\n }\n}\n\n/**\n * A lazy promise that does not run its executor function until then is called.\n */\nexport class LazyPromise<T> implements PromiseLike<T> {\n private executor;\n private promise;\n\n constructor(executor: (resolve?, reject?) => void | Promise<void>) {\n this.executor = executor;\n }\n\n then<TResult1 = T, TResult2 = never>(\n onfulfilled?:\n | ((value: T) => TResult1 | PromiseLike<TResult1>)\n | undefined\n | null,\n onrejected?:\n | ((reason: any) => TResult2 | PromiseLike<TResult2>)\n | undefined\n | null\n ): PromiseLike<TResult1 | TResult2> {\n this.promise ??= new Promise<T>(this.executor);\n return this.promise.then(onfulfilled, onrejected);\n }\n}\n\n/** Lazily call the provided function to resolve the LazyPromise. */\nexport function lazy<T>(fn: () => T | PromiseLike<T>): PromiseLike<T> {\n return new LazyPromise<T>((resolve, reject) => {\n try {\n resolve(fn());\n } catch (e) {\n reject(e);\n }\n });\n}\n\n/**\n * Options for AsyncTaskQueue.\n */\nexport interface AsyncTaskQueueOptions {\n /**\n * If true, the queue will stop executing subsequent tasks if a task fails.\n * If false (default), the queue will continue executing subsequent tasks even if a task fails.\n */\n stopOnError?: boolean;\n}\n\n/**\n * A queue for asynchronous tasks. The queue ensures that only one task runs at a time in order.\n */\nexport class AsyncTaskQueue {\n private last: Promise<any> = Promise.resolve();\n private options: AsyncTaskQueueOptions;\n\n constructor(options?: AsyncTaskQueueOptions) {\n this.options = options || {};\n }\n\n /**\n * Adds a task to the queue.\n * The task will be executed when its turn comes up in the queue.\n * @param task A function that returns a value or a PromiseLike.\n */\n enqueue(task: () => any | PromiseLike<any>) {\n if (this.options.stopOnError) {\n this.last = this.last.then(() => lazy(task)).then((res) => res);\n } else {\n this.last = this.last\n .catch(() => {})\n .then(() => lazy(task))\n .then((res) => res);\n }\n // Prevent unhandled promise rejections.\n this.last.catch(() => {});\n }\n\n /**\n * Waits for all tasks currently in the queue to complete.\n */\n async merge() {\n await this.last;\n }\n}\n\n/** A lightweight, cross-platform EventEmitter. */\nexport class EventEmitter {\n private listeners: Record<string, ((...args: any[]) => void)[]> = {};\n\n on(event: string, listener: (...args: any[]) => void) {\n if (!this.listeners[event]) {\n this.listeners[event] = [];\n }\n this.listeners[event].push(listener);\n }\n\n off(event: string, listener: (...args: any[]) => void) {\n if (!this.listeners[event]) return;\n this.listeners[event] = this.listeners[event].filter((l) => l !== listener);\n }\n\n emit(event: string, ...args: any[]) {\n if (!this.listeners[event]) return;\n this.listeners[event].forEach((l) => l(...args));\n }\n}\n"],"mappings":"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","names":[]}