unwrapped 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # unwrapped
2
2
 
3
+ ## 0.1.15
4
+
5
+ ### Patch Changes
6
+
7
+ - 514010d: debug
8
+
9
+ ## 0.1.14
10
+
11
+ ### Patch Changes
12
+
13
+ - 1150da3: added notifyProgress to generator
14
+
3
15
  ## 0.1.13
4
16
 
5
17
  ### Patch Changes
@@ -637,6 +637,8 @@ var AsyncResult = class _AsyncResult {
637
637
  * @returns itself
638
638
  */
639
639
  updateFromAction(action) {
640
+ console.log("===== updateFromAction called =====");
641
+ console.log("Action function:", action);
640
642
  const promise = action((progress) => this.updateProgress(progress));
641
643
  return this.updateFromResultPromise(promise);
642
644
  }
@@ -797,8 +799,11 @@ var AsyncResult = class _AsyncResult {
797
799
  * @param generatorFunc a generator function that yields AsyncResult instances
798
800
  */
799
801
  runInPlace(generatorFunc) {
802
+ console.log("===== runInPlace called =====");
803
+ console.log("Generator function:", generatorFunc);
800
804
  return this.updateFromAction((notify) => {
801
805
  const iterator = generatorFunc(notify);
806
+ console.log("Generator iterator:", iterator);
802
807
  return _AsyncResult._runGeneratorProcessor(iterator)();
803
808
  });
804
809
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/index.ts","../../src/core/error.ts","../../src/core/result.ts","../../src/core/asyncResult.ts","../../src/core/asyncResultCollection.ts","../../src/core/cache.ts","../../src/core/utils.ts"],"sourcesContent":["export * from \"./error\";\nexport * from \"./result\";\nexport * from \"./asyncResult\";\nexport * from \"./asyncResultCollection\";\nexport * from \"./cache\";\nexport * from \"./utils\";","/**\n * Base class for error handling, providing structured error information and logging.\n * @class ErrorBase\n * @property {string} code - The error code.\n * @property {string | undefined} message - The error message (optional).\n * @property {unknown} thrownError - The original error object, if any (optional).\n * \n * @constructor\n * @param {string} code - The error code.\n * @param {string} [message] - The error message.\n * @param {unknown} [thrownError] - The original error object, if any.\n * @param {boolean} [log=true] - Whether to log the error upon creation.\n */\nexport class ErrorBase {\n code: string;\n message?: string | undefined;\n thrownError?: unknown;\n\n constructor(code: string, message?: string, thrownError?: unknown, log: boolean = true) {\n this.code = code;\n this.message = message;\n this.thrownError = thrownError;\n\n if (log) {\n this.logError();\n }\n }\n\n /**\n * Converts the error to a string representation, on the format \"Error {code}: {message}\".\n * @returns a string representation of the error\n */\n toString(): string {\n return `Error ${this.code}: ${this.message ?? ''}`;\n }\n\n /**\n * Logs the error to the console, uses console.error and ErrorBase.toString() internally.\n * Logs thrownError if it was provided on creation.\n */\n logError(): void {\n if (this.thrownError) {\n console.error(this.toString(), this.thrownError);\n } else {\n console.error(this.toString());\n }\n }\n}\n","import { ErrorBase } from \"./error\";\n\n/**\n * Type representing the state of a Result, either success with a value of type T,\n * or error with an error of type E (defaulting to ErrorBase).\n */\nexport type ResultState<T, E extends ErrorBase = ErrorBase> =\n | { status: 'success'; value: T }\n | { status: 'error'; error: E };\n\n/**\n * Class representing the result of an operation that can either succeed with a value of type T,\n * or fail with an error of type E (defaulting to ErrorBase).\n * Provides methods for unwrapping the result, chaining operations, and handling errors.\n * @class Result\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class Result<T, E extends ErrorBase = ErrorBase> {\n private _state: ResultState<T, E>;\n\n /**\n * Creates a new Result instance with the given state.\n * @param state the state of the created Result\n */\n constructor(state: ResultState<T, E>) {\n this._state = state;\n }\n\n /** Returns the internal state of the Result. */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the Result is successful.\n * @returns whether or not the result is successful\n */\n isSuccess(): boolean {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the Result is an error.\n * @returns whether or not the result is an error\n */\n isError(): boolean {\n return this._state.status === 'error';\n }\n\n /**\n * Creates a successful Result with the given value.\n * @param value the result of the successful operation\n * @returns a successful Result\n */\n static ok<T, E extends ErrorBase = ErrorBase>(value: T): Result<T, E> {\n return new Result({ status: 'success', value });\n }\n\n /**\n * Creates an error Result with the given error.\n * @param error the error of the failed operation\n * @returns an error Result\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): Result<never, E> {\n return new Result({ status: 'error', error });\n }\n\n /**\n * Creates an error Result (containing an ErrorBase) with the given error code and optional message.\n * @param code the error code\n * @param message an optional error message\n * @returns an error Result\n */\n static errTag(code: string, message?: string, thrownError?: unknown): Result<never, ErrorBase> {\n return Result.err(new ErrorBase(code, message, thrownError));\n }\n\n /**\n * Returns the successful value (if the Result is successful) or null (if it is an error).\n * @returns either the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value (if the Result is successful) or throws an error (if it is an error).\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap a Result that is not successful');\n }\n\n /**\n * Returns the successful value (if the Result is successful) or a default value (if it is an error).\n * @param defaultValue the default value to return if the Result is an error\n * @returns either the successful value or the default value\n */\n unwrapOr<O>(defaultValue: O): T | O {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return defaultValue;\n }\n\n /**\n * Transforms a Promise of a successful value into a Promise of a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * @param promise the promise to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return promise\n .then((value) => Result.ok<T, E>(value))\n .catch((error) => Result.err(errorMapper(error)));\n }\n\n /**\n * Executes an asynchronous function and transforms its result into a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * Same as Result.tryPromise(fn(), errorMapper).\n * @param fn the asynchronous function to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryFunction<T, E extends ErrorBase = ErrorBase>(fn: () => Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return Result.tryPromise(fn(), errorMapper);\n }\n\n /**\n * Chains the current Result with another operation that returns a ResultState.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * @param fn a function taking as input the successful value of the result, and returning a ResultState describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => ResultState<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return new Result<O, E | E2>(fn(this._state.value));\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * Chains the current Result with another operation that returns a Result.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * Same as chain, but the function returns a Result directly instead of a ResultState.\n * @param fn a function taking as input the successful value of the result, and returning a Result describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => Result<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return fn(this._state.value);\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * @yields the current Result, and if it is successful, returns its value.\n * This allows using Result instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<Result<number>, number, any> {\n * const result1 = yield* Result.ok(5);\n * const result2 = yield* Result.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<Result<T, E>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n /**\n * Runs a generator function that yields Result instances, propagating errors automatically.\n * If any yielded Result is an error, the execution stops and the error is returned.\n * If all yielded Results are successful, returns a successful Result with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for Result handling in generator functions.\n * \n * @param generator a generator function that yields Result instances\n * @returns a Result containing either the final successful value or the first encountered error\n * \n * @example\n * const result = Result.run(function* () {\n * const value1 = yield* Result.ok(5);\n * const value2 = yield* Result.ok(10);\n * return value1 + value2;\n * });\n */\n static run<T, E extends ErrorBase = ErrorBase>(generator: () => Generator<Result<any, E>, T, any>): Result<T, E> {\n const iterator = generator();\n let result = iterator.next();\n\n while (!result.done) {\n const yielded = result.value;\n if (yielded._state.status === 'error') {\n return Result.err(yielded._state.error);\n }\n result = iterator.next(yielded._state.value);\n }\n\n return Result.ok(result.value);\n }\n}\n","import { ErrorBase } from \"./error\";\nimport { Result, type ResultState } from \"./result\";\n\n/**\n * Type representing the state of an AsyncResult.\n * It can be 'idle', 'loading' with a promise and an optional progress information of type P, or a settled ResultState (success or error).\n */\nexport type AsyncResultState<T, E extends ErrorBase = ErrorBase, P = unknown> =\n | { status: 'idle' }\n | { status: 'loading'; promise: Promise<Result<T, E>>; progress?: P }\n | ResultState<T, E>;\n\n\n/**\n * An Action is a function returning a Promise of a Result.\n */\nexport type Action<T, E extends ErrorBase = ErrorBase, P = unknown> = (notifyProgress: (progress: P) => void) => Promise<Result<T, E>>;\n\n/**\n * A LazyAction is an object containing a trigger function to start the action, and the AsyncResult representing the action's state.\n */\nexport type LazyAction<T, E extends ErrorBase = ErrorBase, P = unknown> = {\n trigger: () => void;\n result: AsyncResult<T, E, P>;\n};\n\n/**\n * A ChainStep is a function that takes an arbitrary input and returns a Result or a Promise of a Result.\n * It takes an input of type I and returns either a Result<O, E> or a Promise<Result<O, E>>.\n * \n * Used for chaining operations on AsyncResult.\n */\nexport type ChainStep<I, O, E extends ErrorBase = ErrorBase> = (input: I) => Result<O, E> | Promise<Result<O, E>>;\n\n/**\n * A FlatChainStep is a function that takes an arbitrary input and returns an AsyncResult.\n * It takes an input of type I and returns an AsyncResult<O, E>.\n * \n * Used for flat-chaining operations on AsyncResult.\n */\nexport type FlatChainStep<I, O, E extends ErrorBase = ErrorBase, P = unknown> = (input: I) => AsyncResult<O, E, P>;\n\n/**\n * Type representing a generator function that yields AsyncResult instances and returns a final value of type T.\n * \n * Used for running generators with AsyncResult.run().\n */\nexport type AsyncResultGenerator<T> = Generator<AsyncResult<any, any>, T, any>;\n\n/**\n * Type representing a listener function for AsyncResult state changes.\n */\nexport type AsyncResultListener<T, E extends ErrorBase = ErrorBase, P = unknown> = (result: AsyncResult<T, E, P>) => any;\n\nexport interface AsyncResultListenerOptions {\n immediate?: boolean;\n callOnProgressUpdates?: boolean;\n}\n\ninterface AsyncResultListenerEntry<T, E extends ErrorBase, P> {\n listener: AsyncResultListener<T, E, P>;\n options: AsyncResultListenerOptions;\n}\n\n/**\n * Class representing the asynchronous result of an operation that can be idle, loading, successful, or failed.\n * Provides methods for listening to state changes, updating state, chaining operations, and converting to and from promises.\n * @class AsyncResult\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @template P - The type of the progress information for loading state (default is unknown).\n */\nexport class AsyncResult<T, E extends ErrorBase = ErrorBase, P = unknown> {\n private _state: AsyncResultState<T, E, P>;\n private _listeners: Set<AsyncResultListenerEntry<T, E, P>> = new Set();\n\n constructor(state?: AsyncResultState<T, E, P>) {\n this._state = state || { status: 'idle' };\n }\n\n\n\n // === Getting current state ===\n\n /**\n * Returns the internal state of the AsyncResult.\n */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the AsyncResult is successful.\n * @returns whether or not the result is successful\n */\n isSuccess() {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the AsyncResult is an error.\n * @returns whether or not the result is an error\n */\n isError() {\n return this._state.status === 'error';\n }\n\n /**\n * Checks if the AsyncResult is idle.\n * @returns whether or not the result is idle\n */\n isIdle() {\n return this._state.status === 'idle';\n }\n\n /**\n * Checks if the AsyncResult is loading.\n * @returns whether or not the result is loading\n */\n isLoading() {\n return this._state.status === 'loading';\n }\n\n\n\n // === Unwrapping values ===\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise returns null.\n * @returns the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap an AsyncResult that is not successful');\n }\n\n /**\n * Returns the error value if the AsyncResult is in an error state, otherwise returns null.\n * @returns the error value or null\n */\n unwrapErrorOrNull(): E | null {\n if (this._state.status === 'error') {\n return this._state.error;\n }\n return null;\n }\n\n /**\n * Returns the progress information if the AsyncResult is in a loading state, otherwise returns null.\n * @returns the progress information or null\n */\n getProgressOrNull(): P | null {\n if (this._state.status === 'loading') {\n return this._state.progress ?? null;\n }\n return null;\n }\n\n // === Creating/updating from settled values ===\n\n private set state(newState: AsyncResultState<T, E, P>) {\n const oldState = this._state;\n\n this._state = newState;\n this._listeners.forEach((listenerEntry) => {\n if ((oldState.status !== 'loading' || newState.status !== 'loading') || listenerEntry.options.callOnProgressUpdates) {\n listenerEntry.listener(this)\n }\n });\n }\n\n private setState(newState: AsyncResultState<T, E, P>) {\n this.state = newState;\n }\n\n /**\n * Creates a successful AsyncResult with the given value.\n * @param value the result of the successful operation\n * @returns a successful AsyncResult\n */\n static ok<T>(value: T): AsyncResult<T, never> {\n return new AsyncResult<T, never>({ status: 'success', value });\n }\n\n /**\n * Creates an error AsyncResult with the given error.\n * @param error the error of the failed operation\n * @returns an error AsyncResult\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): AsyncResult<never, E> {\n return new AsyncResult<never, E>({ status: 'error', error });\n }\n\n /**\n * Creates an error AsyncResult with a new ErrorBase constructed from the given parameters.\n * @param code the error code\n * @param message the error message (optional)\n * @param thrownError the original error object, if any (optional)\n * @param log whether to log the error upon creation (default is true)\n * @returns an error AsyncResult\n */\n static errTag(code: string, message?: string, thrownError?: unknown, log: boolean = true): AsyncResult<never, ErrorBase> {\n const error = new ErrorBase(code, message, thrownError, log);\n return AsyncResult.err(error);\n }\n\n /**\n * Updates the AsyncResult to a successful state with the given value.\n * Like AsyncResult.ok, but in place.\n * @param value the successful value\n */\n updateFromValue(value: T) {\n this.state = { status: 'success', value };\n return this;\n }\n\n /**\n * Updates the AsyncResult to an error state with the given error.\n * Like AsyncResult.err, but in place.\n * @param error the error\n */\n updateFromError(error: E) {\n this.state = { status: 'error', error };\n return this;\n }\n\n /**\n * Updates the progress information of the AsyncResult if it is currently loading.\n * @param progress progress information to include in the loading state\n */\n updateProgress(progress: P) {\n if (this._state.status === 'loading') {\n this.state = { ...this._state, progress };\n }\n return this;\n }\n\n\n // === Creating/updating from promises ===\n\n /**\n * Creates an AsyncResult from a promise that resolves to a value.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromResultPromise, but for promise that only resolves to a successful value and not a Result.\n * \n * @param promise the promise that resolves to a value\n * @returns an AsyncResult representing the state of the promise\n */\n static fromValuePromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromValuePromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromValuePromise, but in place.\n * \n * @param promise the promise that resolves to a value\n */\n updateFromValuePromise(promise: Promise<T>) {\n const resultStatePromise = async (): Promise<Result<T, E>> => {\n try {\n const value = await promise;\n return Result.ok(value);\n } catch (error) {\n return Result.err(error as E);\n }\n };\n return this.updateFromResultPromise(resultStatePromise());\n }\n\n\n // === Waiting for settled state and get result ===\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading.\n * @returns itself once settled\n */\n async waitForSettled(): Promise<AsyncResult<T, E, P>> {\n if (this._state.status === 'loading') {\n try {\n const value = await this._state.promise;\n this._state = value.state;\n } catch (error) {\n this._state = { status: 'error', error: error as E };\n }\n }\n return this;\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns a Result representing the settled state.\n * @returns a Result representing the settled state\n */\n async toResultPromise(): Promise<Result<T, E>> {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'idle' || settled.state.status === 'loading') {\n throw new Error('Cannot convert idle or loading AsyncResult to ResultState');\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n return Result.ok(settled.state.value);\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n async toValueOrThrowPromise(): Promise<T> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrThrow();\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or null.\n * @returns either the successful value or null\n */\n async toValueOrNullPromise(): Promise<T | null> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrNull();\n }\n\n /**\n * Creates an AsyncResult from a promise that resolves to a Result.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * @param promise the promise that resolves to a Result\n * @returns an AsyncResult representing the state of the promise\n */\n static fromResultPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromResultPromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The promise must produce a Result once settled (meaning it should return the error in the result when possible).\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but in place.\n * \n * @param promise the promise that resolves to a Result\n */\n updateFromResultPromise(promise: Promise<Result<T, E>>) {\n this.state = { status: 'loading', promise };\n promise\n .then((res) => {\n this.state = res.state;\n })\n .catch((error) => {\n this.updateFromError(new ErrorBase('defect_on_updateFromResultPromise', 'The promise provided to AsyncResult rejected', error) as E);\n });\n return this;\n }\n\n\n // === Listeners ===\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes.\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listen(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const entry: AsyncResultListenerEntry<T, E, P> = { listener, options };\n this._listeners.add(entry);\n\n if (options.immediate) {\n listener(this);\n }\n\n return () => {\n this._listeners.delete(entry);\n };\n }\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes, and automatically unsubscribes once it is settled (success or error).\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listenUntilSettled(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const unsub = this.listen((result) => {\n listener(result);\n if (result.state.status === 'success' || result.state.status === 'error') {\n unsub();\n }\n }, options);\n\n return unsub;\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on a success.\n * @param callback callback called once the AsyncResult settled on a success\n * @returns A function to unsubscribe early\n */\n onSuccessOnce(callback: (value: T) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on a success.\n * @param callback callback called every time the AsyncResult settles on a success\n * @returns A function to unsubscribe\n */\n onSuccessPerpetual(callback: (value: T) => void) {\n return this.listen((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on an error.\n * @param callback callback called once the AsyncResult settled on an error\n * @returns A function to unsubscribe early\n */\n onErrorOnce(callback: (error: E) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on an error.\n * @param callback callback called every time the AsyncResult settles on an error\n * @returns A function to unsubscribe\n */\n onErrorPerpetual(callback: (error: E) => void) {\n return this.listen((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n // === Mirroring ===\n\n /**\n * Mirrors the state of another AsyncResult into this one.\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirror(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listen((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n /**\n * Mirrors the state of another AsyncResult into this one, until the other AsyncResult is settled (success or error).\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match, until the other AsyncResult is settled.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirrorUntilSettled(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listenUntilSettled((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n\n // === Actions ===\n\n /**\n * Creates an AsyncResult from an Action.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the Action's promise resolves.\n * If the Action's promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but for Actions.\n * \n * @param action the Action to run to produce the AsyncResult\n * @return an AsyncResult representing the state of the Action\n */\n static fromAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): AsyncResult<T, E, P> {\n return new AsyncResult<T, E, P>().updateFromAction(action);\n }\n\n /**\n * Updates the AsyncResult based on the given Action.\n * Like AsyncResult.fromAction, but in place.\n * @param action an action that will be called directly\n * @returns itself\n */\n updateFromAction(action: Action<T, E, P>) {\n const promise = action((progress) => this.updateProgress(progress));\n return this.updateFromResultPromise(promise);\n }\n\n /**\n * Creates a LazyAction that can be triggered to run the given Action.\n * @param action the Action to run when triggered\n * @returns an object containing the trigger function and the associated AsyncResult\n */\n static makeLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyAction<T, E, P> {\n const result = new AsyncResult<T, E, P>();\n const trigger = () => {\n result.updateFromAction(action);\n };\n\n return { trigger, result };\n }\n\n // === Chaining ===\n\n /**\n * Chains the current AsyncResult with another operation that returns a Result or a Promise of a Result.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * @param fn a function taking as input the successful value of the result, and returning a Result or a Promise of a Result describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: ChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'loading' || settled.state.status === 'idle') {\n throw new Error('Unexpected state after waitForSettled'); // TODO handle this case properly\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n return fn(settled.state.value);\n };\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n /**\n * Chains the current AsyncResult with another operation that returns an AsyncResult.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * Like chain, but for functions returning AsyncResult instead of Result.\n * \n * @param fn a function taking as input the successful value of the result, and returning an AsyncResult describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n const nextAsyncResult = fn(settled.state.value);\n const nextSettled = await nextAsyncResult.toResultPromise();\n return nextSettled;\n }\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n // pipeParallel PipeFunction[] -> AsyncResult<T, E>[]\n // pipeParallelAndCollapse PipeFunction[] -> AsyncResult<T[], E>\n\n /**\n * Ensures that all provided AsyncResults are successful.\n * If all are successful, returns an AsyncResult containing an array of their values.\n * If any AsyncResult is an error, returns an AsyncResult with the first encountered error.\n * @param results an array of AsyncResults to check\n * @returns an AsyncResult containing either an array of successful values or the first encountered error\n */\n static ensureAvailable<R extends readonly AsyncResult<any, any>[]>(results: R): AsyncResult<{ [K in keyof R]: R[K] extends AsyncResult<infer T, any> ? T : never }, R[number] extends AsyncResult<any, infer E> ? E : never> {\n if (results.length === 0) {\n // empty case — TS infers void tuple, so handle gracefully\n return AsyncResult.ok(undefined as never);\n }\n\n const promise = Promise.all(results.map((r) => r.waitForSettled())).then(\n (settledResults) => {\n for (const res of settledResults) {\n if (res.state.status === 'error') {\n return Result.err(res.state.error);\n }\n }\n\n const values = settledResults.map((r) => r.unwrapOrNull()!) as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof R]: R[K] extends AsyncResult<infer T, any>\n ? T\n : never;\n };\n\n return Result.ok(values);\n }\n );\n\n return AsyncResult.fromResultPromise(promise);\n }\n\n // === Generator support ===\n\n /**\n * Yields the current AsyncResult, and if it is successful, returns its value.\n * This allows using AsyncResult instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<AsyncResult<number>, number, any> {\n * const result1 = yield* AsyncResult.ok(5);\n * const result2 = yield* AsyncResult.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<AsyncResult<T, E, P>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n private static _runGeneratorProcessor<T, E extends ErrorBase>(iterator: AsyncResultGenerator<T>): () => Promise<Result<T, E>> {\n return async (): Promise<Result<T, E>> => {\n let result = iterator.next();\n\n while (!result.done) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const yielded = result.value as AsyncResult<any, E>;\n const settled = await yielded.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n result = iterator.next(settled.state.value);\n }\n\n return Result.ok(result.value);\n }\n }\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically.\n * If any yielded AsyncResult is an error, the execution stops and the error is returned.\n * If all yielded AsyncResults are successful, returns a successful AsyncResult with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n * @returns a AsyncResult containing either the final successful value or the first encountered error\n * \n * @example\n * const result = AsyncResult.run(function* () {\n * const value1 = yield* AsyncResult.ok(5);\n * const value2 = yield* AsyncResult.ok(10);\n * return value1 + value2;\n * }\n */\n static run<T, E extends ErrorBase = ErrorBase, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): AsyncResult<T, E, P> {\n return AsyncResult.fromAction(async (notifyProgress: (progress: P) => void) => {\n const iterator = generatorFunc(notifyProgress);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically, and updates this AsyncResult in place.\n * If any yielded AsyncResult is an error, the execution stops and this AsyncResult is updated to that error.\n * If all yielded AsyncResults are successful, this AsyncResult is updated to a successful state with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n */\n runInPlace(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>) {\n return this.updateFromAction((notify) => {\n const iterator = generatorFunc(notify);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n // === Debuging ===\n\n\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? \"<Anonymous AsyncResult>\"} ; State at ${time} :`, this.state);\n }\n\n debug(name?: string) {\n return this.listen((r) => r.log(name));\n }\n}\n","import type { AsyncResult } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\nimport type { Result } from \"./result\";\n\n/**\n * The possible states of an AsyncResultList.\n */\nexport type AsyncResultCollectionState = \"any-loading\" | \"all-settled\";\n\nexport interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {\n key: string;\n result: AsyncResult<T, E>;\n unsub: () => void;\n}\n\n/**\n * Manages a collection of AsyncResult tasks with state tracking and listener support.\n * \n * This class provides a way to group multiple async operations, track their overall state\n * (whether any are loading or all have settled), and react to state changes through listeners.\n * \n * @template T - The success value type for all AsyncResult tasks in this collection\n * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase\n * \n * @example\n * ```typescript\n * const collection = new AsyncResultCollection<User>();\n * const userTask = new AsyncResult<User>();\n * \n * collection.add('user-1', userTask);\n * \n * collection.listen((taskQueue) => {\n * console.log('Collection state changed:', taskQueue.state);\n * });\n * ```\n * \n * @remarks\n * - Tasks can be automatically removed when they settle or kept in the collection\n * - The collection state is either \"any-loading\" (at least one task is loading) or \"all-settled\" (no tasks loading)\n * - Listeners are notified whenever the collection state changes\n * - Use filtering methods to query tasks by their state (success, error, loading)\n */\nexport class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {\n private _list = new Map<string, AsyncResultCollectionItem<T, E>>();\n private _listeners: Set<(taskQueue: AsyncResultCollection<T, E>) => void> = new Set();\n private _state: AsyncResultCollectionState = \"all-settled\";\n\n // === Getters ===\n\n /**\n * Gets the current tasks in the AsyncResultList.\n */\n get tasks() {\n return this._list;\n }\n\n /**\n * Gets the number of tasks in the list.\n */\n get length(): number {\n return this._list.size;\n }\n\n /**\n * Gets all tasks in the list as an array.\n */\n get items(): AsyncResult<T, E>[] {\n return Array.from(this._list.values()).map(i => i.result);\n }\n\n /**\n * Gets all tasks in the list as an array of key-value pairs.\n * Each pair contains the key and the corresponding AsyncResult.\n */\n get entries(): [string, AsyncResult<T, E>][] {\n return Array.from(this._list.entries()).map(([key, item]) => [key, item.result]);\n }\n\n /**\n * Gets the current state of the AsyncResultList.\n */\n get state() {\n return this._state;\n }\n\n private set state(s: AsyncResultCollectionState) {\n this._state = s;\n this._listeners.forEach(f => f(this));\n }\n\n private _onTaskFinished() {\n this.state = this.anyLoading() ? \"any-loading\" : \"all-settled\";\n }\n\n // === Listeners ===\n\n /**\n * Adds a listener that gets called whenever the state of the AsyncResultList changes.\n * @param listener the function to call when the state changes\n * @returns a function to unsubscribe the listener\n */\n listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void) {\n this._listeners.add(listener);\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.\n * @param listener the function to call when an item succeeds\n * @returns a function to unsubscribe the listener\n */\n onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isSuccess()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList errors.\n * @param listener the function to call when an item errors\n * @returns a function to unsubscribe the listener\n */\n onItemError(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isError()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n // === Managing tasks ===\n\n /**\n * Adds an AsyncResult task to the list.\n * @param key the unique key for the task\n * @param task the AsyncResult task to add\n * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)\n * @returns the added AsyncResult task\n */\n add(key: string, task: AsyncResult<T, E>, removeOnSettle: boolean = true): AsyncResult<T, E> {\n let unsub = null;\n if (removeOnSettle) {\n unsub = task.listenUntilSettled((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n this._list.delete(key);\n }, { immediate: true, callOnProgressUpdates: true });\n } else {\n unsub = task.listen((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n }, { immediate: true, callOnProgressUpdates: true });\n }\n\n this._list.set(key, { key, result: task, unsub });\n this.state = \"any-loading\";\n\n return task;\n }\n\n /**\n * Removes a task from the list by its key.\n * @param key the unique key of the task to remove\n * @returns true if the task was removed, false if it was not found\n */\n remove(key: string): boolean {\n const item = this._list.get(key);\n if (!item) return false;\n\n item.unsub();\n this._list.delete(key);\n this._onTaskFinished(); // We may have terminated the last loading task, so we need to update the state.\n return true;\n }\n\n /**\n * Clears all tasks from the list and sets the state to \"all-settled\".\n */\n clear() {\n this._list.forEach(({ unsub }) => unsub());\n this._list.clear();\n this.state = \"all-settled\";\n }\n\n // === Querying tasks ===\n\n /**\n * Checks if any task in the list is currently loading.\n * @returns true if any task is loading, false otherwise\n */\n anyLoading(): boolean {\n for (const item of this._list.values()) {\n if (item.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate.\n * @param predicate the function to test each task\n * @returns an array of tasks that satisfy the predicate\n */\n getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[] {\n const filtered: AsyncResult<T, E>[] = [];\n for (const item of this._list.values()) {\n if (predicate(item.result)) {\n filtered.push(item.result);\n }\n }\n return filtered;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate and maps them using the provided function.\n * @param filterPredicate the function to test each task\n * @param mapFunc the function to map each task\n * @returns an array of mapped values\n */\n getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[] {\n const results: U[] = [];\n for (const item of this._list.values()) {\n if (filterPredicate(item.result)) {\n results.push(mapFunc(item.result));\n }\n }\n return results;\n }\n\n /**\n * Gets all tasks that have succeeded.\n * @returns an array of successful AsyncResult tasks\n */\n getAllSuccess(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isSuccess());\n }\n\n /**\n * Gets the success values of all tasks that have succeeded.\n * @returns an array of successful values\n */\n getAllSuccessValues(): T[] {\n return this.getAllFilteredAndMap((task) => task.isSuccess(), (task) => task.unwrapOrThrow());\n }\n\n /**\n * Gets all tasks that have errored.\n * @returns an array of error AsyncResult tasks\n */\n getAllErrors(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isError());\n }\n\n /**\n * Gets the error values of all tasks that have errored.\n * @returns an array of error values\n */\n getAllErrorValues(): E[] {\n return this.getAllFilteredAndMap((task) => task.isError(), (task) => task.unwrapErrorOrNull()!);\n }\n\n /**\n * Gets all tasks that are currently loading.\n * @returns an array of loading AsyncResult tasks\n */\n getAllLoading(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isLoading());\n }\n\n /**\n * Gets the promises of all tasks that are currently loading.\n * @returns an array of promises for loading tasks\n */\n getAllLoadingPromises(): Promise<Result<T, E>>[] {\n return this.getAllFilteredAndMap((task) => task.isLoading(), (task) => task.toResultPromise());\n }\n\n // === Debugging utilities ===\n\n /**\n * Logs the current state and tasks of the AsyncResultList to the console.\n * @param name an optional name to identify the log\n */\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? '<Anonymous TaskQueue>'} ; State at ${time} :`, this.state, this._list);\n }\n\n /**\n * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.\n * @param name an optional name to identify the log\n * @returns a function to unsubscribe the debug listener\n */\n debug(name?: string) {\n return this.listen(() => {\n this.log(name);\n });\n }\n}","import { AsyncResult, type AsyncResultState, type ChainStep } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\n\ntype KeyedAsyncCacheRefetchOptions = {\n policy: 'refetch' | 'if-error' | 'no-refetch';\n};\n\ntype CacheItem<P, V, E extends ErrorBase = ErrorBase> = {\n result: AsyncResult<V, E>;\n fetcherParams: P;\n valid: boolean;\n lastFetched?: number;\n ttl?: number;\n};\n\nconst _defaultRefetchOptions: KeyedAsyncCacheRefetchOptions = { policy: 'no-refetch' };\n\nfunction defaultParamsToKey<P>(params: P): string {\n if (typeof params === 'object') {\n return JSON.stringify(params);\n }\n return String(params);\n}\n\n/**\n * A cache for asynchronous operations that maps parameter sets to their corresponding AsyncResult.\n * Supports automatic refetching based on specified policies.\n * \n * @template P - The type of the parameters used to fetch values.\n * @template V - The type of the values being fetched.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {\n private _cache: Map<string, CacheItem<P, V, E>> = new Map();\n private _fetcher: ChainStep<P, V, E>;\n private _paramsToKey: (params: P) => string;\n private _cacheTTL?: number;\n\n /**\n * Creates a new KeyedAsyncCache instance.\n * @param fetcher the function used to fetch values based on parameters\n * @param paramsToKey a function that converts parameters to a unique string key (default uses JSON.stringify for objects)\n * @param cacheTTL optional time-to-live for cache entries in milliseconds\n */\n constructor(fetcher: ChainStep<P, V, E>, paramsToKey: (params: P) => string = defaultParamsToKey, cacheTTL: number = Infinity) {\n this._fetcher = fetcher;\n this._paramsToKey = paramsToKey;\n this._cacheTTL = cacheTTL;\n }\n\n private makeCacheItem(result: AsyncResult<V, E>, fetcherParams: P, ttl?: number | undefined): CacheItem<P, V, E> {\n return {\n result,\n fetcherParams,\n ttl: ttl ?? this._cacheTTL,\n valid: true,\n };\n }\n\n private shouldRefetch(existingResult: CacheItem<P, V, E>, refetch: KeyedAsyncCacheRefetchOptions): boolean {\n if (!existingResult.valid) {\n return true;\n }\n if (refetch.policy === 'refetch') {\n return true;\n }\n if (refetch.policy === 'if-error') {\n return existingResult.result.state.status === 'error';\n }\n if (existingResult.ttl !== undefined && existingResult.lastFetched !== undefined) {\n const now = Date.now();\n if (now - existingResult.lastFetched > existingResult.ttl) {\n return true;\n }\n }\n return false;\n }\n\n private updateOrCreateCacheItemFromParams(params: P, cacheItem?: CacheItem<P, V, E>) {\n const promise = Promise.resolve(this._fetcher(params));\n let result = cacheItem?.result.updateFromResultPromise(promise) ?? AsyncResult.fromResultPromise(promise);\n cacheItem = cacheItem ?? this.makeCacheItem(result, params);\n \n promise.then(() => {\n cacheItem.lastFetched = Date.now();\n });\n\n return cacheItem;\n }\n\n /**\n * Gets the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns the AsyncResult corresponding to the given parameters\n */\n get(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): AsyncResult<V, E> {\n const key = this._paramsToKey(params);\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n if (!this.shouldRefetch(cacheItem, refetch)) {\n return cacheItem.result;\n } else {\n this.updateOrCreateCacheItemFromParams(params, cacheItem);\n return cacheItem.result;\n }\n }\n \n const cacheItem = this.updateOrCreateCacheItemFromParams(params);\n this._cache.set(key, cacheItem);\n return cacheItem.result;\n }\n\n /**\n * Gets the settled state of the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * Waits for the AsyncResult to settle before returning its state.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns a promise resolving to the settled state of the AsyncResult\n */\n async getSettledState(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): Promise<AsyncResultState<V, E>> {\n const asyncResult = this.get(params, refetch);\n await asyncResult.waitForSettled();\n return asyncResult.state;\n }\n\n /**\n * Checks if any cached AsyncResult is currently loading.\n * @returns whether any cached AsyncResult is loading\n */\n anyLoading(): boolean {\n for (const cacheItem of this._cache.values()) {\n if (cacheItem.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clears the entire cache.\n */\n clear() {\n this._cache.clear();\n }\n\n /**\n * Invalidates the cache entry for the given key.\n * @param key the key of the cache entry to invalidate\n */\n invalidateKey(key: string) {\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n cacheItem.valid = false;\n }\n }\n\n /**\n * Invalidates the cache entry for the given parameters.\n * @param params the parameters of the cache entry to invalidate\n */\n invalidateParams(params: P) {\n const key = this._paramsToKey(params);\n this.invalidateKey(key);\n }\n\n /**\n * Invalidates all cache entries.\n */\n invalidateAll() {\n for (const cacheItem of this._cache.values()) {\n cacheItem.valid = false;\n }\n }\n\n /**\n * Gets all cache items.\n * @returns an array of all cache items\n */\n get items() {\n return Array.from(this._cache.values());\n }\n\n /**\n * Gets the number of cache items.\n * @returns the number of cache items\n */\n get size() {\n return this._cache.size;\n }\n\n /**\n * Gets all cache items with successful results.\n * @returns an array of cache items with successful results\n */\n get successfulItems() {\n return Array.from(this._cache.values()).filter(item => item.result.isSuccess());\n }\n}\n","import { AsyncResult } from \"./asyncResult\";\n\nexport function delay(ms: number): AsyncResult<true> {\n return AsyncResult.fromValuePromise(new Promise(resolve => {\n setTimeout(() => resolve(true), ms);\n }));\n}"],"mappings":"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","names":["cacheItem"]}
1
+ {"version":3,"sources":["../../src/core/index.ts","../../src/core/error.ts","../../src/core/result.ts","../../src/core/asyncResult.ts","../../src/core/asyncResultCollection.ts","../../src/core/cache.ts","../../src/core/utils.ts"],"sourcesContent":["export * from \"./error\";\nexport * from \"./result\";\nexport * from \"./asyncResult\";\nexport * from \"./asyncResultCollection\";\nexport * from \"./cache\";\nexport * from \"./utils\";","/**\n * Base class for error handling, providing structured error information and logging.\n * @class ErrorBase\n * @property {string} code - The error code.\n * @property {string | undefined} message - The error message (optional).\n * @property {unknown} thrownError - The original error object, if any (optional).\n * \n * @constructor\n * @param {string} code - The error code.\n * @param {string} [message] - The error message.\n * @param {unknown} [thrownError] - The original error object, if any.\n * @param {boolean} [log=true] - Whether to log the error upon creation.\n */\nexport class ErrorBase {\n code: string;\n message?: string | undefined;\n thrownError?: unknown;\n\n constructor(code: string, message?: string, thrownError?: unknown, log: boolean = true) {\n this.code = code;\n this.message = message;\n this.thrownError = thrownError;\n\n if (log) {\n this.logError();\n }\n }\n\n /**\n * Converts the error to a string representation, on the format \"Error {code}: {message}\".\n * @returns a string representation of the error\n */\n toString(): string {\n return `Error ${this.code}: ${this.message ?? ''}`;\n }\n\n /**\n * Logs the error to the console, uses console.error and ErrorBase.toString() internally.\n * Logs thrownError if it was provided on creation.\n */\n logError(): void {\n if (this.thrownError) {\n console.error(this.toString(), this.thrownError);\n } else {\n console.error(this.toString());\n }\n }\n}\n","import { ErrorBase } from \"./error\";\n\n/**\n * Type representing the state of a Result, either success with a value of type T,\n * or error with an error of type E (defaulting to ErrorBase).\n */\nexport type ResultState<T, E extends ErrorBase = ErrorBase> =\n | { status: 'success'; value: T }\n | { status: 'error'; error: E };\n\n/**\n * Class representing the result of an operation that can either succeed with a value of type T,\n * or fail with an error of type E (defaulting to ErrorBase).\n * Provides methods for unwrapping the result, chaining operations, and handling errors.\n * @class Result\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class Result<T, E extends ErrorBase = ErrorBase> {\n private _state: ResultState<T, E>;\n\n /**\n * Creates a new Result instance with the given state.\n * @param state the state of the created Result\n */\n constructor(state: ResultState<T, E>) {\n this._state = state;\n }\n\n /** Returns the internal state of the Result. */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the Result is successful.\n * @returns whether or not the result is successful\n */\n isSuccess(): boolean {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the Result is an error.\n * @returns whether or not the result is an error\n */\n isError(): boolean {\n return this._state.status === 'error';\n }\n\n /**\n * Creates a successful Result with the given value.\n * @param value the result of the successful operation\n * @returns a successful Result\n */\n static ok<T, E extends ErrorBase = ErrorBase>(value: T): Result<T, E> {\n return new Result({ status: 'success', value });\n }\n\n /**\n * Creates an error Result with the given error.\n * @param error the error of the failed operation\n * @returns an error Result\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): Result<never, E> {\n return new Result({ status: 'error', error });\n }\n\n /**\n * Creates an error Result (containing an ErrorBase) with the given error code and optional message.\n * @param code the error code\n * @param message an optional error message\n * @returns an error Result\n */\n static errTag(code: string, message?: string, thrownError?: unknown): Result<never, ErrorBase> {\n return Result.err(new ErrorBase(code, message, thrownError));\n }\n\n /**\n * Returns the successful value (if the Result is successful) or null (if it is an error).\n * @returns either the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value (if the Result is successful) or throws an error (if it is an error).\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap a Result that is not successful');\n }\n\n /**\n * Returns the successful value (if the Result is successful) or a default value (if it is an error).\n * @param defaultValue the default value to return if the Result is an error\n * @returns either the successful value or the default value\n */\n unwrapOr<O>(defaultValue: O): T | O {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return defaultValue;\n }\n\n /**\n * Transforms a Promise of a successful value into a Promise of a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * @param promise the promise to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return promise\n .then((value) => Result.ok<T, E>(value))\n .catch((error) => Result.err(errorMapper(error)));\n }\n\n /**\n * Executes an asynchronous function and transforms its result into a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * Same as Result.tryPromise(fn(), errorMapper).\n * @param fn the asynchronous function to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryFunction<T, E extends ErrorBase = ErrorBase>(fn: () => Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return Result.tryPromise(fn(), errorMapper);\n }\n\n /**\n * Chains the current Result with another operation that returns a ResultState.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * @param fn a function taking as input the successful value of the result, and returning a ResultState describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => ResultState<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return new Result<O, E | E2>(fn(this._state.value));\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * Chains the current Result with another operation that returns a Result.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * Same as chain, but the function returns a Result directly instead of a ResultState.\n * @param fn a function taking as input the successful value of the result, and returning a Result describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => Result<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return fn(this._state.value);\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * @yields the current Result, and if it is successful, returns its value.\n * This allows using Result instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<Result<number>, number, any> {\n * const result1 = yield* Result.ok(5);\n * const result2 = yield* Result.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<Result<T, E>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n /**\n * Runs a generator function that yields Result instances, propagating errors automatically.\n * If any yielded Result is an error, the execution stops and the error is returned.\n * If all yielded Results are successful, returns a successful Result with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for Result handling in generator functions.\n * \n * @param generator a generator function that yields Result instances\n * @returns a Result containing either the final successful value or the first encountered error\n * \n * @example\n * const result = Result.run(function* () {\n * const value1 = yield* Result.ok(5);\n * const value2 = yield* Result.ok(10);\n * return value1 + value2;\n * });\n */\n static run<T, E extends ErrorBase = ErrorBase>(generator: () => Generator<Result<any, E>, T, any>): Result<T, E> {\n const iterator = generator();\n let result = iterator.next();\n\n while (!result.done) {\n const yielded = result.value;\n if (yielded._state.status === 'error') {\n return Result.err(yielded._state.error);\n }\n result = iterator.next(yielded._state.value);\n }\n\n return Result.ok(result.value);\n }\n}\n","import { ErrorBase } from \"./error\";\nimport { Result, type ResultState } from \"./result\";\n\n/**\n * Type representing the state of an AsyncResult.\n * It can be 'idle', 'loading' with a promise and an optional progress information of type P, or a settled ResultState (success or error).\n */\nexport type AsyncResultState<T, E extends ErrorBase = ErrorBase, P = unknown> =\n | { status: 'idle' }\n | { status: 'loading'; promise: Promise<Result<T, E>>; progress?: P }\n | ResultState<T, E>;\n\n\n/**\n * An Action is a function returning a Promise of a Result.\n */\nexport type Action<T, E extends ErrorBase = ErrorBase, P = unknown> = (notifyProgress: (progress: P) => void) => Promise<Result<T, E>>;\n\n/**\n * A LazyAction is an object containing a trigger function to start the action, and the AsyncResult representing the action's state.\n */\nexport type LazyAction<T, E extends ErrorBase = ErrorBase, P = unknown> = {\n trigger: () => void;\n result: AsyncResult<T, E, P>;\n};\n\n/**\n * A ChainStep is a function that takes an arbitrary input and returns a Result or a Promise of a Result.\n * It takes an input of type I and returns either a Result<O, E> or a Promise<Result<O, E>>.\n * \n * Used for chaining operations on AsyncResult.\n */\nexport type ChainStep<I, O, E extends ErrorBase = ErrorBase> = (input: I) => Result<O, E> | Promise<Result<O, E>>;\n\n/**\n * A FlatChainStep is a function that takes an arbitrary input and returns an AsyncResult.\n * It takes an input of type I and returns an AsyncResult<O, E>.\n * \n * Used for flat-chaining operations on AsyncResult.\n */\nexport type FlatChainStep<I, O, E extends ErrorBase = ErrorBase, P = unknown> = (input: I) => AsyncResult<O, E, P>;\n\n/**\n * Type representing a generator function that yields AsyncResult instances and returns a final value of type T.\n * \n * Used for running generators with AsyncResult.run().\n */\nexport type AsyncResultGenerator<T> = Generator<AsyncResult<any, any>, T, any>;\n\n/**\n * Type representing a listener function for AsyncResult state changes.\n */\nexport type AsyncResultListener<T, E extends ErrorBase = ErrorBase, P = unknown> = (result: AsyncResult<T, E, P>) => any;\n\nexport interface AsyncResultListenerOptions {\n immediate?: boolean;\n callOnProgressUpdates?: boolean;\n}\n\ninterface AsyncResultListenerEntry<T, E extends ErrorBase, P> {\n listener: AsyncResultListener<T, E, P>;\n options: AsyncResultListenerOptions;\n}\n\n/**\n * Class representing the asynchronous result of an operation that can be idle, loading, successful, or failed.\n * Provides methods for listening to state changes, updating state, chaining operations, and converting to and from promises.\n * @class AsyncResult\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @template P - The type of the progress information for loading state (default is unknown).\n */\nexport class AsyncResult<T, E extends ErrorBase = ErrorBase, P = unknown> {\n private _state: AsyncResultState<T, E, P>;\n private _listeners: Set<AsyncResultListenerEntry<T, E, P>> = new Set();\n\n constructor(state?: AsyncResultState<T, E, P>) {\n this._state = state || { status: 'idle' };\n }\n\n\n\n // === Getting current state ===\n\n /**\n * Returns the internal state of the AsyncResult.\n */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the AsyncResult is successful.\n * @returns whether or not the result is successful\n */\n isSuccess() {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the AsyncResult is an error.\n * @returns whether or not the result is an error\n */\n isError() {\n return this._state.status === 'error';\n }\n\n /**\n * Checks if the AsyncResult is idle.\n * @returns whether or not the result is idle\n */\n isIdle() {\n return this._state.status === 'idle';\n }\n\n /**\n * Checks if the AsyncResult is loading.\n * @returns whether or not the result is loading\n */\n isLoading() {\n return this._state.status === 'loading';\n }\n\n\n\n // === Unwrapping values ===\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise returns null.\n * @returns the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap an AsyncResult that is not successful');\n }\n\n /**\n * Returns the error value if the AsyncResult is in an error state, otherwise returns null.\n * @returns the error value or null\n */\n unwrapErrorOrNull(): E | null {\n if (this._state.status === 'error') {\n return this._state.error;\n }\n return null;\n }\n\n /**\n * Returns the progress information if the AsyncResult is in a loading state, otherwise returns null.\n * @returns the progress information or null\n */\n getProgressOrNull(): P | null {\n if (this._state.status === 'loading') {\n return this._state.progress ?? null;\n }\n return null;\n }\n\n // === Creating/updating from settled values ===\n\n private set state(newState: AsyncResultState<T, E, P>) {\n const oldState = this._state;\n\n this._state = newState;\n this._listeners.forEach((listenerEntry) => {\n if ((oldState.status !== 'loading' || newState.status !== 'loading') || listenerEntry.options.callOnProgressUpdates) {\n listenerEntry.listener(this)\n }\n });\n }\n\n private setState(newState: AsyncResultState<T, E, P>) {\n this.state = newState;\n }\n\n /**\n * Creates a successful AsyncResult with the given value.\n * @param value the result of the successful operation\n * @returns a successful AsyncResult\n */\n static ok<T>(value: T): AsyncResult<T, never> {\n return new AsyncResult<T, never>({ status: 'success', value });\n }\n\n /**\n * Creates an error AsyncResult with the given error.\n * @param error the error of the failed operation\n * @returns an error AsyncResult\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): AsyncResult<never, E> {\n return new AsyncResult<never, E>({ status: 'error', error });\n }\n\n /**\n * Creates an error AsyncResult with a new ErrorBase constructed from the given parameters.\n * @param code the error code\n * @param message the error message (optional)\n * @param thrownError the original error object, if any (optional)\n * @param log whether to log the error upon creation (default is true)\n * @returns an error AsyncResult\n */\n static errTag(code: string, message?: string, thrownError?: unknown, log: boolean = true): AsyncResult<never, ErrorBase> {\n const error = new ErrorBase(code, message, thrownError, log);\n return AsyncResult.err(error);\n }\n\n /**\n * Updates the AsyncResult to a successful state with the given value.\n * Like AsyncResult.ok, but in place.\n * @param value the successful value\n */\n updateFromValue(value: T) {\n this.state = { status: 'success', value };\n return this;\n }\n\n /**\n * Updates the AsyncResult to an error state with the given error.\n * Like AsyncResult.err, but in place.\n * @param error the error\n */\n updateFromError(error: E) {\n this.state = { status: 'error', error };\n return this;\n }\n\n /**\n * Updates the progress information of the AsyncResult if it is currently loading.\n * @param progress progress information to include in the loading state\n */\n updateProgress(progress: P) {\n if (this._state.status === 'loading') {\n this.state = { ...this._state, progress };\n }\n return this;\n }\n\n\n // === Creating/updating from promises ===\n\n /**\n * Creates an AsyncResult from a promise that resolves to a value.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromResultPromise, but for promise that only resolves to a successful value and not a Result.\n * \n * @param promise the promise that resolves to a value\n * @returns an AsyncResult representing the state of the promise\n */\n static fromValuePromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromValuePromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromValuePromise, but in place.\n * \n * @param promise the promise that resolves to a value\n */\n updateFromValuePromise(promise: Promise<T>) {\n const resultStatePromise = async (): Promise<Result<T, E>> => {\n try {\n const value = await promise;\n return Result.ok(value);\n } catch (error) {\n return Result.err(error as E);\n }\n };\n return this.updateFromResultPromise(resultStatePromise());\n }\n\n\n // === Waiting for settled state and get result ===\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading.\n * @returns itself once settled\n */\n async waitForSettled(): Promise<AsyncResult<T, E, P>> {\n if (this._state.status === 'loading') {\n try {\n const value = await this._state.promise;\n this._state = value.state;\n } catch (error) {\n this._state = { status: 'error', error: error as E };\n }\n }\n return this;\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns a Result representing the settled state.\n * @returns a Result representing the settled state\n */\n async toResultPromise(): Promise<Result<T, E>> {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'idle' || settled.state.status === 'loading') {\n throw new Error('Cannot convert idle or loading AsyncResult to ResultState');\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n return Result.ok(settled.state.value);\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n async toValueOrThrowPromise(): Promise<T> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrThrow();\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or null.\n * @returns either the successful value or null\n */\n async toValueOrNullPromise(): Promise<T | null> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrNull();\n }\n\n /**\n * Creates an AsyncResult from a promise that resolves to a Result.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * @param promise the promise that resolves to a Result\n * @returns an AsyncResult representing the state of the promise\n */\n static fromResultPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromResultPromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The promise must produce a Result once settled (meaning it should return the error in the result when possible).\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but in place.\n * \n * @param promise the promise that resolves to a Result\n */\n updateFromResultPromise(promise: Promise<Result<T, E>>) {\n this.state = { status: 'loading', promise };\n promise\n .then((res) => {\n this.state = res.state;\n })\n .catch((error) => {\n this.updateFromError(new ErrorBase('defect_on_updateFromResultPromise', 'The promise provided to AsyncResult rejected', error) as E);\n });\n return this;\n }\n\n\n // === Listeners ===\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes.\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listen(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const entry: AsyncResultListenerEntry<T, E, P> = { listener, options };\n this._listeners.add(entry);\n\n if (options.immediate) {\n listener(this);\n }\n\n return () => {\n this._listeners.delete(entry);\n };\n }\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes, and automatically unsubscribes once it is settled (success or error).\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listenUntilSettled(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const unsub = this.listen((result) => {\n listener(result);\n if (result.state.status === 'success' || result.state.status === 'error') {\n unsub();\n }\n }, options);\n\n return unsub;\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on a success.\n * @param callback callback called once the AsyncResult settled on a success\n * @returns A function to unsubscribe early\n */\n onSuccessOnce(callback: (value: T) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on a success.\n * @param callback callback called every time the AsyncResult settles on a success\n * @returns A function to unsubscribe\n */\n onSuccessPerpetual(callback: (value: T) => void) {\n return this.listen((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on an error.\n * @param callback callback called once the AsyncResult settled on an error\n * @returns A function to unsubscribe early\n */\n onErrorOnce(callback: (error: E) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on an error.\n * @param callback callback called every time the AsyncResult settles on an error\n * @returns A function to unsubscribe\n */\n onErrorPerpetual(callback: (error: E) => void) {\n return this.listen((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n // === Mirroring ===\n\n /**\n * Mirrors the state of another AsyncResult into this one.\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirror(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listen((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n /**\n * Mirrors the state of another AsyncResult into this one, until the other AsyncResult is settled (success or error).\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match, until the other AsyncResult is settled.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirrorUntilSettled(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listenUntilSettled((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n\n // === Actions ===\n\n /**\n * Creates an AsyncResult from an Action.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the Action's promise resolves.\n * If the Action's promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but for Actions.\n * \n * @param action the Action to run to produce the AsyncResult\n * @return an AsyncResult representing the state of the Action\n */\n static fromAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): AsyncResult<T, E, P> {\n return new AsyncResult<T, E, P>().updateFromAction(action);\n }\n\n /**\n * Updates the AsyncResult based on the given Action.\n * Like AsyncResult.fromAction, but in place.\n * @param action an action that will be called directly\n * @returns itself\n */\n updateFromAction(action: Action<T, E, P>) {\n console.log(\"===== updateFromAction called =====\");\n console.log(\"Action function:\", action);\n const promise = action((progress) => this.updateProgress(progress));\n return this.updateFromResultPromise(promise);\n }\n\n /**\n * Creates a LazyAction that can be triggered to run the given Action.\n * @param action the Action to run when triggered\n * @returns an object containing the trigger function and the associated AsyncResult\n */\n static makeLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyAction<T, E, P> {\n const result = new AsyncResult<T, E, P>();\n const trigger = () => {\n result.updateFromAction(action);\n };\n\n return { trigger, result };\n }\n\n // === Chaining ===\n\n /**\n * Chains the current AsyncResult with another operation that returns a Result or a Promise of a Result.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * @param fn a function taking as input the successful value of the result, and returning a Result or a Promise of a Result describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: ChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'loading' || settled.state.status === 'idle') {\n throw new Error('Unexpected state after waitForSettled'); // TODO handle this case properly\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n return fn(settled.state.value);\n };\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n /**\n * Chains the current AsyncResult with another operation that returns an AsyncResult.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * Like chain, but for functions returning AsyncResult instead of Result.\n * \n * @param fn a function taking as input the successful value of the result, and returning an AsyncResult describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n const nextAsyncResult = fn(settled.state.value);\n const nextSettled = await nextAsyncResult.toResultPromise();\n return nextSettled;\n }\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n // pipeParallel PipeFunction[] -> AsyncResult<T, E>[]\n // pipeParallelAndCollapse PipeFunction[] -> AsyncResult<T[], E>\n\n /**\n * Ensures that all provided AsyncResults are successful.\n * If all are successful, returns an AsyncResult containing an array of their values.\n * If any AsyncResult is an error, returns an AsyncResult with the first encountered error.\n * @param results an array of AsyncResults to check\n * @returns an AsyncResult containing either an array of successful values or the first encountered error\n */\n static ensureAvailable<R extends readonly AsyncResult<any, any>[]>(results: R): AsyncResult<{ [K in keyof R]: R[K] extends AsyncResult<infer T, any> ? T : never }, R[number] extends AsyncResult<any, infer E> ? E : never> {\n if (results.length === 0) {\n // empty case — TS infers void tuple, so handle gracefully\n return AsyncResult.ok(undefined as never);\n }\n\n const promise = Promise.all(results.map((r) => r.waitForSettled())).then(\n (settledResults) => {\n for (const res of settledResults) {\n if (res.state.status === 'error') {\n return Result.err(res.state.error);\n }\n }\n\n const values = settledResults.map((r) => r.unwrapOrNull()!) as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof R]: R[K] extends AsyncResult<infer T, any>\n ? T\n : never;\n };\n\n return Result.ok(values);\n }\n );\n\n return AsyncResult.fromResultPromise(promise);\n }\n\n // === Generator support ===\n\n /**\n * Yields the current AsyncResult, and if it is successful, returns its value.\n * This allows using AsyncResult instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<AsyncResult<number>, number, any> {\n * const result1 = yield* AsyncResult.ok(5);\n * const result2 = yield* AsyncResult.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<AsyncResult<T, E, P>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n private static _runGeneratorProcessor<T, E extends ErrorBase>(iterator: AsyncResultGenerator<T>): () => Promise<Result<T, E>> {\n return async (): Promise<Result<T, E>> => {\n let result = iterator.next();\n\n while (!result.done) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const yielded = result.value as AsyncResult<any, E>;\n const settled = await yielded.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n result = iterator.next(settled.state.value);\n }\n\n return Result.ok(result.value);\n }\n }\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically.\n * If any yielded AsyncResult is an error, the execution stops and the error is returned.\n * If all yielded AsyncResults are successful, returns a successful AsyncResult with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n * @returns a AsyncResult containing either the final successful value or the first encountered error\n * \n * @example\n * const result = AsyncResult.run(function* () {\n * const value1 = yield* AsyncResult.ok(5);\n * const value2 = yield* AsyncResult.ok(10);\n * return value1 + value2;\n * }\n */\n static run<T, E extends ErrorBase = ErrorBase, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): AsyncResult<T, E, P> {\n return AsyncResult.fromAction(async (notifyProgress: (progress: P) => void) => {\n const iterator = generatorFunc(notifyProgress);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically, and updates this AsyncResult in place.\n * If any yielded AsyncResult is an error, the execution stops and this AsyncResult is updated to that error.\n * If all yielded AsyncResults are successful, this AsyncResult is updated to a successful state with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n */\n runInPlace(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>) {\n console.log(\"===== runInPlace called =====\");\n console.log(\"Generator function:\", generatorFunc);\n return this.updateFromAction((notify) => {\n const iterator = generatorFunc(notify);\n console.log(\"Generator iterator:\", iterator);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n // === Debuging ===\n\n\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? \"<Anonymous AsyncResult>\"} ; State at ${time} :`, this.state);\n }\n\n debug(name?: string) {\n return this.listen((r) => r.log(name));\n }\n}\n","import type { AsyncResult } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\nimport type { Result } from \"./result\";\n\n/**\n * The possible states of an AsyncResultList.\n */\nexport type AsyncResultCollectionState = \"any-loading\" | \"all-settled\";\n\nexport interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {\n key: string;\n result: AsyncResult<T, E>;\n unsub: () => void;\n}\n\n/**\n * Manages a collection of AsyncResult tasks with state tracking and listener support.\n * \n * This class provides a way to group multiple async operations, track their overall state\n * (whether any are loading or all have settled), and react to state changes through listeners.\n * \n * @template T - The success value type for all AsyncResult tasks in this collection\n * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase\n * \n * @example\n * ```typescript\n * const collection = new AsyncResultCollection<User>();\n * const userTask = new AsyncResult<User>();\n * \n * collection.add('user-1', userTask);\n * \n * collection.listen((taskQueue) => {\n * console.log('Collection state changed:', taskQueue.state);\n * });\n * ```\n * \n * @remarks\n * - Tasks can be automatically removed when they settle or kept in the collection\n * - The collection state is either \"any-loading\" (at least one task is loading) or \"all-settled\" (no tasks loading)\n * - Listeners are notified whenever the collection state changes\n * - Use filtering methods to query tasks by their state (success, error, loading)\n */\nexport class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {\n private _list = new Map<string, AsyncResultCollectionItem<T, E>>();\n private _listeners: Set<(taskQueue: AsyncResultCollection<T, E>) => void> = new Set();\n private _state: AsyncResultCollectionState = \"all-settled\";\n\n // === Getters ===\n\n /**\n * Gets the current tasks in the AsyncResultList.\n */\n get tasks() {\n return this._list;\n }\n\n /**\n * Gets the number of tasks in the list.\n */\n get length(): number {\n return this._list.size;\n }\n\n /**\n * Gets all tasks in the list as an array.\n */\n get items(): AsyncResult<T, E>[] {\n return Array.from(this._list.values()).map(i => i.result);\n }\n\n /**\n * Gets all tasks in the list as an array of key-value pairs.\n * Each pair contains the key and the corresponding AsyncResult.\n */\n get entries(): [string, AsyncResult<T, E>][] {\n return Array.from(this._list.entries()).map(([key, item]) => [key, item.result]);\n }\n\n /**\n * Gets the current state of the AsyncResultList.\n */\n get state() {\n return this._state;\n }\n\n private set state(s: AsyncResultCollectionState) {\n this._state = s;\n this._listeners.forEach(f => f(this));\n }\n\n private _onTaskFinished() {\n this.state = this.anyLoading() ? \"any-loading\" : \"all-settled\";\n }\n\n // === Listeners ===\n\n /**\n * Adds a listener that gets called whenever the state of the AsyncResultList changes.\n * @param listener the function to call when the state changes\n * @returns a function to unsubscribe the listener\n */\n listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void) {\n this._listeners.add(listener);\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.\n * @param listener the function to call when an item succeeds\n * @returns a function to unsubscribe the listener\n */\n onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isSuccess()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList errors.\n * @param listener the function to call when an item errors\n * @returns a function to unsubscribe the listener\n */\n onItemError(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isError()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n // === Managing tasks ===\n\n /**\n * Adds an AsyncResult task to the list.\n * @param key the unique key for the task\n * @param task the AsyncResult task to add\n * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)\n * @returns the added AsyncResult task\n */\n add(key: string, task: AsyncResult<T, E>, removeOnSettle: boolean = true): AsyncResult<T, E> {\n let unsub = null;\n if (removeOnSettle) {\n unsub = task.listenUntilSettled((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n this._list.delete(key);\n }, { immediate: true, callOnProgressUpdates: true });\n } else {\n unsub = task.listen((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n }, { immediate: true, callOnProgressUpdates: true });\n }\n\n this._list.set(key, { key, result: task, unsub });\n this.state = \"any-loading\";\n\n return task;\n }\n\n /**\n * Removes a task from the list by its key.\n * @param key the unique key of the task to remove\n * @returns true if the task was removed, false if it was not found\n */\n remove(key: string): boolean {\n const item = this._list.get(key);\n if (!item) return false;\n\n item.unsub();\n this._list.delete(key);\n this._onTaskFinished(); // We may have terminated the last loading task, so we need to update the state.\n return true;\n }\n\n /**\n * Clears all tasks from the list and sets the state to \"all-settled\".\n */\n clear() {\n this._list.forEach(({ unsub }) => unsub());\n this._list.clear();\n this.state = \"all-settled\";\n }\n\n // === Querying tasks ===\n\n /**\n * Checks if any task in the list is currently loading.\n * @returns true if any task is loading, false otherwise\n */\n anyLoading(): boolean {\n for (const item of this._list.values()) {\n if (item.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate.\n * @param predicate the function to test each task\n * @returns an array of tasks that satisfy the predicate\n */\n getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[] {\n const filtered: AsyncResult<T, E>[] = [];\n for (const item of this._list.values()) {\n if (predicate(item.result)) {\n filtered.push(item.result);\n }\n }\n return filtered;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate and maps them using the provided function.\n * @param filterPredicate the function to test each task\n * @param mapFunc the function to map each task\n * @returns an array of mapped values\n */\n getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[] {\n const results: U[] = [];\n for (const item of this._list.values()) {\n if (filterPredicate(item.result)) {\n results.push(mapFunc(item.result));\n }\n }\n return results;\n }\n\n /**\n * Gets all tasks that have succeeded.\n * @returns an array of successful AsyncResult tasks\n */\n getAllSuccess(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isSuccess());\n }\n\n /**\n * Gets the success values of all tasks that have succeeded.\n * @returns an array of successful values\n */\n getAllSuccessValues(): T[] {\n return this.getAllFilteredAndMap((task) => task.isSuccess(), (task) => task.unwrapOrThrow());\n }\n\n /**\n * Gets all tasks that have errored.\n * @returns an array of error AsyncResult tasks\n */\n getAllErrors(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isError());\n }\n\n /**\n * Gets the error values of all tasks that have errored.\n * @returns an array of error values\n */\n getAllErrorValues(): E[] {\n return this.getAllFilteredAndMap((task) => task.isError(), (task) => task.unwrapErrorOrNull()!);\n }\n\n /**\n * Gets all tasks that are currently loading.\n * @returns an array of loading AsyncResult tasks\n */\n getAllLoading(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isLoading());\n }\n\n /**\n * Gets the promises of all tasks that are currently loading.\n * @returns an array of promises for loading tasks\n */\n getAllLoadingPromises(): Promise<Result<T, E>>[] {\n return this.getAllFilteredAndMap((task) => task.isLoading(), (task) => task.toResultPromise());\n }\n\n // === Debugging utilities ===\n\n /**\n * Logs the current state and tasks of the AsyncResultList to the console.\n * @param name an optional name to identify the log\n */\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? '<Anonymous TaskQueue>'} ; State at ${time} :`, this.state, this._list);\n }\n\n /**\n * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.\n * @param name an optional name to identify the log\n * @returns a function to unsubscribe the debug listener\n */\n debug(name?: string) {\n return this.listen(() => {\n this.log(name);\n });\n }\n}","import { AsyncResult, type AsyncResultState, type ChainStep } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\n\ntype KeyedAsyncCacheRefetchOptions = {\n policy: 'refetch' | 'if-error' | 'no-refetch';\n};\n\ntype CacheItem<P, V, E extends ErrorBase = ErrorBase> = {\n result: AsyncResult<V, E>;\n fetcherParams: P;\n valid: boolean;\n lastFetched?: number;\n ttl?: number;\n};\n\nconst _defaultRefetchOptions: KeyedAsyncCacheRefetchOptions = { policy: 'no-refetch' };\n\nfunction defaultParamsToKey<P>(params: P): string {\n if (typeof params === 'object') {\n return JSON.stringify(params);\n }\n return String(params);\n}\n\n/**\n * A cache for asynchronous operations that maps parameter sets to their corresponding AsyncResult.\n * Supports automatic refetching based on specified policies.\n * \n * @template P - The type of the parameters used to fetch values.\n * @template V - The type of the values being fetched.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {\n private _cache: Map<string, CacheItem<P, V, E>> = new Map();\n private _fetcher: ChainStep<P, V, E>;\n private _paramsToKey: (params: P) => string;\n private _cacheTTL?: number;\n\n /**\n * Creates a new KeyedAsyncCache instance.\n * @param fetcher the function used to fetch values based on parameters\n * @param paramsToKey a function that converts parameters to a unique string key (default uses JSON.stringify for objects)\n * @param cacheTTL optional time-to-live for cache entries in milliseconds\n */\n constructor(fetcher: ChainStep<P, V, E>, paramsToKey: (params: P) => string = defaultParamsToKey, cacheTTL: number = Infinity) {\n this._fetcher = fetcher;\n this._paramsToKey = paramsToKey;\n this._cacheTTL = cacheTTL;\n }\n\n private makeCacheItem(result: AsyncResult<V, E>, fetcherParams: P, ttl?: number | undefined): CacheItem<P, V, E> {\n return {\n result,\n fetcherParams,\n ttl: ttl ?? this._cacheTTL,\n valid: true,\n };\n }\n\n private shouldRefetch(existingResult: CacheItem<P, V, E>, refetch: KeyedAsyncCacheRefetchOptions): boolean {\n if (!existingResult.valid) {\n return true;\n }\n if (refetch.policy === 'refetch') {\n return true;\n }\n if (refetch.policy === 'if-error') {\n return existingResult.result.state.status === 'error';\n }\n if (existingResult.ttl !== undefined && existingResult.lastFetched !== undefined) {\n const now = Date.now();\n if (now - existingResult.lastFetched > existingResult.ttl) {\n return true;\n }\n }\n return false;\n }\n\n private updateOrCreateCacheItemFromParams(params: P, cacheItem?: CacheItem<P, V, E>) {\n const promise = Promise.resolve(this._fetcher(params));\n let result = cacheItem?.result.updateFromResultPromise(promise) ?? AsyncResult.fromResultPromise(promise);\n cacheItem = cacheItem ?? this.makeCacheItem(result, params);\n \n promise.then(() => {\n cacheItem.lastFetched = Date.now();\n });\n\n return cacheItem;\n }\n\n /**\n * Gets the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns the AsyncResult corresponding to the given parameters\n */\n get(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): AsyncResult<V, E> {\n const key = this._paramsToKey(params);\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n if (!this.shouldRefetch(cacheItem, refetch)) {\n return cacheItem.result;\n } else {\n this.updateOrCreateCacheItemFromParams(params, cacheItem);\n return cacheItem.result;\n }\n }\n \n const cacheItem = this.updateOrCreateCacheItemFromParams(params);\n this._cache.set(key, cacheItem);\n return cacheItem.result;\n }\n\n /**\n * Gets the settled state of the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * Waits for the AsyncResult to settle before returning its state.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns a promise resolving to the settled state of the AsyncResult\n */\n async getSettledState(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): Promise<AsyncResultState<V, E>> {\n const asyncResult = this.get(params, refetch);\n await asyncResult.waitForSettled();\n return asyncResult.state;\n }\n\n /**\n * Checks if any cached AsyncResult is currently loading.\n * @returns whether any cached AsyncResult is loading\n */\n anyLoading(): boolean {\n for (const cacheItem of this._cache.values()) {\n if (cacheItem.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clears the entire cache.\n */\n clear() {\n this._cache.clear();\n }\n\n /**\n * Invalidates the cache entry for the given key.\n * @param key the key of the cache entry to invalidate\n */\n invalidateKey(key: string) {\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n cacheItem.valid = false;\n }\n }\n\n /**\n * Invalidates the cache entry for the given parameters.\n * @param params the parameters of the cache entry to invalidate\n */\n invalidateParams(params: P) {\n const key = this._paramsToKey(params);\n this.invalidateKey(key);\n }\n\n /**\n * Invalidates all cache entries.\n */\n invalidateAll() {\n for (const cacheItem of this._cache.values()) {\n cacheItem.valid = false;\n }\n }\n\n /**\n * Gets all cache items.\n * @returns an array of all cache items\n */\n get items() {\n return Array.from(this._cache.values());\n }\n\n /**\n * Gets the number of cache items.\n * @returns the number of cache items\n */\n get size() {\n return this._cache.size;\n }\n\n /**\n * Gets all cache items with successful results.\n * @returns an array of cache items with successful results\n */\n get successfulItems() {\n return Array.from(this._cache.values()).filter(item => item.result.isSuccess());\n }\n}\n","import { AsyncResult } from \"./asyncResult\";\n\nexport function delay(ms: number): AsyncResult<true> {\n return AsyncResult.fromValuePromise(new Promise(resolve => {\n setTimeout(() => resolve(true), ms);\n }));\n}"],"mappings":"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","names":["cacheItem"]}
@@ -606,6 +606,8 @@ var AsyncResult = class _AsyncResult {
606
606
  * @returns itself
607
607
  */
608
608
  updateFromAction(action) {
609
+ console.log("===== updateFromAction called =====");
610
+ console.log("Action function:", action);
609
611
  const promise = action((progress) => this.updateProgress(progress));
610
612
  return this.updateFromResultPromise(promise);
611
613
  }
@@ -766,8 +768,11 @@ var AsyncResult = class _AsyncResult {
766
768
  * @param generatorFunc a generator function that yields AsyncResult instances
767
769
  */
768
770
  runInPlace(generatorFunc) {
771
+ console.log("===== runInPlace called =====");
772
+ console.log("Generator function:", generatorFunc);
769
773
  return this.updateFromAction((notify) => {
770
774
  const iterator = generatorFunc(notify);
775
+ console.log("Generator iterator:", iterator);
771
776
  return _AsyncResult._runGeneratorProcessor(iterator)();
772
777
  });
773
778
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/error.ts","../../src/core/result.ts","../../src/core/asyncResult.ts","../../src/core/asyncResultCollection.ts","../../src/core/cache.ts","../../src/core/utils.ts"],"sourcesContent":["/**\n * Base class for error handling, providing structured error information and logging.\n * @class ErrorBase\n * @property {string} code - The error code.\n * @property {string | undefined} message - The error message (optional).\n * @property {unknown} thrownError - The original error object, if any (optional).\n * \n * @constructor\n * @param {string} code - The error code.\n * @param {string} [message] - The error message.\n * @param {unknown} [thrownError] - The original error object, if any.\n * @param {boolean} [log=true] - Whether to log the error upon creation.\n */\nexport class ErrorBase {\n code: string;\n message?: string | undefined;\n thrownError?: unknown;\n\n constructor(code: string, message?: string, thrownError?: unknown, log: boolean = true) {\n this.code = code;\n this.message = message;\n this.thrownError = thrownError;\n\n if (log) {\n this.logError();\n }\n }\n\n /**\n * Converts the error to a string representation, on the format \"Error {code}: {message}\".\n * @returns a string representation of the error\n */\n toString(): string {\n return `Error ${this.code}: ${this.message ?? ''}`;\n }\n\n /**\n * Logs the error to the console, uses console.error and ErrorBase.toString() internally.\n * Logs thrownError if it was provided on creation.\n */\n logError(): void {\n if (this.thrownError) {\n console.error(this.toString(), this.thrownError);\n } else {\n console.error(this.toString());\n }\n }\n}\n","import { ErrorBase } from \"./error\";\n\n/**\n * Type representing the state of a Result, either success with a value of type T,\n * or error with an error of type E (defaulting to ErrorBase).\n */\nexport type ResultState<T, E extends ErrorBase = ErrorBase> =\n | { status: 'success'; value: T }\n | { status: 'error'; error: E };\n\n/**\n * Class representing the result of an operation that can either succeed with a value of type T,\n * or fail with an error of type E (defaulting to ErrorBase).\n * Provides methods for unwrapping the result, chaining operations, and handling errors.\n * @class Result\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class Result<T, E extends ErrorBase = ErrorBase> {\n private _state: ResultState<T, E>;\n\n /**\n * Creates a new Result instance with the given state.\n * @param state the state of the created Result\n */\n constructor(state: ResultState<T, E>) {\n this._state = state;\n }\n\n /** Returns the internal state of the Result. */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the Result is successful.\n * @returns whether or not the result is successful\n */\n isSuccess(): boolean {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the Result is an error.\n * @returns whether or not the result is an error\n */\n isError(): boolean {\n return this._state.status === 'error';\n }\n\n /**\n * Creates a successful Result with the given value.\n * @param value the result of the successful operation\n * @returns a successful Result\n */\n static ok<T, E extends ErrorBase = ErrorBase>(value: T): Result<T, E> {\n return new Result({ status: 'success', value });\n }\n\n /**\n * Creates an error Result with the given error.\n * @param error the error of the failed operation\n * @returns an error Result\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): Result<never, E> {\n return new Result({ status: 'error', error });\n }\n\n /**\n * Creates an error Result (containing an ErrorBase) with the given error code and optional message.\n * @param code the error code\n * @param message an optional error message\n * @returns an error Result\n */\n static errTag(code: string, message?: string, thrownError?: unknown): Result<never, ErrorBase> {\n return Result.err(new ErrorBase(code, message, thrownError));\n }\n\n /**\n * Returns the successful value (if the Result is successful) or null (if it is an error).\n * @returns either the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value (if the Result is successful) or throws an error (if it is an error).\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap a Result that is not successful');\n }\n\n /**\n * Returns the successful value (if the Result is successful) or a default value (if it is an error).\n * @param defaultValue the default value to return if the Result is an error\n * @returns either the successful value or the default value\n */\n unwrapOr<O>(defaultValue: O): T | O {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return defaultValue;\n }\n\n /**\n * Transforms a Promise of a successful value into a Promise of a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * @param promise the promise to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return promise\n .then((value) => Result.ok<T, E>(value))\n .catch((error) => Result.err(errorMapper(error)));\n }\n\n /**\n * Executes an asynchronous function and transforms its result into a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * Same as Result.tryPromise(fn(), errorMapper).\n * @param fn the asynchronous function to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryFunction<T, E extends ErrorBase = ErrorBase>(fn: () => Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return Result.tryPromise(fn(), errorMapper);\n }\n\n /**\n * Chains the current Result with another operation that returns a ResultState.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * @param fn a function taking as input the successful value of the result, and returning a ResultState describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => ResultState<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return new Result<O, E | E2>(fn(this._state.value));\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * Chains the current Result with another operation that returns a Result.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * Same as chain, but the function returns a Result directly instead of a ResultState.\n * @param fn a function taking as input the successful value of the result, and returning a Result describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => Result<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return fn(this._state.value);\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * @yields the current Result, and if it is successful, returns its value.\n * This allows using Result instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<Result<number>, number, any> {\n * const result1 = yield* Result.ok(5);\n * const result2 = yield* Result.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<Result<T, E>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n /**\n * Runs a generator function that yields Result instances, propagating errors automatically.\n * If any yielded Result is an error, the execution stops and the error is returned.\n * If all yielded Results are successful, returns a successful Result with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for Result handling in generator functions.\n * \n * @param generator a generator function that yields Result instances\n * @returns a Result containing either the final successful value or the first encountered error\n * \n * @example\n * const result = Result.run(function* () {\n * const value1 = yield* Result.ok(5);\n * const value2 = yield* Result.ok(10);\n * return value1 + value2;\n * });\n */\n static run<T, E extends ErrorBase = ErrorBase>(generator: () => Generator<Result<any, E>, T, any>): Result<T, E> {\n const iterator = generator();\n let result = iterator.next();\n\n while (!result.done) {\n const yielded = result.value;\n if (yielded._state.status === 'error') {\n return Result.err(yielded._state.error);\n }\n result = iterator.next(yielded._state.value);\n }\n\n return Result.ok(result.value);\n }\n}\n","import { ErrorBase } from \"./error\";\nimport { Result, type ResultState } from \"./result\";\n\n/**\n * Type representing the state of an AsyncResult.\n * It can be 'idle', 'loading' with a promise and an optional progress information of type P, or a settled ResultState (success or error).\n */\nexport type AsyncResultState<T, E extends ErrorBase = ErrorBase, P = unknown> =\n | { status: 'idle' }\n | { status: 'loading'; promise: Promise<Result<T, E>>; progress?: P }\n | ResultState<T, E>;\n\n\n/**\n * An Action is a function returning a Promise of a Result.\n */\nexport type Action<T, E extends ErrorBase = ErrorBase, P = unknown> = (notifyProgress: (progress: P) => void) => Promise<Result<T, E>>;\n\n/**\n * A LazyAction is an object containing a trigger function to start the action, and the AsyncResult representing the action's state.\n */\nexport type LazyAction<T, E extends ErrorBase = ErrorBase, P = unknown> = {\n trigger: () => void;\n result: AsyncResult<T, E, P>;\n};\n\n/**\n * A ChainStep is a function that takes an arbitrary input and returns a Result or a Promise of a Result.\n * It takes an input of type I and returns either a Result<O, E> or a Promise<Result<O, E>>.\n * \n * Used for chaining operations on AsyncResult.\n */\nexport type ChainStep<I, O, E extends ErrorBase = ErrorBase> = (input: I) => Result<O, E> | Promise<Result<O, E>>;\n\n/**\n * A FlatChainStep is a function that takes an arbitrary input and returns an AsyncResult.\n * It takes an input of type I and returns an AsyncResult<O, E>.\n * \n * Used for flat-chaining operations on AsyncResult.\n */\nexport type FlatChainStep<I, O, E extends ErrorBase = ErrorBase, P = unknown> = (input: I) => AsyncResult<O, E, P>;\n\n/**\n * Type representing a generator function that yields AsyncResult instances and returns a final value of type T.\n * \n * Used for running generators with AsyncResult.run().\n */\nexport type AsyncResultGenerator<T> = Generator<AsyncResult<any, any>, T, any>;\n\n/**\n * Type representing a listener function for AsyncResult state changes.\n */\nexport type AsyncResultListener<T, E extends ErrorBase = ErrorBase, P = unknown> = (result: AsyncResult<T, E, P>) => any;\n\nexport interface AsyncResultListenerOptions {\n immediate?: boolean;\n callOnProgressUpdates?: boolean;\n}\n\ninterface AsyncResultListenerEntry<T, E extends ErrorBase, P> {\n listener: AsyncResultListener<T, E, P>;\n options: AsyncResultListenerOptions;\n}\n\n/**\n * Class representing the asynchronous result of an operation that can be idle, loading, successful, or failed.\n * Provides methods for listening to state changes, updating state, chaining operations, and converting to and from promises.\n * @class AsyncResult\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @template P - The type of the progress information for loading state (default is unknown).\n */\nexport class AsyncResult<T, E extends ErrorBase = ErrorBase, P = unknown> {\n private _state: AsyncResultState<T, E, P>;\n private _listeners: Set<AsyncResultListenerEntry<T, E, P>> = new Set();\n\n constructor(state?: AsyncResultState<T, E, P>) {\n this._state = state || { status: 'idle' };\n }\n\n\n\n // === Getting current state ===\n\n /**\n * Returns the internal state of the AsyncResult.\n */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the AsyncResult is successful.\n * @returns whether or not the result is successful\n */\n isSuccess() {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the AsyncResult is an error.\n * @returns whether or not the result is an error\n */\n isError() {\n return this._state.status === 'error';\n }\n\n /**\n * Checks if the AsyncResult is idle.\n * @returns whether or not the result is idle\n */\n isIdle() {\n return this._state.status === 'idle';\n }\n\n /**\n * Checks if the AsyncResult is loading.\n * @returns whether or not the result is loading\n */\n isLoading() {\n return this._state.status === 'loading';\n }\n\n\n\n // === Unwrapping values ===\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise returns null.\n * @returns the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap an AsyncResult that is not successful');\n }\n\n /**\n * Returns the error value if the AsyncResult is in an error state, otherwise returns null.\n * @returns the error value or null\n */\n unwrapErrorOrNull(): E | null {\n if (this._state.status === 'error') {\n return this._state.error;\n }\n return null;\n }\n\n /**\n * Returns the progress information if the AsyncResult is in a loading state, otherwise returns null.\n * @returns the progress information or null\n */\n getProgressOrNull(): P | null {\n if (this._state.status === 'loading') {\n return this._state.progress ?? null;\n }\n return null;\n }\n\n // === Creating/updating from settled values ===\n\n private set state(newState: AsyncResultState<T, E, P>) {\n const oldState = this._state;\n\n this._state = newState;\n this._listeners.forEach((listenerEntry) => {\n if ((oldState.status !== 'loading' || newState.status !== 'loading') || listenerEntry.options.callOnProgressUpdates) {\n listenerEntry.listener(this)\n }\n });\n }\n\n private setState(newState: AsyncResultState<T, E, P>) {\n this.state = newState;\n }\n\n /**\n * Creates a successful AsyncResult with the given value.\n * @param value the result of the successful operation\n * @returns a successful AsyncResult\n */\n static ok<T>(value: T): AsyncResult<T, never> {\n return new AsyncResult<T, never>({ status: 'success', value });\n }\n\n /**\n * Creates an error AsyncResult with the given error.\n * @param error the error of the failed operation\n * @returns an error AsyncResult\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): AsyncResult<never, E> {\n return new AsyncResult<never, E>({ status: 'error', error });\n }\n\n /**\n * Creates an error AsyncResult with a new ErrorBase constructed from the given parameters.\n * @param code the error code\n * @param message the error message (optional)\n * @param thrownError the original error object, if any (optional)\n * @param log whether to log the error upon creation (default is true)\n * @returns an error AsyncResult\n */\n static errTag(code: string, message?: string, thrownError?: unknown, log: boolean = true): AsyncResult<never, ErrorBase> {\n const error = new ErrorBase(code, message, thrownError, log);\n return AsyncResult.err(error);\n }\n\n /**\n * Updates the AsyncResult to a successful state with the given value.\n * Like AsyncResult.ok, but in place.\n * @param value the successful value\n */\n updateFromValue(value: T) {\n this.state = { status: 'success', value };\n return this;\n }\n\n /**\n * Updates the AsyncResult to an error state with the given error.\n * Like AsyncResult.err, but in place.\n * @param error the error\n */\n updateFromError(error: E) {\n this.state = { status: 'error', error };\n return this;\n }\n\n /**\n * Updates the progress information of the AsyncResult if it is currently loading.\n * @param progress progress information to include in the loading state\n */\n updateProgress(progress: P) {\n if (this._state.status === 'loading') {\n this.state = { ...this._state, progress };\n }\n return this;\n }\n\n\n // === Creating/updating from promises ===\n\n /**\n * Creates an AsyncResult from a promise that resolves to a value.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromResultPromise, but for promise that only resolves to a successful value and not a Result.\n * \n * @param promise the promise that resolves to a value\n * @returns an AsyncResult representing the state of the promise\n */\n static fromValuePromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromValuePromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromValuePromise, but in place.\n * \n * @param promise the promise that resolves to a value\n */\n updateFromValuePromise(promise: Promise<T>) {\n const resultStatePromise = async (): Promise<Result<T, E>> => {\n try {\n const value = await promise;\n return Result.ok(value);\n } catch (error) {\n return Result.err(error as E);\n }\n };\n return this.updateFromResultPromise(resultStatePromise());\n }\n\n\n // === Waiting for settled state and get result ===\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading.\n * @returns itself once settled\n */\n async waitForSettled(): Promise<AsyncResult<T, E, P>> {\n if (this._state.status === 'loading') {\n try {\n const value = await this._state.promise;\n this._state = value.state;\n } catch (error) {\n this._state = { status: 'error', error: error as E };\n }\n }\n return this;\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns a Result representing the settled state.\n * @returns a Result representing the settled state\n */\n async toResultPromise(): Promise<Result<T, E>> {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'idle' || settled.state.status === 'loading') {\n throw new Error('Cannot convert idle or loading AsyncResult to ResultState');\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n return Result.ok(settled.state.value);\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n async toValueOrThrowPromise(): Promise<T> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrThrow();\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or null.\n * @returns either the successful value or null\n */\n async toValueOrNullPromise(): Promise<T | null> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrNull();\n }\n\n /**\n * Creates an AsyncResult from a promise that resolves to a Result.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * @param promise the promise that resolves to a Result\n * @returns an AsyncResult representing the state of the promise\n */\n static fromResultPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromResultPromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The promise must produce a Result once settled (meaning it should return the error in the result when possible).\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but in place.\n * \n * @param promise the promise that resolves to a Result\n */\n updateFromResultPromise(promise: Promise<Result<T, E>>) {\n this.state = { status: 'loading', promise };\n promise\n .then((res) => {\n this.state = res.state;\n })\n .catch((error) => {\n this.updateFromError(new ErrorBase('defect_on_updateFromResultPromise', 'The promise provided to AsyncResult rejected', error) as E);\n });\n return this;\n }\n\n\n // === Listeners ===\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes.\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listen(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const entry: AsyncResultListenerEntry<T, E, P> = { listener, options };\n this._listeners.add(entry);\n\n if (options.immediate) {\n listener(this);\n }\n\n return () => {\n this._listeners.delete(entry);\n };\n }\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes, and automatically unsubscribes once it is settled (success or error).\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listenUntilSettled(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const unsub = this.listen((result) => {\n listener(result);\n if (result.state.status === 'success' || result.state.status === 'error') {\n unsub();\n }\n }, options);\n\n return unsub;\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on a success.\n * @param callback callback called once the AsyncResult settled on a success\n * @returns A function to unsubscribe early\n */\n onSuccessOnce(callback: (value: T) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on a success.\n * @param callback callback called every time the AsyncResult settles on a success\n * @returns A function to unsubscribe\n */\n onSuccessPerpetual(callback: (value: T) => void) {\n return this.listen((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on an error.\n * @param callback callback called once the AsyncResult settled on an error\n * @returns A function to unsubscribe early\n */\n onErrorOnce(callback: (error: E) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on an error.\n * @param callback callback called every time the AsyncResult settles on an error\n * @returns A function to unsubscribe\n */\n onErrorPerpetual(callback: (error: E) => void) {\n return this.listen((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n // === Mirroring ===\n\n /**\n * Mirrors the state of another AsyncResult into this one.\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirror(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listen((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n /**\n * Mirrors the state of another AsyncResult into this one, until the other AsyncResult is settled (success or error).\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match, until the other AsyncResult is settled.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirrorUntilSettled(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listenUntilSettled((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n\n // === Actions ===\n\n /**\n * Creates an AsyncResult from an Action.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the Action's promise resolves.\n * If the Action's promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but for Actions.\n * \n * @param action the Action to run to produce the AsyncResult\n * @return an AsyncResult representing the state of the Action\n */\n static fromAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): AsyncResult<T, E, P> {\n return new AsyncResult<T, E, P>().updateFromAction(action);\n }\n\n /**\n * Updates the AsyncResult based on the given Action.\n * Like AsyncResult.fromAction, but in place.\n * @param action an action that will be called directly\n * @returns itself\n */\n updateFromAction(action: Action<T, E, P>) {\n const promise = action((progress) => this.updateProgress(progress));\n return this.updateFromResultPromise(promise);\n }\n\n /**\n * Creates a LazyAction that can be triggered to run the given Action.\n * @param action the Action to run when triggered\n * @returns an object containing the trigger function and the associated AsyncResult\n */\n static makeLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyAction<T, E, P> {\n const result = new AsyncResult<T, E, P>();\n const trigger = () => {\n result.updateFromAction(action);\n };\n\n return { trigger, result };\n }\n\n // === Chaining ===\n\n /**\n * Chains the current AsyncResult with another operation that returns a Result or a Promise of a Result.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * @param fn a function taking as input the successful value of the result, and returning a Result or a Promise of a Result describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: ChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'loading' || settled.state.status === 'idle') {\n throw new Error('Unexpected state after waitForSettled'); // TODO handle this case properly\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n return fn(settled.state.value);\n };\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n /**\n * Chains the current AsyncResult with another operation that returns an AsyncResult.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * Like chain, but for functions returning AsyncResult instead of Result.\n * \n * @param fn a function taking as input the successful value of the result, and returning an AsyncResult describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n const nextAsyncResult = fn(settled.state.value);\n const nextSettled = await nextAsyncResult.toResultPromise();\n return nextSettled;\n }\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n // pipeParallel PipeFunction[] -> AsyncResult<T, E>[]\n // pipeParallelAndCollapse PipeFunction[] -> AsyncResult<T[], E>\n\n /**\n * Ensures that all provided AsyncResults are successful.\n * If all are successful, returns an AsyncResult containing an array of their values.\n * If any AsyncResult is an error, returns an AsyncResult with the first encountered error.\n * @param results an array of AsyncResults to check\n * @returns an AsyncResult containing either an array of successful values or the first encountered error\n */\n static ensureAvailable<R extends readonly AsyncResult<any, any>[]>(results: R): AsyncResult<{ [K in keyof R]: R[K] extends AsyncResult<infer T, any> ? T : never }, R[number] extends AsyncResult<any, infer E> ? E : never> {\n if (results.length === 0) {\n // empty case — TS infers void tuple, so handle gracefully\n return AsyncResult.ok(undefined as never);\n }\n\n const promise = Promise.all(results.map((r) => r.waitForSettled())).then(\n (settledResults) => {\n for (const res of settledResults) {\n if (res.state.status === 'error') {\n return Result.err(res.state.error);\n }\n }\n\n const values = settledResults.map((r) => r.unwrapOrNull()!) as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof R]: R[K] extends AsyncResult<infer T, any>\n ? T\n : never;\n };\n\n return Result.ok(values);\n }\n );\n\n return AsyncResult.fromResultPromise(promise);\n }\n\n // === Generator support ===\n\n /**\n * Yields the current AsyncResult, and if it is successful, returns its value.\n * This allows using AsyncResult instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<AsyncResult<number>, number, any> {\n * const result1 = yield* AsyncResult.ok(5);\n * const result2 = yield* AsyncResult.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<AsyncResult<T, E, P>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n private static _runGeneratorProcessor<T, E extends ErrorBase>(iterator: AsyncResultGenerator<T>): () => Promise<Result<T, E>> {\n return async (): Promise<Result<T, E>> => {\n let result = iterator.next();\n\n while (!result.done) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const yielded = result.value as AsyncResult<any, E>;\n const settled = await yielded.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n result = iterator.next(settled.state.value);\n }\n\n return Result.ok(result.value);\n }\n }\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically.\n * If any yielded AsyncResult is an error, the execution stops and the error is returned.\n * If all yielded AsyncResults are successful, returns a successful AsyncResult with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n * @returns a AsyncResult containing either the final successful value or the first encountered error\n * \n * @example\n * const result = AsyncResult.run(function* () {\n * const value1 = yield* AsyncResult.ok(5);\n * const value2 = yield* AsyncResult.ok(10);\n * return value1 + value2;\n * }\n */\n static run<T, E extends ErrorBase = ErrorBase, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): AsyncResult<T, E, P> {\n return AsyncResult.fromAction(async (notifyProgress: (progress: P) => void) => {\n const iterator = generatorFunc(notifyProgress);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically, and updates this AsyncResult in place.\n * If any yielded AsyncResult is an error, the execution stops and this AsyncResult is updated to that error.\n * If all yielded AsyncResults are successful, this AsyncResult is updated to a successful state with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n */\n runInPlace(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>) {\n return this.updateFromAction((notify) => {\n const iterator = generatorFunc(notify);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n // === Debuging ===\n\n\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? \"<Anonymous AsyncResult>\"} ; State at ${time} :`, this.state);\n }\n\n debug(name?: string) {\n return this.listen((r) => r.log(name));\n }\n}\n","import type { AsyncResult } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\nimport type { Result } from \"./result\";\n\n/**\n * The possible states of an AsyncResultList.\n */\nexport type AsyncResultCollectionState = \"any-loading\" | \"all-settled\";\n\nexport interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {\n key: string;\n result: AsyncResult<T, E>;\n unsub: () => void;\n}\n\n/**\n * Manages a collection of AsyncResult tasks with state tracking and listener support.\n * \n * This class provides a way to group multiple async operations, track their overall state\n * (whether any are loading or all have settled), and react to state changes through listeners.\n * \n * @template T - The success value type for all AsyncResult tasks in this collection\n * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase\n * \n * @example\n * ```typescript\n * const collection = new AsyncResultCollection<User>();\n * const userTask = new AsyncResult<User>();\n * \n * collection.add('user-1', userTask);\n * \n * collection.listen((taskQueue) => {\n * console.log('Collection state changed:', taskQueue.state);\n * });\n * ```\n * \n * @remarks\n * - Tasks can be automatically removed when they settle or kept in the collection\n * - The collection state is either \"any-loading\" (at least one task is loading) or \"all-settled\" (no tasks loading)\n * - Listeners are notified whenever the collection state changes\n * - Use filtering methods to query tasks by their state (success, error, loading)\n */\nexport class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {\n private _list = new Map<string, AsyncResultCollectionItem<T, E>>();\n private _listeners: Set<(taskQueue: AsyncResultCollection<T, E>) => void> = new Set();\n private _state: AsyncResultCollectionState = \"all-settled\";\n\n // === Getters ===\n\n /**\n * Gets the current tasks in the AsyncResultList.\n */\n get tasks() {\n return this._list;\n }\n\n /**\n * Gets the number of tasks in the list.\n */\n get length(): number {\n return this._list.size;\n }\n\n /**\n * Gets all tasks in the list as an array.\n */\n get items(): AsyncResult<T, E>[] {\n return Array.from(this._list.values()).map(i => i.result);\n }\n\n /**\n * Gets all tasks in the list as an array of key-value pairs.\n * Each pair contains the key and the corresponding AsyncResult.\n */\n get entries(): [string, AsyncResult<T, E>][] {\n return Array.from(this._list.entries()).map(([key, item]) => [key, item.result]);\n }\n\n /**\n * Gets the current state of the AsyncResultList.\n */\n get state() {\n return this._state;\n }\n\n private set state(s: AsyncResultCollectionState) {\n this._state = s;\n this._listeners.forEach(f => f(this));\n }\n\n private _onTaskFinished() {\n this.state = this.anyLoading() ? \"any-loading\" : \"all-settled\";\n }\n\n // === Listeners ===\n\n /**\n * Adds a listener that gets called whenever the state of the AsyncResultList changes.\n * @param listener the function to call when the state changes\n * @returns a function to unsubscribe the listener\n */\n listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void) {\n this._listeners.add(listener);\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.\n * @param listener the function to call when an item succeeds\n * @returns a function to unsubscribe the listener\n */\n onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isSuccess()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList errors.\n * @param listener the function to call when an item errors\n * @returns a function to unsubscribe the listener\n */\n onItemError(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isError()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n // === Managing tasks ===\n\n /**\n * Adds an AsyncResult task to the list.\n * @param key the unique key for the task\n * @param task the AsyncResult task to add\n * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)\n * @returns the added AsyncResult task\n */\n add(key: string, task: AsyncResult<T, E>, removeOnSettle: boolean = true): AsyncResult<T, E> {\n let unsub = null;\n if (removeOnSettle) {\n unsub = task.listenUntilSettled((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n this._list.delete(key);\n }, { immediate: true, callOnProgressUpdates: true });\n } else {\n unsub = task.listen((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n }, { immediate: true, callOnProgressUpdates: true });\n }\n\n this._list.set(key, { key, result: task, unsub });\n this.state = \"any-loading\";\n\n return task;\n }\n\n /**\n * Removes a task from the list by its key.\n * @param key the unique key of the task to remove\n * @returns true if the task was removed, false if it was not found\n */\n remove(key: string): boolean {\n const item = this._list.get(key);\n if (!item) return false;\n\n item.unsub();\n this._list.delete(key);\n this._onTaskFinished(); // We may have terminated the last loading task, so we need to update the state.\n return true;\n }\n\n /**\n * Clears all tasks from the list and sets the state to \"all-settled\".\n */\n clear() {\n this._list.forEach(({ unsub }) => unsub());\n this._list.clear();\n this.state = \"all-settled\";\n }\n\n // === Querying tasks ===\n\n /**\n * Checks if any task in the list is currently loading.\n * @returns true if any task is loading, false otherwise\n */\n anyLoading(): boolean {\n for (const item of this._list.values()) {\n if (item.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate.\n * @param predicate the function to test each task\n * @returns an array of tasks that satisfy the predicate\n */\n getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[] {\n const filtered: AsyncResult<T, E>[] = [];\n for (const item of this._list.values()) {\n if (predicate(item.result)) {\n filtered.push(item.result);\n }\n }\n return filtered;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate and maps them using the provided function.\n * @param filterPredicate the function to test each task\n * @param mapFunc the function to map each task\n * @returns an array of mapped values\n */\n getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[] {\n const results: U[] = [];\n for (const item of this._list.values()) {\n if (filterPredicate(item.result)) {\n results.push(mapFunc(item.result));\n }\n }\n return results;\n }\n\n /**\n * Gets all tasks that have succeeded.\n * @returns an array of successful AsyncResult tasks\n */\n getAllSuccess(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isSuccess());\n }\n\n /**\n * Gets the success values of all tasks that have succeeded.\n * @returns an array of successful values\n */\n getAllSuccessValues(): T[] {\n return this.getAllFilteredAndMap((task) => task.isSuccess(), (task) => task.unwrapOrThrow());\n }\n\n /**\n * Gets all tasks that have errored.\n * @returns an array of error AsyncResult tasks\n */\n getAllErrors(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isError());\n }\n\n /**\n * Gets the error values of all tasks that have errored.\n * @returns an array of error values\n */\n getAllErrorValues(): E[] {\n return this.getAllFilteredAndMap((task) => task.isError(), (task) => task.unwrapErrorOrNull()!);\n }\n\n /**\n * Gets all tasks that are currently loading.\n * @returns an array of loading AsyncResult tasks\n */\n getAllLoading(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isLoading());\n }\n\n /**\n * Gets the promises of all tasks that are currently loading.\n * @returns an array of promises for loading tasks\n */\n getAllLoadingPromises(): Promise<Result<T, E>>[] {\n return this.getAllFilteredAndMap((task) => task.isLoading(), (task) => task.toResultPromise());\n }\n\n // === Debugging utilities ===\n\n /**\n * Logs the current state and tasks of the AsyncResultList to the console.\n * @param name an optional name to identify the log\n */\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? '<Anonymous TaskQueue>'} ; State at ${time} :`, this.state, this._list);\n }\n\n /**\n * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.\n * @param name an optional name to identify the log\n * @returns a function to unsubscribe the debug listener\n */\n debug(name?: string) {\n return this.listen(() => {\n this.log(name);\n });\n }\n}","import { AsyncResult, type AsyncResultState, type ChainStep } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\n\ntype KeyedAsyncCacheRefetchOptions = {\n policy: 'refetch' | 'if-error' | 'no-refetch';\n};\n\ntype CacheItem<P, V, E extends ErrorBase = ErrorBase> = {\n result: AsyncResult<V, E>;\n fetcherParams: P;\n valid: boolean;\n lastFetched?: number;\n ttl?: number;\n};\n\nconst _defaultRefetchOptions: KeyedAsyncCacheRefetchOptions = { policy: 'no-refetch' };\n\nfunction defaultParamsToKey<P>(params: P): string {\n if (typeof params === 'object') {\n return JSON.stringify(params);\n }\n return String(params);\n}\n\n/**\n * A cache for asynchronous operations that maps parameter sets to their corresponding AsyncResult.\n * Supports automatic refetching based on specified policies.\n * \n * @template P - The type of the parameters used to fetch values.\n * @template V - The type of the values being fetched.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {\n private _cache: Map<string, CacheItem<P, V, E>> = new Map();\n private _fetcher: ChainStep<P, V, E>;\n private _paramsToKey: (params: P) => string;\n private _cacheTTL?: number;\n\n /**\n * Creates a new KeyedAsyncCache instance.\n * @param fetcher the function used to fetch values based on parameters\n * @param paramsToKey a function that converts parameters to a unique string key (default uses JSON.stringify for objects)\n * @param cacheTTL optional time-to-live for cache entries in milliseconds\n */\n constructor(fetcher: ChainStep<P, V, E>, paramsToKey: (params: P) => string = defaultParamsToKey, cacheTTL: number = Infinity) {\n this._fetcher = fetcher;\n this._paramsToKey = paramsToKey;\n this._cacheTTL = cacheTTL;\n }\n\n private makeCacheItem(result: AsyncResult<V, E>, fetcherParams: P, ttl?: number | undefined): CacheItem<P, V, E> {\n return {\n result,\n fetcherParams,\n ttl: ttl ?? this._cacheTTL,\n valid: true,\n };\n }\n\n private shouldRefetch(existingResult: CacheItem<P, V, E>, refetch: KeyedAsyncCacheRefetchOptions): boolean {\n if (!existingResult.valid) {\n return true;\n }\n if (refetch.policy === 'refetch') {\n return true;\n }\n if (refetch.policy === 'if-error') {\n return existingResult.result.state.status === 'error';\n }\n if (existingResult.ttl !== undefined && existingResult.lastFetched !== undefined) {\n const now = Date.now();\n if (now - existingResult.lastFetched > existingResult.ttl) {\n return true;\n }\n }\n return false;\n }\n\n private updateOrCreateCacheItemFromParams(params: P, cacheItem?: CacheItem<P, V, E>) {\n const promise = Promise.resolve(this._fetcher(params));\n let result = cacheItem?.result.updateFromResultPromise(promise) ?? AsyncResult.fromResultPromise(promise);\n cacheItem = cacheItem ?? this.makeCacheItem(result, params);\n \n promise.then(() => {\n cacheItem.lastFetched = Date.now();\n });\n\n return cacheItem;\n }\n\n /**\n * Gets the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns the AsyncResult corresponding to the given parameters\n */\n get(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): AsyncResult<V, E> {\n const key = this._paramsToKey(params);\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n if (!this.shouldRefetch(cacheItem, refetch)) {\n return cacheItem.result;\n } else {\n this.updateOrCreateCacheItemFromParams(params, cacheItem);\n return cacheItem.result;\n }\n }\n \n const cacheItem = this.updateOrCreateCacheItemFromParams(params);\n this._cache.set(key, cacheItem);\n return cacheItem.result;\n }\n\n /**\n * Gets the settled state of the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * Waits for the AsyncResult to settle before returning its state.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns a promise resolving to the settled state of the AsyncResult\n */\n async getSettledState(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): Promise<AsyncResultState<V, E>> {\n const asyncResult = this.get(params, refetch);\n await asyncResult.waitForSettled();\n return asyncResult.state;\n }\n\n /**\n * Checks if any cached AsyncResult is currently loading.\n * @returns whether any cached AsyncResult is loading\n */\n anyLoading(): boolean {\n for (const cacheItem of this._cache.values()) {\n if (cacheItem.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clears the entire cache.\n */\n clear() {\n this._cache.clear();\n }\n\n /**\n * Invalidates the cache entry for the given key.\n * @param key the key of the cache entry to invalidate\n */\n invalidateKey(key: string) {\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n cacheItem.valid = false;\n }\n }\n\n /**\n * Invalidates the cache entry for the given parameters.\n * @param params the parameters of the cache entry to invalidate\n */\n invalidateParams(params: P) {\n const key = this._paramsToKey(params);\n this.invalidateKey(key);\n }\n\n /**\n * Invalidates all cache entries.\n */\n invalidateAll() {\n for (const cacheItem of this._cache.values()) {\n cacheItem.valid = false;\n }\n }\n\n /**\n * Gets all cache items.\n * @returns an array of all cache items\n */\n get items() {\n return Array.from(this._cache.values());\n }\n\n /**\n * Gets the number of cache items.\n * @returns the number of cache items\n */\n get size() {\n return this._cache.size;\n }\n\n /**\n * Gets all cache items with successful results.\n * @returns an array of cache items with successful results\n */\n get successfulItems() {\n return Array.from(this._cache.values()).filter(item => item.result.isSuccess());\n }\n}\n","import { AsyncResult } from \"./asyncResult\";\n\nexport function delay(ms: number): AsyncResult<true> {\n return AsyncResult.fromValuePromise(new Promise(resolve => {\n setTimeout(() => resolve(true), ms);\n }));\n}"],"mappings":"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","names":["cacheItem"]}
1
+ {"version":3,"sources":["../../src/core/error.ts","../../src/core/result.ts","../../src/core/asyncResult.ts","../../src/core/asyncResultCollection.ts","../../src/core/cache.ts","../../src/core/utils.ts"],"sourcesContent":["/**\n * Base class for error handling, providing structured error information and logging.\n * @class ErrorBase\n * @property {string} code - The error code.\n * @property {string | undefined} message - The error message (optional).\n * @property {unknown} thrownError - The original error object, if any (optional).\n * \n * @constructor\n * @param {string} code - The error code.\n * @param {string} [message] - The error message.\n * @param {unknown} [thrownError] - The original error object, if any.\n * @param {boolean} [log=true] - Whether to log the error upon creation.\n */\nexport class ErrorBase {\n code: string;\n message?: string | undefined;\n thrownError?: unknown;\n\n constructor(code: string, message?: string, thrownError?: unknown, log: boolean = true) {\n this.code = code;\n this.message = message;\n this.thrownError = thrownError;\n\n if (log) {\n this.logError();\n }\n }\n\n /**\n * Converts the error to a string representation, on the format \"Error {code}: {message}\".\n * @returns a string representation of the error\n */\n toString(): string {\n return `Error ${this.code}: ${this.message ?? ''}`;\n }\n\n /**\n * Logs the error to the console, uses console.error and ErrorBase.toString() internally.\n * Logs thrownError if it was provided on creation.\n */\n logError(): void {\n if (this.thrownError) {\n console.error(this.toString(), this.thrownError);\n } else {\n console.error(this.toString());\n }\n }\n}\n","import { ErrorBase } from \"./error\";\n\n/**\n * Type representing the state of a Result, either success with a value of type T,\n * or error with an error of type E (defaulting to ErrorBase).\n */\nexport type ResultState<T, E extends ErrorBase = ErrorBase> =\n | { status: 'success'; value: T }\n | { status: 'error'; error: E };\n\n/**\n * Class representing the result of an operation that can either succeed with a value of type T,\n * or fail with an error of type E (defaulting to ErrorBase).\n * Provides methods for unwrapping the result, chaining operations, and handling errors.\n * @class Result\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class Result<T, E extends ErrorBase = ErrorBase> {\n private _state: ResultState<T, E>;\n\n /**\n * Creates a new Result instance with the given state.\n * @param state the state of the created Result\n */\n constructor(state: ResultState<T, E>) {\n this._state = state;\n }\n\n /** Returns the internal state of the Result. */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the Result is successful.\n * @returns whether or not the result is successful\n */\n isSuccess(): boolean {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the Result is an error.\n * @returns whether or not the result is an error\n */\n isError(): boolean {\n return this._state.status === 'error';\n }\n\n /**\n * Creates a successful Result with the given value.\n * @param value the result of the successful operation\n * @returns a successful Result\n */\n static ok<T, E extends ErrorBase = ErrorBase>(value: T): Result<T, E> {\n return new Result({ status: 'success', value });\n }\n\n /**\n * Creates an error Result with the given error.\n * @param error the error of the failed operation\n * @returns an error Result\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): Result<never, E> {\n return new Result({ status: 'error', error });\n }\n\n /**\n * Creates an error Result (containing an ErrorBase) with the given error code and optional message.\n * @param code the error code\n * @param message an optional error message\n * @returns an error Result\n */\n static errTag(code: string, message?: string, thrownError?: unknown): Result<never, ErrorBase> {\n return Result.err(new ErrorBase(code, message, thrownError));\n }\n\n /**\n * Returns the successful value (if the Result is successful) or null (if it is an error).\n * @returns either the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value (if the Result is successful) or throws an error (if it is an error).\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap a Result that is not successful');\n }\n\n /**\n * Returns the successful value (if the Result is successful) or a default value (if it is an error).\n * @param defaultValue the default value to return if the Result is an error\n * @returns either the successful value or the default value\n */\n unwrapOr<O>(defaultValue: O): T | O {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return defaultValue;\n }\n\n /**\n * Transforms a Promise of a successful value into a Promise of a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * @param promise the promise to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return promise\n .then((value) => Result.ok<T, E>(value))\n .catch((error) => Result.err(errorMapper(error)));\n }\n\n /**\n * Executes an asynchronous function and transforms its result into a Result,\n * catching any thrown errors and mapping them using the provided errorMapper function.\n * Same as Result.tryPromise(fn(), errorMapper).\n * @param fn the asynchronous function to execute\n * @param errorMapper a function that maps a thrown error to a Result error\n * @returns a Promise resolving to a Result containing either the successful value or the mapped error\n */\n static tryFunction<T, E extends ErrorBase = ErrorBase>(fn: () => Promise<T>, errorMapper: (error: unknown) => E): Promise<Result<T, E>> {\n return Result.tryPromise(fn(), errorMapper);\n }\n\n /**\n * Chains the current Result with another operation that returns a ResultState.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * @param fn a function taking as input the successful value of the result, and returning a ResultState describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => ResultState<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return new Result<O, E | E2>(fn(this._state.value));\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * Chains the current Result with another operation that returns a Result.\n * If the current Result is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * Same as chain, but the function returns a Result directly instead of a ResultState.\n * @param fn a function taking as input the successful value of the result, and returning a Result describing the result of its own operation\n * @returns a new Result that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: (input: T) => Result<O, E | E2>): Result<O, E | E2> {\n if (this._state.status === 'success') {\n return fn(this._state.value);\n }\n return Result.err<E>(this._state.error);\n }\n\n /**\n * @yields the current Result, and if it is successful, returns its value.\n * This allows using Result instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<Result<number>, number, any> {\n * const result1 = yield* Result.ok(5);\n * const result2 = yield* Result.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<Result<T, E>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n /**\n * Runs a generator function that yields Result instances, propagating errors automatically.\n * If any yielded Result is an error, the execution stops and the error is returned.\n * If all yielded Results are successful, returns a successful Result with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for Result handling in generator functions.\n * \n * @param generator a generator function that yields Result instances\n * @returns a Result containing either the final successful value or the first encountered error\n * \n * @example\n * const result = Result.run(function* () {\n * const value1 = yield* Result.ok(5);\n * const value2 = yield* Result.ok(10);\n * return value1 + value2;\n * });\n */\n static run<T, E extends ErrorBase = ErrorBase>(generator: () => Generator<Result<any, E>, T, any>): Result<T, E> {\n const iterator = generator();\n let result = iterator.next();\n\n while (!result.done) {\n const yielded = result.value;\n if (yielded._state.status === 'error') {\n return Result.err(yielded._state.error);\n }\n result = iterator.next(yielded._state.value);\n }\n\n return Result.ok(result.value);\n }\n}\n","import { ErrorBase } from \"./error\";\nimport { Result, type ResultState } from \"./result\";\n\n/**\n * Type representing the state of an AsyncResult.\n * It can be 'idle', 'loading' with a promise and an optional progress information of type P, or a settled ResultState (success or error).\n */\nexport type AsyncResultState<T, E extends ErrorBase = ErrorBase, P = unknown> =\n | { status: 'idle' }\n | { status: 'loading'; promise: Promise<Result<T, E>>; progress?: P }\n | ResultState<T, E>;\n\n\n/**\n * An Action is a function returning a Promise of a Result.\n */\nexport type Action<T, E extends ErrorBase = ErrorBase, P = unknown> = (notifyProgress: (progress: P) => void) => Promise<Result<T, E>>;\n\n/**\n * A LazyAction is an object containing a trigger function to start the action, and the AsyncResult representing the action's state.\n */\nexport type LazyAction<T, E extends ErrorBase = ErrorBase, P = unknown> = {\n trigger: () => void;\n result: AsyncResult<T, E, P>;\n};\n\n/**\n * A ChainStep is a function that takes an arbitrary input and returns a Result or a Promise of a Result.\n * It takes an input of type I and returns either a Result<O, E> or a Promise<Result<O, E>>.\n * \n * Used for chaining operations on AsyncResult.\n */\nexport type ChainStep<I, O, E extends ErrorBase = ErrorBase> = (input: I) => Result<O, E> | Promise<Result<O, E>>;\n\n/**\n * A FlatChainStep is a function that takes an arbitrary input and returns an AsyncResult.\n * It takes an input of type I and returns an AsyncResult<O, E>.\n * \n * Used for flat-chaining operations on AsyncResult.\n */\nexport type FlatChainStep<I, O, E extends ErrorBase = ErrorBase, P = unknown> = (input: I) => AsyncResult<O, E, P>;\n\n/**\n * Type representing a generator function that yields AsyncResult instances and returns a final value of type T.\n * \n * Used for running generators with AsyncResult.run().\n */\nexport type AsyncResultGenerator<T> = Generator<AsyncResult<any, any>, T, any>;\n\n/**\n * Type representing a listener function for AsyncResult state changes.\n */\nexport type AsyncResultListener<T, E extends ErrorBase = ErrorBase, P = unknown> = (result: AsyncResult<T, E, P>) => any;\n\nexport interface AsyncResultListenerOptions {\n immediate?: boolean;\n callOnProgressUpdates?: boolean;\n}\n\ninterface AsyncResultListenerEntry<T, E extends ErrorBase, P> {\n listener: AsyncResultListener<T, E, P>;\n options: AsyncResultListenerOptions;\n}\n\n/**\n * Class representing the asynchronous result of an operation that can be idle, loading, successful, or failed.\n * Provides methods for listening to state changes, updating state, chaining operations, and converting to and from promises.\n * @class AsyncResult\n * @template T - The type of the successful result value.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @template P - The type of the progress information for loading state (default is unknown).\n */\nexport class AsyncResult<T, E extends ErrorBase = ErrorBase, P = unknown> {\n private _state: AsyncResultState<T, E, P>;\n private _listeners: Set<AsyncResultListenerEntry<T, E, P>> = new Set();\n\n constructor(state?: AsyncResultState<T, E, P>) {\n this._state = state || { status: 'idle' };\n }\n\n\n\n // === Getting current state ===\n\n /**\n * Returns the internal state of the AsyncResult.\n */\n get state() {\n return this._state;\n }\n\n /**\n * Checks if the AsyncResult is successful.\n * @returns whether or not the result is successful\n */\n isSuccess() {\n return this._state.status === 'success';\n }\n\n /**\n * Checks if the AsyncResult is an error.\n * @returns whether or not the result is an error\n */\n isError() {\n return this._state.status === 'error';\n }\n\n /**\n * Checks if the AsyncResult is idle.\n * @returns whether or not the result is idle\n */\n isIdle() {\n return this._state.status === 'idle';\n }\n\n /**\n * Checks if the AsyncResult is loading.\n * @returns whether or not the result is loading\n */\n isLoading() {\n return this._state.status === 'loading';\n }\n\n\n\n // === Unwrapping values ===\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise returns null.\n * @returns the successful value or null\n */\n unwrapOrNull(): T | null {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return null;\n }\n\n /**\n * Returns the successful value if the AsyncResult is in a success state, otherwise throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n unwrapOrThrow(): T {\n if (this._state.status === 'success') {\n return this._state.value;\n }\n throw new Error('Tried to unwrap an AsyncResult that is not successful');\n }\n\n /**\n * Returns the error value if the AsyncResult is in an error state, otherwise returns null.\n * @returns the error value or null\n */\n unwrapErrorOrNull(): E | null {\n if (this._state.status === 'error') {\n return this._state.error;\n }\n return null;\n }\n\n /**\n * Returns the progress information if the AsyncResult is in a loading state, otherwise returns null.\n * @returns the progress information or null\n */\n getProgressOrNull(): P | null {\n if (this._state.status === 'loading') {\n return this._state.progress ?? null;\n }\n return null;\n }\n\n // === Creating/updating from settled values ===\n\n private set state(newState: AsyncResultState<T, E, P>) {\n const oldState = this._state;\n\n this._state = newState;\n this._listeners.forEach((listenerEntry) => {\n if ((oldState.status !== 'loading' || newState.status !== 'loading') || listenerEntry.options.callOnProgressUpdates) {\n listenerEntry.listener(this)\n }\n });\n }\n\n private setState(newState: AsyncResultState<T, E, P>) {\n this.state = newState;\n }\n\n /**\n * Creates a successful AsyncResult with the given value.\n * @param value the result of the successful operation\n * @returns a successful AsyncResult\n */\n static ok<T>(value: T): AsyncResult<T, never> {\n return new AsyncResult<T, never>({ status: 'success', value });\n }\n\n /**\n * Creates an error AsyncResult with the given error.\n * @param error the error of the failed operation\n * @returns an error AsyncResult\n */\n static err<E extends ErrorBase = ErrorBase>(error: E): AsyncResult<never, E> {\n return new AsyncResult<never, E>({ status: 'error', error });\n }\n\n /**\n * Creates an error AsyncResult with a new ErrorBase constructed from the given parameters.\n * @param code the error code\n * @param message the error message (optional)\n * @param thrownError the original error object, if any (optional)\n * @param log whether to log the error upon creation (default is true)\n * @returns an error AsyncResult\n */\n static errTag(code: string, message?: string, thrownError?: unknown, log: boolean = true): AsyncResult<never, ErrorBase> {\n const error = new ErrorBase(code, message, thrownError, log);\n return AsyncResult.err(error);\n }\n\n /**\n * Updates the AsyncResult to a successful state with the given value.\n * Like AsyncResult.ok, but in place.\n * @param value the successful value\n */\n updateFromValue(value: T) {\n this.state = { status: 'success', value };\n return this;\n }\n\n /**\n * Updates the AsyncResult to an error state with the given error.\n * Like AsyncResult.err, but in place.\n * @param error the error\n */\n updateFromError(error: E) {\n this.state = { status: 'error', error };\n return this;\n }\n\n /**\n * Updates the progress information of the AsyncResult if it is currently loading.\n * @param progress progress information to include in the loading state\n */\n updateProgress(progress: P) {\n if (this._state.status === 'loading') {\n this.state = { ...this._state, progress };\n }\n return this;\n }\n\n\n // === Creating/updating from promises ===\n\n /**\n * Creates an AsyncResult from a promise that resolves to a value.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromResultPromise, but for promise that only resolves to a successful value and not a Result.\n * \n * @param promise the promise that resolves to a value\n * @returns an AsyncResult representing the state of the promise\n */\n static fromValuePromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<T>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromValuePromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The AsyncResult is initially in a loading state, and updates to a successful state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with the caught error.\n * \n * Like AsyncResult.fromValuePromise, but in place.\n * \n * @param promise the promise that resolves to a value\n */\n updateFromValuePromise(promise: Promise<T>) {\n const resultStatePromise = async (): Promise<Result<T, E>> => {\n try {\n const value = await promise;\n return Result.ok(value);\n } catch (error) {\n return Result.err(error as E);\n }\n };\n return this.updateFromResultPromise(resultStatePromise());\n }\n\n\n // === Waiting for settled state and get result ===\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading.\n * @returns itself once settled\n */\n async waitForSettled(): Promise<AsyncResult<T, E, P>> {\n if (this._state.status === 'loading') {\n try {\n const value = await this._state.promise;\n this._state = value.state;\n } catch (error) {\n this._state = { status: 'error', error: error as E };\n }\n }\n return this;\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns a Result representing the settled state.\n * @returns a Result representing the settled state\n */\n async toResultPromise(): Promise<Result<T, E>> {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'idle' || settled.state.status === 'loading') {\n throw new Error('Cannot convert idle or loading AsyncResult to ResultState');\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n return Result.ok(settled.state.value);\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or throws an error.\n * @returns the successful value\n * @throws an normal JS Error if the result is not successful\n */\n async toValueOrThrowPromise(): Promise<T> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrThrow();\n }\n\n /**\n * Waits for the AsyncResult to settle (either success or error) if it is currently loading, and returns the successful value or null.\n * @returns either the successful value or null\n */\n async toValueOrNullPromise(): Promise<T | null> {\n const settled = await this.waitForSettled();\n return settled.unwrapOrNull();\n }\n\n /**\n * Creates an AsyncResult from a promise that resolves to a Result.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the promise resolves.\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * @param promise the promise that resolves to a Result\n * @returns an AsyncResult representing the state of the promise\n */\n static fromResultPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>): AsyncResult<T, E> {\n const result = new AsyncResult<T, E>();\n result.updateFromResultPromise(promise);\n return result;\n }\n\n /**\n * Updates the AsyncResult to a loading state with the given promise.\n * The promise must produce a Result once settled (meaning it should return the error in the result when possible).\n * If the promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but in place.\n * \n * @param promise the promise that resolves to a Result\n */\n updateFromResultPromise(promise: Promise<Result<T, E>>) {\n this.state = { status: 'loading', promise };\n promise\n .then((res) => {\n this.state = res.state;\n })\n .catch((error) => {\n this.updateFromError(new ErrorBase('defect_on_updateFromResultPromise', 'The promise provided to AsyncResult rejected', error) as E);\n });\n return this;\n }\n\n\n // === Listeners ===\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes.\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listen(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const entry: AsyncResultListenerEntry<T, E, P> = { listener, options };\n this._listeners.add(entry);\n\n if (options.immediate) {\n listener(this);\n }\n\n return () => {\n this._listeners.delete(entry);\n };\n }\n\n /**\n * Adds a listener that is called whenever the AsyncResult state changes, and automatically unsubscribes once it is settled (success or error).\n * @param listener the listener function to add\n * @param immediate whether to call the listener immediately with the current state (default is true)\n * @returns a function to remove the listener\n */\n listenUntilSettled(listener: AsyncResultListener<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n const unsub = this.listen((result) => {\n listener(result);\n if (result.state.status === 'success' || result.state.status === 'error') {\n unsub();\n }\n }, options);\n\n return unsub;\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on a success.\n * @param callback callback called once the AsyncResult settled on a success\n * @returns A function to unsubscribe early\n */\n onSuccessOnce(callback: (value: T) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on a success.\n * @param callback callback called every time the AsyncResult settles on a success\n * @returns A function to unsubscribe\n */\n onSuccessPerpetual(callback: (value: T) => void) {\n return this.listen((result) => {\n if (result.isSuccess()) {\n callback(result.unwrapOrThrow());\n }\n });\n }\n\n /**\n * Adds a one-time listener that is called once the AsyncResult settles on an error.\n * @param callback callback called once the AsyncResult settled on an error\n * @returns A function to unsubscribe early\n */\n onErrorOnce(callback: (error: E) => void) {\n return this.listenUntilSettled((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n /**\n * Adds a perpetual listener that is called every time the AsyncResult settles on an error.\n * @param callback callback called every time the AsyncResult settles on an error\n * @returns A function to unsubscribe\n */\n onErrorPerpetual(callback: (error: E) => void) {\n return this.listen((result) => {\n if (result.isError()) {\n callback(result.unwrapErrorOrNull()!);\n }\n });\n }\n\n // === Mirroring ===\n\n /**\n * Mirrors the state of another AsyncResult into this one.\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirror(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listen((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n /**\n * Mirrors the state of another AsyncResult into this one, until the other AsyncResult is settled (success or error).\n * Whenever the other AsyncResult changes state, this AsyncResult is updated to match, until the other AsyncResult is settled.\n * @param other the AsyncResult to mirror\n * @returns a function to stop mirroring\n */\n mirrorUntilSettled(other: AsyncResult<T, E, P>, options: AsyncResultListenerOptions = { immediate: true, callOnProgressUpdates: true }) {\n return other.listenUntilSettled((newState) => {\n this.setState(newState.state);\n }, options);\n }\n\n\n // === Actions ===\n\n /**\n * Creates an AsyncResult from an Action.\n * The AsyncResult is initially in a loading state, and updates to the settled state once the Action's promise resolves.\n * If the Action's promise rejects, the AsyncResult is updated to an error state with a default ErrorBase.\n * \n * Like AsyncResult.fromResultPromise, but for Actions.\n * \n * @param action the Action to run to produce the AsyncResult\n * @return an AsyncResult representing the state of the Action\n */\n static fromAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): AsyncResult<T, E, P> {\n return new AsyncResult<T, E, P>().updateFromAction(action);\n }\n\n /**\n * Updates the AsyncResult based on the given Action.\n * Like AsyncResult.fromAction, but in place.\n * @param action an action that will be called directly\n * @returns itself\n */\n updateFromAction(action: Action<T, E, P>) {\n console.log(\"===== updateFromAction called =====\");\n console.log(\"Action function:\", action);\n const promise = action((progress) => this.updateProgress(progress));\n return this.updateFromResultPromise(promise);\n }\n\n /**\n * Creates a LazyAction that can be triggered to run the given Action.\n * @param action the Action to run when triggered\n * @returns an object containing the trigger function and the associated AsyncResult\n */\n static makeLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyAction<T, E, P> {\n const result = new AsyncResult<T, E, P>();\n const trigger = () => {\n result.updateFromAction(action);\n };\n\n return { trigger, result };\n }\n\n // === Chaining ===\n\n /**\n * Chains the current AsyncResult with another operation that returns a Result or a Promise of a Result.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * @param fn a function taking as input the successful value of the result, and returning a Result or a Promise of a Result describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n chain<O, E2 extends ErrorBase = ErrorBase>(fn: ChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.waitForSettled();\n if (settled.state.status === 'loading' || settled.state.status === 'idle') {\n throw new Error('Unexpected state after waitForSettled'); // TODO handle this case properly\n }\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n return fn(settled.state.value);\n };\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n /**\n * Chains the current AsyncResult with another operation that returns an AsyncResult.\n * \n * If the current AsyncResult is loading, waits for it to settle first, then applies the provided function to its value.\n * If the current AsyncResult is successful, applies the provided function to its value.\n * Otherwise, returns the current error.\n * \n * Useful to describe a sequence of operations that can each fail, and short-circuit on the first failure.\n * \n * Like chain, but for functions returning AsyncResult instead of Result.\n * \n * @param fn a function taking as input the successful value of the result, and returning an AsyncResult describing the result of its own operation\n * @returns a new AsyncResult that has either the successful value of the operation, or either the error of the current result or the error returned by fn\n */\n flatChain<O, E2 extends ErrorBase = ErrorBase>(fn: FlatChainStep<T, O, E | E2>): AsyncResult<O, E | E2> {\n const newResultBuilder = async (): Promise<Result<O, E | E2>> => {\n const settled = await this.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n\n const nextAsyncResult = fn(settled.state.value);\n const nextSettled = await nextAsyncResult.toResultPromise();\n return nextSettled;\n }\n\n return AsyncResult.fromResultPromise<O, E | E2>(newResultBuilder());\n }\n\n // pipeParallel PipeFunction[] -> AsyncResult<T, E>[]\n // pipeParallelAndCollapse PipeFunction[] -> AsyncResult<T[], E>\n\n /**\n * Ensures that all provided AsyncResults are successful.\n * If all are successful, returns an AsyncResult containing an array of their values.\n * If any AsyncResult is an error, returns an AsyncResult with the first encountered error.\n * @param results an array of AsyncResults to check\n * @returns an AsyncResult containing either an array of successful values or the first encountered error\n */\n static ensureAvailable<R extends readonly AsyncResult<any, any>[]>(results: R): AsyncResult<{ [K in keyof R]: R[K] extends AsyncResult<infer T, any> ? T : never }, R[number] extends AsyncResult<any, infer E> ? E : never> {\n if (results.length === 0) {\n // empty case — TS infers void tuple, so handle gracefully\n return AsyncResult.ok(undefined as never);\n }\n\n const promise = Promise.all(results.map((r) => r.waitForSettled())).then(\n (settledResults) => {\n for (const res of settledResults) {\n if (res.state.status === 'error') {\n return Result.err(res.state.error);\n }\n }\n\n const values = settledResults.map((r) => r.unwrapOrNull()!) as {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [K in keyof R]: R[K] extends AsyncResult<infer T, any>\n ? T\n : never;\n };\n\n return Result.ok(values);\n }\n );\n\n return AsyncResult.fromResultPromise(promise);\n }\n\n // === Generator support ===\n\n /**\n * Yields the current AsyncResult, and if it is successful, returns its value.\n * This allows using AsyncResult instances in generator functions to simplify error handling and propagation.\n * @example\n * function* example(): Generator<AsyncResult<number>, number, any> {\n * const result1 = yield* AsyncResult.ok(5);\n * const result2 = yield* AsyncResult.ok(10);\n * return result1 + result2;\n * }\n */\n *[Symbol.iterator](): Generator<AsyncResult<T, E, P>, T, any> {\n yield this;\n\n if (this._state.status === 'success') {\n return this._state.value;\n }\n return undefined as T;\n }\n\n private static _runGeneratorProcessor<T, E extends ErrorBase>(iterator: AsyncResultGenerator<T>): () => Promise<Result<T, E>> {\n return async (): Promise<Result<T, E>> => {\n let result = iterator.next();\n\n while (!result.done) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const yielded = result.value as AsyncResult<any, E>;\n const settled = await yielded.toResultPromise();\n if (settled.state.status === 'error') {\n return Result.err(settled.state.error);\n }\n result = iterator.next(settled.state.value);\n }\n\n return Result.ok(result.value);\n }\n }\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically.\n * If any yielded AsyncResult is an error, the execution stops and the error is returned.\n * If all yielded AsyncResults are successful, returns a successful AsyncResult with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n * @returns a AsyncResult containing either the final successful value or the first encountered error\n * \n * @example\n * const result = AsyncResult.run(function* () {\n * const value1 = yield* AsyncResult.ok(5);\n * const value2 = yield* AsyncResult.ok(10);\n * return value1 + value2;\n * }\n */\n static run<T, E extends ErrorBase = ErrorBase, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): AsyncResult<T, E, P> {\n return AsyncResult.fromAction(async (notifyProgress: (progress: P) => void) => {\n const iterator = generatorFunc(notifyProgress);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n /**\n * Runs a generator function that yields AsyncResult instances, propagating errors automatically, and updates this AsyncResult in place.\n * If any yielded AsyncResult is an error, the execution stops and this AsyncResult is updated to that error.\n * If all yielded AsyncResults are successful, this AsyncResult is updated to a successful state with the final returned value.\n * \n * This serves the same purpose as chain/flatChain, but allows for a more linear and readable style of coding.\n * Think of it as \"async/await\" but for AsyncResult handling in generator functions.\n * \n * @param generatorFunc a generator function that yields AsyncResult instances\n */\n runInPlace(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>) {\n console.log(\"===== runInPlace called =====\");\n console.log(\"Generator function:\", generatorFunc);\n return this.updateFromAction((notify) => {\n const iterator = generatorFunc(notify);\n console.log(\"Generator iterator:\", iterator);\n return AsyncResult._runGeneratorProcessor<T, E>(iterator)();\n });\n }\n\n\n // === Debuging ===\n\n\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? \"<Anonymous AsyncResult>\"} ; State at ${time} :`, this.state);\n }\n\n debug(name?: string) {\n return this.listen((r) => r.log(name));\n }\n}\n","import type { AsyncResult } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\nimport type { Result } from \"./result\";\n\n/**\n * The possible states of an AsyncResultList.\n */\nexport type AsyncResultCollectionState = \"any-loading\" | \"all-settled\";\n\nexport interface AsyncResultCollectionItem<T = any, E extends ErrorBase = ErrorBase> {\n key: string;\n result: AsyncResult<T, E>;\n unsub: () => void;\n}\n\n/**\n * Manages a collection of AsyncResult tasks with state tracking and listener support.\n * \n * This class provides a way to group multiple async operations, track their overall state\n * (whether any are loading or all have settled), and react to state changes through listeners.\n * \n * @template T - The success value type for all AsyncResult tasks in this collection\n * @template E - The error type for all AsyncResult tasks, defaults to ErrorBase\n * \n * @example\n * ```typescript\n * const collection = new AsyncResultCollection<User>();\n * const userTask = new AsyncResult<User>();\n * \n * collection.add('user-1', userTask);\n * \n * collection.listen((taskQueue) => {\n * console.log('Collection state changed:', taskQueue.state);\n * });\n * ```\n * \n * @remarks\n * - Tasks can be automatically removed when they settle or kept in the collection\n * - The collection state is either \"any-loading\" (at least one task is loading) or \"all-settled\" (no tasks loading)\n * - Listeners are notified whenever the collection state changes\n * - Use filtering methods to query tasks by their state (success, error, loading)\n */\nexport class AsyncResultCollection<T = any, E extends ErrorBase = ErrorBase> {\n private _list = new Map<string, AsyncResultCollectionItem<T, E>>();\n private _listeners: Set<(taskQueue: AsyncResultCollection<T, E>) => void> = new Set();\n private _state: AsyncResultCollectionState = \"all-settled\";\n\n // === Getters ===\n\n /**\n * Gets the current tasks in the AsyncResultList.\n */\n get tasks() {\n return this._list;\n }\n\n /**\n * Gets the number of tasks in the list.\n */\n get length(): number {\n return this._list.size;\n }\n\n /**\n * Gets all tasks in the list as an array.\n */\n get items(): AsyncResult<T, E>[] {\n return Array.from(this._list.values()).map(i => i.result);\n }\n\n /**\n * Gets all tasks in the list as an array of key-value pairs.\n * Each pair contains the key and the corresponding AsyncResult.\n */\n get entries(): [string, AsyncResult<T, E>][] {\n return Array.from(this._list.entries()).map(([key, item]) => [key, item.result]);\n }\n\n /**\n * Gets the current state of the AsyncResultList.\n */\n get state() {\n return this._state;\n }\n\n private set state(s: AsyncResultCollectionState) {\n this._state = s;\n this._listeners.forEach(f => f(this));\n }\n\n private _onTaskFinished() {\n this.state = this.anyLoading() ? \"any-loading\" : \"all-settled\";\n }\n\n // === Listeners ===\n\n /**\n * Adds a listener that gets called whenever the state of the AsyncResultList changes.\n * @param listener the function to call when the state changes\n * @returns a function to unsubscribe the listener\n */\n listen(listener: (taskQueue: AsyncResultCollection<T, E>) => void) {\n this._listeners.add(listener);\n return () => {\n this._listeners.delete(listener);\n };\n }\n\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList succeeds.\n * @param listener the function to call when an item succeeds\n * @returns a function to unsubscribe the listener\n */\n onItemSuccess(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isSuccess()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n /**\n * Adds a listener that gets called whenever any item in the AsyncResultList errors.\n * @param listener the function to call when an item errors\n * @returns a function to unsubscribe the listener\n */\n onItemError(listener: (task: AsyncResult<T, E>, key: string) => void) {\n return this.listen((taskQueue) => {\n for (const item of taskQueue._list.values()) {\n if (item.result.isError()) {\n listener(item.result, item.key);\n }\n }\n });\n }\n\n // === Managing tasks ===\n\n /**\n * Adds an AsyncResult task to the list.\n * @param key the unique key for the task\n * @param task the AsyncResult task to add\n * @param removeOnSettle whether to remove the task from the list once it settles (defaults to true)\n * @returns the added AsyncResult task\n */\n add(key: string, task: AsyncResult<T, E>, removeOnSettle: boolean = true): AsyncResult<T, E> {\n let unsub = null;\n if (removeOnSettle) {\n unsub = task.listenUntilSettled((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n this._list.delete(key);\n }, { immediate: true, callOnProgressUpdates: true });\n } else {\n unsub = task.listen((r) => {\n if (r.isLoading() || r.isIdle()) return;\n this._onTaskFinished();\n }, { immediate: true, callOnProgressUpdates: true });\n }\n\n this._list.set(key, { key, result: task, unsub });\n this.state = \"any-loading\";\n\n return task;\n }\n\n /**\n * Removes a task from the list by its key.\n * @param key the unique key of the task to remove\n * @returns true if the task was removed, false if it was not found\n */\n remove(key: string): boolean {\n const item = this._list.get(key);\n if (!item) return false;\n\n item.unsub();\n this._list.delete(key);\n this._onTaskFinished(); // We may have terminated the last loading task, so we need to update the state.\n return true;\n }\n\n /**\n * Clears all tasks from the list and sets the state to \"all-settled\".\n */\n clear() {\n this._list.forEach(({ unsub }) => unsub());\n this._list.clear();\n this.state = \"all-settled\";\n }\n\n // === Querying tasks ===\n\n /**\n * Checks if any task in the list is currently loading.\n * @returns true if any task is loading, false otherwise\n */\n anyLoading(): boolean {\n for (const item of this._list.values()) {\n if (item.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate.\n * @param predicate the function to test each task\n * @returns an array of tasks that satisfy the predicate\n */\n getAllFiltered(predicate: (task: AsyncResult<T, E>) => boolean): AsyncResult<T, E>[] {\n const filtered: AsyncResult<T, E>[] = [];\n for (const item of this._list.values()) {\n if (predicate(item.result)) {\n filtered.push(item.result);\n }\n }\n return filtered;\n }\n\n /**\n * Gets all tasks that satisfy the given predicate and maps them using the provided function.\n * @param filterPredicate the function to test each task\n * @param mapFunc the function to map each task\n * @returns an array of mapped values\n */\n getAllFilteredAndMap<U>(filterPredicate: (task: AsyncResult<T, E>) => boolean, mapFunc: (task: AsyncResult<T, E>) => U): U[] {\n const results: U[] = [];\n for (const item of this._list.values()) {\n if (filterPredicate(item.result)) {\n results.push(mapFunc(item.result));\n }\n }\n return results;\n }\n\n /**\n * Gets all tasks that have succeeded.\n * @returns an array of successful AsyncResult tasks\n */\n getAllSuccess(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isSuccess());\n }\n\n /**\n * Gets the success values of all tasks that have succeeded.\n * @returns an array of successful values\n */\n getAllSuccessValues(): T[] {\n return this.getAllFilteredAndMap((task) => task.isSuccess(), (task) => task.unwrapOrThrow());\n }\n\n /**\n * Gets all tasks that have errored.\n * @returns an array of error AsyncResult tasks\n */\n getAllErrors(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isError());\n }\n\n /**\n * Gets the error values of all tasks that have errored.\n * @returns an array of error values\n */\n getAllErrorValues(): E[] {\n return this.getAllFilteredAndMap((task) => task.isError(), (task) => task.unwrapErrorOrNull()!);\n }\n\n /**\n * Gets all tasks that are currently loading.\n * @returns an array of loading AsyncResult tasks\n */\n getAllLoading(): AsyncResult<T, E>[] {\n return this.getAllFiltered((task) => task.isLoading());\n }\n\n /**\n * Gets the promises of all tasks that are currently loading.\n * @returns an array of promises for loading tasks\n */\n getAllLoadingPromises(): Promise<Result<T, E>>[] {\n return this.getAllFilteredAndMap((task) => task.isLoading(), (task) => task.toResultPromise());\n }\n\n // === Debugging utilities ===\n\n /**\n * Logs the current state and tasks of the AsyncResultList to the console.\n * @param name an optional name to identify the log\n */\n log(name?: string) {\n const time = (new Date()).toTimeString().slice(0, 8);\n console.log(`${name ?? '<Anonymous TaskQueue>'} ; State at ${time} :`, this.state, this._list);\n }\n\n /**\n * Sets up a listener to log the state and tasks of the AsyncResultList whenever it changes.\n * @param name an optional name to identify the log\n * @returns a function to unsubscribe the debug listener\n */\n debug(name?: string) {\n return this.listen(() => {\n this.log(name);\n });\n }\n}","import { AsyncResult, type AsyncResultState, type ChainStep } from \"./asyncResult\";\nimport type { ErrorBase } from \"./error\";\n\ntype KeyedAsyncCacheRefetchOptions = {\n policy: 'refetch' | 'if-error' | 'no-refetch';\n};\n\ntype CacheItem<P, V, E extends ErrorBase = ErrorBase> = {\n result: AsyncResult<V, E>;\n fetcherParams: P;\n valid: boolean;\n lastFetched?: number;\n ttl?: number;\n};\n\nconst _defaultRefetchOptions: KeyedAsyncCacheRefetchOptions = { policy: 'no-refetch' };\n\nfunction defaultParamsToKey<P>(params: P): string {\n if (typeof params === 'object') {\n return JSON.stringify(params);\n }\n return String(params);\n}\n\n/**\n * A cache for asynchronous operations that maps parameter sets to their corresponding AsyncResult.\n * Supports automatic refetching based on specified policies.\n * \n * @template P - The type of the parameters used to fetch values.\n * @template V - The type of the values being fetched.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n */\nexport class KeyedAsyncCache<P, V, E extends ErrorBase = ErrorBase> {\n private _cache: Map<string, CacheItem<P, V, E>> = new Map();\n private _fetcher: ChainStep<P, V, E>;\n private _paramsToKey: (params: P) => string;\n private _cacheTTL?: number;\n\n /**\n * Creates a new KeyedAsyncCache instance.\n * @param fetcher the function used to fetch values based on parameters\n * @param paramsToKey a function that converts parameters to a unique string key (default uses JSON.stringify for objects)\n * @param cacheTTL optional time-to-live for cache entries in milliseconds\n */\n constructor(fetcher: ChainStep<P, V, E>, paramsToKey: (params: P) => string = defaultParamsToKey, cacheTTL: number = Infinity) {\n this._fetcher = fetcher;\n this._paramsToKey = paramsToKey;\n this._cacheTTL = cacheTTL;\n }\n\n private makeCacheItem(result: AsyncResult<V, E>, fetcherParams: P, ttl?: number | undefined): CacheItem<P, V, E> {\n return {\n result,\n fetcherParams,\n ttl: ttl ?? this._cacheTTL,\n valid: true,\n };\n }\n\n private shouldRefetch(existingResult: CacheItem<P, V, E>, refetch: KeyedAsyncCacheRefetchOptions): boolean {\n if (!existingResult.valid) {\n return true;\n }\n if (refetch.policy === 'refetch') {\n return true;\n }\n if (refetch.policy === 'if-error') {\n return existingResult.result.state.status === 'error';\n }\n if (existingResult.ttl !== undefined && existingResult.lastFetched !== undefined) {\n const now = Date.now();\n if (now - existingResult.lastFetched > existingResult.ttl) {\n return true;\n }\n }\n return false;\n }\n\n private updateOrCreateCacheItemFromParams(params: P, cacheItem?: CacheItem<P, V, E>) {\n const promise = Promise.resolve(this._fetcher(params));\n let result = cacheItem?.result.updateFromResultPromise(promise) ?? AsyncResult.fromResultPromise(promise);\n cacheItem = cacheItem ?? this.makeCacheItem(result, params);\n \n promise.then(() => {\n cacheItem.lastFetched = Date.now();\n });\n\n return cacheItem;\n }\n\n /**\n * Gets the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns the AsyncResult corresponding to the given parameters\n */\n get(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): AsyncResult<V, E> {\n const key = this._paramsToKey(params);\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n if (!this.shouldRefetch(cacheItem, refetch)) {\n return cacheItem.result;\n } else {\n this.updateOrCreateCacheItemFromParams(params, cacheItem);\n return cacheItem.result;\n }\n }\n \n const cacheItem = this.updateOrCreateCacheItemFromParams(params);\n this._cache.set(key, cacheItem);\n return cacheItem.result;\n }\n\n /**\n * Gets the settled state of the AsyncResult for the given parameters, fetching it if not cached or if refetching is required.\n * Waits for the AsyncResult to settle before returning its state.\n * @param params the parameters to fetch the value\n * @param refetch options determining whether to refetch the value\n * @returns a promise resolving to the settled state of the AsyncResult\n */\n async getSettledState(params: P, refetch: KeyedAsyncCacheRefetchOptions = _defaultRefetchOptions): Promise<AsyncResultState<V, E>> {\n const asyncResult = this.get(params, refetch);\n await asyncResult.waitForSettled();\n return asyncResult.state;\n }\n\n /**\n * Checks if any cached AsyncResult is currently loading.\n * @returns whether any cached AsyncResult is loading\n */\n anyLoading(): boolean {\n for (const cacheItem of this._cache.values()) {\n if (cacheItem.result.isLoading()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Clears the entire cache.\n */\n clear() {\n this._cache.clear();\n }\n\n /**\n * Invalidates the cache entry for the given key.\n * @param key the key of the cache entry to invalidate\n */\n invalidateKey(key: string) {\n if (this._cache.has(key)) {\n const cacheItem = this._cache.get(key)!;\n cacheItem.valid = false;\n }\n }\n\n /**\n * Invalidates the cache entry for the given parameters.\n * @param params the parameters of the cache entry to invalidate\n */\n invalidateParams(params: P) {\n const key = this._paramsToKey(params);\n this.invalidateKey(key);\n }\n\n /**\n * Invalidates all cache entries.\n */\n invalidateAll() {\n for (const cacheItem of this._cache.values()) {\n cacheItem.valid = false;\n }\n }\n\n /**\n * Gets all cache items.\n * @returns an array of all cache items\n */\n get items() {\n return Array.from(this._cache.values());\n }\n\n /**\n * Gets the number of cache items.\n * @returns the number of cache items\n */\n get size() {\n return this._cache.size;\n }\n\n /**\n * Gets all cache items with successful results.\n * @returns an array of cache items with successful results\n */\n get successfulItems() {\n return Array.from(this._cache.values()).filter(item => item.result.isSuccess());\n }\n}\n","import { AsyncResult } from \"./asyncResult\";\n\nexport function delay(ms: number): AsyncResult<true> {\n return AsyncResult.fromValuePromise(new Promise(resolve => {\n setTimeout(() => resolve(true), ms);\n }));\n}"],"mappings":";AAaO,IAAM,YAAN,MAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,MAAc,SAAkB,aAAuB,MAAe,MAAM;AACpF,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,cAAc;AAEnB,QAAI,KAAK;AACL,WAAK,SAAS;AAAA,IAClB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAmB;AACf,WAAO,SAAS,KAAK,IAAI,KAAK,KAAK,WAAW,EAAE;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAiB;AACb,QAAI,KAAK,aAAa;AAClB,cAAQ,MAAM,KAAK,SAAS,GAAG,KAAK,WAAW;AAAA,IACnD,OAAO;AACH,cAAQ,MAAM,KAAK,SAAS,CAAC;AAAA,IACjC;AAAA,EACJ;AACJ;;;AC7BO,IAAM,SAAN,MAAM,QAA2C;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,OAA0B;AAClC,SAAK,SAAS;AAAA,EAClB;AAAA;AAAA,EAGA,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAqB;AACjB,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAmB;AACf,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,GAAuC,OAAwB;AAClE,WAAO,IAAI,QAAO,EAAE,QAAQ,WAAW,MAAM,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAqC,OAA4B;AACpE,WAAO,IAAI,QAAO,EAAE,QAAQ,SAAS,MAAM,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO,MAAc,SAAkB,aAAiD;AAC3F,WAAO,QAAO,IAAI,IAAI,UAAU,MAAM,SAAS,WAAW,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAyB;AACrB,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmB;AACf,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAY,cAAwB;AAChC,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,WAA+C,SAAqB,aAA2D;AAClI,WAAO,QACF,KAAK,CAAC,UAAU,QAAO,GAAS,KAAK,CAAC,EACtC,MAAM,CAAC,UAAU,QAAO,IAAI,YAAY,KAAK,CAAC,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,YAAgD,IAAsB,aAA2D;AACpI,WAAO,QAAO,WAAW,GAAG,GAAG,WAAW;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAA2C,IAA6D;AACpG,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,IAAI,QAAkB,GAAG,KAAK,OAAO,KAAK,CAAC;AAAA,IACtD;AACA,WAAO,QAAO,IAAO,KAAK,OAAO,KAAK;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAA+C,IAAwD;AACnG,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,GAAG,KAAK,OAAO,KAAK;AAAA,IAC/B;AACA,WAAO,QAAO,IAAO,KAAK,OAAO,KAAK;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,EAAE,OAAO,QAAQ,IAAqC;AAClD,UAAM;AAEN,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,OAAO,IAAwC,WAAkE;AAC7G,UAAM,WAAW,UAAU;AAC3B,QAAI,SAAS,SAAS,KAAK;AAE3B,WAAO,CAAC,OAAO,MAAM;AACjB,YAAM,UAAU,OAAO;AACvB,UAAI,QAAQ,OAAO,WAAW,SAAS;AACnC,eAAO,QAAO,IAAI,QAAQ,OAAO,KAAK;AAAA,MAC1C;AACA,eAAS,SAAS,KAAK,QAAQ,OAAO,KAAK;AAAA,IAC/C;AAEA,WAAO,QAAO,GAAG,OAAO,KAAK;AAAA,EACjC;AACJ;;;ACpJO,IAAM,cAAN,MAAM,aAA6D;AAAA,EAC9D;AAAA,EACA,aAAqD,oBAAI,IAAI;AAAA,EAErE,YAAY,OAAmC;AAC3C,SAAK,SAAS,SAAS,EAAE,QAAQ,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY;AACR,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AACN,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AACL,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY;AACR,WAAO,KAAK,OAAO,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,eAAyB;AACrB,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmB;AACf,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,UAAM,IAAI,MAAM,uDAAuD;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAC1B,QAAI,KAAK,OAAO,WAAW,SAAS;AAChC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA8B;AAC1B,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO,YAAY;AAAA,IACnC;AACA,WAAO;AAAA,EACX;AAAA;AAAA,EAIA,IAAY,MAAM,UAAqC;AACnD,UAAM,WAAW,KAAK;AAEtB,SAAK,SAAS;AACd,SAAK,WAAW,QAAQ,CAAC,kBAAkB;AACvC,UAAK,SAAS,WAAW,aAAa,SAAS,WAAW,aAAc,cAAc,QAAQ,uBAAuB;AACjH,sBAAc,SAAS,IAAI;AAAA,MAC/B;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEQ,SAAS,UAAqC;AAClD,SAAK,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,GAAM,OAAiC;AAC1C,WAAO,IAAI,aAAsB,EAAE,QAAQ,WAAW,MAAM,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAqC,OAAiC;AACzE,WAAO,IAAI,aAAsB,EAAE,QAAQ,SAAS,MAAM,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,OAAO,MAAc,SAAkB,aAAuB,MAAe,MAAqC;AACrH,UAAM,QAAQ,IAAI,UAAU,MAAM,SAAS,aAAa,GAAG;AAC3D,WAAO,aAAY,IAAI,KAAK;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,OAAU;AACtB,SAAK,QAAQ,EAAE,QAAQ,WAAW,MAAM;AACxC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,OAAU;AACtB,SAAK,QAAQ,EAAE,QAAQ,SAAS,MAAM;AACtC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,UAAa;AACxB,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,WAAK,QAAQ,EAAE,GAAG,KAAK,QAAQ,SAAS;AAAA,IAC5C;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,iBAAqD,SAAwC;AAChG,UAAM,SAAS,IAAI,aAAkB;AACrC,WAAO,uBAAuB,OAAO;AACrC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,uBAAuB,SAAqB;AACxC,UAAM,qBAAqB,YAAmC;AAC1D,UAAI;AACA,cAAM,QAAQ,MAAM;AACpB,eAAO,OAAO,GAAG,KAAK;AAAA,MAC1B,SAAS,OAAO;AACZ,eAAO,OAAO,IAAI,KAAU;AAAA,MAChC;AAAA,IACJ;AACA,WAAO,KAAK,wBAAwB,mBAAmB,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAgD;AAClD,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,UAAI;AACA,cAAM,QAAQ,MAAM,KAAK,OAAO;AAChC,aAAK,SAAS,MAAM;AAAA,MACxB,SAAS,OAAO;AACZ,aAAK,SAAS,EAAE,QAAQ,SAAS,MAAkB;AAAA,MACvD;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAyC;AAC3C,UAAM,UAAU,MAAM,KAAK,eAAe;AAC1C,QAAI,QAAQ,MAAM,WAAW,UAAU,QAAQ,MAAM,WAAW,WAAW;AACvE,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC/E;AACA,QAAI,QAAQ,MAAM,WAAW,SAAS;AAClC,aAAO,OAAO,IAAI,QAAQ,MAAM,KAAK;AAAA,IACzC;AACA,WAAO,OAAO,GAAG,QAAQ,MAAM,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBAAoC;AACtC,UAAM,UAAU,MAAM,KAAK,eAAe;AAC1C,WAAO,QAAQ,cAAc;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,uBAA0C;AAC5C,UAAM,UAAU,MAAM,KAAK,eAAe;AAC1C,WAAO,QAAQ,aAAa;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,kBAAsD,SAAmD;AAC5G,UAAM,SAAS,IAAI,aAAkB;AACrC,WAAO,wBAAwB,OAAO;AACtC,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,wBAAwB,SAAgC;AACpD,SAAK,QAAQ,EAAE,QAAQ,WAAW,QAAQ;AAC1C,YACK,KAAK,CAAC,QAAQ;AACX,WAAK,QAAQ,IAAI;AAAA,IACrB,CAAC,EACA,MAAM,CAAC,UAAU;AACd,WAAK,gBAAgB,IAAI,UAAU,qCAAqC,gDAAgD,KAAK,CAAM;AAAA,IACvI,CAAC;AACL,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,UAAwC,UAAsC,EAAE,WAAW,MAAM,uBAAuB,KAAK,GAAG;AACnI,UAAM,QAA2C,EAAE,UAAU,QAAQ;AACrE,SAAK,WAAW,IAAI,KAAK;AAEzB,QAAI,QAAQ,WAAW;AACnB,eAAS,IAAI;AAAA,IACjB;AAEA,WAAO,MAAM;AACT,WAAK,WAAW,OAAO,KAAK;AAAA,IAChC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,UAAwC,UAAsC,EAAE,WAAW,MAAM,uBAAuB,KAAK,GAAG;AAC/I,UAAM,QAAQ,KAAK,OAAO,CAAC,WAAW;AAClC,eAAS,MAAM;AACf,UAAI,OAAO,MAAM,WAAW,aAAa,OAAO,MAAM,WAAW,SAAS;AACtE,cAAM;AAAA,MACV;AAAA,IACJ,GAAG,OAAO;AAEV,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,UAA8B;AACxC,WAAO,KAAK,mBAAmB,CAAC,WAAW;AACvC,UAAI,OAAO,UAAU,GAAG;AACpB,iBAAS,OAAO,cAAc,CAAC;AAAA,MACnC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,UAA8B;AAC7C,WAAO,KAAK,OAAO,CAAC,WAAW;AAC3B,UAAI,OAAO,UAAU,GAAG;AACpB,iBAAS,OAAO,cAAc,CAAC;AAAA,MACnC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,UAA8B;AACtC,WAAO,KAAK,mBAAmB,CAAC,WAAW;AACvC,UAAI,OAAO,QAAQ,GAAG;AAClB,iBAAS,OAAO,kBAAkB,CAAE;AAAA,MACxC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,UAA8B;AAC3C,WAAO,KAAK,OAAO,CAAC,WAAW;AAC3B,UAAI,OAAO,QAAQ,GAAG;AAClB,iBAAS,OAAO,kBAAkB,CAAE;AAAA,MACxC;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,OAA6B,UAAsC,EAAE,WAAW,MAAM,uBAAuB,KAAK,GAAG;AACxH,WAAO,MAAM,OAAO,CAAC,aAAa;AAC9B,WAAK,SAAS,SAAS,KAAK;AAAA,IAChC,GAAG,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,OAA6B,UAAsC,EAAE,WAAW,MAAM,uBAAuB,KAAK,GAAG;AACpI,WAAO,MAAM,mBAAmB,CAAC,aAAa;AAC1C,WAAK,SAAS,SAAS,KAAK;AAAA,IAChC,GAAG,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,WAA4D,QAA+C;AAC9G,WAAO,IAAI,aAAqB,EAAE,iBAAiB,MAAM;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,QAAyB;AACtC,YAAQ,IAAI,qCAAqC;AACjD,YAAQ,IAAI,oBAAoB,MAAM;AACtC,UAAM,UAAU,OAAO,CAAC,aAAa,KAAK,eAAe,QAAQ,CAAC;AAClE,WAAO,KAAK,wBAAwB,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAgE,QAA8C;AACjH,UAAM,SAAS,IAAI,aAAqB;AACxC,UAAM,UAAU,MAAM;AAClB,aAAO,iBAAiB,MAAM;AAAA,IAClC;AAEA,WAAO,EAAE,SAAS,OAAO;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAA2C,IAAqD;AAC5F,UAAM,mBAAmB,YAAwC;AAC7D,YAAM,UAAU,MAAM,KAAK,eAAe;AAC1C,UAAI,QAAQ,MAAM,WAAW,aAAa,QAAQ,MAAM,WAAW,QAAQ;AACvE,cAAM,IAAI,MAAM,uCAAuC;AAAA,MAC3D;AACA,UAAI,QAAQ,MAAM,WAAW,SAAS;AAClC,eAAO,OAAO,IAAI,QAAQ,MAAM,KAAK;AAAA,MACzC;AAEA,aAAO,GAAG,QAAQ,MAAM,KAAK;AAAA,IACjC;AAEA,WAAO,aAAY,kBAA6B,iBAAiB,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,UAA+C,IAAyD;AACpG,UAAM,mBAAmB,YAAwC;AAC7D,YAAM,UAAU,MAAM,KAAK,gBAAgB;AAC3C,UAAI,QAAQ,MAAM,WAAW,SAAS;AAClC,eAAO,OAAO,IAAI,QAAQ,MAAM,KAAK;AAAA,MACzC;AAEA,YAAM,kBAAkB,GAAG,QAAQ,MAAM,KAAK;AAC9C,YAAM,cAAc,MAAM,gBAAgB,gBAAgB;AAC1D,aAAO;AAAA,IACX;AAEA,WAAO,aAAY,kBAA6B,iBAAiB,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,gBAA4D,SAA0J;AACzN,QAAI,QAAQ,WAAW,GAAG;AAEtB,aAAO,aAAY,GAAG,MAAkB;AAAA,IAC5C;AAEA,UAAM,UAAU,QAAQ,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE;AAAA,MAChE,CAAC,mBAAmB;AAChB,mBAAW,OAAO,gBAAgB;AAC9B,cAAI,IAAI,MAAM,WAAW,SAAS;AAC9B,mBAAO,OAAO,IAAI,IAAI,MAAM,KAAK;AAAA,UACrC;AAAA,QACJ;AAEA,cAAM,SAAS,eAAe,IAAI,CAAC,MAAM,EAAE,aAAa,CAAE;AAO1D,eAAO,OAAO,GAAG,MAAM;AAAA,MAC3B;AAAA,IACJ;AAEA,WAAO,aAAY,kBAAkB,OAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,EAAE,OAAO,QAAQ,IAA6C;AAC1D,UAAM;AAEN,QAAI,KAAK,OAAO,WAAW,WAAW;AAClC,aAAO,KAAK,OAAO;AAAA,IACvB;AACA,WAAO;AAAA,EACX;AAAA,EAEA,OAAe,uBAA+C,UAAgE;AAC1H,WAAO,YAAmC;AACtC,UAAI,SAAS,SAAS,KAAK;AAE3B,aAAO,CAAC,OAAO,MAAM;AAEjB,cAAM,UAAU,OAAO;AACvB,cAAM,UAAU,MAAM,QAAQ,gBAAgB;AAC9C,YAAI,QAAQ,MAAM,WAAW,SAAS;AAClC,iBAAO,OAAO,IAAI,QAAQ,MAAM,KAAK;AAAA,QACzC;AACA,iBAAS,SAAS,KAAK,QAAQ,MAAM,KAAK;AAAA,MAC9C;AAEA,aAAO,OAAO,GAAG,OAAO,KAAK;AAAA,IACjC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,OAAO,IAAqD,eAAyG;AACjK,WAAO,aAAY,WAAW,OAAO,mBAA0C;AAC3E,YAAM,WAAW,cAAc,cAAc;AAC7C,aAAO,aAAY,uBAA6B,QAAQ,EAAE;AAAA,IAC9D,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,eAAmF;AAC1F,YAAQ,IAAI,+BAA+B;AAC3C,YAAQ,IAAI,uBAAuB,aAAa;AAChD,WAAO,KAAK,iBAAiB,CAAC,WAAW;AACrC,YAAM,WAAW,cAAc,MAAM;AACrC,cAAQ,IAAI,uBAAuB,QAAQ;AAC3C,aAAO,aAAY,uBAA6B,QAAQ,EAAE;AAAA,IAC9D,CAAC;AAAA,EACL;AAAA;AAAA,EAMA,IAAI,MAAe;AACf,UAAM,QAAQ,oBAAI,KAAK,GAAG,aAAa,EAAE,MAAM,GAAG,CAAC;AACnD,YAAQ,IAAI,GAAG,QAAQ,yBAAyB,eAAe,IAAI,MAAM,KAAK,KAAK;AAAA,EACvF;AAAA,EAEA,MAAM,MAAe;AACjB,WAAO,KAAK,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC;AAAA,EACzC;AACJ;;;ACprBO,IAAM,wBAAN,MAAsE;AAAA,EACjE,QAAQ,oBAAI,IAA6C;AAAA,EACzD,aAAoE,oBAAI,IAAI;AAAA,EAC5E,SAAqC;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7C,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACjB,WAAO,KAAK,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAA6B;AAC7B,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,IAAI,OAAK,EAAE,MAAM;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAyC;AACzC,WAAO,MAAM,KAAK,KAAK,MAAM,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAQ;AACR,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAY,MAAM,GAA+B;AAC7C,SAAK,SAAS;AACd,SAAK,WAAW,QAAQ,OAAK,EAAE,IAAI,CAAC;AAAA,EACxC;AAAA,EAEQ,kBAAkB;AACtB,SAAK,QAAQ,KAAK,WAAW,IAAI,gBAAgB;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,UAA4D;AAC/D,SAAK,WAAW,IAAI,QAAQ;AAC5B,WAAO,MAAM;AACT,WAAK,WAAW,OAAO,QAAQ;AAAA,IACnC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,UAA0D;AACpE,WAAO,KAAK,OAAO,CAAC,cAAc;AAC9B,iBAAW,QAAQ,UAAU,MAAM,OAAO,GAAG;AACzC,YAAI,KAAK,OAAO,UAAU,GAAG;AACzB,mBAAS,KAAK,QAAQ,KAAK,GAAG;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,UAA0D;AAClE,WAAO,KAAK,OAAO,CAAC,cAAc;AAC9B,iBAAW,QAAQ,UAAU,MAAM,OAAO,GAAG;AACzC,YAAI,KAAK,OAAO,QAAQ,GAAG;AACvB,mBAAS,KAAK,QAAQ,KAAK,GAAG;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,IAAI,KAAa,MAAyB,iBAA0B,MAAyB;AACzF,QAAI,QAAQ;AACZ,QAAI,gBAAgB;AAChB,cAAQ,KAAK,mBAAmB,CAAC,MAAM;AACnC,YAAI,EAAE,UAAU,KAAK,EAAE,OAAO,EAAG;AACjC,aAAK,gBAAgB;AACrB,aAAK,MAAM,OAAO,GAAG;AAAA,MACzB,GAAG,EAAE,WAAW,MAAM,uBAAuB,KAAK,CAAC;AAAA,IACvD,OAAO;AACH,cAAQ,KAAK,OAAO,CAAC,MAAM;AACvB,YAAI,EAAE,UAAU,KAAK,EAAE,OAAO,EAAG;AACjC,aAAK,gBAAgB;AAAA,MACzB,GAAG,EAAE,WAAW,MAAM,uBAAuB,KAAK,CAAC;AAAA,IACvD;AAEA,SAAK,MAAM,IAAI,KAAK,EAAE,KAAK,QAAQ,MAAM,MAAM,CAAC;AAChD,SAAK,QAAQ;AAEb,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,KAAsB;AACzB,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,KAAM,QAAO;AAElB,SAAK,MAAM;AACX,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACJ,SAAK,MAAM,QAAQ,CAAC,EAAE,MAAM,MAAM,MAAM,CAAC;AACzC,SAAK,MAAM,MAAM;AACjB,SAAK,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAsB;AAClB,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACpC,UAAI,KAAK,OAAO,UAAU,GAAG;AACzB,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,WAAsE;AACjF,UAAM,WAAgC,CAAC;AACvC,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACpC,UAAI,UAAU,KAAK,MAAM,GAAG;AACxB,iBAAS,KAAK,KAAK,MAAM;AAAA,MAC7B;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAAwB,iBAAuD,SAA8C;AACzH,UAAM,UAAe,CAAC;AACtB,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACpC,UAAI,gBAAgB,KAAK,MAAM,GAAG;AAC9B,gBAAQ,KAAK,QAAQ,KAAK,MAAM,CAAC;AAAA,MACrC;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAqC;AACjC,WAAO,KAAK,eAAe,CAAC,SAAS,KAAK,UAAU,CAAC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAA2B;AACvB,WAAO,KAAK,qBAAqB,CAAC,SAAS,KAAK,UAAU,GAAG,CAAC,SAAS,KAAK,cAAc,CAAC;AAAA,EAC/F;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAoC;AAChC,WAAO,KAAK,eAAe,CAAC,SAAS,KAAK,QAAQ,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAyB;AACrB,WAAO,KAAK,qBAAqB,CAAC,SAAS,KAAK,QAAQ,GAAG,CAAC,SAAS,KAAK,kBAAkB,CAAE;AAAA,EAClG;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAqC;AACjC,WAAO,KAAK,eAAe,CAAC,SAAS,KAAK,UAAU,CAAC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAiD;AAC7C,WAAO,KAAK,qBAAqB,CAAC,SAAS,KAAK,UAAU,GAAG,CAAC,SAAS,KAAK,gBAAgB,CAAC;AAAA,EACjG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,MAAe;AACf,UAAM,QAAQ,oBAAI,KAAK,GAAG,aAAa,EAAE,MAAM,GAAG,CAAC;AACnD,YAAQ,IAAI,GAAG,QAAQ,uBAAuB,eAAe,IAAI,MAAM,KAAK,OAAO,KAAK,KAAK;AAAA,EACjG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAe;AACjB,WAAO,KAAK,OAAO,MAAM;AACrB,WAAK,IAAI,IAAI;AAAA,IACjB,CAAC;AAAA,EACL;AACJ;;;ACrSA,IAAM,yBAAwD,EAAE,QAAQ,aAAa;AAErF,SAAS,mBAAsB,QAAmB;AAC9C,MAAI,OAAO,WAAW,UAAU;AAC5B,WAAO,KAAK,UAAU,MAAM;AAAA,EAChC;AACA,SAAO,OAAO,MAAM;AACxB;AAUO,IAAM,kBAAN,MAA6D;AAAA,EACxD,SAA0C,oBAAI,IAAI;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQR,YAAY,SAA6B,cAAqC,oBAAoB,WAAmB,UAAU;AAC3H,SAAK,WAAW;AAChB,SAAK,eAAe;AACpB,SAAK,YAAY;AAAA,EACrB;AAAA,EAEQ,cAAc,QAA2B,eAAkB,KAA8C;AAC7G,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,KAAK,OAAO,KAAK;AAAA,MACjB,OAAO;AAAA,IACX;AAAA,EACJ;AAAA,EAEQ,cAAc,gBAAoC,SAAiD;AACvG,QAAI,CAAC,eAAe,OAAO;AACvB,aAAO;AAAA,IACX;AACA,QAAI,QAAQ,WAAW,WAAW;AAC9B,aAAO;AAAA,IACX;AACA,QAAI,QAAQ,WAAW,YAAY;AAC/B,aAAO,eAAe,OAAO,MAAM,WAAW;AAAA,IAClD;AACA,QAAI,eAAe,QAAQ,UAAa,eAAe,gBAAgB,QAAW;AAC9E,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,MAAM,eAAe,cAAc,eAAe,KAAK;AACvD,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA,EAEQ,kCAAkC,QAAW,WAAgC;AACjF,UAAM,UAAU,QAAQ,QAAQ,KAAK,SAAS,MAAM,CAAC;AACrD,QAAI,SAAS,WAAW,OAAO,wBAAwB,OAAO,KAAK,YAAY,kBAAkB,OAAO;AACxG,gBAAY,aAAa,KAAK,cAAc,QAAQ,MAAM;AAE1D,YAAQ,KAAK,MAAM;AACf,gBAAU,cAAc,KAAK,IAAI;AAAA,IACrC,CAAC;AAED,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,QAAW,UAAyC,wBAA2C;AAC/F,UAAM,MAAM,KAAK,aAAa,MAAM;AACpC,QAAI,KAAK,OAAO,IAAI,GAAG,GAAG;AACtB,YAAMA,aAAY,KAAK,OAAO,IAAI,GAAG;AACrC,UAAI,CAAC,KAAK,cAAcA,YAAW,OAAO,GAAG;AACzC,eAAOA,WAAU;AAAA,MACrB,OAAO;AACH,aAAK,kCAAkC,QAAQA,UAAS;AACxD,eAAOA,WAAU;AAAA,MACrB;AAAA,IACJ;AAEA,UAAM,YAAY,KAAK,kCAAkC,MAAM;AAC/D,SAAK,OAAO,IAAI,KAAK,SAAS;AAC9B,WAAO,UAAU;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,QAAW,UAAyC,wBAAyD;AAC/H,UAAM,cAAc,KAAK,IAAI,QAAQ,OAAO;AAC5C,UAAM,YAAY,eAAe;AACjC,WAAO,YAAY;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAsB;AAClB,eAAW,aAAa,KAAK,OAAO,OAAO,GAAG;AAC1C,UAAI,UAAU,OAAO,UAAU,GAAG;AAC9B,eAAO;AAAA,MACX;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACJ,SAAK,OAAO,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,KAAa;AACvB,QAAI,KAAK,OAAO,IAAI,GAAG,GAAG;AACtB,YAAM,YAAY,KAAK,OAAO,IAAI,GAAG;AACrC,gBAAU,QAAQ;AAAA,IACtB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,QAAW;AACxB,UAAM,MAAM,KAAK,aAAa,MAAM;AACpC,SAAK,cAAc,GAAG;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB;AACZ,eAAW,aAAa,KAAK,OAAO,OAAO,GAAG;AAC1C,gBAAU,QAAQ;AAAA,IACtB;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,QAAQ;AACR,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,OAAO;AACP,WAAO,KAAK,OAAO;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,kBAAkB;AAClB,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC,EAAE,OAAO,UAAQ,KAAK,OAAO,UAAU,CAAC;AAAA,EAClF;AACJ;;;ACpMO,SAAS,MAAM,IAA+B;AACjD,SAAO,YAAY,iBAAiB,IAAI,QAAQ,aAAW;AACvD,eAAW,MAAM,QAAQ,IAAI,GAAG,EAAE;AAAA,EACtC,CAAC,CAAC;AACN;","names":["cacheItem"]}
@@ -66,7 +66,7 @@ declare function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (
66
66
  * @param generatorFunc the generator function to run when triggered
67
67
  * @returns an object containing a ref to the AsyncResult and a trigger function
68
68
  */
69
- declare function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResultGenerator<T>): {
69
+ declare function useLazyGenerator<T, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): {
70
70
  resultRef: Ref<AsyncResult<T, any, P>>;
71
71
  trigger: () => void;
72
72
  };
@@ -78,7 +78,7 @@ declare function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResu
78
78
  * @param options optional settings
79
79
  * @returns ref to the result
80
80
  */
81
- declare function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => AsyncResultGenerator<T>, options?: ReactiveProcessOptions): Ref<AsyncResult<T, E, P>>;
81
+ declare function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs, notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>, options?: ReactiveProcessOptions): Ref<AsyncResult<T, E, P>>;
82
82
  /**
83
83
  * Creates a reactive AsyncResultCollection wrapped in a Vue ref.
84
84
  * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.
@@ -66,7 +66,7 @@ declare function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (
66
66
  * @param generatorFunc the generator function to run when triggered
67
67
  * @returns an object containing a ref to the AsyncResult and a trigger function
68
68
  */
69
- declare function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResultGenerator<T>): {
69
+ declare function useLazyGenerator<T, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): {
70
70
  resultRef: Ref<AsyncResult<T, any, P>>;
71
71
  trigger: () => void;
72
72
  };
@@ -78,7 +78,7 @@ declare function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResu
78
78
  * @param options optional settings
79
79
  * @returns ref to the result
80
80
  */
81
- declare function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => AsyncResultGenerator<T>, options?: ReactiveProcessOptions): Ref<AsyncResult<T, E, P>>;
81
+ declare function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs, notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>, options?: ReactiveProcessOptions): Ref<AsyncResult<T, E, P>>;
82
82
  /**
83
83
  * Creates a reactive AsyncResultCollection wrapped in a Vue ref.
84
84
  * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.
package/dist/vue/index.js CHANGED
@@ -81,14 +81,18 @@ function useLazyGenerator(generatorFunc) {
81
81
  const result = new import_core.AsyncResult();
82
82
  const resultRef = useAsyncResultRef(result);
83
83
  const trigger = () => {
84
- result.runInPlace(generatorFunc);
84
+ result.runInPlace((notifyProgress) => generatorFunc(notifyProgress));
85
85
  };
86
86
  return { resultRef, trigger };
87
87
  }
88
88
  function useReactiveGenerator(source, generatorFunc, options = { immediate: true }) {
89
89
  const resultRef = useAsyncResultRef(new import_core.AsyncResult());
90
90
  (0, import_vue.watch)(source, (newInputs) => {
91
- resultRef.value.runInPlace(() => generatorFunc(newInputs));
91
+ resultRef.value.runInPlace((notifyProgress) => {
92
+ console.log("useReactiveGenerator - running generatorFunc with inputs:", newInputs);
93
+ console.log("useReactiveGenerator - notifyProgress function:", notifyProgress);
94
+ return generatorFunc(newInputs, notifyProgress);
95
+ });
92
96
  }, { immediate: options.immediate });
93
97
  return resultRef;
94
98
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vue/index.ts","../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["export * from \"./composables\"\nexport * from \"./components/asyncResultLoader\"","import { onUnmounted, ref, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, AsyncResultCollection, ErrorBase, type Action, type AsyncResultGenerator, type FlatChainStep, type Result } from \"unwrapped/core\";\n\n\n// === Vue specific types ===\n\ninterface ReactiveProcessOptions {\n immediate: boolean;\n}\n\n\n\n// === Vue Composables for AsyncResult ===\n\n/**\n * Makes a ref to the given AsyncResult. Whenever the state of the AsyncResult changes,\n * the ref gets retriggered, making those changes visible to Vue's reactivity system.\n * \n * @param asyncResult the result to make reactive\n * @returns the ref to the result\n */\nexport function useAsyncResultRef<T, E extends ErrorBase = ErrorBase, P = unknown>(asyncResult?: AsyncResult<T, E, P>) {\n if (!asyncResult) {\n asyncResult = new AsyncResult<T, E, P>();\n }\n const state = ref<AsyncResult<T, E, P>>(asyncResult) as Ref<AsyncResult<T, E, P>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\n/**\n * Creates an AsyncResult ref from a promise returning a Result.\n * @param promise the promise returning a Result\n * @returns the ref to the AsyncResult\n */\nexport function useAsyncResultRefFromPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\n\n\n// === Vue Composables for Chains ===\n\n/**\n * Watches a source, gives it as inputs to the function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param pipe the function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveChain<Inputs, T, E extends ErrorBase = ErrorBase>(source: WatchSource<Inputs>, pipe: FlatChainStep<Inputs, T, E>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\n\n// === Vue Composables for Actions ===\n\n/**\n * The return type of useLazyAction.\n */\nexport interface LazyActionRef<T, E extends ErrorBase = ErrorBase, P = unknown> {\n resultRef: Ref<AsyncResult<T, E, P>>;\n trigger: () => void;\n}\n\n/**\n * Executes an action immediately and returns a ref to the AsyncResult representing the action's state.\n * \n * Same as useAsyncResultRefFromPromise(action()).\n * \n * @param action the action to execute immediately\n * @returns a ref to the AsyncResult representing the action's state\n */\nexport function useAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): Ref<AsyncResult<T, E, P>> {\n return useAsyncResultRef(AsyncResult.fromAction(action));\n}\n\n/**\n * Creates a lazy action that can be triggered manually.\n * \n * Same as AsyncResult.makeLazyAction(action), but the AsyncResult is wrapped in a ref for Vue reactivity.\n * \n * @param action the action to execute when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyActionRef<T, E, P> {\n const lazyAction = AsyncResult.makeLazyAction<T, E, P>(action);\n const resultRef = useAsyncResultRef(lazyAction.result);\n\n return { resultRef, trigger: lazyAction.trigger };\n}\n\n\n// === Vue Composables for Generators ===\n\n/**\n * Runs a generator function immediately and returns a ref to the AsyncResult representing the generator's state.\n * @param generatorFunc the generator function to run immediately\n * @returns a ref to the AsyncResult representing the generator's state\n */\nexport function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (progress: P) => void) => AsyncResultGenerator<T>): Ref<AsyncResult<T, any, P>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\n/**\n * Creates a lazy generator that can be triggered manually.\n * \n * @param generatorFunc the generator function to run when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResultGenerator<T>): { resultRef: Ref<AsyncResult<T, any, P>>, trigger: () => void } {\n const result = new AsyncResult<T, any, P>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace(generatorFunc);\n }\n\n return { resultRef, trigger };\n}\n\n/**\n * Watches a source, gives it as inputs to the generator function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param generatorFunc the generator function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => AsyncResultGenerator<T>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E, P>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E, P>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace(() => generatorFunc(newInputs));\n }, { immediate: options.immediate });\n\n return resultRef;\n}\n\n\n// === Vue Composables for AsyncResultCollection ===\n\n/**\n * Creates a reactive AsyncResultCollection wrapped in a Vue ref.\n * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.\n * \n * @template T - The type of the values in the AsyncResultCollection.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @returns a ref to the AsyncResultCollection\n */\nexport function useAsyncResultCollection<T = any, E extends ErrorBase = ErrorBase>() {\n const list = new AsyncResultCollection<T, E>();\n const listRef = ref(list);\n\n list.listen(() => {\n triggerRef(listRef);\n });\n\n return listRef;\n}","import { defineComponent, watch, h, type VNode, type SlotsType } from \"vue\"\nimport { ErrorBase, type AsyncResult } from \"unwrapped/core\"\nimport { useAsyncResultRef } from \"../composables\"\n\ninterface CustomSlots<E extends ErrorBase = ErrorBase, P = unknown> {\n loading?: (props: { progress?: P }) => VNode;\n error?: (props: { error: E }) => VNode;\n idle?: () => VNode;\n}\n\n/**\n * Factory function to create a component that displays different content based on an AsyncResult's state. Provides slots for loading, error, idle, and success states and passes the relevant data to each slot, and are typed appropriately.\n * @param slots predefined slots for loading, error, and idle states. Useful for not having to repeat the same template for displaying a framework-specific spinner while in loading state, or a custom error message.\n * @param name Optional internal name for the component\n * @returns An instantiable component that accepts an AsyncResult prop and a default slot for the success state.\n * \n * @example\n * // loaders.ts - Create reusable loader with default loading/error UI\n * const MyLoader = makeAsyncResultLoader({\n * loading: () => h(Spinner),\n * error: ({ error }) => h(ErrorDisplay, { error }),\n * idle: () => h('div', 'Ready')\n * });\n * \n * // MyPage.vue - Use the loader with custom success content\n * <MyLoader :result=\"myAsyncResult\">\n * <template #default=\"{ value }\">\n * <UserProfile :user=\"value\" />\n * </template>\n * </MyLoader>\n */\nexport function makeAsyncResultLoader<T, E extends ErrorBase = ErrorBase, P = unknown>(slots: CustomSlots<E, P>, name = \"AsyncResultLoader\") {\n return defineComponent({\n name,\n props: {\n result: {\n type: Object as () => AsyncResult<T, E, P>,\n required: true\n }\n },\n slots: Object as SlotsType<CustomSlots<E, P> & { default: { value: T } }>,\n setup(props, context) {\n let resultRef = useAsyncResultRef(props.result);\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult, oldResult) => {\n if (newResult === oldResult) return;\n resultRef = useAsyncResultRef(newResult);\n },\n { immediate: true }\n )\n\n return () => {\n const s = resultRef.value.state;\n\n const renderDefault = context.slots.default ?? (() => h(\"div\", { class: \"success\" }, \"Success\"));\n const renderError = context.slots.error ?? slots.error ?? (() => h(\"div\", { class: \"error\" }, \"Error\"));\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => h(\"div\", { class: \"loading\" }, \"Loading…\"));\n const renderIdle = context.slots.idle ?? slots.idle ?? (() => h(\"div\", { class: \"idle\" }, \"Idle\"));\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return renderLoading({ progress: s.progress });\n\n case \"error\":\n return renderError({ error: s.error });\n\n case \"success\":\n return renderDefault({ value: s.value });\n\n default:\n return renderIdle();\n }\n }\n }\n })\n}"],"mappings":"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","names":["import_vue","import_core"]}
1
+ {"version":3,"sources":["../../src/vue/index.ts","../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["export * from \"./composables\"\nexport * from \"./components/asyncResultLoader\"","import { onUnmounted, ref, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, AsyncResultCollection, ErrorBase, type Action, type AsyncResultGenerator, type FlatChainStep, type Result } from \"unwrapped/core\";\n\n\n// === Vue specific types ===\n\ninterface ReactiveProcessOptions {\n immediate: boolean;\n}\n\n\n\n// === Vue Composables for AsyncResult ===\n\n/**\n * Makes a ref to the given AsyncResult. Whenever the state of the AsyncResult changes,\n * the ref gets retriggered, making those changes visible to Vue's reactivity system.\n * \n * @param asyncResult the result to make reactive\n * @returns the ref to the result\n */\nexport function useAsyncResultRef<T, E extends ErrorBase = ErrorBase, P = unknown>(asyncResult?: AsyncResult<T, E, P>) {\n if (!asyncResult) {\n asyncResult = new AsyncResult<T, E, P>();\n }\n const state = ref<AsyncResult<T, E, P>>(asyncResult) as Ref<AsyncResult<T, E, P>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\n/**\n * Creates an AsyncResult ref from a promise returning a Result.\n * @param promise the promise returning a Result\n * @returns the ref to the AsyncResult\n */\nexport function useAsyncResultRefFromPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\n\n\n// === Vue Composables for Chains ===\n\n/**\n * Watches a source, gives it as inputs to the function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param pipe the function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveChain<Inputs, T, E extends ErrorBase = ErrorBase>(source: WatchSource<Inputs>, pipe: FlatChainStep<Inputs, T, E>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\n\n// === Vue Composables for Actions ===\n\n/**\n * The return type of useLazyAction.\n */\nexport interface LazyActionRef<T, E extends ErrorBase = ErrorBase, P = unknown> {\n resultRef: Ref<AsyncResult<T, E, P>>;\n trigger: () => void;\n}\n\n/**\n * Executes an action immediately and returns a ref to the AsyncResult representing the action's state.\n * \n * Same as useAsyncResultRefFromPromise(action()).\n * \n * @param action the action to execute immediately\n * @returns a ref to the AsyncResult representing the action's state\n */\nexport function useAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): Ref<AsyncResult<T, E, P>> {\n return useAsyncResultRef(AsyncResult.fromAction(action));\n}\n\n/**\n * Creates a lazy action that can be triggered manually.\n * \n * Same as AsyncResult.makeLazyAction(action), but the AsyncResult is wrapped in a ref for Vue reactivity.\n * \n * @param action the action to execute when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyActionRef<T, E, P> {\n const lazyAction = AsyncResult.makeLazyAction<T, E, P>(action);\n const resultRef = useAsyncResultRef(lazyAction.result);\n\n return { resultRef, trigger: lazyAction.trigger };\n}\n\n\n// === Vue Composables for Generators ===\n\n/**\n * Runs a generator function immediately and returns a ref to the AsyncResult representing the generator's state.\n * @param generatorFunc the generator function to run immediately\n * @returns a ref to the AsyncResult representing the generator's state\n */\nexport function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (progress: P) => void) => AsyncResultGenerator<T>): Ref<AsyncResult<T, any, P>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\n/**\n * Creates a lazy generator that can be triggered manually.\n * \n * @param generatorFunc the generator function to run when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyGenerator<T, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): { resultRef: Ref<AsyncResult<T, any, P>>, trigger: () => void } {\n const result = new AsyncResult<T, any, P>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace((notifyProgress) => generatorFunc(notifyProgress));\n }\n\n return { resultRef, trigger };\n}\n\n/**\n * Watches a source, gives it as inputs to the generator function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param generatorFunc the generator function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs, notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E, P>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E, P>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace((notifyProgress) => {\n console.log(\"useReactiveGenerator - running generatorFunc with inputs:\", newInputs);\n console.log(\"useReactiveGenerator - notifyProgress function:\", notifyProgress);\n return generatorFunc(newInputs, notifyProgress)\n });\n }, { immediate: options.immediate });\n\n return resultRef;\n}\n\n\n// === Vue Composables for AsyncResultCollection ===\n\n/**\n * Creates a reactive AsyncResultCollection wrapped in a Vue ref.\n * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.\n * \n * @template T - The type of the values in the AsyncResultCollection.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @returns a ref to the AsyncResultCollection\n */\nexport function useAsyncResultCollection<T = any, E extends ErrorBase = ErrorBase>() {\n const list = new AsyncResultCollection<T, E>();\n const listRef = ref(list);\n\n list.listen(() => {\n triggerRef(listRef);\n });\n\n return listRef;\n}","import { defineComponent, watch, h, type VNode, type SlotsType } from \"vue\"\nimport { ErrorBase, type AsyncResult } from \"unwrapped/core\"\nimport { useAsyncResultRef } from \"../composables\"\n\ninterface CustomSlots<E extends ErrorBase = ErrorBase, P = unknown> {\n loading?: (props: { progress?: P }) => VNode;\n error?: (props: { error: E }) => VNode;\n idle?: () => VNode;\n}\n\n/**\n * Factory function to create a component that displays different content based on an AsyncResult's state. Provides slots for loading, error, idle, and success states and passes the relevant data to each slot, and are typed appropriately.\n * @param slots predefined slots for loading, error, and idle states. Useful for not having to repeat the same template for displaying a framework-specific spinner while in loading state, or a custom error message.\n * @param name Optional internal name for the component\n * @returns An instantiable component that accepts an AsyncResult prop and a default slot for the success state.\n * \n * @example\n * // loaders.ts - Create reusable loader with default loading/error UI\n * const MyLoader = makeAsyncResultLoader({\n * loading: () => h(Spinner),\n * error: ({ error }) => h(ErrorDisplay, { error }),\n * idle: () => h('div', 'Ready')\n * });\n * \n * // MyPage.vue - Use the loader with custom success content\n * <MyLoader :result=\"myAsyncResult\">\n * <template #default=\"{ value }\">\n * <UserProfile :user=\"value\" />\n * </template>\n * </MyLoader>\n */\nexport function makeAsyncResultLoader<T, E extends ErrorBase = ErrorBase, P = unknown>(slots: CustomSlots<E, P>, name = \"AsyncResultLoader\") {\n return defineComponent({\n name,\n props: {\n result: {\n type: Object as () => AsyncResult<T, E, P>,\n required: true\n }\n },\n slots: Object as SlotsType<CustomSlots<E, P> & { default: { value: T } }>,\n setup(props, context) {\n let resultRef = useAsyncResultRef(props.result);\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult, oldResult) => {\n if (newResult === oldResult) return;\n resultRef = useAsyncResultRef(newResult);\n },\n { immediate: true }\n )\n\n return () => {\n const s = resultRef.value.state;\n\n const renderDefault = context.slots.default ?? (() => h(\"div\", { class: \"success\" }, \"Success\"));\n const renderError = context.slots.error ?? slots.error ?? (() => h(\"div\", { class: \"error\" }, \"Error\"));\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => h(\"div\", { class: \"loading\" }, \"Loading…\"));\n const renderIdle = context.slots.idle ?? slots.idle ?? (() => h(\"div\", { class: \"idle\" }, \"Idle\"));\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return renderLoading({ progress: s.progress });\n\n case \"error\":\n return renderError({ error: s.error });\n\n case \"success\":\n return renderDefault({ value: s.value });\n\n default:\n return renderIdle();\n }\n }\n }\n })\n}"],"mappings":"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","names":["import_vue","import_core"]}
@@ -46,14 +46,18 @@ function useLazyGenerator(generatorFunc) {
46
46
  const result = new AsyncResult();
47
47
  const resultRef = useAsyncResultRef(result);
48
48
  const trigger = () => {
49
- result.runInPlace(generatorFunc);
49
+ result.runInPlace((notifyProgress) => generatorFunc(notifyProgress));
50
50
  };
51
51
  return { resultRef, trigger };
52
52
  }
53
53
  function useReactiveGenerator(source, generatorFunc, options = { immediate: true }) {
54
54
  const resultRef = useAsyncResultRef(new AsyncResult());
55
55
  watch(source, (newInputs) => {
56
- resultRef.value.runInPlace(() => generatorFunc(newInputs));
56
+ resultRef.value.runInPlace((notifyProgress) => {
57
+ console.log("useReactiveGenerator - running generatorFunc with inputs:", newInputs);
58
+ console.log("useReactiveGenerator - notifyProgress function:", notifyProgress);
59
+ return generatorFunc(newInputs, notifyProgress);
60
+ });
57
61
  }, { immediate: options.immediate });
58
62
  return resultRef;
59
63
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["import { onUnmounted, ref, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, AsyncResultCollection, ErrorBase, type Action, type AsyncResultGenerator, type FlatChainStep, type Result } from \"unwrapped/core\";\n\n\n// === Vue specific types ===\n\ninterface ReactiveProcessOptions {\n immediate: boolean;\n}\n\n\n\n// === Vue Composables for AsyncResult ===\n\n/**\n * Makes a ref to the given AsyncResult. Whenever the state of the AsyncResult changes,\n * the ref gets retriggered, making those changes visible to Vue's reactivity system.\n * \n * @param asyncResult the result to make reactive\n * @returns the ref to the result\n */\nexport function useAsyncResultRef<T, E extends ErrorBase = ErrorBase, P = unknown>(asyncResult?: AsyncResult<T, E, P>) {\n if (!asyncResult) {\n asyncResult = new AsyncResult<T, E, P>();\n }\n const state = ref<AsyncResult<T, E, P>>(asyncResult) as Ref<AsyncResult<T, E, P>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\n/**\n * Creates an AsyncResult ref from a promise returning a Result.\n * @param promise the promise returning a Result\n * @returns the ref to the AsyncResult\n */\nexport function useAsyncResultRefFromPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\n\n\n// === Vue Composables for Chains ===\n\n/**\n * Watches a source, gives it as inputs to the function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param pipe the function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveChain<Inputs, T, E extends ErrorBase = ErrorBase>(source: WatchSource<Inputs>, pipe: FlatChainStep<Inputs, T, E>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\n\n// === Vue Composables for Actions ===\n\n/**\n * The return type of useLazyAction.\n */\nexport interface LazyActionRef<T, E extends ErrorBase = ErrorBase, P = unknown> {\n resultRef: Ref<AsyncResult<T, E, P>>;\n trigger: () => void;\n}\n\n/**\n * Executes an action immediately and returns a ref to the AsyncResult representing the action's state.\n * \n * Same as useAsyncResultRefFromPromise(action()).\n * \n * @param action the action to execute immediately\n * @returns a ref to the AsyncResult representing the action's state\n */\nexport function useAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): Ref<AsyncResult<T, E, P>> {\n return useAsyncResultRef(AsyncResult.fromAction(action));\n}\n\n/**\n * Creates a lazy action that can be triggered manually.\n * \n * Same as AsyncResult.makeLazyAction(action), but the AsyncResult is wrapped in a ref for Vue reactivity.\n * \n * @param action the action to execute when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyActionRef<T, E, P> {\n const lazyAction = AsyncResult.makeLazyAction<T, E, P>(action);\n const resultRef = useAsyncResultRef(lazyAction.result);\n\n return { resultRef, trigger: lazyAction.trigger };\n}\n\n\n// === Vue Composables for Generators ===\n\n/**\n * Runs a generator function immediately and returns a ref to the AsyncResult representing the generator's state.\n * @param generatorFunc the generator function to run immediately\n * @returns a ref to the AsyncResult representing the generator's state\n */\nexport function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (progress: P) => void) => AsyncResultGenerator<T>): Ref<AsyncResult<T, any, P>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\n/**\n * Creates a lazy generator that can be triggered manually.\n * \n * @param generatorFunc the generator function to run when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyGenerator<T, P = unknown>(generatorFunc: () => AsyncResultGenerator<T>): { resultRef: Ref<AsyncResult<T, any, P>>, trigger: () => void } {\n const result = new AsyncResult<T, any, P>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace(generatorFunc);\n }\n\n return { resultRef, trigger };\n}\n\n/**\n * Watches a source, gives it as inputs to the generator function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param generatorFunc the generator function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs) => AsyncResultGenerator<T>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E, P>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E, P>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace(() => generatorFunc(newInputs));\n }, { immediate: options.immediate });\n\n return resultRef;\n}\n\n\n// === Vue Composables for AsyncResultCollection ===\n\n/**\n * Creates a reactive AsyncResultCollection wrapped in a Vue ref.\n * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.\n * \n * @template T - The type of the values in the AsyncResultCollection.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @returns a ref to the AsyncResultCollection\n */\nexport function useAsyncResultCollection<T = any, E extends ErrorBase = ErrorBase>() {\n const list = new AsyncResultCollection<T, E>();\n const listRef = ref(list);\n\n list.listen(() => {\n triggerRef(listRef);\n });\n\n return listRef;\n}","import { defineComponent, watch, h, type VNode, type SlotsType } from \"vue\"\nimport { ErrorBase, type AsyncResult } from \"unwrapped/core\"\nimport { useAsyncResultRef } from \"../composables\"\n\ninterface CustomSlots<E extends ErrorBase = ErrorBase, P = unknown> {\n loading?: (props: { progress?: P }) => VNode;\n error?: (props: { error: E }) => VNode;\n idle?: () => VNode;\n}\n\n/**\n * Factory function to create a component that displays different content based on an AsyncResult's state. Provides slots for loading, error, idle, and success states and passes the relevant data to each slot, and are typed appropriately.\n * @param slots predefined slots for loading, error, and idle states. Useful for not having to repeat the same template for displaying a framework-specific spinner while in loading state, or a custom error message.\n * @param name Optional internal name for the component\n * @returns An instantiable component that accepts an AsyncResult prop and a default slot for the success state.\n * \n * @example\n * // loaders.ts - Create reusable loader with default loading/error UI\n * const MyLoader = makeAsyncResultLoader({\n * loading: () => h(Spinner),\n * error: ({ error }) => h(ErrorDisplay, { error }),\n * idle: () => h('div', 'Ready')\n * });\n * \n * // MyPage.vue - Use the loader with custom success content\n * <MyLoader :result=\"myAsyncResult\">\n * <template #default=\"{ value }\">\n * <UserProfile :user=\"value\" />\n * </template>\n * </MyLoader>\n */\nexport function makeAsyncResultLoader<T, E extends ErrorBase = ErrorBase, P = unknown>(slots: CustomSlots<E, P>, name = \"AsyncResultLoader\") {\n return defineComponent({\n name,\n props: {\n result: {\n type: Object as () => AsyncResult<T, E, P>,\n required: true\n }\n },\n slots: Object as SlotsType<CustomSlots<E, P> & { default: { value: T } }>,\n setup(props, context) {\n let resultRef = useAsyncResultRef(props.result);\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult, oldResult) => {\n if (newResult === oldResult) return;\n resultRef = useAsyncResultRef(newResult);\n },\n { immediate: true }\n )\n\n return () => {\n const s = resultRef.value.state;\n\n const renderDefault = context.slots.default ?? (() => h(\"div\", { class: \"success\" }, \"Success\"));\n const renderError = context.slots.error ?? slots.error ?? (() => h(\"div\", { class: \"error\" }, \"Error\"));\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => h(\"div\", { class: \"loading\" }, \"Loading…\"));\n const renderIdle = context.slots.idle ?? slots.idle ?? (() => h(\"div\", { class: \"idle\" }, \"Idle\"));\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return renderLoading({ progress: s.progress });\n\n case \"error\":\n return renderError({ error: s.error });\n\n case \"success\":\n return renderDefault({ value: s.value });\n\n default:\n return renderIdle();\n }\n }\n }\n })\n}"],"mappings":"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","names":["watch","watch"]}
1
+ {"version":3,"sources":["../../src/vue/composables.ts","../../src/vue/components/asyncResultLoader.ts"],"sourcesContent":["import { onUnmounted, ref, triggerRef, watch, type Ref, type WatchSource } from \"vue\";\nimport { AsyncResult, AsyncResultCollection, ErrorBase, type Action, type AsyncResultGenerator, type FlatChainStep, type Result } from \"unwrapped/core\";\n\n\n// === Vue specific types ===\n\ninterface ReactiveProcessOptions {\n immediate: boolean;\n}\n\n\n\n// === Vue Composables for AsyncResult ===\n\n/**\n * Makes a ref to the given AsyncResult. Whenever the state of the AsyncResult changes,\n * the ref gets retriggered, making those changes visible to Vue's reactivity system.\n * \n * @param asyncResult the result to make reactive\n * @returns the ref to the result\n */\nexport function useAsyncResultRef<T, E extends ErrorBase = ErrorBase, P = unknown>(asyncResult?: AsyncResult<T, E, P>) {\n if (!asyncResult) {\n asyncResult = new AsyncResult<T, E, P>();\n }\n const state = ref<AsyncResult<T, E, P>>(asyncResult) as Ref<AsyncResult<T, E, P>>;\n\n const unsub = asyncResult.listen(() => {\n triggerRef(state);\n });\n\n onUnmounted(() => {\n unsub();\n });\n\n return state;\n}\n\n/**\n * Creates an AsyncResult ref from a promise returning a Result.\n * @param promise the promise returning a Result\n * @returns the ref to the AsyncResult\n */\nexport function useAsyncResultRefFromPromise<T, E extends ErrorBase = ErrorBase>(promise: Promise<Result<T, E>>) {\n return useAsyncResultRef(AsyncResult.fromResultPromise(promise));\n}\n\n\n\n// === Vue Composables for Chains ===\n\n/**\n * Watches a source, gives it as inputs to the function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param pipe the function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveChain<Inputs, T, E extends ErrorBase = ErrorBase>(source: WatchSource<Inputs>, pipe: FlatChainStep<Inputs, T, E>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E>> {\n const result = new AsyncResult<T, E>();\n const resultRef = useAsyncResultRef(result);\n\n let unsub: (() => void) | null = null;\n\n watch(source, (newInputs) => {\n unsub?.();\n unsub = result.mirror(pipe(newInputs));\n }, { immediate: options.immediate });\n\n onUnmounted(() => {\n unsub?.();\n });\n\n return resultRef;\n}\n\n\n// === Vue Composables for Actions ===\n\n/**\n * The return type of useLazyAction.\n */\nexport interface LazyActionRef<T, E extends ErrorBase = ErrorBase, P = unknown> {\n resultRef: Ref<AsyncResult<T, E, P>>;\n trigger: () => void;\n}\n\n/**\n * Executes an action immediately and returns a ref to the AsyncResult representing the action's state.\n * \n * Same as useAsyncResultRefFromPromise(action()).\n * \n * @param action the action to execute immediately\n * @returns a ref to the AsyncResult representing the action's state\n */\nexport function useAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): Ref<AsyncResult<T, E, P>> {\n return useAsyncResultRef(AsyncResult.fromAction(action));\n}\n\n/**\n * Creates a lazy action that can be triggered manually.\n * \n * Same as AsyncResult.makeLazyAction(action), but the AsyncResult is wrapped in a ref for Vue reactivity.\n * \n * @param action the action to execute when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyAction<T, E extends ErrorBase = ErrorBase, P = unknown>(action: Action<T, E, P>): LazyActionRef<T, E, P> {\n const lazyAction = AsyncResult.makeLazyAction<T, E, P>(action);\n const resultRef = useAsyncResultRef(lazyAction.result);\n\n return { resultRef, trigger: lazyAction.trigger };\n}\n\n\n// === Vue Composables for Generators ===\n\n/**\n * Runs a generator function immediately and returns a ref to the AsyncResult representing the generator's state.\n * @param generatorFunc the generator function to run immediately\n * @returns a ref to the AsyncResult representing the generator's state\n */\nexport function useGenerator<T, P = unknown>(generatorFunc: (notifyProgress?: (progress: P) => void) => AsyncResultGenerator<T>): Ref<AsyncResult<T, any, P>> {\n const resultRef = useAsyncResultRef(AsyncResult.run(generatorFunc));\n return resultRef;\n}\n\n/**\n * Creates a lazy generator that can be triggered manually.\n * \n * @param generatorFunc the generator function to run when triggered\n * @returns an object containing a ref to the AsyncResult and a trigger function\n */\nexport function useLazyGenerator<T, P = unknown>(generatorFunc: (notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>): { resultRef: Ref<AsyncResult<T, any, P>>, trigger: () => void } {\n const result = new AsyncResult<T, any, P>();\n const resultRef = useAsyncResultRef(result);\n\n const trigger = () => {\n result.runInPlace((notifyProgress) => generatorFunc(notifyProgress));\n }\n\n return { resultRef, trigger };\n}\n\n/**\n * Watches a source, gives it as inputs to the generator function provided, and updates the result contained in the ref accordingly.\n * \n * @param source the inputs to react to\n * @param generatorFunc the generator function to run when the inputs change\n * @param options optional settings\n * @returns ref to the result\n */\nexport function useReactiveGenerator<Inputs, T, E extends ErrorBase = ErrorBase, P = unknown>(source: WatchSource<Inputs>, generatorFunc: (args: Inputs, notifyProgress: (progress: P) => void) => AsyncResultGenerator<T>, options: ReactiveProcessOptions = { immediate: true }): Ref<AsyncResult<T, E, P>> {\n const resultRef = useAsyncResultRef(new AsyncResult<T, E, P>());\n\n watch(source, (newInputs) => {\n resultRef.value.runInPlace((notifyProgress) => {\n console.log(\"useReactiveGenerator - running generatorFunc with inputs:\", newInputs);\n console.log(\"useReactiveGenerator - notifyProgress function:\", notifyProgress);\n return generatorFunc(newInputs, notifyProgress)\n });\n }, { immediate: options.immediate });\n\n return resultRef;\n}\n\n\n// === Vue Composables for AsyncResultCollection ===\n\n/**\n * Creates a reactive AsyncResultCollection wrapped in a Vue ref.\n * The AsyncResultCollection notifies Vue's reactivity system whenever its state changes.\n * \n * @template T - The type of the values in the AsyncResultCollection.\n * @template E - The type of the error, extending ErrorBase (default is ErrorBase).\n * @returns a ref to the AsyncResultCollection\n */\nexport function useAsyncResultCollection<T = any, E extends ErrorBase = ErrorBase>() {\n const list = new AsyncResultCollection<T, E>();\n const listRef = ref(list);\n\n list.listen(() => {\n triggerRef(listRef);\n });\n\n return listRef;\n}","import { defineComponent, watch, h, type VNode, type SlotsType } from \"vue\"\nimport { ErrorBase, type AsyncResult } from \"unwrapped/core\"\nimport { useAsyncResultRef } from \"../composables\"\n\ninterface CustomSlots<E extends ErrorBase = ErrorBase, P = unknown> {\n loading?: (props: { progress?: P }) => VNode;\n error?: (props: { error: E }) => VNode;\n idle?: () => VNode;\n}\n\n/**\n * Factory function to create a component that displays different content based on an AsyncResult's state. Provides slots for loading, error, idle, and success states and passes the relevant data to each slot, and are typed appropriately.\n * @param slots predefined slots for loading, error, and idle states. Useful for not having to repeat the same template for displaying a framework-specific spinner while in loading state, or a custom error message.\n * @param name Optional internal name for the component\n * @returns An instantiable component that accepts an AsyncResult prop and a default slot for the success state.\n * \n * @example\n * // loaders.ts - Create reusable loader with default loading/error UI\n * const MyLoader = makeAsyncResultLoader({\n * loading: () => h(Spinner),\n * error: ({ error }) => h(ErrorDisplay, { error }),\n * idle: () => h('div', 'Ready')\n * });\n * \n * // MyPage.vue - Use the loader with custom success content\n * <MyLoader :result=\"myAsyncResult\">\n * <template #default=\"{ value }\">\n * <UserProfile :user=\"value\" />\n * </template>\n * </MyLoader>\n */\nexport function makeAsyncResultLoader<T, E extends ErrorBase = ErrorBase, P = unknown>(slots: CustomSlots<E, P>, name = \"AsyncResultLoader\") {\n return defineComponent({\n name,\n props: {\n result: {\n type: Object as () => AsyncResult<T, E, P>,\n required: true\n }\n },\n slots: Object as SlotsType<CustomSlots<E, P> & { default: { value: T } }>,\n setup(props, context) {\n let resultRef = useAsyncResultRef(props.result);\n\n // Watch for prop changes & update listener\n watch(\n () => props.result,\n (newResult, oldResult) => {\n if (newResult === oldResult) return;\n resultRef = useAsyncResultRef(newResult);\n },\n { immediate: true }\n )\n\n return () => {\n const s = resultRef.value.state;\n\n const renderDefault = context.slots.default ?? (() => h(\"div\", { class: \"success\" }, \"Success\"));\n const renderError = context.slots.error ?? slots.error ?? (() => h(\"div\", { class: \"error\" }, \"Error\"));\n const renderLoading = context.slots.loading ?? slots.loading ?? (() => h(\"div\", { class: \"loading\" }, \"Loading…\"));\n const renderIdle = context.slots.idle ?? slots.idle ?? (() => h(\"div\", { class: \"idle\" }, \"Idle\"));\n\n // Choose what to render based on status\n switch (s.status) {\n case \"loading\":\n return renderLoading({ progress: s.progress });\n\n case \"error\":\n return renderError({ error: s.error });\n\n case \"success\":\n return renderDefault({ value: s.value });\n\n default:\n return renderIdle();\n }\n }\n }\n })\n}"],"mappings":"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","names":["watch","watch"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unwrapped",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },