UNPKG

@genkit-ai/core

Version:

Genkit AI framework core libraries.

1 lines 6.74 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 * 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 | null)[] = [];\n private err: unknown = null;\n\n send(value: T): void {\n this.buffer.push(value);\n this.ready.resolve();\n }\n\n close(): void {\n this.buffer.push(null);\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.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\n return {\n value,\n done: !value,\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"],"mappings":"AA6BO,SAAS,aAAyB;AACvC,MAAI,SAAkB;AACtB,QAAM,UAAU,IAAI;AAAA,IAClB,CAAC,KAAK,QAAS,CAAC,SAAS,MAAM,IAAI,CAAC,KAAK,GAAG;AAAA,EAC9C;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAMO,MAAM,QAAuC;AAAA,EAC1C,QAAoB,WAAiB;AAAA,EACrC,SAAuB,CAAC;AAAA,EACxB,MAAe;AAAA,EAEvB,KAAK,OAAgB;AACnB,SAAK,OAAO,KAAK,KAAK;AACtB,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,KAAK,IAAI;AACrB,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,KAAoB;AACxB,SAAK,MAAM;AAIX,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA,EAEA,CAAC,OAAO,aAAa,IAAsB;AACzC,WAAO;AAAA,MACL,MAAM,YAAwC;AAC5C,YAAI,KAAK,KAAK;AACZ,gBAAM,KAAK;AAAA,QACb;AAEA,YAAI,CAAC,KAAK,OAAO,QAAQ;AACvB,gBAAM,KAAK,MAAM;AAAA,QACnB;AACA,cAAM,QAAQ,KAAK,OAAO,MAAM;AAChC,YAAI,CAAC,KAAK,OAAO,QAAQ;AACvB,eAAK,QAAQ,WAAiB;AAAA,QAChC;AAEA,eAAO;AAAA,UACL;AAAA,UACA,MAAM,CAAC;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAKO,MAAM,YAAyC;AAAA,EAC5C;AAAA,EACA;AAAA,EAER,YAAY,UAAuD;AACjE,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,KACE,aAIA,YAIkC;AAClC,SAAK,YAAY,IAAI,QAAW,KAAK,QAAQ;AAC7C,WAAO,KAAK,QAAQ,KAAK,aAAa,UAAU;AAAA,EAClD;AACF;AAGO,SAAS,KAAQ,IAA8C;AACpE,SAAO,IAAI,YAAe,CAAC,SAAS,WAAW;AAC7C,QAAI;AACF,cAAQ,GAAG,CAAC;AAAA,IACd,SAAS,GAAG;AACV,aAAO,CAAC;AAAA,IACV;AAAA,EACF,CAAC;AACH;AAgBO,MAAM,eAAe;AAAA,EAClB,OAAqB,QAAQ,QAAQ;AAAA,EACrC;AAAA,EAER,YAAY,SAAiC;AAC3C,SAAK,UAAU,WAAW,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAAoC;AAC1C,QAAI,KAAK,QAAQ,aAAa;AAC5B,WAAK,OAAO,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC,QAAQ,GAAG;AAAA,IAChE,OAAO;AACL,WAAK,OAAO,KAAK,KACd,MAAM,MAAM;AAAA,MAAC,CAAC,EACd,KAAK,MAAM,KAAK,IAAI,CAAC,EACrB,KAAK,CAAC,QAAQ,GAAG;AAAA,IACtB;AAEA,SAAK,KAAK,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ;AACZ,UAAM,KAAK;AAAA,EACb;AACF;","names":[]}