{"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":[]}