{"version":3,"file":"core.umd.cjs","sources":["../src/helpers.ts","../src/models/exceptions/core.ts","../src/models/exceptions/index.ts","../src/models/iterators/smart-iterator.ts","../src/models/aggregators/reduced-iterator.ts","../src/models/aggregators/aggregated-async-iterator.ts","../src/models/iterators/smart-async-iterator.ts","../src/models/aggregators/aggregated-iterator.ts","../src/models/callbacks/callable-object.ts","../src/models/callbacks/publisher.ts","../src/models/callbacks/switchable-callback.ts","../src/models/collections/map-view.ts","../src/models/collections/set-view.ts","../src/models/json/json-storage.ts","../src/models/promises/smart-promise.ts","../src/models/promises/deferred-promise.ts","../src/models/promises/timed-promise.ts","../src/models/promises/promise-queue.ts","../src/utils/date.ts","../src/models/timers/game-loop.ts","../src/models/timers/clock.ts","../src/models/timers/countdown.ts","../src/utils/curve.ts","../src/utils/random.ts","../src/utils/async.ts","../src/utils/dom.ts","../src/utils/iterator.ts","../src/utils/math.ts","../src/utils/string.ts","../src/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\n\n/**\n * An utility constant that indicates whether the current environment is a browser.\n */\n// @ts-ignore\nexport const isBrowser = ((typeof window !== \"undefined\") && (typeof window.document !== \"undefined\"));\n\n/**\n * An utility constant that indicates whether the current environment is a Node.js runtime.\n */\n// @ts-ignore\nexport const isNode = ((typeof process !== \"undefined\") && !!(process.versions?.node));\n\n/**\n * An utility constant that indicates whether the current environment is a Web Worker.\n */\n// @ts-ignore\nexport const isWorker = ((typeof self === \"object\") && (self.constructor?.name === \"DedicatedWorkerGlobalScope\"));\n","/**\n * A class representing an exception, subclass of the native {@link Error} class.  \n * It's the base class for any other further exception.\n *\n * It allows to chain exceptions together, tracking the initial cause of an error and\n * storing its stack trace while providing a clear and friendly message to the user.\n *\n * ---\n *\n * @example\n * ```ts\n * try { loadGameSaves(); }\n * catch (error)\n * {\n *     throw new Exception(\"The game saves may be corrupted. Try to restart the game.\", error);\n *     // Uncaught Exception: The game saves may be corrupted. Try to restart the game.\n *     //     at /src/game/index.ts:37:15\n *     //     at /src/main.ts:23:17\n *     //\n *     // Caused by SyntaxError: Unexpected end of JSON input\n *     //     at /src/models/saves.ts:47:17\n *     //     at /src/game/index.ts:12:9\n *     //     at /src/main.ts:23:17\n * }\n * ```\n */\nexport default class Exception extends Error\n{\n    /**\n     * A static method to convert a generic caught error, ensuring it's an instance of the {@link Exception} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * try { [...] }\n     * catch (error)\n     * {\n     *     const exc = Exception.FromUnknown(error);\n     *\n     *     [...]\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param error The caught error to convert.\n     *\n     * @returns An instance of the {@link Exception} class.\n     */\n    public static FromUnknown(error: unknown): Exception\n    {\n        if (error instanceof Exception)\n        {\n            return error;\n        }\n        if (error instanceof Error)\n        {\n            const exc = new Exception(error.message);\n\n            exc.stack = error.stack;\n            exc.name = error.name;\n\n            return exc;\n        }\n\n        return new Exception(`${error}`);\n    }\n\n    /**\n     * Initializes a new instance of the {@link Exception} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new Exception(\"An error occurred while processing the request.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"Exception\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"Exception\")\n    {\n        super(message);\n\n        this.cause = cause;\n        this.name = name;\n\n        if (cause)\n        {\n            if (cause instanceof Error)\n            {\n                this.stack += `\\n\\nCaused by ${cause.stack}`;\n            }\n            else\n            {\n                this.stack += `\\n\\nCaused by ${cause}`;\n            }\n        }\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"Exception\";\n}\n\n/**\n * An utility class representing that kind of situation where the program should never reach.  \n * Also commonly used to satisfy the type-system, but not part of a real feasible scenario.\n *\n * It provides a clear and friendly message by default.\n *\n * ---\n *\n * @example\n * ```ts\n * function checkCase(value: \"A\" | \"B\" | \"C\"): 1 | 2 | 3\n * {\n *     switch (value)\n *     {\n *         case \"A\": return 1;\n *         case \"B\": return 2;\n *         case \"C\": return 3;\n *         default: throw new FatalErrorException();\n *     }\n * }\n * ```\n */\nexport class FatalErrorException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link FatalErrorException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new FatalErrorException(\"This error should never happen. Please, contact the support team.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"FatalErrorException\"`.\n     */\n    public constructor(message?: string, cause?: unknown, name = \"FatalErrorException\")\n    {\n        if (message === undefined)\n        {\n            message = \"The program has encountered an unrecoverable error and cannot continue as expected. \" +\n                \"Please, try again later. If the problem persists, contact the support team.\";\n        }\n\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"FatalErrorException\";\n}\n\n/**\n * An utility class representing a situation where a feature isn't implemented yet.  \n * It's commonly used as a placeholder for future implementations.\n *\n * It provides a clear and friendly message by default.\n *\n * ---\n *\n * @example\n * ```ts\n * class Database\n * {\n *     public async connect(): Promise<void>\n *     {\n *         throw new NotImplementedException();\n *     }\n * }\n * ```\n */\nexport class NotImplementedException extends FatalErrorException\n{\n    /**\n     * Initializes a new instance of the {@link NotImplementedException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new NotImplementedException(\"This method hasn't been implemented yet. Check back later.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"NotImplementedException\"`.\n     */\n    public constructor(message?: string, cause?: unknown, name = \"NotImplementedException\")\n    {\n        if (message === undefined)\n        {\n            message = \"This feature isn't implemented yet. Please, try again later.\";\n        }\n\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"NotImplementedException\";\n}\n","import Exception from \"./core.js\";\n\n/**\n * A class representing a generic exception that can be thrown when a file\n * operation fails, such as reading, writing, copying, moving, deleting, etc...\n *\n * It can also be used to catch all file-related exceptions at once.\n *\n * ---\n *\n * @example\n * ```ts\n * try { [...] }\n * catch (error)\n * {\n *     if (error instanceof FileException)\n *     {\n *         // A file-related exception occurred. Handle it...\n *     }\n * }\n * ```\n */\nexport class FileException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link FileException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new FileException(\"An error occurred while trying to read the file.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"FileException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"FileException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"FileException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a file already exists.\n *\n * ---\n *\n * @example\n * ```ts\n * import { existsSync } from \"node:fs\";\n *\n * if (existsSync(\"file.txt\"))\n * {\n *     throw new FileExistsException(\"The file named 'file.txt' already exists.\");\n * }\n * ```\n */\nexport class FileExistsException extends FileException\n{\n    /**\n     * Initializes a new instance of the {@link FileExistsException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new FileExistsException(\"The file named 'data.json' already exists on the server.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"FileExistsException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"FileExistsException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"FileExistsException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a file isn't found.\n *\n * ---\n *\n * @example\n * ```ts\n * import { existsSync } from \"node:fs\";\n *\n * if (!existsSync(\"file.txt\"))\n * {\n *     throw new FileNotFoundException(\"The file named 'file.txt' wasn't found.\");\n * }\n * ```\n */\nexport class FileNotFoundException extends FileException\n{\n    /**\n     * Initializes a new instance of the {@link FileNotFoundException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new FileNotFoundException(\"The file named 'data.json' wasn't found on the server.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"FileNotFoundException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"FileNotFoundException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"FileNotFoundException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a key is invalid or not found.  \n * It's commonly used when working with dictionaries, maps, objects, sets, etc...\n *\n * ---\n *\n * @example\n * ```ts\n * const map = new Map<string, number>();\n * if (!map.has(\"hash\"))\n * {\n *     throw new KeyException(\"The key 'hash' wasn't found in the collection.\");\n * }\n * ```\n */\nexport class KeyException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link KeyException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new KeyException(\"The 'id' key wasn't found in the dictionary.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"KeyException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"KeyException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"KeyException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a network operation fails.  \n * It's commonly used when it's unable to connect to a server or when a request times out.\n *\n * ---\n *\n * @example\n * ```ts\n * import axios, { isAxiosError } from \"axios\";\n *\n * try { await axios.get(\"https://api.example.com/data\"); }\n * catch (error)\n * {\n *     if (isAxiosError(error) && !error.response)\n *     {\n *         throw new NetworkException(\n *             \"Unable to establish a connection to the server. \" +\n *             \"Please, check your internet connection and try again.\"\n *         );\n *     }\n * }\n * ```\n */\nexport class NetworkException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link NetworkException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new NetworkException(\"Couldn't connect to the server. Please, try again later.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"NetworkException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"NetworkException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"NetworkException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a permission is denied.  \n * It's commonly used when an user tries to access a restricted resource or perform a forbidden action.\n *\n * ---\n *\n * @example\n * ```ts\n * const $user = useUserStore();\n * if (!$user.isAdmin)\n * {\n *     throw new PermissionException(\"You don't have permission to perform this action.\");\n * }\n * ```\n */\nexport class PermissionException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link PermissionException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new PermissionException(\"You don't have permission to access this resource.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"PermissionException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"PermissionException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"PermissionException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a reference is invalid or not found.  \n * It's commonly used when a variable is `null`, `undefined` or when an object doesn't exist.\n *\n * ---\n *\n * @example\n * ```ts\n * const $el = document.getElementById(\"app\");\n * if ($el === null)\n * {\n *     throw new ReferenceException(\"The element with the ID 'app' wasn't found in the document.\");\n * }\n * ```\n */\nexport class ReferenceException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link ReferenceException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new ReferenceException(\"The 'canvas' element wasn't found in the document.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"ReferenceException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"ReferenceException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"ReferenceException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a runtime error occurs.  \n * It's commonly used when an unexpected condition is encountered during the execution of a program.\n *\n * ---\n *\n * @example\n * ```ts\n * let status: \"enabled\" | \"disabled\" = \"enabled\";\n *\n * function enable(): void\n * {\n *     if (status === \"enabled\") { throw new RuntimeException(\"The feature is already enabled.\"); }\n *     status = \"enabled\";\n * }\n * ```\n */\nexport class RuntimeException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link RuntimeException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new RuntimeException(\"The received input seems to be malformed or corrupted.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"RuntimeException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"RuntimeException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"RuntimeException\";\n}\n\n/**\n * A class representing an exception that can be thrown when an environment\n * isn't properly configured or when a required variable isn't set.  \n * It can also be used when the environment on which the program is running is unsupported.\n *\n * ---\n *\n * @example\n * ```ts\n * if (!navigator.geolocation)\n * {\n *     throw new EnvironmentException(\"The Geolocation API isn't supported in this environment.\");\n * }\n * ```\n */\nexport class EnvironmentException extends RuntimeException\n{\n    /**\n     * Initializes a new instance of the {@link EnvironmentException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new EnvironmentException(\"The required environment variable 'API_KEY' isn't set.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"EnvironmentException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"EnvironmentException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"EnvironmentException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a timeout occurs.  \n * It's commonly used when a task takes too long to complete or when a request times out.\n *\n * ---\n *\n * @example\n * ```ts\n * const timeoutId = setTimeout(() => { throw new TimeoutException(\"The request timed out.\"); }, 5_000);\n * const response = await fetch(\"https://api.example.com/data\");\n *\n * clearTimeout(timeoutId);\n * ```\n */\nexport class TimeoutException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link TimeoutException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new TimeoutException(\"The task took too long to complete.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"TimeoutException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"TimeoutException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"TimeoutException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a type is invalid or not supported.  \n * It's commonly used when a function receives an unexpected type of argument.\n *\n * ---\n *\n * @example\n * ```ts\n * function greet(name: string): void\n * {\n *     if (typeof name !== \"string\")\n *     {\n *         throw new TypeException(\"The 'name' argument must be a valid string.\");\n *     }\n * }\n * ```\n */\nexport class TypeException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link TypeException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new TypeException(\"The 'username' argument must be a valid string.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"TypeException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"TypeException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"TypeException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a value is invalid.  \n * It's commonly used when a function receives an unexpected value as an argument.\n *\n * ---\n *\n * @example\n * ```ts\n * function setVolume(value: number): void\n * {\n *     if (value < 0)\n *     {\n *         throw new ValueException(\"The 'value' argument must be greater than or equal to 0.\");\n *     }\n * }\n * ```\n */\nexport class ValueException extends Exception\n{\n    /**\n     * Initializes a new instance of the {@link ValueException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new ValueException(\"The 'grade' argument cannot be negative.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"ValueException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"ValueException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"ValueException\";\n}\n\n/**\n * A class representing an exception that can be thrown when a value is out of range.  \n * It's commonly used when a function receives an unexpected value as an argument.\n *\n * ---\n *\n * @example\n * ```ts\n * function setVolume(value: number): void\n * {\n *     if ((value < 0) || (value > 100))\n *     {\n *         throw new RangeException(\"The 'value' argument must be between 0 and 100.\");\n *     }\n * }\n * ```\n */\nexport class RangeException extends ValueException\n{\n    /**\n     * Initializes a new instance of the {@link RangeException} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * throw new RangeException(\"The 'percentage' argument must be between 0 and 100.\");\n     * ```\n     *\n     * ---\n     *\n     * @param message The message that describes the error.\n     * @param cause The previous caught error that caused this one, if any.\n     * @param name The name of the exception. Default is `\"RangeException\"`.\n     */\n    public constructor(message: string, cause?: unknown, name = \"RangeException\")\n    {\n        super(message, cause, name);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"RangeException\";\n}\n\nexport { Exception };\nexport { FatalErrorException, NotImplementedException } from \"./core.js\";\n","import AggregatedIterator from \"../aggregators/aggregated-iterator.js\";\nimport { ValueException } from \"../exceptions/index.js\";\n\nimport type { GeneratorFunction, Iteratee, TypeGuardPredicate, Reducer, IteratorLike } from \"./types.js\";\n\n/**\n * A wrapper class representing an enhanced and instantiable version\n * of the native {@link Iterable} & {@link Iterator} interfaces.\n *\n * It provides a set of utility methods to better manipulate and\n * transform iterators in a functional and highly performant way.  \n * It takes inspiration from the native {@link Array} methods like\n * {@link Array.map}, {@link Array.filter}, {@link Array.reduce}, etc...\n *\n * The class is lazy, meaning that the transformations are applied\n * only when the resulting iterator is materialized, not before.  \n * This allows to chain multiple transformations without\n * the need to iterate over the elements multiple times.\n *\n * ---\n *\n * @example\n * ```ts\n * const result = new SmartIterator<number>([\"-5\", \"-4\", \"-3\", \"-2\", \"-1\", \"0\", \"1\", \"2\", \"3\", \"4\", \"5\"])\n *     .map(Number)\n *     .map((value) => value + Math.ceil(Math.abs(value / 2)))\n *     .filter((value) => value >= 0)\n *     .map((value) => value + 1)\n *     .reduce((acc, value) => acc + value);\n *\n * console.log(result); // 31\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterator.\n * @template R The type of the final result of the iterator. Default is `void`.\n * @template N The type of the argument required by the `next` method. Default is `undefined`.\n */\nexport default class SmartIterator<T, R = void, N = undefined> implements Iterator<T, R, N>\n{\n    /**\n     * The native {@link Iterator} object that is being wrapped by this instance.\n     */\n    protected readonly _iterator: Iterator<T, R, N>;\n\n    /**\n     * Initializes a new instance of the {@link SmartIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<string>([\"A\", \"B\", \"C\"]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The iterable object to wrap.\n     */\n    public constructor(iterable: Iterable<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number, void, number>({\n     *     _sum: 0, _count: 0,\n     *\n     *     next: function(value: number)\n     *     {\n     *         this._sum += value;\n     *         this._count += 1;\n     *\n     *         return { done: false, value: this._sum / this._count };\n     *     }\n     * })\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The iterator object to wrap.\n     */\n    public constructor(iterator: Iterator<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>(function* ()\n     * {\n     *     for (let i = 2; i < 65_536; i *= 2) { yield (i - 1); }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The generator function to wrap.\n     */\n    public constructor(generatorFn: GeneratorFunction<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator(values);\n     * ```\n     *\n     * ---\n     *\n     * @param argument The iterable, iterator or generator function to wrap.\n     */\n    public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>);\n    public constructor(argument: IteratorLike<T, R, N> | GeneratorFunction<T, R, N>)\n    {\n        if (argument instanceof Function)\n        {\n            this._iterator = argument();\n        }\n        else if (Symbol.iterator in argument)\n        {\n            this._iterator = argument[Symbol.iterator]() as Iterator<T, R, N>;\n        }\n        else\n        {\n            this._iterator = argument;\n        }\n    }\n\n    /**\n     * Determines whether all elements of the iterator satisfy a given condition.\n     * See also {@link SmartIterator.some}.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element doesn't satisfy the condition, the method will return `false` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link SmartIterator.find} instead.\n     *\n     * If the iterator is infinite and every element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.every((value) => value < 0);\n     *\n     * console.log(result); // false\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns `true` if all elements satisfy the condition, `false` otherwise.\n     */\n    public every(predicate: Iteratee<T, boolean>): boolean\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = this._iterator.next();\n\n            if (result.done) { return true; }\n            if (!(predicate(result.value, index))) { return false; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Determines whether any element of the iterator satisfies a given condition.\n     * See also {@link SmartIterator.every}.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element satisfies the condition, the method will return `true` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link SmartIterator.find} instead.\n     *\n     * If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.some((value) => value < 0);\n     *\n     * console.log(result); // true\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns `true` if any element satisfies the condition, `false` otherwise.\n     */\n    public some(predicate: Iteratee<T, boolean>): boolean\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = this._iterator.next();\n\n            if (result.done) { return false; }\n            if (predicate(result.value, index)) { return true; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.filter((value) => value < 0);\n     *\n     * console.log(result.toArray()); // [-2, -1]\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link SmartIterator} containing only the elements that satisfy the condition.\n     */\n    public filter(predicate: Iteratee<T, boolean>): SmartIterator<T, R>;\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number | string>([-2, \"-1\", \"0\", 1, \"2\"]);\n     * const result = iterator.filter<number>((value) => typeof value === \"number\");\n     *\n     * console.log(result.toArray()); // [-2, 1]\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link SmartIterator} containing only the elements that satisfy the condition.\n     */\n    public filter<S extends T>(predicate: TypeGuardPredicate<T, S>): SmartIterator<S, R>;\n    public filter(predicate: Iteratee<T, boolean>): SmartIterator<T, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<T, R>(function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n                if (predicate(result.value, index)) { yield result.value; }\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Maps the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.map((value) => Math.abs(value));\n     *\n     * console.log(result.toArray()); // [2, 1, 0, 1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link SmartIterator} containing the transformed elements.\n     */\n    public map<V>(iteratee: Iteratee<T, V>): SmartIterator<V, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<V, R>(function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n\n                yield iteratee(result.value, index);\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the first element of the iterator.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Also note that:\n     * - If an empty iterator is provided, a {@link ValueException} will be thrown.\n     * - If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 2, 3, 4, 5]);\n     * const result = iterator.reduce((acc, value) => acc + value);\n     *\n     * console.log(result); // 15\n     * ```\n     *\n     * ---\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     *\n     * @returns The final result of the reduction.\n     */\n    public reduce(reducer: Reducer<T, T>): T;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the provided initial value.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 2, 3, 4, 5]);\n     * const result = iterator.reduce((acc, value) => acc + value, 10);\n     *\n     * console.log(result); // 25\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the type of the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The initial value of the accumulator.\n     *\n     * @returns The final result of the reduction.\n     */\n    public reduce<A>(reducer: Reducer<T, A>, initialValue: A): A;\n    public reduce<A>(reducer: Reducer<T, A>, initialValue?: A): A\n    {\n        let index = 0;\n        let accumulator = initialValue;\n        if (accumulator === undefined)\n        {\n            const result = this._iterator.next();\n            if (result.done) { throw new ValueException(\"Cannot reduce an empty iterator without an initial value.\"); }\n\n            accumulator = (result.value as unknown) as A;\n            index += 1;\n        }\n\n        while (true)\n        {\n            const result = this._iterator.next();\n            if (result.done) { return accumulator; }\n\n            accumulator = reducer(accumulator, result.value, index);\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Flattens the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be flattened into the new iterator.\n     *\n     * Since the iterator is lazy, the flattening process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number[]>([[-2, -1], 0, 1, 2, [3, 4, 5]]);\n     * const result = iterator.flatMap((value) => value);\n     *\n     * console.log(result.toArray()); // [-2, -1, 0, 1, 2, 3, 4, 5]\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link SmartIterator} containing the flattened elements.\n     */\n    public flatMap<V>(iteratee: Iteratee<T, V | readonly V[]>): SmartIterator<V, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<V, R>(function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n\n                const elements = iteratee(result.value, index);\n                if (elements instanceof Array)\n                {\n                    for (const value of elements) { yield value; }\n                }\n                else { yield elements; }\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Drops a given number of elements at the beginning of the iterator.  \n     * The remaining elements will be included in a new iterator.\n     * See also {@link SmartIterator.take}.\n     *\n     * Since the iterator is lazy, the dropping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the dropped elements will be consumed in the process.  \n     * The rest of the iterator will be consumed only once the new one is.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.drop(3);\n     *\n     * console.log(result.toArray()); // [1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @param count The number of elements to drop.\n     *\n     * @returns A new {@link SmartIterator} containing the remaining elements.\n     */\n    public drop(count: number): SmartIterator<T, R | undefined>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<T, R | undefined>(function* ()\n        {\n            let index = 0;\n            while (index < count)\n            {\n                const result = iterator.next();\n                if (result.done) { return; }\n\n                index += 1;\n            }\n\n            while (true)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n\n                yield result.value;\n            }\n        });\n    }\n\n    /**\n     * Takes a given number of elements at the beginning of the iterator.  \n     * These elements will be included in a new iterator.\n     * See also {@link SmartIterator.drop}.\n     *\n     * Since the iterator is lazy, the taking process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the taken elements will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.take(3);\n     *\n     * console.log(result.toArray()); // [-2, -1, 0]\n     * console.log(iterator.toArray()); // [1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @param limit The number of elements to take.\n     *\n     * @returns A new {@link SmartIterator} containing the taken elements.\n     */\n    public take(limit: number): SmartIterator<T, R | undefined>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<T, R | undefined>(function* ()\n        {\n            let index = 0;\n            while (index < limit)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n\n                yield result.value;\n\n                index += 1;\n            }\n\n            return;\n        });\n    }\n\n    /**\n     * Finds the first element of the iterator that satisfies a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.find((value) => value > 0);\n     *\n     * console.log(result); // 1\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns The first element that satisfies the condition, `undefined` otherwise.\n     */\n    public find(predicate: Iteratee<T, boolean>): T | undefined;\n\n    /**\n     * Finds the first element of the iterator that satisfies a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number | string>([-2, \"-1\", \"0\", 1, \"2\"]);\n     * const result = iterator.find<number>((value) => typeof value === \"number\");\n     *\n     * console.log(result); // -2\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the element that satisfies the condition.  \n     * This allows the type-system to infer the correct type of the result.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns The first element that satisfies the condition, `undefined` otherwise.\n     */\n    public find<S extends T>(predicate: TypeGuardPredicate<T, S>): S | undefined;\n    public find(predicate: Iteratee<T, boolean>): T | undefined\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = this._iterator.next();\n\n            if (result.done) { return; }\n            if (predicate(result.value, index)) { return result.value; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Enumerates the elements of the iterator.  \n     * Each element is be paired with its index in a new iterator.\n     *\n     * Since the iterator is lazy, the enumeration process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<string>([\"A\", \"M\", \"N\", \"Z\"]);\n     * const result = iterator.enumerate();\n     *\n     * console.log(result.toArray()); // [[0, \"A\"], [1, \"M\"], [2, \"N\"], [3, \"Z\"]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing the enumerated elements.\n     */\n    public enumerate(): SmartIterator<[number, T], R>\n    {\n        return this.map((value, index) => [index, value]);\n    }\n\n    /**\n     * Removes all duplicate elements from the iterator.  \n     * The first occurrence of each element will be kept.\n     *\n     * Since the iterator is lazy, the deduplication process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 1, 2, 3, 2, 3, 4, 5, 5, 4]);\n     * const result = iterator.unique();\n     *\n     * console.log(result.toArray()); // [1, 2, 3, 4, 5]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing only the unique elements.\n     */\n    public unique(): SmartIterator<T, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartIterator<T, R>(function* ()\n        {\n            const values = new Set<T>();\n            while (true)\n            {\n                const result = iterator.next();\n                if (result.done) { return result.value; }\n                if (values.has(result.value)) { continue; }\n                values.add(result.value);\n\n                yield result.value;\n            }\n        });\n    }\n\n    /**\n     * Counts the number of elements in the iterator.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 2, 3, 4, 5]);\n     * const result = iterator.count();\n     *\n     * console.log(result); // 5\n     * ```\n     *\n     * ---\n     *\n     * @returns The number of elements in the iterator.\n     */\n    public count(): number\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = this._iterator.next();\n            if (result.done) { return index; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Iterates over all elements of the iterator.  \n     * The elements are passed to the function along with their index.\n     *\n     * This method will consume the entire iterator in the process.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([\"A\", \"M\", \"N\", \"Z\"]);\n     * iterator.forEach((value, index) =>\n     * {\n     *     console.log(`${index}: ${value}`); // \"0: A\", \"1: M\", \"2: N\", \"3: Z\"\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param iteratee The function to apply to each element of the iterator.\n     */\n    public forEach(iteratee: Iteratee<T>): void\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = this._iterator.next();\n            if (result.done) { return; }\n\n            iteratee(result.value, index);\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Advances the iterator to the next element and returns the result.  \n     * If the iterator requires it, a value must be provided to be passed to the next element.\n     *\n     * Once the iterator is done, the method will return an object with the `done` property set to `true`.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 2, 3, 4, 5]);\n     *\n     * let result = iterator.next();\n     * while (!result.done)\n     * {\n     *     console.log(result.value); // 1, 2, 3, 4, 5\n     *\n     *     result = iterator.next();\n     * }\n     *\n     * console.log(result); // { done: true, value: undefined }\n     * ```\n     *\n     * ---\n     *\n     * @param values The value to pass to the next element, if required.\n     *\n     * @returns The result of the iteration, containing the value of the operation.\n     */\n    public next(...values: N extends undefined ? [] : [N]): IteratorResult<T, R>\n    {\n        return this._iterator.next(...values);\n    }\n\n    /**\n     * An utility method that may be used to close the iterator gracefully,\n     * free the resources and perform any cleanup operation.  \n     * It may also be used to signal the end or to compute a specific final result of the iteration process.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>({\n     *     _index: 0,\n     *     next: function()\n     *     {\n     *         return { done: false, value: this._index += 1 };\n     *     },\n     *     return: function() { console.log(\"Closing the iterator...\"); }\n     * });\n     *\n     * for (const value of iterator)\n     * {\n     *     if (value > 5) { break; } // Closing the iterator...\n     *\n     *     console.log(value); // 1, 2, 3, 4, 5\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param value The final value of the iterator.\n     *\n     * @returns The result of the iterator.\n     */\n    public return(value?: R): IteratorResult<T, R>\n    {\n        if (this._iterator.return) { return this._iterator.return(value); }\n\n        return { done: true, value: value as R };\n    }\n\n    /**\n     * An utility method that may be used to close the iterator due to an error,\n     * free the resources and perform any cleanup operation.  \n     * It may also be used to signal that an error occurred during the iteration process or to handle it.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>({\n     *     _index: 0,\n     *     next: function()\n     *     {\n     *         return { done: this._index > 10, value: this._index += 1 };\n     *     },\n     *     throw: function(error)\n     *     {\n     *         console.warn(error.message);\n     *\n     *         this._index = 0;\n     *     }\n     * });\n     *\n     * for (const value of iterator) // 1, 2, 3, 4, 5, \"The index is too high.\", 1, 2, 3, 4, 5, ...\n     * {\n     *     try\n     *     {\n     *         if (value > 5) { throw new Error(\"The index is too high.\"); }\n     *\n     *         console.log(value); // 1, 2, 3, 4, 5\n     *     }\n     *     catch (error) { iterator.throw(error); }\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param error The error to throw into the iterator.\n     *\n     * @returns The final result of the iterator.\n     */\n    public throw(error: unknown): IteratorResult<T, R>\n    {\n        if (this._iterator.throw) { return this._iterator.throw(error); }\n\n        throw error;\n    }\n\n    /**\n     * An utility method that aggregates the elements of the iterator using a given key function.  \n     * The elements will be grouped by the resulting keys in a new specialized iterator.\n     * See {@link AggregatedIterator}.\n     *\n     * Since the iterator is lazy, the grouping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * the new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator<number>([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);\n     * const result = iterator.groupBy<string>((value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(result.toObject()); // { odd: [1, 3, 5, 7, 9], even: [2, 4, 6, 8, 10] }\n     * ```\n     *\n     * ---\n     *\n     * @template K The type of the keys used to group the elements.\n     *\n     * @param iteratee The key function to apply to each element of the iterator.\n     *\n     * @returns A new instance of the {@link AggregatedIterator} class containing the grouped elements.\n     */\n    public groupBy<K extends PropertyKey>(iteratee: Iteratee<T, K>): AggregatedIterator<K, T>\n    {\n        return new AggregatedIterator(this.map((element, index) =>\n        {\n            const key = iteratee(element, index);\n\n            return [key, element] as [K, T];\n        }));\n    }\n\n    /**\n     * Materializes the iterator into an array.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartIterator(function* ()\n     * {\n     *     for (let i = 0; i < 5; i += 1) { yield i; }\n     * });\n     * const result = iterator.toArray();\n     *\n     * console.log(result); // [0, 1, 2, 3, 4]\n     * ```\n     *\n     * ---\n     *\n     * @returns The {@link Array} containing all elements of the iterator.\n     */\n    public toArray(): T[]\n    {\n        return Array.from(this as Iterable<T>);\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"SmartIterator\";\n\n    public [Symbol.iterator](): SmartIterator<T, R, N> { return this; }\n}\n","import { ValueException } from \"../exceptions/index.js\";\nimport { SmartIterator } from \"../iterators/index.js\";\nimport type { GeneratorFunction } from \"../iterators/types.js\";\n\nimport AggregatedIterator from \"./aggregated-iterator.js\";\nimport type { KeyedIteratee, KeyedReducer, KeyedTypeGuardPredicate } from \"./types.js\";\n\n/**\n * A class representing an aggregated iterator that has been reduced in a lazy and optimized way.\n *\n * It's part of the {@link AggregatedIterator} and {@link AggregatedAsyncIterator} implementations,\n * providing a way to reduce them into a single value or another aggregated iterable.  \n * For this reason, it isn't recommended to instantiate this class directly\n * (although it's still possible), but rather use the reducing methods provided by the aggregated iterators.\n *\n * It isn't directly iterable, just like its parent class, and needs to specify on what you want to iterate.  \n * See the {@link ReducedIterator.keys}, {@link ReducedIterator.entries}\n * & {@link ReducedIterator.values} methods.  \n * It does, however, provide the same set of methods to perform\n * operations and transformation on the elements of the iterator,  \n * having also the knowledge and context of the groups to which\n * they belong, allowing to handle them in a grouped manner.\n *\n * This is particularly useful when you have group elements and\n * need perform specific operations on the reduced elements.\n *\n * ---\n *\n * @example\n * ```ts\n * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n *     .count();\n *\n * console.log(results.toObject()); // { odd: 4, even: 4 }\n * ```\n *\n * ---\n *\n * @template K The type of the key used to group the elements.\n * @template T The type of the elements in the iterator.\n */\nexport default class ReducedIterator<K extends PropertyKey, T>\n{\n    /**\n     * The internal {@link SmartIterator} object that holds the reduced elements.\n     */\n    protected readonly _elements: SmartIterator<[K, T]>;\n\n    /**\n     * Initializes a new instance of the {@link ReducedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new ReducedIterator<string, number>([[\"A\", 1], [\"B\", 2], [\"C\", 4]]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable A reduced iterable object.\n     */\n    public constructor(iterable: Iterable<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link ReducedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new ReducedIterator<string, number>({\n     *     _index: 0,\n     *     next: () =>\n     *     {\n     *         if (this._index >= 3) { return { done: true, value: undefined }; }\n     *         this._index += 1;\n     *\n     *         return { done: false, value: [[\"A\", \"B\", \"C\"][this._index], (this._index + 1)] };\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param iterator An reduced iterator object.\n     */\n    public constructor(iterator: Iterator<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link ReducedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { range, Random } from \"@byloth/core\";\n     *\n     * const results = new ReducedIterator<string, number>(function* ()\n     * {\n     *     for (const index of range(3))\n     *     {\n     *         yield [[\"A\", \"B\", \"C\"][index], (index + 1)];\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn A generator function that produces the reduced elements.\n     */\n    public constructor(generatorFn: GeneratorFunction<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link ReducedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new ReducedIterator(reducedValues);\n     * ```\n     *\n     * ---\n     *\n     * @param argument An iterable, iterator or generator function that produces the reduced elements.\n     */\n    public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>);\n    public constructor(argument: Iterable<[K, T]> | Iterator<[K, T]> | GeneratorFunction<[K, T]>)\n    {\n        this._elements = new SmartIterator(argument);\n    }\n\n    /**\n     * Determines whether all elements of the reduced iterator satisfy the given condition.\n     * See also {@link ReducedIterator.some}.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * Once a single element doesn't satisfy the condition, the method will return `false` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link ReducedIterator.find} instead.\n     *\n     * If the iterator is infinite and every element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .every((key, value) => value > 0);\n     *\n     * console.log(results); // true\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns `true` if all elements satisfy the condition, `false` otherwise.\n     */\n    public every(predicate: KeyedIteratee<K, T, boolean>): boolean\n    {\n        for (const [index, [key, element]] of this._elements.enumerate())\n        {\n            if (!(predicate(key, element, index))) { return false; }\n        }\n\n        return true;\n    }\n\n    /**\n     * Determines whether any element of the reduced iterator satisfies the given condition.\n     * See also {@link ReducedIterator.every}.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * Once a single element satisfies the condition, the method will return `true` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link ReducedIterator.find} instead.\n     *\n     * If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .some((key, value) => value > 0);\n     *\n     * console.log(results); // true\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns `true` if any element satisfies the condition, `false` otherwise.\n     */\n    public some(predicate: KeyedIteratee<K, T, boolean>): boolean\n    {\n        for (const [index, [key, element]] of this._elements.enumerate())\n        {\n            if (predicate(key, element, index)) { return true; }\n        }\n\n        return false;\n    }\n\n    /**\n     * Filters the elements of the reduced iterator using a given condition.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .filter((key, value) => value > 0);\n     *\n     * console.log(results.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing only the elements that satisfy the condition.\n     */\n    public filter(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T>;\n\n    /**\n     * Filters the elements of the reduced iterator using a given type guard predicate.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number | string>([-3, -1, \"0\", \"2\", 3, 5, \"6\", \"8\"])\n     *     .groupBy((value) => Number(value) % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .filter<number>((key, value) => typeof value === \"number\");\n     *\n     * console.log(results.toObject()); // { odd: 4 }\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing only the elements that satisfy the condition.\n     */\n    public filter<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): ReducedIterator<K, S>;\n    public filter(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T>\n    {\n        const elements = this._elements.enumerate();\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                if (predicate(key, element, index)) { yield [key, element]; }\n            }\n        });\n    }\n\n    /**\n     * Maps the elements of the reduced iterator using a given transformation function.\n     *\n     * This method will iterate over all the elements of the iterator applying the transformation function.  \n     * The result of the transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .map((key, value) => value * 2);\n     *\n     * console.log(results.toObject()); // { odd: 8, even: 32 }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing the transformed elements.\n     */\n    public map<V>(iteratee: KeyedIteratee<K, T, V>): ReducedIterator<K, V>\n    {\n        const elements = this._elements.enumerate();\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                yield [key, iteratee(key, element, index)];\n            }\n        });\n    }\n\n    /**\n     * Reduces the elements of the reduced iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all the elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the first element of the iterator.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Also note that:\n     * - If an empty iterator is provided, a {@link ValueException} will be thrown.\n     * - If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const result = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * console.log(result); // 20\n     * ```\n     *\n     * ---\n     *\n     * @param reducer The reducer function to apply to the elements of the iterator.\n     *\n     * @returns The final value after reducing all the elements of the iterator.\n     */\n    public reduce(reducer: KeyedReducer<K, T, T>): T;\n\n    /**\n     * Reduces the elements of the reduced iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all the elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the provided initial value.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const result = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .reduce((key, { value }, currentValue) => ({ value: value + currentValue }), { value: 0 });\n     *\n     * console.log(result); // { value: 20 }\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the type of the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to the elements of the iterator.\n     * @param initialValue The initial value of the accumulator.\n     *\n     * @returns The final result of the reduction.\n     */\n    public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue: A): A;\n    public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: A): A\n    {\n        let index = 0;\n        let accumulator = initialValue;\n        if (accumulator === undefined)\n        {\n            const result = this._elements.next();\n            if (result.done) { throw new ValueException(\"Cannot reduce an empty iterator without an initial value.\"); }\n\n            accumulator = (result.value[1] as unknown) as A;\n            index += 1;\n        }\n\n        for (const [key, element] of this._elements)\n        {\n            accumulator = reducer(key, accumulator, element, index);\n\n            index += 1;\n        }\n\n        return accumulator;\n    }\n\n    /**\n     * Flattens the elements of the reduced iterator using a given transformation function.\n     *\n     * This method will iterate over all the elements of the iterator applying the transformation function.  \n     * The result of each transformation will be flattened into the new iterator.\n     *\n     * Since the iterator is lazy, the flattening process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator.concat([value]), () => [])\n     *     .flatMap((key, value) => value);\n     *\n     * console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing the flattened elements.\n     */\n    public flatMap<V>(iteratee: KeyedIteratee<K, T, V | readonly V[]>): AggregatedIterator<K, V>\n    {\n        const elements = this._elements.enumerate();\n\n        return new AggregatedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                const values = iteratee(key, element, index);\n\n                if (values instanceof Array)\n                {\n                    for (const value of values) { yield [key, value]; }\n                }\n                else { yield [key, values]; }\n            }\n        });\n    }\n\n    /**\n     * Drops a given number of elements at the beginning of the reduced iterator.  \n     * The remaining elements will be included in the new iterator.\n     * See also {@link ReducedIterator.take}.\n     *\n     * Since the iterator is lazy, the dropping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the dropped elements will be consumed in the process.  \n     * The rest of the iterator will be consumed once the new iterator is.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator.concat(value), () => [])\n     *     .drop(1);\n     *\n     * console.log(results.toObject()); // { even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param count The number of elements to drop.\n     *\n     * @returns A new {@link ReducedIterator} containing the remaining elements.\n     */\n    public drop(count: number): ReducedIterator<K, T>\n    {\n        const elements = this._elements.enumerate();\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                if (index >= count) { yield [key, element]; }\n            }\n        });\n    }\n\n    /**\n     * Takes a given number of elements at the beginning of the reduced iterator.  \n     * The elements will be included in the new iterator.\n     * See also {@link ReducedIterator.drop}.\n     *\n     * Since the iterator is lazy, the taking process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the taken elements will be consumed from the original reduced iterator.  \n     * The rest of the original reduced iterator will be available for further consumption.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const reduced = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator.concat(value), () => []);\n     *\n     * const results = iterator.take(1);\n     *\n     * console.log(results.toObject()); // { odd: [-3, -1, 3, 5] }\n     * console.log(reduced.toObject()); // { even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param limit The number of elements to take.\n     *\n     * @returns A new {@link ReducedIterator} containing the taken elements.\n     */\n    public take(limit: number): ReducedIterator<K, T>\n    {\n        const elements = this._elements.enumerate();\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                if (index >= limit) { break; }\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Finds the first element of the reduced iterator that satisfies the given condition.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -3, -1, 0, 1, 2, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .find((key, value) => value > 0);\n     *\n     * console.log(results); // 16\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns The first element that satisfies the condition, `undefined` otherwise.\n     */\n    public find(predicate: KeyedIteratee<K, T, boolean>): T | undefined;\n\n    /**\n     * Finds the first element of the reduced iterator that satisfies the given type guard predicate.\n     *\n     * This method will iterate over all the elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number | string>([\"-3\", -3, \"-1\", 0, 1, 2, \"5\", 6, 8])\n     *     .groupBy((value) => Number(value) % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .find<number>((key, value) => typeof value === \"number\");\n     *\n     * console.log(results); // 16\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the result.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns The first element that satisfies the condition, `undefined` otherwise.\n     */\n    public find<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): S | undefined;\n    public find(predicate: KeyedIteratee<K, T, boolean>): T | undefined\n    {\n        for (const [index, [key, element]] of this._elements.enumerate())\n        {\n            if (predicate(key, element, index)) { return element; }\n        }\n\n        return undefined;\n    }\n\n    /**\n     * Enumerates the elements of the reduced iterator.  \n     * Each element is paired with its index in a new iterator.\n     *\n     * Since the iterator is lazy, the enumeration process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new ReducedIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .enumerate();\n     *\n     * console.log(results.toObject()); // [[0, 4], [1, 16]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link ReducedIterator} object containing the enumerated elements.\n     */\n    public enumerate(): ReducedIterator<K, [number, T]>\n    {\n        return this.map((_, element, index) => [index, element]);\n    }\n\n    /**\n     * Removes all duplicate elements from the reduced iterator.  \n     * The first occurrence of each element will be kept.\n     *\n     * Since the iterator is lazy, the deduplication process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new ReducedIterator<number>([-3, -1, 0, 2, 3, 6, -3, -1, 1, 5, 6, 8, 7, 2])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .map((key, value) => Math.abs(value))\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .unique();\n     *\n     * console.log(results.toObject()); // { odd: 24 }\n     *\n     * @returns A new {@link ReducedIterator} containing only the unique elements.\n     */\n    public unique(): ReducedIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new ReducedIterator(function* ()\n        {\n            const values = new Set<T>();\n            for (const [key, element] of elements)\n            {\n                if (values.has(element)) { continue; }\n                values.add(element);\n\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Counts the number of elements in the reduced iterator.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .count();\n     *\n     * console.log(results); // 2\n     * ```\n     *\n     * ---\n     *\n     * @returns The number of elements in the iterator.\n     */\n    public count(): number\n    {\n        let index = 0;\n\n        for (const _ of this._elements) { index += 1; }\n\n        return index;\n    }\n\n    /**\n     * Iterates over all elements of the reduced iterator.  \n     * The elements are passed to the function along with their key and index.\n     *\n     * This method will consume the entire iterator in the process.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const reduced = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * reduced.forEach((key, value, index) =>\n     * {\n     *     console.log(`#${index} - ${key}: ${value}`); // \"#0 - odd: 4\", \"#1 - even: 16\"\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param iteratee The function to apply to each element of the reduced iterator.\n     */\n    public forEach(iteratee: KeyedIteratee<K, T>): void\n    {\n        for (const [index, [key, element]] of this._elements.enumerate())\n        {\n            iteratee(key, element, index);\n        }\n    }\n\n    /**\n     * Reaggregates the elements of the reduced iterator.  \n     * The elements are grouped by a new key computed by the given iteratee function.\n     *\n     * Since the iterator is lazy, the reorganizing process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, -6, -8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .reorganizeBy((key, value) => value > 0 ? \"positive\" : \"negative\");\n     *\n     * console.log(results.toObject()); // { positive: 4, negative: -12 }\n     * ```\n     *\n     * ---\n     *\n     * @template J The type of the new keys used to group the elements.\n     *\n     * @param iteratee The function to determine the new key of each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing the elements reorganized by the new keys.\n     */\n    public reorganizeBy<J extends PropertyKey>(iteratee: KeyedIteratee<K, T, J>): AggregatedIterator<J, T>\n    {\n        const elements = this._elements.enumerate();\n\n        return new AggregatedIterator(function* ()\n        {\n            for (const [index, [key, element]] of elements)\n            {\n                yield [iteratee(key, element, index), element];\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the keys of the iterator.\n     *\n     * Since the iterator is lazy, the keys will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const keys = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .keys();\n     *\n     * console.log(keys.toArray()); // [\"odd\", \"even\"]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the keys of the iterator.\n     */\n    public keys(): SmartIterator<K>\n    {\n        const elements = this._elements;\n\n        return new SmartIterator<K>(function* ()\n        {\n            for (const [key] of elements)\n            {\n                yield key;\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the entries of the iterator.  \n     * Each entry is a tuple containing the key and the element.\n     *\n     * Since the iterator is lazy, the entries will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const entries = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .entries();\n     *\n     * console.log(entries.toArray()); // [[\"odd\", 4], [\"even\", 16]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the entries of the iterator.\n     */\n    public entries(): SmartIterator<[K, T]>\n    {\n        return this._elements;\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the values of the iterator.\n     *\n     * Since the iterator is lazy, the values will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const values = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value)\n     *     .values();\n     *\n     * console.log(values.toArray()); // [4, 16]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the values of the iterator.\n     */\n    public values(): SmartIterator<T>\n    {\n        const elements = this._elements;\n\n        return new SmartIterator<T>(function* ()\n        {\n            for (const [_, element] of elements)\n            {\n                yield element;\n            }\n        });\n    }\n\n    /**\n     * Materializes the iterator into an array.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const reduced = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * console.log(reduced.toArray()); // [4, 16]\n     * ```\n     *\n     * ---\n     *\n     * @returns The {@link Array} containing all elements of the iterator.\n     */\n    public toArray(): T[]\n    {\n        return Array.from(this.values());\n    }\n\n    /**\n     * Materializes the iterator into a map.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const reduced = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * console.log(reduced.toMap()); // Map(2) { \"odd\" => 4, \"even\" => 16 }\n     * ```\n     *\n     * ---\n     *\n     * @returns The {@link Map} containing all elements of the iterator.\n     */\n    public toMap(): Map<K, T>\n    {\n        return new Map(this.entries());\n    }\n\n    /**\n     * Materializes the iterator into an object.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const reduced = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * console.log(reduced.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @returns The {@link Object} containing all elements of the iterator.\n     */\n    public toObject(): Record<K, T>\n    {\n        return Object.fromEntries(this.entries()) as Record<K, T>;\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"ReducedIterator\";\n}\n","import { SmartAsyncIterator } from \"../iterators/index.js\";\nimport type {\n    GeneratorFunction,\n    AsyncGeneratorFunction,\n    MaybeAsyncGeneratorFunction,\n    MaybeAsyncIteratorLike\n\n} from \"../iterators/types.js\";\nimport type { MaybePromise } from \"../types.js\";\n\nimport ReducedIterator from \"./reduced-iterator.js\";\nimport type { MaybeAsyncKeyedIteratee, MaybeAsyncKeyedReducer } from \"./types.js\";\n\n/**\n * A class representing an iterator that aggregates elements in a lazy and optimized way.\n *\n * It's part of the {@link SmartAsyncIterator} implementation,\n * providing a way to group elements of an iterable by key.  \n * For this reason, it isn't recommended to instantiate this class directly\n * (although it's still possible), but rather use the {@link SmartAsyncIterator.groupBy} method.\n *\n * It isn't directly iterable like its parent class but rather needs to specify on what you want to iterate.  \n * See the {@link AggregatedAsyncIterator.keys}, {@link AggregatedAsyncIterator.entries}\n * & {@link AggregatedAsyncIterator.values} methods.  \n * It does, however, provide the same set of methods to perform\n * operations and transformations on the elements of the iterator,\n * having also the knowledge and context of the groups to which\n * they belong, allowing to handle them in a grouped manner.\n *\n * This is particularly useful when you need to group elements and\n * then perform specific operations on the groups themselves.\n *\n * ---\n *\n * @example\n * ```ts\n * const elements = fetch([...]); // Promise<[-3, -1, 0, 2, 3, 5, 6, 8]>;\n * const results = new SmartAsyncIterator(elements)\n *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n *     .count();\n *\n * console.log(await results.toObject()); // { odd: 4, even: 4 }\n * ```\n *\n * ---\n *\n * @template K The type of the keys used to group the elements.\n * @template T The type of the elements to aggregate.\n */\nexport default class AggregatedAsyncIterator<K extends PropertyKey, T>\n{\n    /**\n     * The internal {@link SmartAsyncIterator} object that holds the elements to aggregate.\n     */\n    protected readonly _elements: SmartAsyncIterator<[K, T]>;\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new AggregatedAsyncIterator<string, number>([[\"A\", 1], [\"B\", 2], [\"A\", 3], [\"C\", 4], [\"B\", 5]]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The iterable to aggregate.\n     */\n    public constructor(iterable: Iterable<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const elements = fetch([...]); // Promise<[[\"A\", 1], [\"B\", 2], [\"A\", 3], [\"C\", 4], [\"B\", 5]]>\n     * const iterator = new AggregatedAsyncIterator<string, number>(elements);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The iterable to aggregate.\n     */\n    public constructor(iterable: AsyncIterable<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedAsyncIterator<string, number>({\n     *     _index: 0,\n     *     next: () =>\n     *     {\n     *         if (this._index >= 5) { return { done: true, value: undefined }; }\n     *         this._index += 1;\n     *\n     *         return { done: false, value: [Random.Choice([\"A\", \"B\", \"C\"]), (this._index + 1)] };\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The iterator to aggregate.\n     */\n    public constructor(iterator: Iterator<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedAsyncIterator<string, number>({\n     *     _index: 0,\n     *     next: async () =>\n     *     {\n     *         if (this._index >= 5) { return { done: true, value: undefined }; }\n     *         this._index += 1;\n     *\n     *         return { done: false, value: [Random.Choice([\"A\", \"B\", \"C\"]), (this._index + 1)] };\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The iterator to aggregate.\n     */\n    public constructor(iterator: AsyncIterator<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { range, Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedAsyncIterator<string, number>(function* ()\n     * {\n     *     for (const index of range(5))\n     *     {\n     *         yield [Random.Choice([\"A\", \"B\", \"C\"]), (index + 1)];\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The generator function to aggregate.\n     */\n    public constructor(generatorFn: GeneratorFunction<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { range, Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedAsyncIterator<string, number>(async function* ()\n     * {\n     *     for await (const index of range(5))\n     *     {\n     *         yield [Random.Choice([\"A\", \"B\", \"C\"]), (index + 1)];\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The generator function to aggregate.\n     */\n    public constructor(generatorFn: AsyncGeneratorFunction<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new AggregatedAsyncIterator(asyncKeyedValues);\n     * ```\n     *\n     * ---\n     *\n     * @param argument The iterable, iterator or generator function to aggregate.\n     */\n    public constructor(argument: MaybeAsyncIteratorLike<[K, T]> | MaybeAsyncGeneratorFunction<[K, T]>);\n    public constructor(argument: MaybeAsyncIteratorLike<[K, T]> | MaybeAsyncGeneratorFunction<[K, T]>)\n    {\n        this._elements = new SmartAsyncIterator(argument);\n    }\n\n    /**\n     * Determines whether all elements of each group of the iterator satisfy a given condition.\n     * See also {@link AggregatedAsyncIterator.some}.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checjing if they satisfy the condition.  \n     * Once a single element of one group doesn't satisfy the condition,\n     * the result for the respective group will be `false`.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the boolean results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .every(async (key, value) => value >= 0);\n     *\n     * console.log(await results.toObject()); // { odd: false, even: true }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the boolean results for each group.\n     */\n    public async every(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): Promise<ReducedIterator<K, boolean>>\n    {\n        const values = new Map<K, [number, boolean]>();\n\n        for await (const [key, element] of this._elements)\n        {\n            const [index, result] = values.get(key) ?? [0, true];\n\n            if (!(result)) { continue; }\n\n            values.set(key, [index + 1, await predicate(key, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, result]] of values) { yield [key, result]; }\n        });\n    }\n\n    /**\n     * Determines whether any element of each group of the iterator satisfies a given condition.\n     * See also {@link AggregatedAsyncIterator.every}.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checjing if they satisfy the condition.  \n     * Once a single element of one group satisfies the condition,\n     * the result for the respective group will be `true`.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the boolean results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-5, -4, -3, -2, -1, 0])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .some(async (key, value) => value >= 0);\n     *\n     * console.log(await results.toObject()); // { odd: false, even: true }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the boolean results for each group.\n     */\n    public async some(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): Promise<ReducedIterator<K, boolean>>\n    {\n        const values = new Map<K, [number, boolean]>();\n\n        for await (const [key, element] of this._elements)\n        {\n            const [index, result] = values.get(key) ?? [0, false];\n\n            if (result) { continue; }\n\n            values.set(key, [index + 1, await predicate(key, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, result]] of values) { yield [key, result]; }\n        });\n    }\n\n    /**\n     * Filters the elements of the iterator based on a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .filter(async (key, value) => value >= 0);\n     *\n     * console.log(await results.toObject()); // { odd: [3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the elements that satisfy the condition.\n     */\n    public filter(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): AggregatedAsyncIterator<K, T>;\n\n    /**\n     * Filters the elements of the iterator based on a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, \"-1\", 0, \"2\", \"3\", 5, 6, \"8\"])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .filter<number>(async (key, value) => typeof value === \"number\");\n     *\n     * console.log(await results.toObject()); // { odd: [-3, 5], even: [0, 6] }\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the elements that satisfy the condition.\n     */\n    public filter<S extends T>(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): AggregatedAsyncIterator<K, S>;\n    public filter(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): AggregatedAsyncIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, T]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (await predicate(key, element, index)) { yield [key, element]; }\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Maps the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the condition.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .map(async (key, value) => Math.abs(value));\n     *\n     * console.log(await results.toObject()); // { odd: [3, 1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the transformed elements.\n     */\n    public map<V>(iteratee: MaybeAsyncKeyedIteratee<K, T, V>): AggregatedAsyncIterator<K, V>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, V]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                yield [key, await iteratee(key, element, index)];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accoumulator value will be the first element of the iterator.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce(async (key, accumulator, value) => accumulator + value);\n     *\n     * console.log(await results.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public async reduce(reducer: MaybeAsyncKeyedReducer<K, T, T>): Promise<ReducedIterator<K, T>>;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accoumulator value will be the provided initial value.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce(async (key, accumulator, value) => accumulator + value, 0);\n     *\n     * console.log(await results.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The initial value for the accumulator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public async reduce<A extends PropertyKey>(reducer: MaybeAsyncKeyedReducer<K, T, A>, initialValue: MaybePromise<A>)\n        : Promise<ReducedIterator<K, A>>;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accoumulator value will be the provided initial value by the given function.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce(async (key, { value }, currentValue) => ({ value: value + currentValue }), (key) => ({ value: 0 }));\n     *\n     * console.log(await results.toObject()); // { odd: { value: 4 }, even: { value: 16 } }\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The function that provides the initial value for the accumulator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public async reduce<A>(reducer: MaybeAsyncKeyedReducer<K, T, A>, initialValue: (key: K) => MaybePromise<A>)\n        : Promise<ReducedIterator<K, A>>;\n    public async reduce<A>(\n        reducer: MaybeAsyncKeyedReducer<K, T, A>, initialValue?: MaybePromise<A> | ((key: K) => MaybePromise<A>)\n    ): Promise<ReducedIterator<K, A>>\n    {\n        const values = new Map<K, [number, A]>();\n\n        for await (const [key, element] of this._elements)\n        {\n            let index: number;\n            let accumulator: A;\n\n            if (values.has(key)) { [index, accumulator] = values.get(key)!; }\n            else if (initialValue !== undefined)\n            {\n                index = 0;\n\n                if (initialValue instanceof Function) { accumulator = await initialValue(key); }\n                else { accumulator = await initialValue; }\n            }\n            else\n            {\n                values.set(key, [0, (element as unknown) as A]);\n\n                continue;\n            }\n\n            values.set(key, [index + 1, await reducer(key, accumulator, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, accumulator]] of values) { yield [key, accumulator]; }\n        });\n    }\n\n    /**\n     * Flattens the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([[-3, -1], 0, 2, 3, 5, [6, 8]])\n     *      .groupBy(async (values) =>\n     *      {\n     *          const value = values instanceof Array ? values[0] : values;\n     *          return value % 2 === 0 ? \"even\" : \"odd\";\n     *      })\n     *     .flatMap(async (key, values) => values);\n     *\n     * console.log(await results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the transformed elements.\n     */\n    public flatMap<V>(iteratee: MaybeAsyncKeyedIteratee<K, T, V | readonly V[]>): AggregatedAsyncIterator<K, V>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, V]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                const values = await iteratee(key, element, index);\n\n                if (values instanceof Array)\n                {\n                    for (const value of values) { yield [key, value]; }\n                }\n                else { yield [key, values]; }\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Drops a given number of elements from the beginning of each group of the iterator.  \n     * The remaining elements will be included in the new iterator.\n     * See also {@link AggregatedAsyncIterator.take}.\n     *\n     * Since the iterator is lazy, the dropping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .drop(2);\n     *\n     * console.log(await results.toObject()); // { odd: [3, 5], even: [6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param count The number of elements to drop from the beginning of each group.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the remaining elements.\n     */\n    public drop(count: number): AggregatedAsyncIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, T]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (index < count)\n                {\n                    indexes.set(key, index + 1);\n\n                    continue;\n                }\n\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Takes a given number of elements from the beginning of each group of the iterator.  \n     * The elements will be included in the new iterator.\n     * See also {@link AggregatedAsyncIterator.drop}.\n     *\n     * Since the iterator is lazy, the taking process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .take(2);\n     *\n     * console.log(await results.toObject()); // { odd: [-3, -1], even: [0, 2] }\n     * ```\n     *\n     * ---\n     *\n     * @param limit The number of elements to take from the beginning of each group.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the taken elements.\n     */\n    public take(limit: number): AggregatedAsyncIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, T]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (index >= limit) { continue; }\n\n                yield [key, element];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Finds the first element of each group of the iterator that satisfies a given condition.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once the first element of one group satisfies the condition,\n     * the result for the respective group will be the element itself.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain the first element that satisfies the condition for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .find(async (key, value) => value > 0);\n     *\n     * console.log(await results.toObject()); // { odd: 3, even: 2 }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing\n     * the first element that satisfies the condition for each group.\n     */\n    public async find(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): Promise<ReducedIterator<K, T | undefined>>;\n\n    /**\n     * Finds the first element of each group of the iterator that satisfies a given condition.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once the first element of one group satisfies the condition,\n     * the result for the respective group will be the element itself.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain the first element that satisfies the condition for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number | string>([-3, \"-1\", 0, \"2\", \"3\", 5, 6, \"8\"])\n     *     .groupBy(async (value) => Number(value) % 2 === 0 ? \"even\" : \"odd\")\n     *     .find<number>(async (key, value) => typeof value === \"number\");\n     *\n     * console.log(await results.toObject()); // { odd: -3, even: 0 }\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing\n     * the first element that satisfies the condition for each group.\n     */\n    public async find<S extends T>(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>)\n        : Promise<ReducedIterator<K, S | undefined>>;\n\n    public async find(predicate: MaybeAsyncKeyedIteratee<K, T, boolean>): Promise<ReducedIterator<K, T | undefined>>\n    {\n        const values = new Map<K, [number, T | undefined]>();\n\n        for await (const [key, element] of this._elements)\n        {\n            let [index, finding] = values.get(key) ?? [0, undefined];\n\n            if (finding !== undefined) { continue; }\n            if (await predicate(key, element, index)) { finding = element; }\n\n            values.set(key, [index + 1, finding]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, finding]] of values) { yield [key, finding]; }\n        });\n    }\n\n    /**\n     * Enumerates the elements of the iterator.  \n     * Each element is paired with its index within the group in the new iterator.\n     *\n     * Since the iterator is lazy, the enumeration process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .enumerate();\n     *\n     * console.log(results.toObject()); // { odd: [[0, -3], [1, -1], [2, 3]], even: [[0, 0], [1, 2]] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the enumerated elements.\n     */\n    public enumerate(): AggregatedAsyncIterator<K, [number, T]>\n    {\n        return this.map((key, value, index) => [index, value]);\n    }\n\n    /**\n     * Removes all duplicate elements from within each group of the iterator.  \n     * The first occurrence of each element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the deduplication process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 6, -3, -1, 0, 5, 6, 8, 0, 2])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .unique();\n     *\n     * console.log(await results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing only the unique elements.\n     */\n    public unique(): AggregatedAsyncIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[K, T]>\n        {\n            const keys = new Map<K, Set<T>>();\n            for await (const [key, element] of elements)\n            {\n                const values = keys.get(key) ?? new Set<T>();\n                if (values.has(element)) { continue; }\n\n                values.add(element);\n                keys.set(key, values);\n\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Counts the number of elements within each group of the iterator.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .count();\n     *\n     * console.log(await results.toObject()); // { odd: 4, even: 4 }\n     * ```\n     *\n     * ---\n     *\n     * @returns\n     * A {@link Promise} resolving to a new {@link ReducedIterator} containing the number of elements for each group.\n     */\n    public async count(): Promise<ReducedIterator<K, number>>\n    {\n        const counters = new Map<K, number>();\n\n        for await (const [key] of this._elements)\n        {\n            const count = counters.get(key) ?? 0;\n\n            counters.set(key, count + 1);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, count] of counters) { yield [key, count]; }\n        });\n    }\n\n    /**\n     * Iterates over the elements of the iterator.  \n     * The elements are passed to the given iteratee function along with their key and index within the group.\n     *\n     * This method will consume the entire iterator in the process.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartAsyncIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * await aggregator.forEach(async (key, value, index) =>\n     * {\n     *     console.log(`${index}: ${value}`); // \"0: -3\", \"0: 0\", \"1: 2\", \"1: -1\", \"2: 3\"\n     * };\n     * ```\n     *\n     * ---\n     *\n     * @param iteratee The function to execute for each element of the iterator.\n     *\n     * @returns A {@link Promise} that will resolve once the iteration is complete.\n     */\n    public async forEach(iteratee: MaybeAsyncKeyedIteratee<K, T>): Promise<void>\n    {\n        const indexes = new Map<K, number>();\n\n        for await (const [key, element] of this._elements)\n        {\n            const index = indexes.get(key) ?? 0;\n\n            await iteratee(key, element, index);\n\n            indexes.set(key, index + 1);\n        }\n    }\n\n    /**\n     * Changes the key of each element on which the iterator is aggregated.  \n     * The new key is determined by the given iteratee function.\n     *\n     * Since the iterator is lazy, the reorganization process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .map(async (key, value, index) => index % 2 === 0 ? value : -value)\n     *     .reorganizeBy(async (key, value) => value >= 0 ? \"+\" : \"-\");\n     *\n     * console.log(await results.toObject()); // { \"+\": [1, 0, 3, 6], \"-\": [-3, -2, -5, -8] }\n     * ```\n     *\n     * ---\n     *\n     * @template J The type of the new key.\n     *\n     * @param iteratee The function to determine the new key for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedAsyncIterator} containing the elements reorganized by the new keys.\n     */\n    public reorganizeBy<J extends PropertyKey>(iteratee: MaybeAsyncKeyedIteratee<K, T, J>)\n        : AggregatedAsyncIterator<J, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedAsyncIterator(async function* (): AsyncGenerator<[J, T]>\n        {\n            const indexes = new Map<K, number>();\n            for await (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                yield [await iteratee(key, element, index), element];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartAsyncIterator}\n     * object containing all the keys of the iterator.\n     *\n     * Since the iterator is lazy, the keys will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const keys = new SmartAsyncIterator([-3, Symbol(), \"A\", { }, null, [1 , 2, 3], false])\n     *     .groupBy(async (value) => typeof value)\n     *     .keys();\n     *\n     * console.log(await keys.toArray()); // [\"number\", \"symbol\", \"string\", \"object\", \"boolean\"]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartAsyncIterator} containing all the keys of the iterator.\n     */\n    public keys(): SmartAsyncIterator<K>\n    {\n        const elements = this._elements;\n\n        return new SmartAsyncIterator<K>(async function* ()\n        {\n            const keys = new Set<K>();\n            for await (const [key] of elements)\n            {\n                if (keys.has(key)) { continue; }\n                keys.add(key);\n\n                yield key;\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartAsyncIterator}\n     * object containing all the entries of the iterator.  \n     * Each entry is a tuple containing the key and the element.\n     *\n     * Since the iterator is lazy, the entries will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const entries = new SmartAsyncIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .entries();\n     *\n     * console.log(await entries.toArray()); // [[\"odd\", -3], [\"even\", 0], [\"even\", 2], [\"odd\", -1], [\"odd\", 3]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartAsyncIterator} containing all the entries of the iterator.\n     */\n    public entries(): SmartAsyncIterator<[K, T]>\n    {\n        return this._elements;\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartAsyncIterator}\n     * object containing all the values of the iterator.\n     *\n     * Since the iterator is lazy, the values will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const values = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .values();\n     *\n     * console.log(await values.toArray()); // [-3, -1, 0, 2, 3, 5, 6, 8]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartAsyncIterator} containing all the values of the iterator.\n     */\n    public values(): SmartAsyncIterator<T>\n    {\n        const elements = this._elements;\n\n        return new SmartAsyncIterator<T>(async function* ()\n        {\n            for await (const [_, element] of elements) { yield element; }\n        });\n    }\n\n    /**\n     * Materializes the iterator into an array of arrays.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(await aggregator.toArray()); // [[-3, -1, 3, 5], [0, 2, 6, 8]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Promise} resolving to an {@link Array} containing all the values of the iterator.\n     */\n    public async toArray(): Promise<T[][]>\n    {\n        const map = await this.toMap();\n\n        return Array.from(map.values());\n    }\n\n    /**\n     * Materializes the iterator into a map.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(await aggregator.toMap()); // Map(2) { \"odd\" => [-3, -1, 3, 5], \"even\" => [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Promise} resolving to a {@link Map} containing all the entries of the iterator.\n     */\n    public async toMap(): Promise<Map<K, T[]>>\n    {\n        const groups = new Map<K, T[]>();\n\n        for await (const [key, element] of this._elements)\n        {\n            const value = groups.get(key) ?? [];\n\n            value.push(element);\n            groups.set(key, value);\n        }\n\n        return groups;\n    }\n\n    /**\n     * Materializes the iterator into an object.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartAsyncIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy(async (value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(await aggregator.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Promise} resolving to an object containing all the entries of the iterator.\n     */\n    public async toObject(): Promise<Record<K, T[]>>\n    {\n        const groups = { } as Record<K, T[]>;\n\n        for await (const [key, element] of this._elements)\n        {\n            const value = groups[key] ?? [];\n\n            value.push(element);\n            groups[key] = value;\n        }\n\n        return groups;\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"AggregatedAsyncIterator\";\n}\n","import AggregatedAsyncIterator from \"../aggregators/aggregated-async-iterator.js\";\nimport { ValueException } from \"../exceptions/index.js\";\nimport type { MaybePromise } from \"../types.js\";\n\nimport type {\n    GeneratorFunction,\n    AsyncGeneratorFunction,\n    MaybeAsyncGeneratorFunction,\n    MaybeAsyncIteratee,\n    MaybeAsyncReducer,\n    MaybeAsyncIteratorLike\n\n} from \"./types.js\";\n\n/**\n * A wrapper class representing an enhanced and instantiable version\n * of the native {@link AsyncIterable} & {@link AsyncIterator} interfaces.\n *\n * It provides a set of utility methods to better manipulate and transform\n * asynchronous iterators in a functional and highly performant way.  \n * It takes inspiration from the native {@link Array} methods like\n * {@link Array.map}, {@link Array.filter}, {@link Array.reduce}, etc...\n *\n * The class is lazy, meaning that the transformations are applied\n * only when the resulting iterator is materialized, not before.  \n * This allows to chain multiple transformations without\n * the need to iterate over the elements multiple times.\n *\n * ---\n *\n * @example\n * ```ts\n * const result = new SmartAsyncIterator<number>([\"-5\", \"-4\", \"-3\", \"-2\", \"-1\", \"0\", \"1\", \"2\", \"3\", \"4\", \"5\"])\n *     .map((value) => Number(value))\n *     .map((value) => value + Math.ceil(Math.abs(value / 2)))\n *     .filter((value) => value >= 0)\n *     .map((value) => value + 1)\n *     .reduce((acc, value) => acc + value);\n *\n * console.log(await result); // 31\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterator.\n * @template R The type of the final result of the iterator. Default is `void`.\n * @template N The type of the argument passed to the `next` method. Default is `undefined`.\n */\nexport default class SmartAsyncIterator<T, R = void, N = undefined> implements AsyncIterator<T, R, N>\n{\n    /**\n     * The native {@link AsyncIterator} object that is being wrapped by this instance.\n     */\n    protected readonly _iterator: AsyncIterator<T, R, N>;\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<string>([\"A\", \"B\", \"C\"]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The iterable object to wrap.\n     */\n    public constructor(iterable: Iterable<T>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The asynchronous iterable object to wrap.\n     */\n    public constructor(iterable: AsyncIterable<T>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number, void, number>({\n     *     _sum: 0, _count: 0,\n     *\n     *     next: function(value: number)\n     *     {\n     *         this._sum += value;\n     *         this._count += 1;\n     *\n     *         return { done: false, value: this._sum / this._count };\n     *     }\n     * })\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The iterator object to wrap.\n     */\n    public constructor(iterator: Iterator<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number, void, number>({\n     *     _sum: 0, _count: 0,\n     *\n     *     next: async function(value: number)\n     *     {\n     *         this._sum += value;\n     *         this._count += 1;\n     *\n     *         return { done: false, value: this._sum / this._count };\n     *     }\n     * })\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The asynchronous iterator object to wrap.\n     */\n    public constructor(iterator: AsyncIterator<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>(function* ()\n     * {\n     *     for (let i = 2; i < 65_536; i *= 2) { yield (i - 1); }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The generator function to wrap.\n     */\n    public constructor(generatorFn: GeneratorFunction<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>(async function* ()\n     * {\n     *     for await (let i = 2; i < 65_536; i *= 2) { yield (i - 1); }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The asynchronous generator function to wrap.\n     */\n    public constructor(generatorFn: AsyncGeneratorFunction<T, R, N>);\n\n    /**\n     * Initializes a new instance of the {@link SmartAsyncIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator(values);\n     * ```\n     *\n     * ---\n     *\n     * @param argument The synchronous or asynchronous iterable, iterator or generator function to wrap.\n     */\n    public constructor(argument: MaybeAsyncIteratorLike<T, R, N> | MaybeAsyncGeneratorFunction<T, R, N>);\n    public constructor(argument: MaybeAsyncIteratorLike<T, R, N> | MaybeAsyncGeneratorFunction<T, R, N>)\n    {\n        if (argument instanceof Function)\n        {\n            const generator = argument();\n            if (Symbol.asyncIterator in generator)\n            {\n                this._iterator = generator;\n            }\n            else\n            {\n                this._iterator = (async function* ()\n                {\n                    let next: [] | [N] = [];\n\n                    while (true)\n                    {\n                        const result = generator.next(...next);\n                        if (result.done) { return result.value; }\n\n                        next = [yield result.value];\n                    }\n\n                })();\n            }\n        }\n        else if (Symbol.asyncIterator in argument)\n        {\n            this._iterator = argument[Symbol.asyncIterator]() as AsyncIterator<T, R, N>;\n        }\n        else if (Symbol.iterator in argument)\n        {\n            const iterator = argument[Symbol.iterator]();\n            this._iterator = (async function* ()\n            {\n                while (true)\n                {\n                    const result = iterator.next();\n                    if (result.done) { return result.value; }\n\n                    yield result.value;\n                }\n\n            })();\n        }\n        else\n        {\n            this._iterator = (async function* ()\n            {\n                let next: [] | [N] = [];\n\n                while (true)\n                {\n                    const result: IteratorResult<T, R> = await argument.next(...next);\n                    if (result.done) { return result.value; }\n\n                    next = [yield result.value];\n                }\n\n            })();\n        }\n    }\n\n    /**\n     * Determines whether all elements of the iterator satisfy a given condition.\n     * See also {@link SmartAsyncIterator.some}.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element doesn't satisfy the condition, the method will return `false` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link SmartAsyncIterator.find} instead.\n     *\n     * If the iterator is infinite and every element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = await iterator.every(async (value) => value < 0);\n     *\n     * console.log(result); // false\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} that will resolve to `true` if all elements satisfy the condition, `false` otherwise.\n     */\n    public async every(predicate: MaybeAsyncIteratee<T, boolean>): Promise<boolean>\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n\n            if (result.done) { return true; }\n            if (!(await predicate(result.value, index))) { return false; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Determines whether any element of the iterator satisfies a given condition.\n     * See also {@link SmartAsyncIterator.every}.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element satisfies the condition, the method will return `true` immediately.\n     *\n     * This may lead to an unknown final state of the iterator, which may be entirely or partially consumed.  \n     * For this reason, it's recommended to consider it as consumed in any case and to not use it anymore.  \n     * Consider using {@link SmartAsyncIterator.find} instead.\n     *\n     * If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = await iterator.some(async (value) => value > 0);\n     *\n     * console.log(result); // true\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} that will resolve to `true` if any element satisfies the condition, `false` otherwise.\n     */\n    public async some(predicate: MaybeAsyncIteratee<T, boolean>): Promise<boolean>\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n\n            if (result.done) { return false; }\n            if (await predicate(result.value, index)) { return true; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.filter(async (value) => value < 0);\n     *\n     * console.log(await result.toArray()); // [-2, -1]\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing only the elements that satisfy the condition.\n     */\n    public filter(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<T, R>;\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number | string>([-2, \"-1\", \"0\", 1, \"2\"]);\n     * const result = iterator.filter<number>(async (value) => typeof value === \"number\");\n     *\n     * console.log(await result.toArray()); // [-2, 1]\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing only the elements that satisfy the condition.\n     */\n    public filter<S extends T>(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<S, R>;\n    public filter(predicate: MaybeAsyncIteratee<T, boolean>): SmartAsyncIterator<T, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<T, R>(async function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n                if (await predicate(result.value, index)) { yield result.value; }\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Maps the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.map(async (value) => Math.abs(value));\n     *\n     * console.log(await result.toArray()); // [2, 1, 0, 1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing the transformed elements.\n     */\n    public map<V>(iteratee: MaybeAsyncIteratee<T, V>): SmartAsyncIterator<V, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<V, R>(async function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n\n                yield await iteratee(result.value, index);\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the first element of the iterator.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Also note that:\n     * - If an empty iterator is provided, a {@link ValueException} will be thrown.\n     * - If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);\n     * const result = await iterator.reduce(async (acc, value) => acc + value);\n     *\n     * console.log(result); // 15\n     * ```\n     *\n     * ---\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     *\n     * @returns A {@link Promise} that will resolve to the final result of the reduction.\n     */\n    public async reduce(reducer: MaybeAsyncReducer<T, T>): Promise<T>;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the provided initial value.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);\n     * const result = await iterator.reduce(async (acc, value) => acc + value, 10);\n     *\n     * console.log(result); // 25\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the type of the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The initial value of the accumulator.\n     *\n     * @returns A {@link Promise} that will resolve to the final result of the reduction.\n     */\n    public async reduce<A>(reducer: MaybeAsyncReducer<T, A>, initialValue: A): Promise<A>;\n    public async reduce<A>(reducer: MaybeAsyncReducer<T, A>, initialValue?: A): Promise<A>\n    {\n        let index = 0;\n        let accumulator = initialValue;\n        if (accumulator === undefined)\n        {\n            const result = await this._iterator.next();\n            if (result.done) { throw new ValueException(\"Cannot reduce an empty iterator without an initial value.\"); }\n\n            accumulator = (result.value as unknown) as A;\n            index += 1;\n        }\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n            if (result.done) { return accumulator; }\n\n            accumulator = await reducer(accumulator, result.value, index);\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Flattens the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be flattened and included in the new iterator.\n     *\n     * Since the iterator is lazy, the flattening process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number[]>([[-2, -1], 0, 1, 2, [3, 4, 5]]);\n     * const result = iterator.flatMap(async (value) => value);\n     *\n     * console.log(await result.toArray()); // [-2, -1, 0, 1, 2, 3, 4, 5]\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing the flattened elements.\n     */\n    public flatMap<V>(iteratee: MaybeAsyncIteratee<T, V | readonly V[]>): SmartAsyncIterator<V, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<V, R>(async function* ()\n        {\n            let index = 0;\n            while (true)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n\n                const elements = await iteratee(result.value, index);\n                if (elements instanceof Array)\n                {\n                    for (const value of elements) { yield value; }\n                }\n                else { yield elements; }\n\n                index += 1;\n            }\n        });\n    }\n\n    /**\n     * Drops a given number of elements at the beginning of the iterator.  \n     * The remaining elements will be included in a new iterator.\n     * See also {@link SmartAsyncIterator.take}.\n     *\n     * Since the iterator is lazy, the dropping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the dropped elements will be consumed in the process.  \n     * The rest of the iterator will be consumed only once the new one is.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.drop(3);\n     *\n     * console.log(await result.toArray()); // [1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @param count The number of elements to drop.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing the remaining elements.\n     */\n    public drop(count: number): SmartAsyncIterator<T, R | undefined>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<T, R | undefined>(async function* ()\n        {\n            let index = 0;\n            while (index < count)\n            {\n                const result = await iterator.next();\n                if (result.done) { return; }\n\n                index += 1;\n            }\n\n            while (true)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n\n                yield result.value;\n            }\n        });\n    }\n\n    /**\n     * Takes a given number of elements at the beginning of the iterator.  \n     * These elements will be included in a new iterator.\n     * See also {@link SmartAsyncIterator.drop}.\n     *\n     * Since the iterator is lazy, the taking process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * Only the taken elements will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = iterator.take(3);\n     *\n     * console.log(await result.toArray()); // [-2, -1, 0]\n     * console.log(await iterator.toArray()); // [1, 2]\n     * ```\n     *\n     * ---\n     *\n     * @param limit The number of elements to take.\n     *\n     * @returns A new {@link SmartAsyncIterator} containing the taken elements.\n     */\n    public take(limit: number): SmartAsyncIterator<T, R | undefined>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<T, R | undefined>(async function* ()\n        {\n            let index = 0;\n            while (index < limit)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n\n                yield result.value;\n\n                index += 1;\n            }\n\n            return;\n        });\n    }\n\n    /**\n     * Finds the first element of the iterator that satisfies a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([-2, -1, 0, 1, 2]);\n     * const result = await iterator.find(async (value) => value > 0);\n     *\n     * console.log(result); // 1\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} that will resolve to the first element that satisfies the condition, `undefined` otherwise.\n     */\n    public async find(predicate: MaybeAsyncIteratee<T, boolean>): Promise<T | undefined>;\n\n    /**\n     * Finds the first element of the iterator that satisfies a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * The first element that satisfies the condition will be returned immediately.\n     *\n     * Only the elements that are necessary to find the first\n     * satisfying one will be consumed from the original iterator.  \n     * The rest of the original iterator will be available for further consumption.\n     *\n     * Also note that:\n     * - If no element satisfies the condition, `undefined` will be returned once the entire iterator is consumed.\n     * - If the iterator is infinite and no element satisfies the condition, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number | string>([-2, \"-1\", \"0\", 1, \"2\"]);\n     * const result = await iterator.find<number>(async (value) => typeof value === \"number\");\n     *\n     * console.log(result); // -2\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the element that satisfies the condition.  \n     * This allows the type-system to infer the correct type of the result.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns\n     * A {@link Promise} that will resolve to the first element that satisfies the condition, `undefined` otherwise. \n     */\n    public async find<S extends T>(predicate: MaybeAsyncIteratee<T, boolean>): Promise<S | undefined>;\n    public async find(predicate: MaybeAsyncIteratee<T, boolean>): Promise<T | undefined>\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n\n            if (result.done) { return; }\n            if (await predicate(result.value, index)) { return result.value; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Enumerates the elements of the iterator.  \n     * Each element is be paired with its index in a new iterator.\n     *\n     * Since the iterator is lazy, the enumeration process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<string>([\"A\", \"M\", \"N\", \"Z\"]);\n     * const result = iterator.enumerate();\n     *\n     * for await (const [index, value] of result)\n     * {\n     *     console.log(`${index}: ${value}`); // \"0: A\", \"1: M\", \"2: N\", \"3: Z\"\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartAsyncIterator} containing the enumerated elements.\n     */\n    public enumerate(): SmartAsyncIterator<[number, T], R>\n    {\n        return this.map((value, index) => [index, value]);\n    }\n\n    /**\n     * Removes all duplicate elements from the iterator.  \n     * The first occurrence of each element will be kept.\n     *\n     * Since the iterator is lazy, the deduplication process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 1, 2, 3, 2, 3, 4, 5, 5, 4]);\n     * const result = iterator.unique();\n     *\n     * console.log(await result.toArray()); // [1, 2, 3, 4, 5]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartAsyncIterator} containing only the unique elements.\n     */\n    public unique(): SmartAsyncIterator<T, R>\n    {\n        const iterator = this._iterator;\n\n        return new SmartAsyncIterator<T, R>(async function* ()\n        {\n            const values = new Set<T>();\n            while (true)\n            {\n                const result = await iterator.next();\n                if (result.done) { return result.value; }\n                if (values.has(result.value)) { continue; }\n\n                values.add(result.value);\n\n                yield result.value;\n            }\n        });\n    }\n\n    /**\n     * Counts the number of elements in the iterator.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);\n     * const result = await iterator.count();\n     *\n     * console.log(result); // 5\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Promise} that will resolve to the number of elements in the iterator.\n     */\n    public async count(): Promise<number>\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n            if (result.done) { return index; }\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Iterates over all elements of the iterator.  \n     * The elements are passed to the function along with their index.\n     *\n     * This method will consume the entire iterator in the process.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([\"A\", \"M\", \"N\", \"Z\"]);\n     * await iterator.forEach(async (value, index) =>\n     * {\n     *     console.log(`${index}: ${value}`); // \"0: A\", \"1: M\", \"2: N\", \"3: Z\"\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param iteratee The function to apply to each element of the iterator.\n     *\n     * @returns A {@link Promise} that will resolve once the iteration is complete.\n     */\n    public async forEach(iteratee: MaybeAsyncIteratee<T>): Promise<void>\n    {\n        let index = 0;\n\n        while (true)\n        {\n            const result = await this._iterator.next();\n            if (result.done) { return; }\n\n            await iteratee(result.value, index);\n\n            index += 1;\n        }\n    }\n\n    /**\n     * Advances the iterator to the next element and returns the result.  \n     * If the iterator requires it, a value must be provided to be passed to the next element.\n     *\n     * Once the iterator is done, the method will return an object with the `done` property set to `true`.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5]);\n     *\n     * let result = await iterator.next();\n     * while (!result.done)\n     * {\n     *     console.log(result.value); // 1, 2, 3, 4, 5\n     *\n     *     result = await iterator.next();\n     * }\n     *\n     * console.log(result); // { done: true, value: undefined }\n     * ```\n     *\n     * ---\n     *\n     * @param values The value to pass to the next element, if required.\n     *\n     * @returns\n     * A {@link Promise} that will resolve to the result of the iteration, containing the value of the operation.\n     */\n    public next(...values: N extends undefined ? [] : [N]): Promise<IteratorResult<T, R>>\n    {\n        return this._iterator.next(...values);\n    }\n\n    /**\n     * An utility method that may be used to close the iterator gracefully,\n     * free the resources and perform any cleanup operation.  \n     * It may also be used to signal the end or to compute a specific final result of the iteration process.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>({\n     *     _index: 0,\n     *     next: async function()\n     *     {\n     *         return { done: false, value: this._index += 1 };\n     *     },\n     *     return: async function() { console.log(\"Closing the iterator...\"); }\n     * });\n     *\n     * for await (const value of iterator)\n     * {\n     *     if (value > 5) { break; } // Closing the iterator...\n     *\n     *     console.log(value); // 1, 2, 3, 4, 5\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param value The final value of the iterator.\n     *\n     * @returns A {@link Promise} that will resolve to the final result of the iterator.\n     */\n    public async return(value?: MaybePromise<R>): Promise<IteratorResult<T, R>>\n    {\n        const _value = (await value) as R;\n\n        if (this._iterator.return) { return await this._iterator.return(_value); }\n\n        return { done: true, value: _value };\n    }\n\n    /**\n     * An utility method that may be used to close the iterator due to an error,\n     * free the resources and perform any cleanup operation.  \n     * It may also be used to signal that an error occurred during the iteration process or to handle it.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>({\n     *     _index: 0,\n     *     next: async function()\n     *     {\n     *         return { done: this._index > 10, value: this._index += 1 };\n     *     },\n     *     throw: async function(error)\n     *     {\n     *         console.warn(error.message);\n     *\n     *         this._index = 0;\n     *     }\n     * });\n     *\n     * for await (const value of iterator) // 1, 2, 3, 4, 5, \"The index is too high.\", 1, 2, 3, 4, 5, ...\n     * {\n     *     try\n     *     {\n     *         if (value > 5) { throw new Error(\"The index is too high.\"); }\n     *\n     *         console.log(value); // 1, 2, 3, 4, 5\n     *     }\n     *     catch (error) { await iterator.throw(error); }\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param error The error to throw into the iterator.\n     *\n     * @returns A {@link Promise} that will resolve to the final result of the iterator.\n     */\n    public throw(error: unknown): Promise<IteratorResult<T, R>>\n    {\n        if (this._iterator.throw) { return this._iterator.throw(error); }\n\n        throw error;\n    }\n\n    /**\n     * An utility method that aggregates the elements of the iterator using a given key function.  \n     * The elements will be grouped by the resulting keys in a new specialized iterator.\n     * See {@link AggregatedAsyncIterator}.\n     *\n     * Since the iterator is lazy, the grouping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * the new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator<number>([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);\n     * const result = iterator.groupBy<string>(async (value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(await result.toObject()); // { odd: [1, 3, 5, 7, 9], even: [2, 4, 6, 8, 10] }\n     * ```\n     *\n     * ---\n     *\n     * @template K The type of the keys used to group the elements.\n     *\n     * @param iteratee The key function to apply to each element of the iterator.\n     *\n     * @returns A new instance of the {@link AggregatedAsyncIterator} class containing the grouped elements.\n     */\n    public groupBy<K extends PropertyKey>(iteratee: MaybeAsyncIteratee<T, K>): AggregatedAsyncIterator<K, T>\n    {\n        return new AggregatedAsyncIterator(this.map(async (element, index) =>\n        {\n            const key = await iteratee(element, index);\n\n            return [key, element] as [K, T];\n        }));\n    }\n\n    /**\n     * Materializes the iterator into an array.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new SmartAsyncIterator(async function* ()\n     * {\n     *     for (let i = 0; i < 5; i += 1) { yield i; }\n     * });\n     * const result = await iterator.toArray();\n     *\n     * console.log(result); // [0, 1, 2, 3, 4]\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Promise} that will resolve to an array containing all elements of the iterator.\n     */\n    public toArray(): Promise<T[]>\n    {\n        return Array.fromAsync(this as AsyncIterable<T>);\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"SmartAsyncIterator\";\n\n    public [Symbol.asyncIterator](): SmartAsyncIterator<T, R, N> { return this; }\n}\n","import { SmartIterator } from \"../iterators/index.js\";\nimport type { GeneratorFunction, IteratorLike } from \"../iterators/types.js\";\n\nimport ReducedIterator from \"./reduced-iterator.js\";\nimport type { KeyedIteratee, KeyedTypeGuardPredicate, KeyedReducer } from \"./types.js\";\n\n/**\n * A class representing an iterator that aggregates elements in a lazy and optimized way.\n *\n * It's part of the {@link SmartIterator} implementation, providing a way to group elements of an iterable by key.  \n * For this reason, it isn't recommended to instantiate this class directly\n * (although it's still possible), but rather use the {@link SmartIterator.groupBy} method.\n *\n * It isn't directly iterable like its parent class but rather needs to specify on what you want to iterate.  \n * See the {@link AggregatedIterator.keys}, {@link AggregatedIterator.entries}\n * & {@link AggregatedIterator.values} methods.  \n * It does, however, provide the same set of methods to perform\n * operations and transformation on the elements of the iterator,  \n * having also the knowledge and context of the groups to which\n * they belong, allowing to handle them in a grouped manner.\n *\n * This is particularly useful when you need to group elements and\n * then perform specific operations on the groups themselves.\n *\n * ---\n *\n * @example\n * ```ts\n * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n *     .count();\n *\n * console.log(results.toObject()); // { odd: 4, even: 4 }\n * ```\n *\n * ---\n *\n * @template K The type of the keys used to group the elements.\n * @template T The type of the elements to aggregate.\n */\nexport default class AggregatedIterator<K extends PropertyKey, T>\n{\n    /**\n     * The internal {@link SmartIterator} object that holds the elements to aggregate.\n     */\n    protected readonly _elements: SmartIterator<[K, T]>;\n\n    /**\n     * Initializes a new instance of the {@link AggregatedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new AggregatedIterator<string, number>([[\"A\", 1], [\"B\", 2], [\"A\", 3], [\"C\", 4], [\"B\", 5]]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable The iterable to aggregate.\n     */\n    public constructor(iterable: Iterable<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedIterator<string, number>({\n     *     _index: 0,\n     *     next: () =>\n     *     {\n     *         if (this._index >= 5) { return { done: true, value: undefined }; }\n     *         this._index += 1;\n     *\n     *         return { done: false, value: [Random.Choice([\"A\", \"B\", \"C\"]), (this._index + 1)] };\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param iterator The iterator to aggregate.\n     */\n    public constructor(iterator: Iterator<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * import { range, Random } from \"@byloth/core\";\n     *\n     * const iterator = new AggregatedIterator<string, number>(function* ()\n     * {\n     *     for (const index of range(5))\n     *     {\n     *         yield [Random.Choice([\"A\", \"B\", \"C\"]), (index + 1)];\n     *     }\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param generatorFn The generator function to aggregate.\n     */\n    public constructor(generatorFn: GeneratorFunction<[K, T]>);\n\n    /**\n     * Initializes a new instance of the {@link AggregatedIterator} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const iterator = new AggregatedIterator(keyedValues);\n     * ```\n     *\n     * ---\n     *\n     * @param argument The iterable, iterator or generator function to aggregate.\n     */\n    public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>);\n    public constructor(argument: IteratorLike<[K, T]> | GeneratorFunction<[K, T]>)\n    {\n        this._elements = new SmartIterator(argument);\n    }\n\n    /**\n     * Determines whether all elements of each group of the iterator satisfy a given condition.\n     * See also {@link AggregatedIterator.some}.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element of one group doesn't satisfy the condition,\n     * the result for the respective group will be `false`.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the boolean results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .every((key, value) => value >= 0);\n     *\n     * console.log(results.toObject()); // { odd: false, even: true }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing the boolean results for each group.\n     */\n    public every(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>\n    {\n        const values = new Map<K, [number, boolean]>();\n\n        for (const [key, element] of this._elements)\n        {\n            const [index, result] = values.get(key) ?? [0, true];\n\n            if (!(result)) { continue; }\n\n            values.set(key, [index + 1, predicate(key, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, result]] of values) { yield [key, result]; }\n        });\n    }\n\n    /**\n     * Determines whether any elements of each group of the iterator satisfy a given condition.\n     * See also {@link AggregatedIterator.every}.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once a single element of one group satisfies the condition,\n     * the result for the respective group will be `true`.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the boolean results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-5, -4, -3, -2, -1, 0])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .some((key, value) => value >= 0);\n     *\n     * console.log(results.toObject()); // { odd: false, even: true }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A {@link ReducedIterator} containing the boolean results for each group.\n     */\n    public some(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, boolean>\n    {\n        const values = new Map<K, [number, boolean]>();\n\n        for (const [key, element] of this._elements)\n        {\n            const [index, result] = values.get(key) ?? [0, false];\n\n            if (result) { continue; }\n\n            values.set(key, [index + 1, predicate(key, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, result]] of values) { yield [key, result]; }\n        });\n    }\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .filter((key, value) => value >= 0);\n     *\n     * console.log(results.toObject()); // { odd: [3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.\n     */\n    public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>;\n\n    /**\n     * Filters the elements of the iterator using a given condition.\n     *\n     * This method will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * If the condition is met, the element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the filtering process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number | string>([-3, \"-1\", 0, \"2\", \"3\", 5, 6, \"8\"])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .filter<number>((key, value) => typeof value === \"number\");\n     *\n     * console.log(results.toObject()); // { odd: [-3, 5], even: [0, 6] }\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing only the elements that satisfy the condition.\n     */\n    public filter<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): AggregatedIterator<K, S>;\n    public filter(predicate: KeyedIteratee<K, T, boolean>): AggregatedIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (predicate(key, element, index)) { yield [key, element]; }\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Maps the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the mapping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .map((key, value) => Math.abs(value));\n     *\n     * console.log(results.toObject()); // { odd: [3, 1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing the transformed elements.\n     */\n    public map<V>(iteratee: KeyedIteratee<K, T, V>): AggregatedIterator<K, V>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                yield [key, iteratee(key, element, index)];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the first element of the iterator.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value);\n     *\n     * console.log(results.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public reduce(reducer: KeyedReducer<K, T, T>): ReducedIterator<K, T>;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the provided initial value.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, accumulator, value) => accumulator + value, 0);\n     *\n     * console.log(results.toObject()); // { odd: 4, even: 16 }\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the type of the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The initial value of the accumulator.\n     *\n     * @returns A new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public reduce<A extends PropertyKey>(reducer: KeyedReducer<K, T, A>, initialValue: A): ReducedIterator<K, A>;\n\n    /**\n     * Reduces the elements of the iterator using a given reducer function.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator applying the reducer function.  \n     * The result of each iteration will be passed as the accumulator to the next one.\n     *\n     * The first accumulator value will be the provided initial value by the given function.  \n     * The last accumulator value will be the final result of the reduction.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain all the reduced results for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .reduce((key, { value }, currentValue) => ({ value: value + currentValue }), (key) => ({ value: 0 }));\n     *\n     * console.log(results.toObject()); // { odd: { value: 4 }, even: { value: 16 } }\n     * ```\n     *\n     * ---\n     *\n     * @template A The type of the accumulator value which will also be the type of the final result of the reduction.\n     *\n     * @param reducer The reducer function to apply to each element of the iterator.\n     * @param initialValue The function that provides the initial value for the accumulator.\n     *\n     * @returns A new {@link ReducedIterator} containing the reduced results for each group.\n     */\n    public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue: (key: K) => A): ReducedIterator<K, A>;\n    public reduce<A>(reducer: KeyedReducer<K, T, A>, initialValue?: A | ((key: K) => A)): ReducedIterator<K, A>\n    {\n        const values = new Map<K, [number, A]>();\n\n        for (const [key, element] of this._elements)\n        {\n            let index: number;\n            let accumulator: A;\n\n            if (values.has(key)) { [index, accumulator] = values.get(key)!; }\n            else if (initialValue !== undefined)\n            {\n                index = 0;\n\n                if (initialValue instanceof Function) { accumulator = initialValue(key); }\n                else { accumulator = initialValue; }\n            }\n            else\n            {\n                values.set(key, [0, (element as unknown) as A]);\n\n                continue;\n            }\n\n            values.set(key, [index + 1, reducer(key, accumulator, element, index)]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, accumulator]] of values) { yield [key, accumulator]; }\n        });\n    }\n\n    /**\n     * Flattens the elements of the iterator using a given transformation function.\n     *\n     * This method will iterate over all elements of the iterator applying the transformation function.  \n     * The result of each transformation will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the flattening process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number[]>([[-3, -1], 0, 2, 3, 5, [6, 8]])\n     *      .groupBy((values) =>\n     *      {\n     *          const value = values instanceof Array ? values[0] : values;\n     *          return value % 2 === 0 ? \"even\" : \"odd\";\n     *      })\n     *     .flatMap((key, values) => values);\n     *\n     * console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @template V The type of the elements after the transformation.\n     *\n     * @param iteratee The transformation function to apply to each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing the transformed elements.\n     */\n    public flatMap<V>(iteratee: KeyedIteratee<K, T, V | readonly V[]>): AggregatedIterator<K, V>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                const values = iteratee(key, element, index);\n\n                if (values instanceof Array)\n                {\n                    for (const value of values) { yield [key, value]; }\n                }\n                else { yield [key, values]; }\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Drops a given number of elements from the beginning of each group of the iterator.  \n     * The remaining elements will be included in the new iterator.\n     * See also {@link AggregatedIterator.take}.\n     *\n     * Since the iterator is lazy, the dropping process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .drop(2);\n     *\n     * console.log(results.toObject()); // { odd: [3, 5], even: [6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @param count The number of elements to drop from the beginning of each group.\n     *\n     * @returns A new {@link AggregatedIterator} containing the remaining elements.\n     */\n    public drop(count: number): AggregatedIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (index < count)\n                {\n                    indexes.set(key, index + 1);\n\n                    continue;\n                }\n\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Takes a given number of elements from the beginning of each group of the iterator.  \n     * The elements will be included in the new iterator.\n     * See also {@link AggregatedIterator.drop}.\n     *\n     * Since the iterator is lazy, the taking process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .take(2);\n     *\n     * console.log(results.toObject()); // { odd: [-3, -1], even: [0, 2] }\n     * ```\n     *\n     * ---\n     *\n     * @param limit The number of elements to take from the beginning of each group.\n     *\n     * @returns A new {@link AggregatedIterator} containing the taken elements.\n     */\n    public take(limit: number): AggregatedIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                if (index >= limit) { continue; }\n                yield [key, element];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * Finds the first element of each group of the iterator that satisfies a given condition.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once the first element of one group satisfies the condition,\n     * the result for the respective group will be the element itself.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain the first element that satisfies the condition for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .find((key, value) => value > 0);\n     *\n     * console.log(results.toObject()); // { odd: 3, even: 2 }\n     * ```\n     *\n     * ---\n     *\n     * @param predicate The condition to check for each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.\n     */\n    public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>;\n\n    /**\n     * Finds the first element of each group of the iterator that satisfies a given condition.  \n     * This method will consume the entire iterator in the process.\n     *\n     * It will iterate over all elements of the iterator checking if they satisfy the condition.  \n     * Once the first element of one group satisfies the condition,\n     * the result for the respective group will be the element itself.\n     *\n     * Eventually, it will return a new {@link ReducedIterator}\n     * object that will contain the first element that satisfies the condition for each group.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number | string>([-3, \"-1\", 0, \"2\", \"3\", 5, 6, \"8\"])\n     *     .groupBy((value) => Number(value) % 2 === 0 ? \"even\" : \"odd\")\n     *     .find<number>((key, value) => typeof value === \"number\");\n     *\n     * console.log(results.toObject()); // { odd: -3, even: 0 }\n     * ```\n     *\n     * ---\n     *\n     * @template S\n     * The type of the elements that satisfy the condition.  \n     * This allows the type-system to infer the correct type of the new iterator.\n     *\n     * It must be a subtype of the original type of the elements.\n     *\n     * @param predicate The type guard condition to check for each element of the iterator.\n     *\n     * @returns A new {@link ReducedIterator} containing the first element that satisfies the condition for each group.\n     */\n    public find<S extends T>(predicate: KeyedTypeGuardPredicate<K, T, S>): ReducedIterator<K, S | undefined>;\n    public find(predicate: KeyedIteratee<K, T, boolean>): ReducedIterator<K, T | undefined>\n    {\n        const values = new Map<K, [number, T | undefined]>();\n\n        for (const [key, element] of this._elements)\n        {\n            let [index, finding] = values.get(key) ?? [0, undefined];\n\n            if (finding !== undefined) { continue; }\n            if (predicate(key, element, index)) { finding = element; }\n\n            values.set(key, [index + 1, finding]);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, [_, finding]] of values) { yield [key, finding]; }\n        });\n    }\n\n    /**\n     * Enumerates the elements of the iterator.  \n     * Each element is paired with its index within the group in a new iterator.\n     *\n     * Since the iterator is lazy, the enumeration process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .enumerate();\n     *\n     * console.log(results.toObject()); // { odd: [[0, -3], [1, -1], [2, 3]], even: [[0, 0], [1, 2]] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link AggregatedIterator} containing the enumerated elements.\n     */\n    public enumerate(): AggregatedIterator<K, [number, T]>\n    {\n        return this.map((_, value, index) => [index, value]);\n    }\n\n    /**\n     * Removes all duplicate elements from within each group of the iterator.  \n     * The first occurrence of each element will be included in the new iterator.\n     *\n     * Since the iterator is lazy, the deduplication process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 6, -3, -1, 0, 5, 6, 8, 0, 2])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .unique();\n     *\n     * console.log(results.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link AggregatedIterator} containing only the unique elements.\n     */\n    public unique(): AggregatedIterator<K, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const keys = new Map<K, Set<T>>();\n            for (const [key, element] of elements)\n            {\n                const values = keys.get(key) ?? new Set<T>();\n                if (values.has(element)) { continue; }\n\n                values.add(element);\n                keys.set(key, values);\n\n                yield [key, element];\n            }\n        });\n    }\n\n    /**\n     * Counts the number of elements within each group of the iterator.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .count();\n     *\n     * console.log(results.toObject()); // { odd: 4, even: 4 }\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link ReducedIterator} containing the number of elements for each group.\n     */\n    public count(): ReducedIterator<K, number>\n    {\n        const counters = new Map<K, number>();\n\n        for (const [key] of this._elements)\n        {\n            const count = counters.get(key) ?? 0;\n\n            counters.set(key, count + 1);\n        }\n\n        return new ReducedIterator(function* ()\n        {\n            for (const [key, count] of counters) { yield [key, count]; }\n        });\n    }\n\n    /**\n     * Iterates over the elements of the iterator.  \n     * The elements are passed to the given iteratee function along with their key and index within the group.\n     *\n     * This method will consume the entire iterator in the process.  \n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * aggregator.forEach((key, value, index) =>\n     * {\n     *     console.log(`${index}: ${value}`); // \"0: -3\", \"0: 0\", \"1: 2\", \"1: -1\", \"2: 3\"\n     * };\n     * ```\n     *\n     * ---\n     *\n     * @param iteratee The function to execute for each element of the iterator.\n     */\n    public forEach(iteratee: KeyedIteratee<K, T>): void\n    {\n        const indexes = new Map<K, number>();\n        for (const [key, element] of this._elements)\n        {\n            const index = indexes.get(key) ?? 0;\n            iteratee(key, element, index);\n\n            indexes.set(key, index + 1);\n        }\n    }\n\n    /**\n     * Changes the key of each element on which the iterator is aggregated.  \n     * The new key is determined by the given iteratee function.\n     *\n     * Since the iterator is lazy, the reorganization process will\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const results = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .map((key, value, index) => index % 2 === 0 ? value : -value)\n     *     .reorganizeBy((key, value) => value >= 0 ? \"+\" : \"-\");\n     *\n     * console.log(results.toObject()); // { \"+\": [1, 0, 3, 6], \"-\": [-3, -2, -5, -8] }\n     * ```\n     *\n     * ---\n     *\n     * @template J The type of the new key.\n     *\n     * @param iteratee The function to determine the new key for each element of the iterator.\n     *\n     * @returns A new {@link AggregatedIterator} containing the elements reorganized by the new keys.\n     */\n    public reorganizeBy<J extends PropertyKey>(iteratee: KeyedIteratee<K, T, J>): AggregatedIterator<J, T>\n    {\n        const elements = this._elements;\n\n        return new AggregatedIterator(function* ()\n        {\n            const indexes = new Map<K, number>();\n            for (const [key, element] of elements)\n            {\n                const index = indexes.get(key) ?? 0;\n                yield [iteratee(key, element, index), element];\n\n                indexes.set(key, index + 1);\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the keys of the iterator.\n     *\n     * Since the iterator is lazy, the keys will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const keys = new SmartIterator([-3, Symbol(), \"A\", { }, null, [1 , 2, 3], false])\n     *     .groupBy((value) => typeof value)\n     *     .keys();\n     *\n     * console.log(keys.toArray()); // [\"number\", \"symbol\", \"string\", \"object\", \"boolean\"]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the keys of the iterator.\n     */\n    public keys(): SmartIterator<K>\n    {\n        const elements = this._elements;\n\n        return new SmartIterator<K>(function* ()\n        {\n            const keys = new Set<K>();\n            for (const [key] of elements)\n            {\n                if (keys.has(key)) { continue; }\n                keys.add(key);\n\n                yield key;\n            }\n        });\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the entries of the iterator.  \n     * Each entry is a tuple containing the key and the element.\n     *\n     * Since the iterator is lazy, the entries will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const entries = new SmartIterator<number>([-3, 0, 2, -1, 3])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .entries();\n     *\n     * console.log(entries.toArray()); // [[\"odd\", -3], [\"even\", 0], [\"even\", 2], [\"odd\", -1], [\"odd\", 3]]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the entries of the iterator.\n     */\n    public entries(): SmartIterator<[K, T]>\n    {\n        return this._elements;\n    }\n\n    /**\n     * An utility method that returns a new {@link SmartIterator}\n     * object containing all the values of the iterator.\n     *\n     * Since the iterator is lazy, the values will be extracted\n     * be executed once the resulting iterator is materialized.\n     *\n     * A new iterator will be created, holding the reference to the original one.  \n     * This means that the original iterator won't be consumed until the\n     * new one is and that consuming one of them will consume the other as well.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const values = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\")\n     *     .values();\n     *\n     * console.log(values.toArray()); // [-3, -1, 0, 2, 3, 5, 6, 8]\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link SmartIterator} containing all the values of the iterator.\n     */\n    public values(): SmartIterator<T>\n    {\n        const elements = this._elements;\n\n        return new SmartIterator<T>(function* ()\n        {\n            for (const [_, element] of elements) { yield element; }\n        });\n    }\n\n    /**\n     * Materializes the iterator into an array of arrays.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(aggregator.toArray()); // [[-3, -1, 3, 5], [0, 2, 6, 8]]\n     * ```\n     *\n     * ---\n     *\n     * @returns An {@link Array} of arrays containing the elements of the iterator.\n     */\n    public toArray(): T[][]\n    {\n        const map = this.toMap();\n\n        return Array.from(map.values());\n    }\n\n    /**\n     * Materializes the iterator into a map.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(aggregator.toMap()); // Map(2) { \"odd\" => [-3, -1, 3, 5], \"even\" => [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns A {@link Map} containing the elements of the iterator.\n     */\n    public toMap(): Map<K, T[]>\n    {\n        const groups = new Map<K, T[]>();\n\n        for (const [key, element] of this._elements)\n        {\n            const value = groups.get(key) ?? [];\n\n            value.push(element);\n            groups.set(key, value);\n        }\n\n        return groups;\n    }\n\n    /**\n     * Materializes the iterator into an object.  \n     * This method will consume the entire iterator in the process.\n     *\n     * If the iterator is infinite, the method will never return.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const aggregator = new SmartIterator<number>([-3, -1, 0, 2, 3, 5, 6, 8])\n     *     .groupBy((value) => value % 2 === 0 ? \"even\" : \"odd\");\n     *\n     * console.log(aggregator.toObject()); // { odd: [-3, -1, 3, 5], even: [0, 2, 6, 8] }\n     * ```\n     *\n     * ---\n     *\n     * @returns An {@link Object} containing the elements of the iterator.\n     */\n    public toObject(): Record<K, T[]>\n    {\n        const groups = { } as Record<K, T[]>;\n\n        for (const [key, element] of this._elements)\n        {\n            const value = groups[key] ?? [];\n\n            value.push(element);\n            groups[key] = value;\n        }\n\n        return groups;\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"AggregatedIterator\";\n}\n","import type { Callback } from \"./types.js\";\n\nconst SmartFunction = (Function as unknown) as new<A extends unknown[] = [], R = void>(...args: string[])\n    => (...args: A) => R;\n\n/**\n * An abstract class that can be used to implement callable objects.\n *\n * ---\n *\n * @example\n * ```ts\n * class ActivableCallback extends CallableObject<(evt: PointerEvent) => void>\n * {\n *     public enabled = false;\n *     protected _invoke(): void\n *     {\n *         if (this.enabled) { [...] }\n *     }\n * }\n *\n * const callback = new ActivableCallback();\n *\n * window.addEventListener(\"pointerdown\", () => { callback.enabled = true; });\n * window.addEventListener(\"pointermove\", callback);\n * window.addEventListener(\"pointerup\", () => { callback.enabled = false; });\n * ```\n *\n * ---\n *\n * @template T\n * The type signature of the callback function.  \n * It must be a function. Default is `(...args: any[]) => any`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default abstract class CallableObject<T extends Callback<any[], any> = () => void>\n    extends SmartFunction<Parameters<T>, ReturnType<T>>\n{\n    /**\n     * Initializes a new instance of the {@link CallableObject} class.\n     */\n    public constructor()\n    {\n        super(`return this._invoke(...arguments);`);\n\n        const self = this.bind(this);\n        Object.setPrototypeOf(this, self);\n\n        return self as this;\n    }\n\n    /**\n     * The method that will be called when the object is invoked.  \n     * It must be implemented by the derived classes.\n     *\n     * ---\n     *\n     * @param args The arguments that have been passed to the object.\n     *\n     * @returns The return value of the method.\n     */\n    protected abstract _invoke(...args: Parameters<T>): ReturnType<T>;\n\n    public readonly [Symbol.toStringTag]: string = \"CallableObject\";\n}\n","import { ReferenceException } from \"../exceptions/index.js\";\n\nimport type { Callback, CallbackMap, WithWildcard } from \"./types.js\";\n\n/**\n * A class implementing the\n * {@link https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern|Publish-subscribe} pattern.\n *\n * It can be used to create a simple event system where objects can subscribe\n * to events and receive notifications when the events are published.  \n * It's a simple and efficient way to decouple the objects and make them communicate with each other.\n *\n * Using generics, it's also possible to define the type of the events and the callbacks that can be subscribed to them.\n *\n * ---\n *\n * @example\n * ```ts\n * interface EventsMap\n * {\n *     \"player:spawn\": (evt: SpawnEvent) => void;\n *     \"player:move\": ({ x, y }: Point) => void;\n *     \"player:death\": () => void;\n * }\n *\n * const publisher = new Publisher<EventsMap>();\n *\n * let unsubscribe: () => void;\n * publisher.subscribe(\"player:death\", unsubscribe);\n * publisher.subscribe(\"player:spawn\", (evt) =>\n * {\n *     unsubscribe = publisher.subscribe(\"player:move\", ({ x, y }) => { [...] });\n * });\n * ```\n *\n * ---\n *\n * @template T\n * A map containing the names of the emittable events and the\n * related callback signatures that can be subscribed to them.  \n * Default is `Record<string, (...args: unknown[]) => unknown>`.\n *\n * @template E An utility type that extends the `T` map with a wildcard event.\n */\nexport default class Publisher<T extends CallbackMap<T> = CallbackMap, W extends WithWildcard<T> = WithWildcard<T>>\n{\n    /**\n     * A map containing all the subscribers for each event.\n     *\n     * The keys are the names of the events they are subscribed to.  \n     * The values are the arrays of the subscribers themselves.\n     */\n    protected readonly _subscribers: Map<string, Callback<unknown[], unknown>[]>;\n\n    /**\n     * Initializes a new instance of the {@link Publisher} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const publisher = new Publisher();\n     * ```\n     */\n    public constructor()\n    {\n        this._subscribers = new Map();\n    }\n\n    /**\n     * Unsubscribes all the subscribers from all the events.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * publisher.subscribe(\"player:spawn\", (evt) => { [...] });\n     * publisher.subscribe(\"player:move\", (coords) => { [...] });\n     * publisher.subscribe(\"player:move\", () => { [...] });\n     * publisher.subscribe(\"player:move\", ({ x, y }) => { [...] });\n     * publisher.subscribe(\"player:death\", () => { [...] });\n     *\n     * // All these subscribers are working fine...\n     *\n     * publisher.clear();\n     *\n     * // ... but now they're all gone!\n     * ```\n     */\n    public clear(): void\n    {\n        // @ts-expect-error It's an internal event, not part of the public API.\n        this.publish(\"__internals__:clear\");\n\n        this._subscribers.clear();\n    }\n\n    /**\n     * Creates a new scoped instance of the {@link Publisher} class,\n     * which can be used to publish and subscribe events within a specific context.\n     *\n     * It can receive all events published to the parent publisher while also allowing\n     * the scoped publisher to handle its own events independently.  \n     * In fact, events published to the scoped publisher won't be propagated back to the parent publisher.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const publisher = new Publisher();\n     * const context = publisher.createScope();\n     *\n     * publisher.subscribe(\"player:death\", () => { console.log(`Player has died.`); });\n     * context.subscribe(\"player:spawn\", () => { console.log(`Player has spawned.`); });\n     *\n     * publisher.publish(\"player:spawn\"); // Player has spawned.\n     * context.publish(\"player:death\"); // * no output *\n     * ```\n     *\n     * ---\n     *\n     * @template U\n     * A map containing the names of the emittable events and the\n     * related callback signatures that can be subscribed to them.\n     * Default is `T`.\n     *\n     * @template X An utility type that extends the `U` map with a wildcard event.\n     *\n     * @return\n     * A new instance of the {@link Publisher} class that can be\n     * used to publish and subscribe events within a specific context.\n     */\n    public createScope<U extends T = T, X extends WithWildcard<U> = WithWildcard<U>>(): Publisher<U, X>\n    {\n        const scope = new Publisher<U, X>();\n\n        const propagator = (event: (keyof T) & string, ...args: Parameters<T[keyof T]>): void =>\n        {\n            scope.publish(event, ...args);\n        };\n\n        // @ts-expect-error It's an internal event, not part of the public API.\n        this.subscribe(\"__internals__:clear\", () => scope.clear());\n        this.subscribe(\"*\", propagator as W[\"*\"]);\n\n        return scope;\n    }\n\n    /**\n     * Publishes an event to all the subscribers.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * publisher.subscribe(\"player:move\", (coords) => { [...] });\n     * publisher.subscribe(\"player:move\", ({ x, y }) => { [...] });\n     * publisher.subscribe(\"player:move\", (evt) => { [...] });\n     *\n     * publisher.publish(\"player:move\", { x: 10, y: 20 });\n     * ```\n     *\n     * ---\n     *\n     * @template K The key of the map containing the callback signature to publish.\n     *\n     * @param event The name of the event to publish.\n     * @param args The arguments to pass to the subscribers.\n     *\n     * @returns An array containing the return values of all the subscribers.\n     */\n    public publish<K extends keyof T>(event: K & string, ...args: Parameters<T[K]>): ReturnType<T[K]>[]\n    {\n        let results: ReturnType<T[K]>[];\n        let subscribers = this._subscribers.get(event);\n        if (subscribers)\n        {\n            results = subscribers.slice()\n                .map((subscriber) => subscriber(...args)) as ReturnType<T[K]>[];\n        }\n        else { results = []; }\n\n        if (!(event.startsWith(\"__\")))\n        {\n            subscribers = this._subscribers.get(\"*\");\n            if (subscribers)\n            {\n                subscribers.slice()\n                    .forEach((subscriber) => subscriber(event, ...args));\n            }\n        }\n\n        return results;\n    }\n\n    /**\n     * Subscribes to an event and adds a subscriber to be executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * let unsubscribe: () => void;\n     * publisher.subscribe(\"player:death\", unsubscribe);\n     * publisher.subscribe(\"player:spawn\", (evt) =>\n     * {\n     *     unsubscribe = publisher.subscribe(\"player:move\", ({ x, y }) => { [...] });\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @template K The key of the map containing the callback signature to subscribe.\n     *\n     * @param event The name of the event to subscribe to.\n     * @param subscriber The subscriber to execute when the event is published.\n     *\n     * @returns A function that can be used to unsubscribe the subscriber from the event.\n     */\n    public subscribe<K extends keyof W>(event: K & string, subscriber: W[K]): () => void\n    {\n        const subscribers = this._subscribers.get(event) ?? [];\n        subscribers.push(subscriber);\n\n        this._subscribers.set(event, subscribers);\n\n        return () =>\n        {\n            const index = subscribers.indexOf(subscriber);\n            if (index < 0)\n            {\n                throw new ReferenceException(\"Unable to unsubscribe the required subscriber. \" +\n                    \"The subscription was already unsubscribed.\");\n            }\n\n            subscribers.splice(index, 1);\n        };\n    }\n\n    /**\n     * Unsubscribes from an event and removes a subscriber from being executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const onPlayerMove = ({ x, y }: Point) => { [...] };\n     *\n     * publisher.subscribe(\"player:spawn\", (evt) => publisher.subscribe(\"player:move\", onPlayerMove));\n     * publisher.subscribe(\"player:death\", () => publisher.unsubscribe(\"player:move\", onPlayerMove));\n     * ```\n     *\n     * ---\n     *\n     * @template K The key of the map containing the callback signature to unsubscribe.\n     *\n     * @param event The name of the event to unsubscribe from.\n     * @param subscriber The subscriber to remove from the event.\n     */\n    public unsubscribe<K extends keyof W>(event: K & string, subscriber: W[K]): void\n    {\n        const subscribers = this._subscribers.get(event);\n        if (!(subscribers))\n        {\n            throw new ReferenceException(\"Unable to unsubscribe the required subscriber. \" +\n                \"The subscription was already unsubscribed or was never subscribed.\");\n        }\n\n        const index = subscribers.indexOf(subscriber);\n        if (index < 0)\n        {\n            throw new ReferenceException(\"Unable to unsubscribe the required subscriber. \" +\n                \"The subscription was already unsubscribed or was never subscribed.\");\n        }\n\n        subscribers.splice(index, 1);\n        if (subscribers.length === 0) { this._subscribers.delete(event); }\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"Publisher\";\n}\n","import { KeyException, NotImplementedException, RuntimeException } from \"../exceptions/index.js\";\n\nimport CallableObject from \"./callable-object.js\";\nimport type { Callback } from \"./types.js\";\n\nconst Disabler = () => { /* ... */ };\n\n/**\n * A class representing a callback that can be switched between multiple implementations.\n *\n * It can be used to implement different behaviors for the same event handler, allowing\n * it to respond to different states without incurring any overhead during execution.\n *\n * ---\n *\n * @example\n * ```ts\n * const onPointerMove = new SwitchableCallback<(evt: PointerEvent) => void>();\n *\n * onPointerMove.register(\"released\", () => { [...] });\n * onPointerMove.register(\"pressed\", () => { [...] });\n *\n * window.addEventListener(\"pointerdown\", () => { onPointerMove.switch(\"pressed\"); });\n * window.addEventListener(\"pointermove\", onPointerMove);\n * window.addEventListener(\"pointerup\", () => { onPointerMove.switch(\"released\"); });\n * ```\n *\n * ---\n *\n * @template T The type signature of the callback. Default is `(...args: any[]) => any`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default class SwitchableCallback<T extends Callback<any[], any> = Callback> extends CallableObject<T>\n{\n    /**\n     * The currently selected implementation of the callback.\n     */\n    protected _callback: T;\n\n    /**\n     * All the implementations that have been registered for the callback.\n     *\n     * The keys are the names of the implementations they were registered with.  \n     * The values are the implementations themselves.\n     */\n    protected readonly _callbacks: Map<string, T>;\n\n    /**\n     * A flag indicating whether the callback is enabled or not.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use\n     * the {@link SwitchableCallback.isEnabled} getter instead.\n     */\n    protected _isEnabled: boolean;\n\n    /**\n     * A flag indicating whether the callback is enabled or not.\n     *\n     * It indicates whether the callback is currently able to execute the currently selected implementation.  \n     * If it's disabled, the callback will be invoked without executing anything.\n     */\n    public get isEnabled(): boolean { return this._isEnabled; }\n\n    /**\n     * The key that is associated with the currently selected implementation.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link SwitchableCallback.key} getter instead.\n     */\n    protected _key: string;\n\n    /**\n     * The key that is associated with the currently selected implementation.\n     */\n    public get key(): string { return this._key; }\n\n    /**\n     * The function that will be called by the extended class when the object is invoked as a function.\n     */\n    protected readonly _invoke: (...args: Parameters<T>) => ReturnType<T>;\n\n    /**\n     * Initializes a new instance of the {@link SwitchableCallback} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const onPointerMove = new SwitchableCallback<(evt: PointerEvent) => void>();\n     * ```\n     */\n    public constructor();\n\n    /**\n     * Initializes a new instance of the {@link SwitchableCallback}\n     * class with the specified callback enabled by default.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const onPointerMove = new SwitchableCallback<(evt: PointerEvent) => void>((evt) => { [...] });\n     * ```\n     *\n     * ---\n     *\n     * @param callback The callback that will be executed when the object is invoked as a function by default.\n     * @param key The key that is associated by default to the given callback. Default is `default`.\n     */\n    public constructor(callback: T, key?: string);\n    public constructor(callback?: T, key = \"default\")\n    {\n        super();\n\n        this._callbacks = new Map<string, T>();\n        this._isEnabled = true;\n\n        if (callback)\n        {\n            this._callbacks.set(key, callback);\n        }\n        else\n        {\n            key = \"\";\n\n            callback = ((() =>\n            {\n                throw new NotImplementedException(\n                    \"The `SwitchableCallback` has no callback defined yet. \" +\n                    \"Did you forget to call the `register` method?\"\n                );\n\n            }) as unknown) as T;\n        }\n\n        this._key = key;\n\n        this._callback = callback;\n        this._invoke = (...args: Parameters<T>): ReturnType<T> => this._callback(...args);\n    }\n\n    /**\n     * Enables the callback, allowing it to execute the currently selected implementation.\n     *\n     * Also note that:\n     * - If any implementation has been registered yet, a {@link KeyException} will be thrown.  \n     * - If any key is given and it doesn't have any associated\n     * implementation yet, a {@link KeyException} will be thrown.\n     * - If the callback is already enabled, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * window.addEventListener(\"pointerdown\", () => { onPointerMove.enable(); });\n     * window.addEventListener(\"pointermove\", onPointerMove);\n     * ```\n     *\n     * ---\n     *\n     * @param key\n     * The key that is associated with the implementation to enable. Default is the currently selected implementation.\n     */\n    public enable(key?: string): void\n    {\n        if (key === undefined)\n        {\n            if (!(this._key))\n            {\n                throw new KeyException(\n                    \"The `SwitchableCallback` has no callback defined yet. \" +\n                    \"Did you forget to call the `register` method?\"\n                );\n            }\n\n            key = this._key;\n        }\n        else if (!(key))\n        {\n            throw new KeyException(\"The key must be a non-empty string.\");\n        }\n        else if (!(this._callbacks.has(key)))\n        {\n            throw new KeyException(`The key '${key}' doesn't yet have any associated callback.`);\n        }\n\n        if (this._isEnabled)\n        {\n            throw new RuntimeException(\"The `SwitchableCallback` is already enabled.\");\n        }\n\n        this._callback = this._callbacks.get(key)!;\n        this._isEnabled = true;\n    }\n\n    /**\n     * Disables the callback, allowing it to be invoked without executing any implementation.\n     *\n     * If the callback is already disabled, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * window.addEventListener(\"pointermove\", onPointerMove);\n     * window.addEventListener(\"pointerup\", () => { onPointerMove.disable(); });\n     * ```\n     */\n    public disable(): void\n    {\n        if (!(this._isEnabled))\n        {\n            throw new RuntimeException(\"The `SwitchableCallback` is already disabled.\");\n        }\n\n        this._callback = Disabler as T;\n        this._isEnabled = false;\n    }\n\n    /**\n     * Registers a new implementation for the callback.\n     *\n     * Also note that:\n     * - If the callback has no other implementation registered yet, this one will be selected as default.\n     * - If the key has already been used for another implementation, a {@link KeyException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * onPointerMove.register(\"pressed\", () => { [...] });\n     * onPointerMove.register(\"released\", () => { [...] });\n     * ```\n     *\n     * ---\n     *\n     * @param key The key that will be associated with the implementation.\n     * @param callback The implementation to register.\n     */\n    public register(key: string, callback: T): void\n    {\n        if (this._callbacks.size === 0)\n        {\n            this._key = key;\n            this._callback = callback;\n        }\n        else if (this._callbacks.has(key))\n        {\n            throw new KeyException(`The key '${key}' has already been used for another callback.`);\n        }\n\n        this._callbacks.set(key, callback);\n    }\n\n    /**\n     * Unregisters an implementation for the callback.\n     *\n     * Also note that:\n     * - If the key is the currently selected implementation, a {@link KeyException} will be thrown.\n     * - If the key has no associated implementation yet, a {@link KeyException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * onPointerMove.unregister(\"released\");\n     * ```\n     *\n     * ---\n     *\n     * @param key The key that is associated with the implementation to unregister.\n     */\n    public unregister(key: string): void\n    {\n        if (this._key === key)\n        {\n            throw new KeyException(\"Unable to unregister the currently selected callback.\");\n        }\n        if (!(this._callbacks.has(key)))\n        {\n            throw new KeyException(`The key '${key}' doesn't yet have any associated callback.`);\n        }\n\n        this._callbacks.delete(key);\n    }\n\n    /**\n     * Switches the callback to the implementation associated with the given key.\n     *\n     * If the key has no associated implementation yet, a {@link KeyException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * window.addEventListener(\"pointerdown\", () => { onPointerMove.switch(\"pressed\"); });\n     * window.addEventListener(\"pointermove\", onPointerMove);\n     * window.addEventListener(\"pointerup\", () => { onPointerMove.switch(\"released\"); });\n     * ```\n     *\n     * ---\n     *\n     * @param key The key that is associated with the implementation to switch to.\n     */\n    public switch(key: string): void\n    {\n        if (!(this._callbacks.has(key)))\n        {\n            throw new KeyException(`The key '${key}' doesn't yet have any associated callback.`);\n        }\n\n        if (this._key === key) { return; }\n        this._key = key;\n\n        if (this._isEnabled)\n        {\n            this._callback = this._callbacks.get(key)!;\n        }\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"SwitchableCallback\";\n}\n","import Publisher from \"../callbacks/publisher.js\";\nimport type { WithWildcard } from \"../callbacks/types.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type SetView from \"./set-view.js\";\nimport type { MapViewEventsMap } from \"./types.js\";\n\n/**\n * A wrapper class around the native {@link Map} class that provides additional functionality\n * for publishing events when entries are added, removed or the collection is cleared.  \n * There's also a complementary class that works with the native `Set` class.\n * See also {@link SetView}.\n *\n * ---\n *\n * @example\n * ```ts\n * const map = new MapView<string, number>();\n *\n * map.subscribe(\"entry:add\", (key: string, value: number) => console.log(`Added ${key}: ${value}`));\n * map.set(\"answer\", 42); // Added answer: 42\n * ```\n *\n * ---\n *\n * @template K The type of the keys in the map.\n * @template V The type of the values in the map.\n */\nexport default class MapView<K, V> extends Map<K, V>\n{\n    /**\n     * The internal {@link Publisher} instance used to publish events.\n     */\n    protected readonly _publisher: Publisher<MapViewEventsMap<K, V>>;\n\n    /**\n     * Initializes a new instance of the {@link MapView} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const map = new MapView<string, number>([[\"key1\", 2], [\"key2\", 4], [\"key3\", 8]]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable An optional iterable of key-value pairs to initialize the {@link Map} with.\n     */\n    public constructor(iterable?: Iterable<[K, V]> | null)\n    {\n        super();\n\n        this._publisher = new Publisher();\n\n        if (iterable)\n        {\n            for (const [key, value] of iterable) { this.set(key, value); }\n        }\n    }\n\n    /**\n     * Adds a new entry with a specified key and value to the {@link Map}.  \n     * If an entry with the same key already exists, the entry will be overwritten with the new value.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const map = new MapView<string, number>();\n     * map.set(\"key1\", 2)\n     *     .set(\"key2\", 4)\n     *     .set(\"key3\", 8);\n     *\n     * console.log(map); // MapView { \"key1\" => 2, \"key2\" => 4, \"key3\" => 8 }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the entry to add.\n     * @param value The value of the entry to add.\n     *\n     * @returns The current instance of the {@link MapView} class.\n     */\n    public override set(key: K, value: V): this\n    {\n        super.set(key, value);\n\n        this._publisher.publish(\"entry:add\", key, value);\n\n        return this;\n    }\n\n    /**\n     * Removes an entry with a specified key from the {@link Map}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const map = new MapView<string, number>([[\"key1\", 2], [\"key2\", 4], [\"key3\", 8]]);\n     * map.delete(\"key2\"); // true\n     * map.delete(\"key4\"); // false\n     *\n     * console.log(map); // MapView { \"key1\" => 2, \"key3\" => 8 }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the entry to remove.\n     *\n     * @returns `true` if the entry existed and has been removed; otherwise `false` if the entry doesn't exist.\n     */\n    public override delete(key: K): boolean\n    {\n        const value = this.get(key);\n        if (value === undefined) { return false; }\n\n        super.delete(key);\n\n        this._publisher.publish(\"entry:remove\", key, value);\n\n        return true;\n    }\n\n    /**\n     * Removes all entries from the {@link Map}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const map = new MapView<string, number>([[\"key1\", 2], [\"key2\", 4], [\"key3\", 8]]);\n     * map.clear();\n     *\n     * console.log(map); // MapView { }\n     * ```\n     */\n    public override clear(): void\n    {\n        const size = this.size;\n\n        super.clear();\n        if (size > 0) { this._publisher.publish(\"collection:clear\"); }\n    }\n\n    /**\n     * Subscribes to an event and adds a callback to be executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const map = new MapView<string, number>();\n     * const unsubscribe = map.subscribe(\"entry:add\", (key: string, value: number) =>\n     * {\n     *     if (key === \"answer\") { unsubscribe(); }\n     *     console.log(`Added ${key}: ${value}`);\n     * });\n     *\n     * map.set(\"key1\", 2); // Added key1: 2\n     * map.set(\"answer\", 42); // Added answer: 42\n     * map.set(\"key2\", 4);\n     * map.set(\"key3\", 8);\n     * ```\n     *\n     * ---\n     *\n     * @template T The key of the map containing the callback signature to subscribe.\n     *\n     * @param event The name of the event to subscribe to.\n     * @param callback The callback to execute when the event is published.\n     *\n     * @returns A function that can be used to unsubscribe the callback from the event.\n     */\n    public subscribe<T extends keyof WithWildcard<MapViewEventsMap<K, V>>>(\n        event: T & string, callback: WithWildcard<MapViewEventsMap<K, V>>[T]\n    ): () => void\n    {\n        return this._publisher.subscribe(event, callback);\n    }\n\n    /**\n     * Unsubscribes from an event and removes a callback from being executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const callback = (key: string, value: number) => console.log(`Added ${key}: ${value}`);\n     * const map = new MapView<string, number>();\n     *\n     * map.subscribe(\"entry:add\", callback);\n     * map.set(\"key1\", 2); // Added key1: 2\n     *\n     * map.unsubscribe(\"entry:add\", callback);\n     * map.set(\"key2\", 4);\n     * ```\n     *\n     * ---\n     *\n     * @template T The key of the map containing the callback signature to unsubscribe.\n     *\n     * @param event The name of the event to unsubscribe from.\n     * @param callback The callback to remove from the event.\n     */\n    public unsubscribe<T extends keyof WithWildcard<MapViewEventsMap<K, V>>>(\n        event: T & string, callback: WithWildcard<MapViewEventsMap<K, V>>[T]): void\n    {\n        this._publisher.unsubscribe(event, callback);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"MapView\";\n}\n","import Publisher from \"../callbacks/publisher.js\";\nimport type { WithWildcard } from \"../callbacks/types.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type MapView from \"./map-view.js\";\nimport type { SetViewEventsMap } from \"./types.js\";\n\n/**\n * A wrapper class around the native {@link Set} class that provides additional functionality\n * for publishing events when entries are added, removed or the collection is cleared.  \n * There's also a complementary class that works with the native `Map` class.\n * See also {@link MapView}.\n *\n * ---\n *\n * @example\n * ```ts\n * const set = new SetView<number>();\n *\n * set.subscribe(\"entry:add\", (value: number) => console.log(`Added ${value}`));\n * set.add(42); // Added 42\n * ```\n *\n * ---\n *\n * @template T The type of the values in the set.\n */\nexport default class SetView<T> extends Set<T>\n{\n    /**\n     * The internal {@link Publisher} instance used to publish events.\n     */\n    protected readonly _publisher: Publisher<SetViewEventsMap<T>>;\n\n    /**\n     * Initializes a new instance of the {@link SetView} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const set = new SetView<number>([2, 4, 8]);\n     * ```\n     *\n     * ---\n     *\n     * @param iterable An optional iterable of values to initialize the {@link Set} with.\n     */\n    public constructor(iterable?: Iterable<T> | null)\n    {\n        super();\n\n        this._publisher = new Publisher();\n\n        if (iterable)\n        {\n            for (const value of iterable) { this.add(value); }\n        }\n    }\n\n    /**\n     * Appends a new element with a specified value to the end of the {@link Set}.  \n     * If the value already exists, it will not be added again.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const set = new SetView<number>();\n     * set.add(2)\n     *     .add(4)\n     *     .add(8);\n     *\n     * console.log(set); // SetView(4) { 2, 4, 8 }\n     * ```\n     *\n     * ---\n     *\n     * @param value The value to add.\n     *\n     * @returns The current instance of the {@link SetView} class.\n     */\n    public override add(value: T): this\n    {\n        super.add(value);\n\n        this._publisher.publish(\"entry:add\", value);\n\n        return this;\n    }\n\n    /**\n     * Removes the specified value from the {@link Set}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const set = new SetView<number>([2, 4, 8]);\n     * set.delete(4); // true\n     * set.delete(16); // false\n     *\n     * console.log(set); // SetView(2) { 2, 8 }\n     * ```\n     *\n     * ---\n     *\n     * @param value The value to remove.\n     *\n     * @returns `true` if the entry existed and has been removed; otherwise `false` if the entry doesn't exist.\n     */\n    public override delete(value: T): boolean\n    {\n        const result = super.delete(value);\n        if (result) { this._publisher.publish(\"entry:remove\", value); }\n\n        return result;\n    }\n\n    /**\n     * Removes all entries from the {@link Set}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const set = new SetView<number>([2, 4, 8]);\n     * set.clear();\n     *\n     * console.log(set); // SetView(0) { }\n     * ```\n     */\n    public override clear(): void\n    {\n        const size = this.size;\n\n        super.clear();\n        if (size > 0) { this._publisher.publish(\"collection:clear\"); }\n    }\n\n    /**\n     * Subscribes to an event and adds a callback to be executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const set = new SetView<number>();\n     * const unsubscribe = set.subscribe(\"entry:add\", (value: number) =>\n     * {\n     *     if (value === 42) { unsubscribe(); }\n     *     console.log(`Added ${value}`);\n     * });\n     *\n     * set.add(2); // Added 2\n     * set.add(42); // Added 42\n     * set.add(4);\n     * set.add(8);\n     * ```\n     *\n     * ---\n     *\n     * @template K The key of the map containing the callback signature to subscribe.\n     *\n     * @param event The name of the event to subscribe to.\n     * @param callback The callback to execute when the event is published.\n     *\n     * @returns A function that can be used to unsubscribe the callback from the event.\n     */\n    public subscribe<K extends keyof WithWildcard<SetViewEventsMap<T>>>(\n        event: K & string, callback: WithWildcard<SetViewEventsMap<T>>[K]\n    ): () => void\n    {\n        return this._publisher.subscribe(event, callback);\n    }\n\n    /**\n     * Unsubscribes from an event and removes a callback from being executed when the event is published.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const callback = (value: number) => console.log(`Added ${value}`);\n     * const set = new SetView<number>();\n     *\n     * set.subscribe(\"entry:add\", callback);\n     * set.add(2); // Added 2\n     *\n     * set.unsubscribe(\"entry:add\", callback);\n     * set.add(4);\n     * ```\n     *\n     * ---\n     *\n     * @template K The key of the map containing the callback signature to unsubscribe.\n     *\n     * @param event The name of the event to unsubscribe from.\n     * @param callback The callback to remove from the event.\n     */\n    public unsubscribe<K extends keyof WithWildcard<SetViewEventsMap<T>>>(\n        event: K & string, callback: WithWildcard<SetViewEventsMap<T>>[K]\n    ): void\n    {\n        this._publisher.unsubscribe(event, callback);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"SetView\";\n}\n","import { isBrowser } from \"../../helpers.js\";\nimport { EnvironmentException } from \"../exceptions/index.js\";\n\nimport type { JSONValue } from \"./types.js\";\n\n/**\n * A wrapper around the {@link Storage} API to better store and easily retrieve\n * typed JSON values using the classical key-value pair storage system.\n *\n * It allows to handle either the volatile {@link sessionStorage} or the persistent\n * {@link localStorage} at the same time, depending on what's your required use case.\n *\n * ---\n *\n * @example\n * ```ts\n * const jsonStorage = new JSONStorage();\n *\n * jsonStorage.write(\"user:cookieAck\", { value: true, version: \"2023-02-15\" });\n * // ... between sessions ...\n * const cookieAck = jsonStorage.read<{ value: boolean; version: string; }>(\"user:cookieAck\");\n * ```\n */\nexport default class JSONStorage\n{\n    /**\n     * Whether to prefer the {@link localStorage} over the {@link sessionStorage} when calling an ambivalent method.\n     *\n     * If `true`, the persistent storage is preferred. If `false`, the volatile storage is preferred.  \n     * Default is `true`.\n     */\n    protected readonly _preferPersistence: boolean;\n\n    /**\n     * A reference to the volatile {@link sessionStorage} storage.\n     */\n    protected readonly _volatile: Storage;\n\n    /**\n     * A reference to the persistent {@link localStorage} storage.\n     */\n    protected readonly _persistent: Storage;\n\n    /**\n     * Initializes a new instance of the {@link JSONStorage} class.  \n     * It cannot be instantiated outside of a browser environment or an {@link EnvironmentException} is thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const jsonStorage = new JSONStorage();\n     * ```\n     *\n     * ---\n     *\n     * @param preferPersistence\n     * Whether to prefer the {@link localStorage} over the {@link sessionStorage} when calling an ambivalent method.  \n     * If omitted, it defaults to `true` to prefer the persistent storage.\n     */\n    public constructor(preferPersistence = true)\n    {\n        if (!(isBrowser))\n        {\n            throw new EnvironmentException(\n                \"The `JSONStorage` class can only be instantiated within a browser environment.\"\n            );\n        }\n\n        this._preferPersistence = preferPersistence;\n\n        this._volatile = window.sessionStorage;\n        this._persistent = window.localStorage;\n    }\n\n    protected _get<T extends JSONValue>(storage: Storage, key: string): T | undefined;\n    protected _get<T extends JSONValue>(storage: Storage, key: string, defaultValue: T): T;\n    protected _get<T extends JSONValue>(storage: Storage, key: string, defaultValue?: T): T | undefined;\n    protected _get<T extends JSONValue>(storage: Storage, key: string, defaultValue?: T): T | undefined\n    {\n        const value = storage.getItem(key);\n        if (value)\n        {\n            try\n            {\n                return JSON.parse(value);\n            }\n            catch\n            {\n                // eslint-disable-next-line no-console\n                console.warn(\n                    `The \"${value}\" value for \"${key}\"` +\n                    \" property cannot be parsed. Clearing the storage...\");\n\n                storage.removeItem(key);\n            }\n        }\n\n        return defaultValue;\n    }\n    protected _set<T extends JSONValue>(storage: Storage, key: string, newValue?: T): void\n    {\n        const encodedValue = JSON.stringify(newValue);\n        if (encodedValue)\n        {\n            storage.setItem(key, encodedValue);\n        }\n        else\n        {\n            storage.removeItem(key);\n        }\n    }\n\n    /**\n     * Retrieves the value with the specified key from the default storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.get<TValue>(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     *\n     * @returns The value with the specified key or `undefined` if the key doesn't exist.\n     */\n    public get<T extends JSONValue>(key: string): T | undefined;\n\n    /**\n     * Retrieves the value with the specified key from the default storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.get<TValue>(\"key\", defaultValue);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return if the key doesn't exist.\n     * @param persistent\n     * Whether to prefer the persistent {@link localStorage} over the volatile {@link sessionStorage}.  \n     * If omitted, it defaults to the `preferPersistence` value set in the constructor.\n     *\n     * @returns The value with the specified key or the provided default value if the key doesn't exist.\n     */\n    public get<T extends JSONValue>(key: string, defaultValue: T, persistent?: boolean): T;\n\n    /**\n     * Retrieves the value with the specified key from the default storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.get<TValue>(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return (which may be `undefined`) if the key doesn't exist.\n     * @param persistent\n     * Whether to prefer the persistent {@link localStorage} over the volatile {@link sessionStorage}.  \n     * If omitted, it defaults to the `preferPersistence` value set in the constructor.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public get<T extends JSONValue>(key: string, defaultValue?: T, persistent?: boolean): T | undefined;\n    public get<T extends JSONValue>(key: string, defaultValue?: T, persistent = this._preferPersistence)\n        : T | undefined\n    {\n        const storage = persistent ? this._persistent : this._volatile;\n\n        return this._get<T>(storage, key, defaultValue);\n    }\n\n    /**\n     * Retrieves the value with the specified key from the volatile {@link sessionStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.recall<TValue>(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     *\n     * @returns The value with the specified key or `undefined` if the key doesn't exist.\n     */\n    public recall<T extends JSONValue>(key: string): T | undefined;\n\n    /**\n     * Retrieves the value with the specified key from the volatile {@link sessionStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.recall<TValue>(\"key\", defaultValue);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public recall<T extends JSONValue>(key: string, defaultValue: T): T;\n\n    /**\n     * Retrieves the value with the specified key from the volatile {@link sessionStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.recall<TValue>(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return (which may be `undefined`) if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public recall<T extends JSONValue>(key: string, defaultValue?: T): T | undefined;\n    public recall<T extends JSONValue>(key: string, defaultValue?: T): T | undefined\n    {\n        return this._get<T>(this._volatile, key, defaultValue);\n    }\n\n    /**\n     * Retrieves the value with the specified key looking first in the volatile\n     * {@link sessionStorage} and then, if not found, in the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.retrieve<TValue>(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     *\n     * @returns The value with the specified key or `undefined` if the key doesn't exist.\n     */\n    public retrieve<T extends JSONValue>(key: string): T | undefined;\n\n    /**\n     * Retrieves the value with the specified key looking first in the volatile\n     * {@link sessionStorage} and then, if not found, in the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.retrieve<TValue>(\"key\", defaultValue);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public retrieve<T extends JSONValue>(key: string, defaultValue: T): T;\n\n    /**\n     * Retrieves the value with the specified key looking first in the volatile\n     * {@link sessionStorage} and then, if not found, in the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.retrieve<TValue>(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return (which may be `undefined`) if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public retrieve<T extends JSONValue>(key: string, defaultValue?: T): T | undefined;\n    public retrieve<T extends JSONValue>(key: string, defaultValue?: T): T | undefined\n    {\n        return this.recall<T>(key) ?? this.read<T>(key, defaultValue);\n    }\n\n    /**\n     * Retrieves the value with the specified key from the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.read<TValue>(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     *\n     * @returns The value with the specified key or `undefined` if the key doesn't exist.\n     */\n    public read<T extends JSONValue>(key: string): T | undefined;\n\n    /**\n     * Retrieves the value with the specified key from the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.read<TValue>(\"key\", defaultValue);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public read<T extends JSONValue>(key: string, defaultValue: T): T;\n\n    /**\n     * Retrieves the value with the specified key from the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const value: TValue = jsonStorage.read<TValue>(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to retrieve.\n     *\n     * @param key The key of the value to retrieve.\n     * @param defaultValue The default value to return (which may be `undefined`) if the key doesn't exist.\n     *\n     * @returns The value with the specified key or the default value if the key doesn't exist.\n     */\n    public read<T extends JSONValue>(key: string, defaultValue?: T): T | undefined;\n    public read<T extends JSONValue>(key: string, defaultValue?: T): T | undefined\n    {\n        return this._get<T>(this._persistent, key, defaultValue);\n    }\n\n    /**\n     * Checks whether the value with the specified key exists within the default storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * if (jsonStorage.has(\"key\"))\n     * {\n     *    // The key exists. Do something...\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to check.\n     * @param persistent\n     * Whether to prefer the persistent {@link localStorage} over the volatile {@link sessionStorage}.  \n     * If omitted, it defaults to the `preferPersistence` value set in the constructor.\n     *\n     * @returns `true` if the key exists, `false` otherwise.\n     */\n    public has(key: string, persistent?: boolean): boolean\n    {\n        const storage = persistent ? this._persistent : this._volatile;\n\n        return storage.getItem(key) !== null;\n    }\n\n    /**\n     * Checks whether the value with the specified key exists within the volatile {@link sessionStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * if (jsonStorage.knows(\"key\"))\n     * {\n     *    // The key exists. Do something...\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to check.\n     *\n     * @returns `true` if the key exists, `false` otherwise.\n     */\n    public knows(key: string): boolean\n    {\n        return this._volatile.getItem(key) !== null;\n    }\n\n    /**\n     * Checks whether the value with the specified key exists looking first in the\n     * volatile {@link sessionStorage} and then, if not found, in the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * if (jsonStorage.find(\"key\"))\n     * {\n     *    // The key exists. Do something...\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to check.\n     *\n     * @returns `true` if the key exists, `false` otherwise.\n     */\n    public find(key: string): boolean\n    {\n        return this.knows(key) ?? this.exists(key);\n    }\n\n    /**\n     * Checks whether the value with the specified key exists within the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * if (jsonStorage.exists(\"key\"))\n     * {\n     *    // The key exists. Do something...\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to check.\n     *\n     * @returns `true` if the key exists, `false` otherwise.\n     */\n    public exists(key: string): boolean\n    {\n        return this._persistent.getItem(key) !== null;\n    }\n\n    /**\n     * Sets the value with the specified key in the default storage.  \n     * If the value is `undefined` or omitted, the key is removed from the storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.set(\"key\");\n     * jsonStorage.set(\"key\", value);\n     * jsonStorage.set(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to set.\n     *\n     * @param key The key of the value to set.\n     * @param newValue The new value to set. If it's `undefined` or omitted, the key is removed instead.\n     * @param persistent\n     * Whether to prefer the persistent {@link localStorage} over the volatile {@link sessionStorage}.  \n     * If omitted, it defaults to the `preferPersistence` value set in the constructor.\n     */\n    public set<T extends JSONValue>(key: string, newValue?: T, persistent = this._preferPersistence): void\n    {\n        const storage = persistent ? this._persistent : this._volatile;\n\n        this._set<T>(storage, key, newValue);\n    }\n\n    /**\n     * Sets the value with the specified key in the volatile {@link sessionStorage}.  \n     * If the value is `undefined` or omitted, the key is removed from the storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.remember(\"key\");\n     * jsonStorage.remember(\"key\", value);\n     * jsonStorage.remember(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to set.\n     *\n     * @param key The key of the value to set.\n     * @param newValue The new value to set. If it's `undefined` or omitted, the key is removed instead.\n     */\n    public remember<T extends JSONValue>(key: string, newValue?: T): void\n    {\n        this._set<T>(this._volatile, key, newValue);\n    }\n\n    /**\n     * Sets the value with the specified key in the persistent {@link localStorage}.  \n     * If the value is `undefined` or omitted, the key is removed from the storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.write(\"key\");\n     * jsonStorage.write(\"key\", value);\n     * jsonStorage.write(\"key\", obj?.value);\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of the value to set.\n     *\n     * @param key The key of the value to set.\n     * @param newValue The new value to set. If it's `undefined` or omitted, the key is removed instead.\n     */\n    public write<T extends JSONValue>(key: string, newValue?: T): void\n    {\n        this._set<T>(this._persistent, key, newValue);\n    }\n\n    /**\n     * Removes the value with the specified key from the default storage.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.delete(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to remove.\n     * @param persistent\n     * Whether to prefer the persistent {@link localStorage} over the volatile {@link sessionStorage}.  \n     * If omitted, it defaults to the `preferPersistence` value set in the constructor.\n     */\n    public delete(key: string, persistent?: boolean): void\n    {\n        const storage = persistent ? this._persistent : this._volatile;\n\n        storage.removeItem(key);\n    }\n\n    /**\n     * Removes the value with the specified key from the volatile {@link sessionStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.forget(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to remove.\n     */\n    public forget(key: string): void\n    {\n        this._volatile.removeItem(key);\n    }\n\n    /**\n     * Removes the value with the specified key from the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.erase(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to remove.\n     */\n    public erase(key: string): void\n    {\n        this._persistent.removeItem(key);\n    }\n\n    /**\n     * Removes the value with the specified key from both the\n     * volatile {@link sessionStorage} and the persistent {@link localStorage}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * jsonStorage.clear(\"key\");\n     * ```\n     *\n     * ---\n     *\n     * @param key The key of the value to remove.\n     */\n    public clear(key: string): void\n    {\n        this._volatile.removeItem(key);\n        this._persistent.removeItem(key);\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"JSONStorage\";\n}\n","import type { FulfilledHandler, PromiseExecutor, RejectedHandler } from \"./types.js\";\n\n/**\n * A wrapper class representing an enhanced version of the native {@link Promise} object.\n *\n * It provides additional properties to check the state of the promise itself.  \n * The state can be either `pending`, `fulfilled` or `rejected` and is accessible through\n * the {@link SmartPromise.isPending}, {@link SmartPromise.isFulfilled} & {@link SmartPromise.isRejected} properties.\n *\n * ---\n *\n * @example\n * ```ts\n * const promise = new SmartPromise<string>((resolve, reject) =>\n * {\n *     setTimeout(() => resolve(\"Hello, World!\"), 1_000);\n * });\n *\n * console.log(promise.isPending); // true\n * console.log(promise.isFulfilled); // false\n *\n * console.log(await promise); // \"Hello, World!\"\n *\n * console.log(promise.isPending); // false\n * console.log(promise.isFulfilled); // true\n * ```\n *\n * ---\n *\n * @template T The type of value the promise will eventually resolve to. Default is `void`.\n */\nexport default class SmartPromise<T = void> implements Promise<T>\n{\n    /**\n     * Wraps a new {@link SmartPromise} object around an existing native {@link Promise} object.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const request = fetch(\"https://api.example.com/data\");\n     * const smartRequest = SmartPromise.FromPromise(request);\n     *\n     * console.log(request.isPending); // Throws an error: `isPending` is not a property of `Promise`.\n     * console.log(smartRequest.isPending); // true\n     *\n     * const response = await request;\n     * console.log(smartRequest.isFulfilled); // true\n     * ```\n     *\n     * ---\n     *\n     * @param promise The promise to wrap.\n     *\n     * @returns A new {@link SmartPromise} object that wraps the provided promise.\n     */\n    public static FromPromise<T>(promise: Promise<T>): SmartPromise<T>\n    {\n        return new SmartPromise((resolve, reject) => promise.then(resolve, reject));\n    }\n\n    /**\n     * A flag indicating whether the promise is still pending or not.\n     *\n     * The protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link SmartPromise.isPending} getter instead.\n     */\n    protected _isPending: boolean;\n\n    /**\n     * A flag indicating whether the promise is still pending or not.\n     */\n    public get isPending(): boolean\n    {\n        return this._isPending;\n    }\n\n    /**\n     * A flag indicating whether the promise has been fulfilled or not.\n     *\n     * The protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link SmartPromise.isFulfilled} getter instead.\n     */\n    protected _isFulfilled: boolean;\n\n    /**\n     * A flag indicating whether the promise has been fulfilled or not.\n     */\n    public get isFulfilled(): boolean\n    {\n        return this._isFulfilled;\n    }\n\n    /**\n     * A flag indicating whether the promise has been rejected or not.\n     *\n     * The protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link SmartPromise.isRejected} getter instead.\n     */\n    protected _isRejected: boolean;\n\n    /**\n     * A flag indicating whether the promise has been rejected or not.\n     */\n    public get isRejected(): boolean\n    {\n        return this._isRejected;\n    }\n\n    /**\n     * The native {@link Promise} object wrapped by this instance.\n     */\n    protected readonly _promise: Promise<T>;\n\n    /**\n     * Initializes a new instance of the {@link SmartPromise} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise<string>((resolve, reject) =>\n     * {\n     *     setTimeout(() => resolve(\"Hello, World!\"), 1_000);\n     * });\n     * ```\n     *\n     * ---\n     *\n     * @param executor\n     * The function responsible for eventually resolving or rejecting the promise.  \n     * Similarly to the native {@link Promise} object, it's immediately executed after the promise is created.\n     */\n    public constructor(executor: PromiseExecutor<T>)\n    {\n        this._isPending = true;\n        this._isFulfilled = false;\n        this._isRejected = false;\n\n        const _onFulfilled = (result: T): T =>\n        {\n            this._isPending = false;\n            this._isFulfilled = true;\n\n            return result;\n        };\n        const _onRejected = (reason: unknown): never =>\n        {\n            this._isPending = false;\n            this._isRejected = true;\n\n            throw reason;\n        };\n\n        this._promise = new Promise<T>(executor)\n            .then(_onFulfilled, _onRejected);\n    }\n\n    /**\n     * Creates a new {@link Promise} identical to the one wrapped by this instance, with a different reference.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise<string>((resolve, reject) =>\n     * {\n     *     setTimeout(() => resolve(\"Hello, World!\"), 1_000);\n     * });\n     *\n     * console.log(await promise.then()); // \"Hello, World!\"\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link Promise} identical to the original one.\n     */\n    public then(onFulfilled?: null): Promise<T>;\n\n    /**\n     * Attaches a callback that executes right after the promise is fulfilled.\n     *\n     * The previous result of the promise is passed as the argument to the callback.  \n     * The callback's return value is considered the new promise's result instead.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise<string>((resolve, reject) =>\n     * {\n     *     setTimeout(() => resolve(\"Hello, World!\"), 1_000);\n     * });\n     *\n     * promise.then((result) => console.log(result)); // \"Hello, World!\"\n     * ```\n     *\n     * ---\n     *\n     * @template F The type of value the new promise will eventually resolve to. Default is `T`.\n     *\n     * @param onFulfilled The callback to execute once the promise is fulfilled.\n     *\n     * @returns A new {@link Promise} resolved with the return value of the callback.\n     */\n    public then<F = T>(onFulfilled: FulfilledHandler<T, F>, onRejected?: null): Promise<F>;\n\n    /**\n     * Attaches callbacks that executes right after the promise is fulfilled or rejected.\n     *\n     * The previous result of the promise is passed as the argument to the fulfillment callback.  \n     * The fulfillment callback's return value is considered the new promise's result instead.\n     *\n     * If an error is thrown during execution, the rejection callback is then executed instead.\n     *\n     * Also note that:\n     * - If the rejection callback runs properly, the error is considered handled.  \n     * The rejection callback's return value is considered the new promise's result.\n     * - If the rejection callback throws an error, the new promise is rejected with that error.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise((resolve, reject) =>\n     * {\n     *     setTimeout(resolve, Math.random() * 1_000);\n     *     setTimeout(reject, Math.random() * 1_000);\n     * });\n     *\n     * promise.then(() => console.log(\"OK!\"), () => console.log(\"KO!\")); // \"OK!\" or \"KO!\"\n     * ```\n     *\n     * ---\n     *\n     * @template F The type of value the new promise will eventually resolve to. Default is `T`.\n     * @template R The type of value the new promise will eventually resolve to. Default is `never`.\n     *\n     * @param onFulfilled The callback to execute once the promise is fulfilled.\n     * @param onRejected The callback to execute once the promise is rejected.\n     *\n     * @returns A new {@link Promise} resolved or rejected based on the callbacks.\n     */\n    public then<F = T, R = never>(onFulfilled: FulfilledHandler<T, F>, onRejected: RejectedHandler<unknown, R>)\n        : Promise<F | R>;\n    public then<F = T, R = never>(\n        onFulfilled?: FulfilledHandler<T, F> | null,\n        onRejected?: RejectedHandler<unknown, R> | null): Promise<F | R>\n    {\n        return this._promise.then(onFulfilled, onRejected);\n    }\n\n    /**\n     * Creates a new {@link Promise} identical to the one wrapped by this instance, with a different reference.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise((resolve, reject) =>\n     * {\n     *     setTimeout(() => reject(new Error(\"An unknown error occurred.\")), 1_000);\n     * });\n     *\n     * promise.catch(); // Uncaught Error: An unknown error occurred.\n     * ```\n     *\n     * ---\n     *\n     * @returns A new {@link Promise} identical to the original one.\n     */\n    public catch(onRejected?: null): Promise<T>;\n\n    /**\n     * Attaches a callback to handle the potential rejection of the promise.  \n     * If it happens, the callback is then executed.\n     *\n     * Also note that:\n     * - If the callback runs properly, the error is considered handled.  \n     * The callback's return value is considered the new promise's result.\n     * - If the callback throws an error, the new promise is rejected with that error.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise((resolve, reject) =>\n     * {\n     *     setTimeout(() => reject(new Error(\"An unknown error occurred.\")), 1_000);\n     * });\n     *\n     * promise.catch((reason) => console.error(reason)); // \"Error: An unknown error occurred.\"\n     * ```\n     *\n     * ---\n     *\n     * @template R The type of value the new promise will eventually resolve to. Default is `T`.\n     *\n     * @param onRejected The callback to execute once the promise is rejected.\n     *\n     * @returns A new {@link Promise} able to catch and handle the potential error.\n     */\n    public catch<R = never>(onRejected: RejectedHandler<unknown, R>): Promise<T | R>;\n    public catch<R = never>(onRejected?: RejectedHandler<unknown, R> | null): Promise<T | R>\n    {\n        return this._promise.catch(onRejected);\n    }\n\n    /**\n     * Attaches a callback that executes right after the promise is settled, regardless of the outcome.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new SmartPromise((resolve, reject) =>\n     * {\n     *     setTimeout(resolve, Math.random() * 1_000);\n     *     setTimeout(reject, Math.random() * 1_000);\n     * });\n     *\n     *\n     * promise\n     *     .then(() => console.log(\"OK!\")) // Logs \"OK!\" if the promise is fulfilled.\n     *     .catch(() => console.log(\"KO!\")) // Logs \"KO!\" if the promise is rejected.\n     *     .finally(() => console.log(\"Done!\")); // Always logs \"Done!\".\n     * ```\n     *\n     * ---\n     *\n     * @param onFinally The callback to execute when once promise is settled.\n     *\n     * @returns A new {@link Promise} that executes the callback once the promise is settled.\n     */\n    public finally(onFinally?: (() => void) | null): Promise<T>\n    {\n        return this._promise.finally(onFinally);\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"SmartPromise\";\n}\n","import type { PromiseResolver, PromiseRejecter, FulfilledHandler, RejectedHandler } from \"./types.js\";\n\nimport SmartPromise from \"./smart-promise.js\";\n\n/**\n * A class representing a {@link SmartPromise} that can be resolved or rejected from the \"outside\".  \n * The `resolve` and `reject` methods are exposed to allow the promise to be settled from another context.\n *\n * It's particularly useful in scenarios where the promise is created and needs to be awaited in one place,  \n * while being resolved or rejected in another (e.g. an event handler for an user interaction).\n *\n * This is a change in the approach to promises: instead of defining how the promise will be resolved (or rejected),  \n * you define how to handle the resolution (or rejection) when it occurs.\n *\n * ---\n *\n * @example\n * ```ts\n * const promise = new DeferredPromise<string, string[]>((value: string) => value.split(\" \"));\n *\n * promise.then((result) => console.log(result)); // [\"Hello,\", \"World!\"]\n * promise.resolve(\"Hello, World!\");\n * ```\n *\n * ---\n *\n * @template T The type of value the promise expects to initially be resolved with. Default is `void`.\n * @template F\n * The type of value returned by the `onFulfilled` callback.  \n * This will be the actual type of value the promise will eventually resolve to. Default is `T`.\n * @template R\n * The type of value possibly returned by the `onRejected` callback.  \n * This will be coupled with the type of value the promise will eventually resolve to, if provided. Default is `never`.\n */\nexport default class DeferredPromise<T = void, F = T, R = never> extends SmartPromise<F | R>\n{\n    /**\n     * The exposed function that allows to resolve the promise.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link DeferredPromise.resolve} getter instead.\n     */\n    protected readonly _resolve: PromiseResolver<T>;\n\n    /**\n     * The exposed function that allows to reject the promise.\n     */\n    public get resolve(): PromiseResolver<T> { return this._resolve; }\n\n    /**\n     * The exposed function that allows to reject the promise.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link DeferredPromise.reject} getter instead.\n     */\n    protected readonly _reject: PromiseRejecter;\n\n    /**\n     * The exposed function that allows to reject the promise.\n     */\n    public get reject(): PromiseRejecter { return this._reject; }\n\n    /**\n     * The native {@link Promise} object wrapped by this instance.\n     */\n    declare protected readonly _promise: Promise<F | R>;\n\n    /**\n     * Initializes a new instance of the {@link DeferredPromise} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new DeferredPromise<string, string[]>((value: string) => value.split(\" \"));\n     * ```\n     *\n     * ---\n     *\n     * @param onFulfilled The callback to execute once the promise is fulfilled.\n     * @param onRejected The callback to execute once the promise is rejected.\n     */\n    public constructor(onFulfilled?: FulfilledHandler<T, F> | null, onRejected?: RejectedHandler<unknown, R> | null)\n    {\n        let _resolve: PromiseResolver<T>;\n        let _reject: PromiseRejecter;\n\n        super((resolve, reject) =>\n        {\n            // ReferenceError: Must call super constructor in derived class before accessing\n            //                  'this' or returning from derived constructor.\n            //\n            _resolve = resolve as PromiseResolver<T>;\n            _reject = reject;\n        });\n\n        this._promise = this._promise.then(onFulfilled as FulfilledHandler<F | R>, onRejected);\n\n        this._resolve = _resolve!;\n        this._reject = _reject!;\n    }\n\n    /**\n     * Watches another promise and resolves or rejects this promise when the other one is settled.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new Promise<string>((resolve) => setTimeout(() => resolve(\"Hello, World!\"), 1_000));\n     * const deferred = new DeferredPromise<string, string[]>((value: string) => value.split(\" \"));\n     *\n     * deferred.then((result) => console.log(result)); // [\"Hello,\", \"World!\"]\n     * deferred.watch(promise);\n     * ```\n     *\n     * ---\n     *\n     * @param otherPromise The promise to watch.\n     *\n     * @returns The current instance of the {@link DeferredPromise} class.\n     */\n    public watch(otherPromise: PromiseLike<T>): this\n    {\n        otherPromise.then(this.resolve, this.reject);\n\n        return this;\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"DeferredPromise\";\n}\n","import { TimeoutException } from \"../exceptions/index.js\";\n\nimport SmartPromise from \"./smart-promise.js\";\nimport type { MaybePromise, PromiseExecutor } from \"./types.js\";\n\n/**\n * A class representing a {@link SmartPromise} that rejects automatically after a given time.  \n * It's useful for operations that must be completed within a certain time frame.\n *\n * If the operation takes longer than the specified time, the promise is rejected with a {@link TimeoutException}.\n *\n * ---\n *\n * @example\n * ```ts\n * const promise = new TimedPromise<string>((resolve, reject) =>\n * {\n *     setTimeout(() => resolve(\"Hello, World!\"), Math.random() * 10_000);\n *\n * }, 5_000);\n *\n * promise\n *     .then((result) => console.log(result))  // \"Hello, World!\"\n *     .catch((error) => console.error(error)); // TimeoutException: The operation has timed out.\n * ```\n *\n * ---\n *\n * @template T The type of value the promise will eventually resolve to. Default is `void`.\n */\nexport default class TimedPromise<T = void> extends SmartPromise<T>\n{\n    /**\n     * Initializes a new instance of the {@link TimedPromise} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const promise = new TimedPromise<string>((resolve, reject) =>\n     * {\n     *    setTimeout(() => resolve(\"Hello, World!\"), Math.random() * 10_000);\n     *\n     * }, 5_000);\n     * ```\n     *\n     * ---\n     *\n     * @param executor\n     * The function responsible for eventually resolving or rejecting the promise.  \n     * Similarly to the native {@link Promise} object, it's immediately executed after the promise is created.\n     *\n     * @param timeout The maximum time in milliseconds that the operation can take before timing out.\n     */\n    public constructor(executor: PromiseExecutor<T>, timeout?: number)\n    {\n        super((resolve, reject) =>\n        {\n            const _resolve = (result: MaybePromise<T>) =>\n            {\n                clearTimeout(_timeoutId);\n                resolve(result);\n            };\n            const _reject = (reason: unknown) =>\n            {\n                clearTimeout(_timeoutId);\n                reject(reason);\n            };\n\n            const _timeout = () => _reject(new TimeoutException(\"The operation has timed out.\"));\n            const _timeoutId = setTimeout(_timeout, timeout);\n\n            executor(_resolve, _reject);\n        });\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"TimedPromise\";\n}\n","import type { Callback } from \"../callbacks/types.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { TimeoutException, ValueException } from \"../exceptions/index.js\";\n\nimport DeferredPromise from \"./deferred-promise.js\";\nimport SmartPromise from \"./smart-promise.js\";\nimport TimedPromise from \"./timed-promise.js\";\nimport type { MaybePromise, PromiseRejecter, PromiseResolver } from \"./types.js\";\n\n/**\n * A class that represents a queue of asynchronous operations, allowing them to be executed sequentially.\n *\n * It extends the {@link SmartPromise} class, providing a way to manage multiple promises in a controlled manner.   \n * This class is useful for scenarios where you need to ensure\n * that only one asynchronous operation is executed at a time,\n * such as when dealing with API requests, file operations or any other\n * asynchronous tasks that need to be handled in a specific order.\n *\n * ---\n *\n * @example\n * ```ts\n * const queue = new PromiseQueue();\n *\n * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve(\"First\"), 2000)))\n * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve(\"Second\"), 500)))\n * queue.enqueue(() => new Promise((resolve) => setTimeout(() => resolve(\"Third\"), 1000)))\n *\n * await queue; // \"First\", \"Second\", \"Third\"\n * ```\n */\nexport default class PromiseQueue extends SmartPromise<void>\n{\n    /**\n     * The number of promises currently in the queue.\n     */\n    protected _count: number;\n\n    /**\n     * A flag indicating whether the promise is still pending or not.\n     */\n    public override get isPending(): boolean\n    {\n        return this._count > 0;\n    }\n    /**\n     * A flag indicating whether the promise has been fulfilled or not.\n     */\n    public override get isFulfilled(): boolean\n    {\n        return this._count === 0;\n    }\n\n    /**\n     * A flag indicating whether the promise has been rejected or not.\n     *\n     * Please note the {@link PromiseQueue} doesn't support rejection states.  \n     * Accessing this property will always result in a {@link ValueException}.\n     */\n    public override get isRejected(): never\n    {\n        throw new ValueException(\"`PromiseQueue` doesn't support rejection states.\");\n    }\n\n    /**\n     * The native {@link Promise} object wrapped by this instance.\n     */\n    declare protected _promise: Promise<void>;\n\n    /**\n     * Initializes a new instance of the {@link PromiseQueue} class.\n     */\n    public constructor()\n    {\n        super((resolve) => resolve());\n\n        this._count = 0;\n\n        this._isPending = false;\n        this._isFulfilled = false;\n        this._isRejected = false;\n    }\n\n    /**\n     * Enqueues a {@link DeferredPromise} into the queue.\n     *\n     * The promise will be executed in sequence after previously enqueued promises.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const queue = new PromiseQueue();\n     * const deferred = new DeferredPromise(() => console.log(\"Hello, world!\"));\n     * \n     * queue.enqueue(deferred); // \"Hello, world!\"\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of value the promise will eventually resolve to.\n     *\n     * @param promise A `DeferredPromise<void, T>` instance to enqueue.\n     *\n     * @returns A {@link Promise} that resolves to the value of the enqueued promise.\n     */\n    public enqueue<T>(promise: DeferredPromise<void, T>): Promise<T>;\n\n    /**\n     * Enqueues a {@link DeferredPromise} into the queue with an optional timeout.\n     *\n     * The promise will be executed in sequence after previously enqueued promises.  \n     * If the promise takes longer than the specified timeout, it will be rejected with a {@link TimeoutException}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const queue = new PromiseQueue();\n     * const deferred = new DeferredPromise(() => console.log(\"Hello, world!\"));\n     *\n     * queue.enqueue(deferred, 5000); // \"Hello, world!\"\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of value the promise will eventually resolve to.\n     *\n     * @param promise A `DeferredPromise<void, T>` instance to enqueue.\n     * @param timeout The maximum time in milliseconds that the operation can take before timing out.\n     *\n     * @returns\n     * A {@link TimedPromise} that resolves to the value of the enqueued promise or rejects\n     * with a `TimeoutException` if the operation takes longer than the specified timeout.\n     */\n    public enqueue<T>(promise: DeferredPromise<void, T>, timeout: number): TimedPromise<T>;\n\n    /**\n     * Enqueues a callback that returns a {@link MaybePromise} value of type `T` into the queue.\n     *\n     * The executor will be executed in sequence after previously enqueued promises.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const queue = new PromiseQueue();\n     *\n     * queue.enqueue(() => console.log(\"Hello, world!\")); // \"Hello, world!\"\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of value the promise will eventually resolve to.\n     *\n     * @param executor A callback that returns a `MaybePromise<T>` value to enqueue.\n     *\n     * @returns A {@link Promise} that resolves to the value of the enqueued executor.\n     */\n    public enqueue<T>(executor: Callback<[], MaybePromise<T>>): Promise<T>;\n\n    /**\n     * Enqueues a callback that returns a {@link MaybePromise}\n     * value of type `T` into the queue with an optional timeout.\n     *\n     * The executor will be executed in sequence after previously enqueued promises.  \n     * If the executor takes longer than the specified timeout, it will be rejected with a {@link TimeoutException}.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const queue = new PromiseQueue();\n     *\n     * queue.enqueue(() => console.log(\"Hello, world!\"), 5000); // \"Hello, world!\"\n     * ```\n     *\n     * ---\n     *\n     * @template T The type of value the promise will eventually resolve to.\n     *\n     * @param executor A callback that returns a `MaybePromise<T>` value to enqueue.\n     * @param timeout The maximum time in milliseconds that the operation can take before timing out.\n     *\n     * @returns\n     * A {@link TimedPromise} that resolves to the value of the enqueued executor or rejects\n     * with a `TimeoutException` if the operation takes longer than the specified timeout.\n     */\n    public enqueue<T>(executor: Callback<[], MaybePromise<T>>, timeout?: number): TimedPromise<T>;\n    public enqueue<T>(executor: DeferredPromise<void, T> | Callback<[], MaybePromise<T>>, timeout?: number)\n        : Promise<T> | TimedPromise<T>\n    {\n        this._count += 1;\n\n        if (executor instanceof DeferredPromise)\n        {\n            const _executor = executor as DeferredPromise<void, T>;\n\n            executor = () =>\n            {\n                _executor.resolve();\n\n                return _executor;\n            };\n        }\n\n        const _executor = (resolve: PromiseResolver<T>, reject: PromiseRejecter) =>\n        {\n            this._promise = this._promise\n                .then(executor)\n                .then((value) => { this._count -= 1; resolve(value); })\n                .catch((value) => { this._count -= 1; reject(value); });\n        };\n\n        if (timeout) { return new TimedPromise<T>(_executor, timeout); }\n\n        return new Promise<T>(_executor);\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"PromiseQueue\";\n}\n","/* eslint-disable @typescript-eslint/prefer-literal-enum-member */\n\nimport { RangeException, SmartIterator } from \"../models/index.js\";\n\n/**\n * An enumeration that represents the time units and their conversion factors.  \n * It can be used as utility to express time values in a more\n * readable way or to convert time values between different units.\n *\n * ---\n *\n * @example\n * ```ts\n * setTimeout(() => { [...] }, 5 * TimeUnit.Minute);\n * ```\n */\nexport enum TimeUnit\n{\n    /**\n     * A millisecond: the base time unit.\n     */\n    Millisecond = 1,\n\n    /**\n     * A second: 1000 milliseconds.\n     */\n    Second = 1_000,\n\n    /**\n     * A minute: 60 seconds.\n     */\n    Minute = 60 * Second,\n\n    /**\n     * An hour: 60 minutes.\n     */\n    Hour = 60 * Minute,\n\n    /**\n     * A day: 24 hours.\n     */\n    Day = 24 * Hour,\n\n    /**\n     * A week: 7 days.\n     */\n    Week = 7 * Day,\n\n    /**\n     * A month: 30 days.\n     */\n    Month = 30 * Day,\n\n    /**\n     * A year: 365 days.\n     */\n    Year = 365 * Day\n}\n\n/**\n * An enumeration that represents the days of the week.  \n * It can be used as utility to identify the days of the week when working with dates.\n *\n * ---\n *\n * @example\n * ```ts\n * const today = new Date();\n * if (today.getUTCDay() === WeekDay.Sunday)\n * {\n *     // Today is Sunday. Do something...\n * }\n * ```\n */\nexport enum WeekDay\n{\n    /**\n     * Sunday\n     */\n    Sunday = 0,\n\n    /**\n     * Monday\n     */\n    Monday = 1,\n\n    /**\n     * Tuesday\n     */\n    Tuesday = 2,\n\n    /**\n     * Wednesday\n     */\n    Wednesday = 3,\n\n    /**\n     * Thursday\n     */\n    Thursday = 4,\n\n    /**\n     * Friday\n     */\n    Friday = 5,\n\n    /**\n     * Saturday\n     */\n    Saturday = 6\n}\n\n/**\n * An utility function that calculates the difference between two dates.  \n * The difference can be expressed in different time units.\n *\n * ---\n *\n * @example\n * ```ts\n * const start = new Date(\"2025-01-01\");\n * const end = new Date(\"2025-01-31\");\n *\n * dateDifference(start, end, TimeUnit.Minute); // 43200\n * ```\n *\n * ---\n *\n * @param start The start date.\n * @param end The end date.\n * @param unit The time unit to express the difference. `TimeUnit.Day` by default.\n *\n * @returns The difference between the two dates in the specified time unit.\n */\nexport function dateDifference(start: number | string | Date, end: number | string | Date, unit = TimeUnit.Day): number\n{\n    let _round: (value: number) => number;\n\n    start = new Date(start);\n    end = new Date(end);\n\n    if (start < end) { _round = Math.floor; }\n    else { _round = Math.ceil; }\n\n    return _round((end.getTime() - start.getTime()) / unit);\n}\n\n/**\n * An utility function that generates an iterator over a range of dates.  \n * The step between the dates can be expressed in different time units.\n *\n * ---\n *\n * @example\n * ```ts\n * const start = new Date(\"2025-01-01\");\n * const end = new Date(\"2025-01-31\");\n *\n * for (const date of dateRange(start, end, TimeUnit.Week))\n * {\n *     date.toISOString().slice(8, 10); // \"01\", \"08\", \"15\", \"22\", \"29\"\n * }\n * ```\n *\n * ---\n *\n * @param start The start date (included).\n * @param end\n * The end date (excluded).\n *\n * Must be greater than the start date. Otherwise, a {@link RangeException} will be thrown.\n *\n * @param step The time unit to express the step between the dates. `TimeUnit.Day` by default.\n *\n * @returns A {@link SmartIterator} object that generates the dates in the range.\n */\nexport function dateRange(start: number | string | Date, end: number | string | Date, step = TimeUnit.Day)\n    : SmartIterator<Date>\n{\n    start = new Date(start);\n    end = new Date(end);\n\n    if (start >= end) { throw new RangeException(\"The end date must be greater than the start date.\"); }\n\n    return new SmartIterator<Date>(function* ()\n    {\n        const endTime = end.getTime();\n\n        let unixTime: number = start.getTime();\n        while (unixTime < endTime)\n        {\n            yield new Date(unixTime);\n\n            unixTime += step;\n        }\n    });\n}\n\n/**\n * An utility function that rounds a date to the nearest time unit.  \n * The rounding can be expressed in different time units.\n *\n * ---\n *\n * @example\n * ```ts\n * const date = new Date(\"2025-01-01T12:34:56.789Z\");\n *\n * dateRound(date, TimeUnit.Hour); // 2025-01-01T12:00:00.000Z\n * ```\n *\n * ---\n *\n * @param date The date to round.\n * @param unit\n * The time unit to express the rounding. `TimeUnit.Day` by default.\n *\n * Must be greater than a millisecond and less than or equal to a day.  \n * Otherwise, a {@link RangeException} will be thrown.\n *\n * @returns The rounded date.\n */\nexport function dateRound(date: number | string | Date, unit = TimeUnit.Day): Date\n{\n    if (unit <= TimeUnit.Millisecond)\n    {\n        throw new RangeException(\n            \"Rounding a timestamp by milliseconds or less makes no sense.\" +\n            \"Use the timestamp value directly instead.\"\n        );\n    }\n    if (unit > TimeUnit.Day)\n    {\n        throw new RangeException(\n            \"Rounding by more than a day leads to unexpected results. \" +\n            \"Consider using other methods to round dates by weeks, months or years.\"\n        );\n    }\n\n    date = new Date(date);\n    return new Date(Math.floor(date.getTime() / unit) * unit);\n}\n\n/**\n * An utility function that gets the week of a date.  \n * The first day of the week can be optionally specified.\n *\n * ---\n *\n * @example\n * ```ts\n * const date = new Date(\"2025-01-01\");\n *\n * getWeek(date, WeekDay.Monday); // 2024-12-30\n * ```\n *\n * ---\n *\n * @param date The date to get the week of.\n * @param firstDay The first day of the week. `WeekDay.Sunday` by default.\n *\n * @returns The first day of the week of the specified date.\n */\nexport function getWeek(date: number | string | Date, firstDay = WeekDay.Sunday): Date\n{\n    date = new Date(date);\n\n    const startCorrector = 7 - firstDay;\n    const weekDayIndex = (date.getUTCDay() + startCorrector) % 7;\n    const firstDayTime = date.getTime() - (TimeUnit.Day * weekDayIndex);\n\n    return dateRound(new Date(firstDayTime));\n}\n","import type { Interval } from \"../../core/types.js\";\nimport { isBrowser } from \"../../helpers.js\";\n\nimport Publisher from \"../callbacks/publisher.js\";\nimport { FatalErrorException, RuntimeException } from \"../exceptions/index.js\";\n\ninterface GameLoopEventsMap\n{\n    start: () => void;\n    stop: () => void;\n}\n\n/**\n * A class representing a {@link https://en.wikipedia.org/wiki/Video_game_programming#Game_structure|game loop} pattern\n * that allows to run a function at a specific frame rate.\n *\n * In a browser environment, it uses the native {@link requestAnimationFrame}\n * function to run the callback at the refresh rate of the screen.  \n * In a non-browser environment, however, it uses the {@link setInterval}\n * function to run the callback at the specified fixed interval of time.\n *\n * Every time the callback is executed, it receives the\n * elapsed time since the start of the game loop.  \n * It's also possible to subscribe to the `start` & `stop` events to receive notifications when they occur.\n *\n * ---\n *\n * @example\n * ```ts\n * const loop = new GameLoop((elapsedTime: number) =>\n * {\n *     console.log(`The game loop has been running for ${elapsedTime}ms.`);\n * });\n *\n * loop.onStart(() => { console.log(\"The game loop has started.\"); });\n * loop.onStop(() => { console.log(\"The game loop has stopped.\"); });\n *\n * loop.start();\n * ```\n */\nexport default class GameLoop\n{\n    /**\n     * The handle of the interval or the animation frame, depending on the environment.  \n     * It's used to stop the game loop when the {@link GameLoop._stop} method is called.\n     */\n    protected _handle?: number | Interval;\n\n    /**\n     * The time when the game loop has started.  \n     * In addition to indicating the {@link https://en.wikipedia.org/wiki/Unix_time|Unix timestamp}\n     * of the start of the game loop, it's also used to calculate the elapsed time.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link GameLoop.startTime} getter instead.\n     */\n    protected _startTime: number;\n\n    /**\n     * The time when the game loop has started.  \n     * In addition to indicating the {@link https://en.wikipedia.org/wiki/Unix_time|Unix timestamp}\n     * of the start of the game loop, it's also used to calculate the elapsed time.\n     */\n    public get startTime(): number\n    {\n        return this._startTime;\n    }\n\n    /**\n     * A flag indicating whether the game loop is currently running or not.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link GameLoop.isRunning} getter instead.\n     */\n    protected _isRunning: boolean;\n\n    /**\n     * A flag indicating whether the game loop is currently running or not.\n     */\n    public get isRunning(): boolean\n    {\n        return this._isRunning;\n    }\n\n    /**\n     * The elapsed time since the start of the game loop.  \n     * It's calculated as the difference between the current time and the {@link GameLoop.startTime}.\n     */\n    public get elapsedTime(): number\n    {\n        return performance.now() - this._startTime;\n    }\n\n    /**\n     * The {@link Publisher} object that will be used to publish the events of the game loop.\n     */\n    protected readonly _publisher: Publisher<GameLoopEventsMap>;\n\n    /**\n     * The internal method actually responsible for starting the game loop.\n     *\n     * Depending on the current environment, it could use the\n     * {@link requestAnimationFrame} or the {@link setInterval} function.\n     */\n    protected readonly _start: () => void;\n\n    /**\n     * The internal method actually responsible for stopping the game loop.\n     *\n     * Depending on the current environment, it could use the\n     * {@link cancelAnimationFrame} or the {@link clearInterval} function.\n     */\n    protected readonly _stop: () => void;\n\n    /**\n     * Initializes a new instance of the {@link GameLoop} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const loop = new GameLoop((elapsedTime: number) => { [...] });\n     * ```\n     *\n     * ---\n     *\n     * @param callback The function that will be executed at each iteration of the game loop.\n     * @param msIfNotBrowser\n     * The interval in milliseconds that will be used if the current environment isn't a browser. Default is `40`.\n     */\n    public constructor(callback: FrameRequestCallback, msIfNotBrowser = 40)\n    {\n        this._startTime = 0;\n        this._isRunning = false;\n\n        if (isBrowser)\n        {\n            this._start = () =>\n            {\n                callback(this.elapsedTime);\n\n                this._handle = window.requestAnimationFrame(this._start);\n            };\n\n            this._stop = () => window.cancelAnimationFrame(this._handle as number);\n        }\n        else\n        {\n            // eslint-disable-next-line no-console\n            console.warn(\n                \"Not a browser environment detected. \" +\n                `Using setInterval@${msIfNotBrowser}ms instead of requestAnimationFrame...`\n            );\n\n            this._start = () =>\n            {\n                this._handle = setInterval(() => callback(this.elapsedTime), msIfNotBrowser);\n            };\n\n            this._stop = () => clearInterval(this._handle as Interval);\n        }\n\n        this._publisher = new Publisher();\n    }\n\n    /**\n     * Starts the execution of the game loop.\n     *\n     * If the game loop is already running, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * loop.onStart(() => { [...] }); // This callback will be executed.\n     * loop.start();\n     * ```\n     *\n     * ---\n     *\n     * @param elapsedTime The elapsed time to set as default when the game loop starts. Default is `0`.\n     */\n    public start(elapsedTime = 0): void\n    {\n        if (this._isRunning) { throw new RuntimeException(\"The game loop has already been started.\"); }\n\n        this._startTime = performance.now() - elapsedTime;\n        this._start();\n        this._isRunning = true;\n\n        this._publisher.publish(\"start\");\n    }\n\n    /**\n     * Stops the execution of the game loop.\n     *\n     * If the game loop hasn't yet started, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * loop.onStop(() => { [...] }); // This callback will be executed.\n     * loop.stop();\n     * ```\n     */\n    public stop(): void\n    {\n        if (!(this._isRunning))\n        {\n            throw new RuntimeException(\"The game loop had already stopped or hadn't yet started.\");\n        }\n        if (!(this._handle)) { throw new FatalErrorException(); }\n\n        this._stop();\n        this._handle = undefined;\n        this._isRunning = false;\n\n        this._publisher.publish(\"stop\");\n    }\n\n    /**\n     * Subscribes to the `start` event of the game loop.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * loop.onStart(() => { console.log(\"The game loop has started.\"); });\n     * ```\n     *\n     * ---\n     *\n     * @param callback The function that will be executed when the game loop starts.\n     *\n     * @returns A function that can be used to unsubscribe from the event.\n     */\n    public onStart(callback: () => void): () => void\n    {\n        return this._publisher.subscribe(\"start\", callback);\n    }\n\n    /**\n     * Subscribes to the `stop` event of the game loop.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * loop.onStop(() => { console.log(\"The game loop has stopped.\"); });\n     * ```\n     *\n     * ---\n     *\n     * @param callback The function that will be executed when the game loop stops.\n     *\n     * @returns A function that can be used to unsubscribe from the event.\n     */\n    public onStop(callback: () => void): () => void\n    {\n        return this._publisher.subscribe(\"stop\", callback);\n    }\n\n    public readonly [Symbol.toStringTag]: string = \"GameLoop\";\n}\n","import { TimeUnit } from \"../../utils/date.js\";\n\nimport Publisher from \"../callbacks/publisher.js\";\nimport { FatalErrorException, RangeException, RuntimeException } from \"../exceptions/index.js\";\n\nimport GameLoop from \"./game-loop.js\";\n\ninterface ClockEventsMap\n{\n    start: () => void;\n    stop: () => void;\n    tick: (elapsedTime: number) => void;\n}\n\n/**\n * A class representing a clock.\n *\n * It can be started, stopped and, when running, it ticks at a specific frame rate.  \n * It's possible to subscribe to these events to receive notifications when they occur.\n *\n * ---\n *\n * @example\n * ```ts\n * const clock = new Clock();\n *\n * clock.onStart(() => { console.log(\"The clock has started.\"); });\n * clock.onTick((elapsedTime) => { console.log(`The clock has ticked at ${elapsedTime}ms.`); });\n * clock.onStop(() => { console.log(\"The clock has stopped.\"); });\n *\n * clock.start();\n * ```\n */\nexport default class Clock extends GameLoop\n{\n    /**\n     * The {@link Publisher} object that will be used to publish the events of the clock.\n     */\n    declare protected readonly _publisher: Publisher<ClockEventsMap>;\n\n    /**\n     * Initializes a new instance of the {@link Clock} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const clock = new Clock();\n     * ```\n     *\n     * ---\n     *\n     * @param msIfNotBrowser\n     * The interval in milliseconds at which the clock will tick if the environment is not a browser.  \n     * `TimeUnit.Second` by default.\n     */\n    public constructor(msIfNotBrowser: number = TimeUnit.Second)\n    {\n        super((elapsedTime) => this._publisher.publish(\"tick\", elapsedTime), msIfNotBrowser);\n    }\n\n    /**\n     * Starts the execution of the clock.\n     *\n     * If the clock is already running, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * clock.onStart(() => { [...] }); // This callback will be executed.\n     * clock.start();\n     * ```\n     *\n     * ---\n     *\n     * @param elapsedTime The elapsed time to set as default when the clock starts. Default is `0`.\n     */\n    public override start(elapsedTime = 0): void\n    {\n        if (this._isRunning) { throw new RuntimeException(\"The clock has already been started.\"); }\n\n        this._startTime = performance.now() - elapsedTime;\n        this._start();\n        this._isRunning = true;\n\n        this._publisher.publish(\"start\");\n    }\n\n    /**\n     * Stops the execution of the clock.\n     *\n     * If the clock hasn't yet started, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * clock.onStop(() => { [...] }); // This callback will be executed.\n     * clock.stop();\n     * ```\n     */\n    public override stop(): void\n    {\n        if (!(this._isRunning)) { throw new RuntimeException(\"The clock had already stopped or hadn't yet started.\"); }\n        if (!(this._handle)) { throw new FatalErrorException(); }\n\n        this._stop();\n        this._handle = undefined;\n        this._isRunning = false;\n\n        this._publisher.publish(\"stop\");\n    }\n\n    /**\n     * Subscribes to the `tick` event of the clock.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * clock.onTick((elapsedTime) => { [...] }); // This callback will be executed.\n     * clock.start();\n     * ```\n     *\n     * ---\n     *\n     * @param callback The callback that will be executed when the clock ticks.\n     * @param tickStep\n     * The minimum time in milliseconds that must pass from the previous execution of the callback to the next one.\n     *\n     * - If it's a positive number, the callback will be executed only if the\n     * time passed from the previous execution is greater than this number.\n     * - If it's `0`, the callback will be executed every tick without even checking for the time.\n     * - If it's a negative number, a {@link RangeException} will be thrown.\n     *\n     * @returns A function that can be used to unsubscribe from the event.\n     */\n    public onTick(callback: (elapsedTime: number) => void, tickStep = 0): () => void\n    {\n        if (tickStep < 0) { throw new RangeException(\"The tick step must be a non-negative number.\"); }\n        if (tickStep === 0) { return this._publisher.subscribe(\"tick\", callback); }\n\n        let lastTick = 0;\n\n        return this._publisher.subscribe(\"tick\", (elapsedTime: number) =>\n        {\n            if ((elapsedTime - lastTick) < tickStep) { return; }\n\n            callback(elapsedTime);\n            lastTick = elapsedTime;\n        });\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"Clock\";\n}\n","import { TimeUnit } from \"../../utils/date.js\";\n\nimport Publisher from \"../callbacks/publisher.js\";\nimport { FatalErrorException, RangeException, RuntimeException } from \"../exceptions/index.js\";\nimport { DeferredPromise, SmartPromise } from \"../promises/index.js\";\nimport type { Callback } from \"../types.js\";\n\nimport GameLoop from \"./game-loop.js\";\n\ninterface CountdownEventsMap\n{\n    start: () => void;\n    stop: (reason: unknown) => void;\n    tick: (remainingTime: number) => void;\n    expire: () => void;\n\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    [key: string]: Callback<any[], any>;\n}\n\n/**\n * A class representing a countdown.\n *\n * It can be started, stopped, when running it ticks at a specific frame rate and it expires when the time's up.  \n * It's possible to subscribe to these events to receive notifications when they occur.\n *\n * ---\n *\n * @example\n * ```ts\n * const countdown = new Countdown(10_000);\n *\n * countdown.onStart(() => { console.log(\"The countdown has started.\"); });\n * countdown.onTick((remainingTime) => { console.log(`The countdown has ${remainingTime}ms remaining.`); });\n * countdown.onStop((reason) => { console.log(`The countdown has stopped because of ${reason}.`); });\n * countdown.onExpire(() => { console.log(\"The countdown has expired.\"); });\n *\n * countdown.start();\n * ```\n */\nexport default class Countdown extends GameLoop\n{\n    /**\n     * The {@link Publisher} object that will be used to publish the events of the countdown.\n     */\n    declare protected readonly _publisher: Publisher<CountdownEventsMap>;\n\n    /**\n     * The total duration of the countdown in milliseconds.\n     *\n     * This protected property is the only one that can be modified directly by the derived classes.  \n     * If you're looking for the public and readonly property, use the {@link Countdown.duration} getter instead.\n     */\n    protected _duration: number;\n\n    /**\n     * The total duration of the countdown in milliseconds.\n     */\n    public get duration(): number\n    {\n        return this._duration;\n    }\n\n    /**\n     * The remaining time of the countdown in milliseconds.  \n     * It's calculated as the difference between the total duration and the elapsed time.\n     */\n    public get remainingTime(): number\n    {\n        return this._duration - this.elapsedTime;\n    }\n\n    /**\n     * The {@link DeferredPromise} that will be resolved or rejected when the countdown expires or stops.\n     */\n    protected _deferrer?: DeferredPromise<void>;\n\n    /**\n     * Initializes a new instance of the {@link Countdown} class.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * const countdown = new Countdown(10_000);\n     * ```\n     *\n     * ---\n     *\n     * @param duration\n     * The total duration of the countdown in milliseconds.\n     *\n     * @param msIfNotBrowser\n     * The interval in milliseconds at which the countdown will tick if the environment is not a browser.  \n     * `TimeUnit.Second` by default.\n     */\n    public constructor(duration: number, msIfNotBrowser: number = TimeUnit.Second)\n    {\n        const callback = () =>\n        {\n            const remainingTime = this.remainingTime;\n            if (remainingTime <= 0)\n            {\n                this._deferrerStop();\n\n                this._publisher.publish(\"tick\", 0);\n                this._publisher.publish(\"expire\");\n            }\n            else\n            {\n                this._publisher.publish(\"tick\", remainingTime);\n            }\n        };\n\n        super(callback, msIfNotBrowser);\n\n        this._duration = duration;\n    }\n\n    /**\n     * The internal method actually responsible for stopping the\n     * countdown and resolving or rejecting the {@link Countdown._deferrer} promise.\n     *\n     * ---\n     *\n     * @param reason\n     * The reason why the countdown has stopped.\n     *\n     * - If it's `undefined`, the promise will be resolved.\n     * - If it's a value, the promise will be rejected with that value.\n     */\n    protected _deferrerStop(reason?: unknown): void\n    {\n        if (!(this._isRunning)) { throw new RuntimeException(\"The countdown hadn't yet started.\"); }\n        if (!(this._deferrer)) { throw new FatalErrorException(); }\n\n        this._stop();\n        this._handle = undefined;\n        this._isRunning = false;\n\n        if (reason !== undefined) { this._deferrer.reject(reason); }\n        else { this._deferrer.resolve(); }\n\n        this._deferrer = undefined;\n    }\n\n    /**\n     * Starts the execution of the countdown.\n     *\n     * If the countdown is already running, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * countdown.onStart(() => { [...] }); // This callback will be executed.\n     * countdown.start();\n     * ```\n     *\n     * ---\n     *\n     * @param remainingTime\n     * The remaining time to set as default when the countdown starts.  \n     * Default is the {@link Countdown.duration} itself.\n     *\n     * @returns A {@link SmartPromise} that will be resolved or rejected when the countdown expires or stops.\n     */\n    public override start(remainingTime: number = this.duration): SmartPromise<void>\n    {\n        if (this._isRunning) { throw new RuntimeException(\"The countdown had already stopped or hadn't yet started.\"); }\n        if (this._deferrer) { throw new FatalErrorException(); }\n\n        this._deferrer = new DeferredPromise();\n        super.start(this.duration - remainingTime);\n\n        this._publisher.publish(\"start\");\n\n        return this._deferrer;\n    }\n\n    /**\n     * Stops the execution of the countdown.\n     *\n     * If the countdown hasn't yet started, a {@link RuntimeException} will be thrown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * countdown.onStop(() => { [...] }); // This callback will be executed.\n     * countdown.stop();\n     * ```\n     *\n     * ---\n     *\n     * @param reason\n     * The reason why the countdown has stopped.\n     *\n     * - If it's `undefined`, the promise will be resolved.\n     * - If it's a value, the promise will be rejected with that value.\n     */\n    public override stop(reason?: unknown): void\n    {\n        // TODO: Once solved Issues #6 & #10, make the `reason` parameter required.\n        //       - https://github.com/Byloth/core/issues/6\n        //       - https://github.com/Byloth/core/issues/10\n        //\n        this._deferrerStop(reason);\n\n        this._publisher.publish(\"stop\", reason);\n    }\n\n    /**\n     * Subscribes to the `expire` event of the countdown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * countdown.onExpire(() => { [...] }); // This callback will be executed once the countdown has expired.\n     * countdown.start();\n     * ```\n     *\n     * ---\n     *\n     * @param callback The callback that will be executed when the countdown expires.\n     *\n     * @returns A function that can be used to unsubscribe from the event.\n     */\n    public onExpire(callback: () => void): () => void\n    {\n        return this._publisher.subscribe(\"expire\", callback);\n    }\n\n    /**\n     * Subscribes to the `tick` event of the countdown.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * countdown.onTick((remainingTime) => { [...] }); // This callback will be executed.\n     * countdown.start();\n     * ```\n     *\n     * ---\n     *\n     * @param callback The callback that will be executed when the countdown ticks.\n     * @param tickStep\n     * The minimum time in milliseconds that must pass from the previous execution of the callback to the next one.\n     *\n     * - If it's a positive number, the callback will be executed only if the\n     * time passed from the previous execution is greater than this number.\n     * - If it's `0`, the callback will be executed every tick without even checking for the time.\n     * - If it's a negative number, a {@link RangeException} will be thrown.\n     *\n     * @returns A function that can be used to unsubscribe from the event.\n     */\n    public onTick(callback: (remainingTime: number) => void, tickStep = 0): () => void\n    {\n        if (tickStep < 0) { throw new RangeException(\"The tick step must be a non-negative number.\"); }\n        if (tickStep === 0) { return this._publisher.subscribe(\"tick\", callback); }\n\n        let lastTick = this.remainingTime;\n\n        return this._publisher.subscribe(\"tick\", (remainingTime: number) =>\n        {\n            if ((lastTick - remainingTime) < tickStep) { return; }\n\n            callback(remainingTime);\n            lastTick = remainingTime;\n        });\n    }\n\n    public override readonly [Symbol.toStringTag]: string = \"Countdown\";\n}\n","import { SmartIterator, ValueException } from \"../models/index.js\";\n\n/**\n * An utility class that provides a set of methods to generate sequences of numbers following specific curves.  \n * It can be used to generate sequences of values that can be\n * used in animations, transitions and other different scenarios.\n *\n * It cannot be instantiated directly.\n */\nexport default class Curve\n{\n    /**\n     * Generates a given number of values following a linear curve.  \n     * The values are equally spaced and normalized between 0 and 1.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * for (const value of Curve.Linear(5))\n     * {\n     *     console.log(value); // 0, 0.25, 0.5, 0.75, 1\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param values The number of values to generate.\n     *\n     * @returns A {@link SmartIterator} object that generates the values following a linear curve.\n     */\n    public static Linear(values: number): SmartIterator<number>\n    {\n        const steps = (values - 1);\n\n        return new SmartIterator<number>(function* ()\n        {\n            for (let index = 0; index < values; index += 1) { yield index / steps; }\n        });\n    }\n\n    /**\n     * Generates a given number of values following an exponential curve.  \n     * The values are equally spaced and normalized between 0 and 1.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * for (const value of Curve.Exponential(6))\n     * {\n     *     console.log(value); // 0, 0.04, 0.16, 0.36, 0.64, 1\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param values The number of values to generate.\n     * @param base\n     * The base of the exponential curve. Default is `2`.\n     *\n     * Also note that:\n     * - If it's equal to `1`, the curve will be linear.\n     * - If it's included between `0` and `1`, the curve will be logarithmic.\n     *\n     * The base cannot be negative. If so, a {@link ValueException} will be thrown.\n     *\n     * @returns A {@link SmartIterator} object that generates the values following an exponential curve.\n     */\n    public static Exponential(values: number, base = 2): SmartIterator<number>\n    {\n        if (base < 0) { throw new ValueException(\"The base of the exponential curve cannot be negative.\"); }\n\n        const steps = (values - 1);\n\n        return new SmartIterator<number>(function* ()\n        {\n            for (let index = 0; index < values; index += 1) { yield Math.pow(index / steps, base); }\n        });\n    }\n\n    private constructor() { /* ... */ }\n\n    public readonly [Symbol.toStringTag]: string = \"Curve\";\n}\n","import { ValueException } from \"../models/index.js\";\n\n/**\n * A wrapper class around the native {@link Math.random} function that\n * provides a set of methods to generate random values more easily.  \n * It can be used to generate random numbers, booleans and other different values.\n *\n * It cannot be instantiated directly.\n */\nexport default class Random\n{\n    /**\n     * Generates a random boolean value.\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * if (Random.Boolean())\n     * {\n     *    // Do something...\n     * }\n     * ```\n     *\n     * ---\n     *\n     * @param ratio\n     * The probability of generating `true`.\n     *\n     * It must be included between `0` and `1`. Default is `0.5`.\n     *\n     * @returns A random boolean value.\n     */\n    public static Boolean(ratio = 0.5): boolean\n    {\n        return (Math.random() < ratio);\n    }\n\n    /**\n     * Generates a random integer value between `0` (included) and `max` (excluded).\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * Random.Integer(5); // 0, 1, 2, 3, 4\n     * ```\n     *\n     * ---\n     *\n     * @param max The maximum value (excluded).\n     *\n     * @returns A random integer value.\n     */\n    public static Integer(max: number): number;\n\n    /**\n     * Generates a random integer value between `min` (included) and `max` (excluded).\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * Random.Integer(2, 7); // 2, 3, 4, 5, 6\n     * ```\n     *\n     * ---\n     *\n     * @param min The minimum value (included).\n     * @param max The maximum value (excluded).\n     *\n     * @returns A random integer value.\n     */\n    public static Integer(min: number, max: number): number;\n    public static Integer(min: number, max?: number): number\n    {\n        if (max === undefined) { return Math.floor(Math.random() * min); }\n\n        return Math.floor(Math.random() * (max - min) + min);\n    }\n\n    /**\n     * Generates a random decimal value between `0` (included) and `1` (excluded).\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * Random.Decimal(); // 0.123456789\n     * ```\n     *\n     * ---\n     *\n     * @returns A random decimal value.\n     */\n    public static Decimal(): number;\n\n    /**\n     * Generates a random decimal value between `0` (included) and `max` (excluded).\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * Random.Decimal(5); // 2.3456789\n     * ```\n     *\n     * ---\n     *\n     * @param max The maximum value (excluded).\n     *\n     * @returns A random decimal value.\n     */\n    public static Decimal(max: number): number;\n\n    /**\n     * Generates a random decimal value between `min` (included) and `max` (excluded).\n     *\n     * ---\n     *\n     * @example\n     * ```ts\n     * Random.Decimal(2, 7); // 4.56789\n     * ```\n     *\n     * ---\n     *\n     * @param min The minimum value (included).\n     * @param max The maximum value (excluded).\n     *\n     * @returns A random decimal value\n     */\n    public static Decimal(min: number, max: number): number;\n    public static Decimal(min?: number, max?: number): number\n    {\n        if (min === undefined) { return Math.random(); }\n        if (max === undefined) { return (Math.random() * min); }\n\n        return (Math.random() * (max - min) + min);\n    }\n\n    /**\n     * Picks a random valid index from a given array of elements.\n     *\n     * ---\n     *\n     * @template T The type of the elements in the array.\n     *\n     * @param elements\n     * The array of elements to pick from.\n     *\n     * It must contain at least one element. Otherwise, a {@link ValueException} will be thrown.\n     *\n     * @returns A valid random index from the given array.\n     */\n    public static Index<T>(elements: readonly T[]): number\n    {\n        if (elements.length === 0) { throw new ValueException(\"You must provide at least one element.\"); }\n\n        return this.Integer(elements.length);\n    }\n\n    /**\n     * Picks a random element from a given array of elements.\n     *\n     * ---\n     *\n     * @template T The type of the elements in the array.\n     *\n     * @param elements\n     * The array of elements to pick from.\n     *\n     * It must contain at least one element. Otherwise, a {@link ValueException} will be thrown.\n     *\n     * @returns A random element from the given array.\n     */\n    public static Choice<T>(elements: readonly T[]): T\n    {\n        return elements[Random.Index(elements)];\n    }\n\n    private constructor() { /* ... */ }\n\n    public readonly [Symbol.toStringTag]: string = \"Random\";\n}\n","/**\n * Returns a promise that resolves after a certain number of milliseconds.  \n * It can be used to pause or delay the execution of an asynchronous function.\n *\n * ---\n *\n * @example\n * ```ts\n * doSomething();\n * await delay(1_000);\n * doSomethingElse();\n * ```\n *\n * ---\n *\n * @param milliseconds The number of milliseconds to wait before resolving the promise.\n *\n * @returns A {@link Promise} that resolves after the specified number of milliseconds.\n */\nexport function delay(milliseconds: number): Promise<void>\n{\n    return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n\n/**\n * Returns a promise that resolves on the next animation frame.  \n * It can be used to synchronize operations with the browser's rendering cycle.\n *\n * ---\n *\n * @example\n * ```ts\n * const $el = document.querySelector(\".element\");\n *\n * $el.classList.add(\"animate\");\n * await nextAnimationFrame();\n * $el.style.opacity = \"1\";\n * ```\n *\n * ---\n *\n * @returns A {@link Promise} that resolves on the next animation frame.\n */\nexport function nextAnimationFrame(): Promise<void>\n{\n    return new Promise((resolve) => requestAnimationFrame(() => resolve()));\n}\n\n/**\n * Returns a promise that resolves on the next microtask.  \n * It can be used to yield to the event loop in long-running operations to prevent blocking the main thread.\n *\n * ---\n *\n * @example\n * ```ts\n * for (let i = 0; i < 100_000_000; i += 1)\n * {\n *     doSomething(i);\n *\n *     if (i % 100 === 0) await yieldToEventLoop();\n * }\n * ```\n *\n * ---\n *\n * @returns A {@link Promise} that resolves on the next microtask.\n */\nexport function yieldToEventLoop(): Promise<void>\n{\n    return new Promise((resolve) => setTimeout(resolve));\n}\n","/**\n * Appends a script element to the document body.  \n * It can be used to load external scripts dynamically.\n *\n * ---\n *\n * @example\n * ```ts\n * await loadScript(\"https://analytics.service/script.js?id=0123456789\");\n * ```\n *\n * ---\n *\n * @param scriptUrl The URL of the script to load.\n * @param scriptType The type of the script to load. Default is `\"text/javascript\"`.\n *\n * @returns\n * A {@link Promise} that resolves when the script has been loaded successfully or rejects if an error occurs.\n */\nexport function loadScript(scriptUrl: string, scriptType = \"text/javascript\"): Promise<void>\n{\n    return new Promise<void>((resolve, reject) =>\n    {\n        const script = document.createElement(\"script\");\n\n        script.async = true;\n        script.defer = true;\n        script.src = scriptUrl;\n        script.type = scriptType;\n\n        script.onload = (evt) => resolve();\n        script.onerror = (reason) => reject(reason);\n\n        document.body.appendChild(script);\n    });\n}\n","import { RangeException, SmartIterator } from \"../models/index.js\";\n\n/**\n * An utility function that chains multiple iterables into a single one.\n *\n * Since the iterator is lazy, the chaining process will be\n * executed only once the resulting iterator is materialized.\n *\n * A new iterator will be created, holding the reference to the original one.  \n * This means that the original iterator won't be consumed until the\n * new one is and that consuming one of them will consume the other as well.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const value of chain([1, 2, 3], [4, 5, 6], [7, 8, 9]))\n * {\n *     console.log(value); // 1, 2, 3, 4, 5, 6, 7, 8, 9\n * }\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterables.\n *\n * @param iterables The list of iterables to chain.\n *\n * @returns A new {@link SmartIterator} object that chains the iterables into a single one.\n */\nexport function chain<T>(...iterables: readonly Iterable<T>[]): SmartIterator<T>\n{\n    return new SmartIterator<T>(function* ()\n    {\n        for (const iterable of iterables)\n        {\n            for (const element of iterable) { yield element; }\n        }\n    });\n}\n\n/**\n * An utility function that counts the number of elements in an iterable.\n *\n * Also note that:\n * - If the iterable isn't an {@link Array}, it will be consumed entirely in the process.\n * - If the iterable is an infinite generator, the function will never return.\n *\n * ---\n *\n * @example\n * ```ts\n * count([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); // 10\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterable.\n *\n * @param elements The iterable to count.\n *\n * @returns The number of elements in the iterable.\n */\nexport function count<T>(elements: Iterable<T>): number\n{\n    if (elements instanceof Array) { return elements.length; }\n\n    let _count = 0;\n    for (const _ of elements) { _count += 1; }\n\n    return _count;\n}\n\n/**\n * An utility function that enumerates the elements of an iterable.  \n * Each element is paired with its index in a new iterator.\n *\n * Since the iterator is lazy, the enumeration process will\n * be executed once the resulting iterator is materialized.\n *\n * A new iterator will be created, holding the reference to the original one.  \n * This means that the original iterator won't be consumed until the\n * new one is and that consuming one of them will consume the other as well.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const [index, value] of enumerate([\"A\", \"M\", \"N\", \"Z\"]))\n * {\n *     console.log(`${index}: ${value}`); // \"0: A\", \"1: M\", \"2: N\", \"3: Z\"\n * }\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterable.\n *\n * @param elements The iterable to enumerate.\n *\n * @returns A new {@link SmartIterator} object containing the enumerated elements.\n */\nexport function enumerate<T>(elements: Iterable<T>): SmartIterator<[number, T]>\n{\n    return new SmartIterator<[number, T]>(function* ()\n    {\n        let index = 0;\n        for (const element of elements)\n        {\n            yield [index, element];\n\n            index += 1;\n        }\n    });\n}\n\n/**\n * An utility function that generates an iterator over a range of numbers.  \n * The values are included between `0` (included) and `end` (excluded).\n *\n * The default step between the numbers is `1`.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const number of range(5))\n * {\n *    console.log(number); // 0, 1, 2, 3, 4\n * }\n * ```\n *\n * ---\n *\n * @param end\n * The end value (excluded).\n *\n * If the `end` value is negative, the step will be `-1` leading to generate the numbers in reverse order.\n *\n * @returns A {@link SmartIterator} object that generates the numbers in the range.\n */\nexport function range(end: number): SmartIterator<number>;\n\n/**\n * An utility function that generates an iterator over a range of numbers.  \n * The values are included between `start` (included) and `end` (excluded).\n *\n * The step between the numbers can be specified with a custom value. Default is `1`.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const number of range(2, 7))\n * {\n *    console.log(number); // 2, 3, 4, 5, 6\n * }\n * ```\n *\n * ---\n *\n * @param start\n * The start value (included).\n *\n * If the `start` value is greater than the `end` value, the iterator will generate the numbers in reverse order.\n *\n * @param end\n * The end value (excluded).\n *\n * If the `end` value is less than the `start` value, the iterator will generate the numbers in reverse order.\n *\n * @param step\n * The step between the numbers. Default is `1`.\n *\n * Must be a positive number. Otherwise, a {@link RangeError} will be thrown.\n *\n * @returns A {@link SmartIterator} object that generates the numbers in the range.\n */\nexport function range(start: number, end: number, step?: number): SmartIterator<number>;\nexport function range(start: number, end?: number, step = 1): SmartIterator<number>\n{\n    if (step <= 0)\n    {\n        throw new RangeException(\n            \"Step must be always a positive number, even when generating numbers in reverse order.\"\n        );\n    }\n\n    if (end === undefined)\n    {\n        end = start;\n        start = 0;\n    }\n\n    if (start > end)\n    {\n        return new SmartIterator<number>(function* ()\n        {\n            for (let index = start; index > end; index -= step) { yield index; }\n        });\n    }\n\n    return new SmartIterator<number>(function* ()\n    {\n        for (let index = start; index < end; index += step) { yield index; }\n    });\n}\n\n/**\n * An utility function shuffles the elements of a given iterable.\n *\n * The function uses the {@link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle|Fisher-Yates}\n * algorithm to shuffle the elements.\n *\n * Also note that:\n * - If the iterable is an {@link Array}, it won't be modified since the shuffling isn't done in-place.\n * - If the iterable isn't an {@link Array}, it will be consumed entirely in the process.\n * - If the iterable is an infinite generator, the function will never return.\n *\n * ---\n *\n * @example\n * ```ts\n * shuffle([1, 2, 3, 4, 5]); // [3, 1, 5, 2, 4]\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterable.\n *\n * @param iterable The iterable to shuffle.\n *\n * @returns A new `Array` containing the shuffled elements of the given iterable.\n */\nexport function shuffle<T>(iterable: Iterable<T>): T[]\n{\n    const array = Array.from(iterable);\n\n    for (let index = array.length - 1; index > 0; index -= 1)\n    {\n        const jndex = Math.floor(Math.random() * (index + 1));\n\n        [array[index], array[jndex]] = [array[jndex], array[index]];\n    }\n\n    return array;\n}\n\n/**\n * An utility function that filters the elements of an iterable ensuring that they are all unique.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const value of unique([1, 1, 2, 3, 2, 3, 4, 5, 5, 4]))\n * {\n *     console.log(value); // 1, 2, 3, 4, 5\n * }\n * ```\n *\n * ---\n *\n * @template T The type of elements in the iterable.\n *\n * @param elements The iterable to filter.\n *\n * @returns A {@link SmartIterator} object that iterates over the unique elements of the given iterable.\n */\nexport function unique<T>(elements: Iterable<T>): SmartIterator<T>\n{\n    return new SmartIterator<T>(function* ()\n    {\n        const values = new Set<T>();\n        for (const element of elements)\n        {\n            if (values.has(element)) { continue; }\n\n            values.add(element);\n\n            yield element;\n        }\n    });\n}\n\n/**\n * An utility function that zips two iterables into a single one.  \n * The resulting iterable will contain the elements of the two iterables paired together.\n *\n * The function will stop when one of the two iterables is exhausted.\n *\n * ---\n *\n * @example\n * ```ts\n * for (const [number, char] of zip([1, 2, 3, 4], [\"A\", \"M\", \"N\" \"Z\"]))\n * {\n *     console.log(`${number} - ${char}`); // \"1 - A\", \"2 - M\", \"3 - N\", \"4 - Z\"\n * }\n * ```\n *\n * ---\n *\n * @template T The type of elements in the first iterable.\n * @template U The type of elements in the second iterable.\n *\n * @param first The first iterable to zip.\n * @param second The second iterable to zip.\n *\n * @returns A {@link SmartIterator} object that iterates over the zipped elements of the two given iterables.\n */\nexport function zip<T, U>(first: Iterable<T>, second: Iterable<U>): SmartIterator<[T, U]>\n{\n    const firstIterator = first[Symbol.iterator]();\n    const secondIterator = second[Symbol.iterator]();\n\n    return new SmartIterator<[T, U]>(function* ()\n    {\n        while (true)\n        {\n            const firstResult = firstIterator.next();\n            const secondResult = secondIterator.next();\n\n            if ((firstResult.done) || (secondResult.done)) { break; }\n\n            yield [firstResult.value, secondResult.value];\n        }\n    });\n}\n","import { ValueException } from \"../models/exceptions/index.js\";\nimport { zip } from \"./iterator.js\";\n\n/**\n * Computes the average of a given list of values.  \n * The values can be weighted using an additional list of weights.\n *\n * ---\n *\n * @example\n * ```ts\n * average([1, 2, 3, 4, 5]); // 3\n * average([6, 8.5, 4], [3, 2, 1]); // 6.5\n * ```\n *\n * ---\n *\n * @template T The type of the values in the list. It must be or extend a `number` object.\n *\n * @param values\n * The list of values to compute the average.\n *\n * It must contain at least one element. Otherwise, a {@link ValueException} will be thrown.\n *\n * @param weights\n * The list of weights to apply to the values.  \n * It should contain the same number of elements as the values list or\n * the smaller number of elements between the two lists will be considered.\n *\n * The sum of the weights must be greater than zero. Otherwise, a {@link ValueException} will be thrown.\n *\n * @returns The average of the specified values.\n */\nexport function average<T extends number>(values: Iterable<T>, weights?: Iterable<number>): number\n{\n    if (weights === undefined)\n    {\n        let _sum = 0;\n        let _index = 0;\n\n        for (const value of values)\n        {\n            _sum += value;\n            _index += 1;\n        }\n\n        if (_index === 0) { throw new ValueException(\"You must provide at least one value.\"); }\n\n        return _sum / _index;\n    }\n\n    let _sum = 0;\n    let _count = 0;\n    let _index = 0;\n\n    for (const [value, weight] of zip(values, weights))\n    {\n        if (weight <= 0)\n        {\n            throw new ValueException(`The weight for the value #${_index} must be greater than zero.`);\n        }\n\n        _sum += value * weight;\n        _count += weight;\n        _index += 1;\n    }\n\n    if (_index === 0) { throw new ValueException(\"You must provide at least one value and weight.\"); }\n    if (_count <= 0) { throw new ValueException(\"The sum of weights must be greater than zero.\"); }\n\n    return _sum / _count;\n}\n\n/**\n * An utility function to compute the hash of a given string.\n *\n * The hash is computed using a simple variation of the\n * {@link http://www.cse.yorku.ca/~oz/hash.html#djb2|djb2} algorithm.  \n * However, the hash is garanteed to be a 32-bit signed integer.\n *\n * ---\n *\n * @example\n * ```ts\n * hash(\"Hello, world!\"); // -1880044555\n * hash(\"How are you?\"); // 1761539132\n * ```\n *\n * ---\n *\n * @param value The string to hash.\n *\n * @returns The hash of the specified string.\n */\nexport function hash(value: string): number\n{\n    let hashedValue = 0;\n    for (let index = 0; index < value.length; index += 1)\n    {\n        const char = value.charCodeAt(index);\n\n        hashedValue = ((hashedValue << 5) - hashedValue) + char;\n        hashedValue |= 0;\n    }\n\n    return hashedValue;\n}\n\n/**\n * Sums all the values of a given list.\n *\n * ---\n *\n * @example\n * ```ts\n * sum([1, 2, 3, 4, 5]); // 15\n * ```\n *\n * ---\n *\n * @template T The type of the values in the list. It must be or extend a `number` object.\n *\n * @param values The list of values to sum.\n *\n * @returns The sum of the specified values.\n */\nexport function sum<T extends number>(values: Iterable<T>): number\n{\n    let _sum = 0;\n    for (const value of values) { _sum += value; }\n\n    return _sum;\n}\n","/**\n * Capitalize the first letter of a string.\n *\n * ---\n *\n * @example\n * ```ts\n * capitalize('hello'); // 'Hello'\n * ```\n *\n * ---\n *\n * @param value The string to capitalize.\n *\n * @returns The capitalized string.\n */\nexport function capitalize(value: string): string\n{\n    return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;\n}\n","export const VERSION = \"2.1.5\";\n\nexport type { Constructor, Interval, Timeout, ValueOf } from \"./core/types.js\";\n\nexport { isBrowser, isNode, isWorker } from \"./helpers.js\";\n\nexport {\n    AggregatedIterator,\n    AggregatedAsyncIterator,\n    CallableObject,\n    Clock,\n    Countdown,\n    DeferredPromise,\n    EnvironmentException,\n    Exception,\n    FatalErrorException,\n    FileException,\n    FileExistsException,\n    FileNotFoundException,\n    GameLoop,\n    JSONStorage,\n    KeyException,\n    MapView,\n    NotImplementedException,\n    NetworkException,\n    PermissionException,\n    PromiseQueue,\n    Publisher,\n    RangeException,\n    ReducedIterator,\n    ReferenceException,\n    RuntimeException,\n    SetView,\n    SmartIterator,\n    SmartAsyncIterator,\n    SmartPromise,\n    SwitchableCallback,\n    TimeoutException,\n    TimedPromise,\n    TypeException,\n    ValueException\n\n} from \"./models/index.js\";\n\nexport type {\n    AsyncGeneratorFunction,\n    AsyncIteratee,\n    AsyncIteratorLike,\n    AsyncKeyedIteratee,\n    AsyncKeyedReducer,\n    AsyncReducer,\n    Callback,\n    CallbackMap,\n    FulfilledHandler,\n    GeneratorFunction,\n    Iteratee,\n    IteratorLike,\n    JSONArray,\n    JSONObject,\n    JSONValue,\n    KeyedIteratee,\n    KeyedReducer,\n    KeyedTypeGuardPredicate,\n    MapViewEventsMap,\n    MaybeAsyncKeyedIteratee,\n    MaybeAsyncKeyedReducer,\n    MaybeAsyncGeneratorFunction,\n    MaybeAsyncIteratee,\n    MaybeAsyncIteratorLike,\n    MaybeAsyncReducer,\n    MaybePromise,\n    PromiseExecutor,\n    PromiseRejecter,\n    PromiseResolver,\n    Publishable,\n    ReadonlyMapView,\n    ReadonlySetView,\n    Reducer,\n    RejectedHandler,\n    SetViewEventsMap,\n    Subscribable,\n    TypeGuardPredicate\n\n} from \"./models/types.js\";\n\nexport {\n    average,\n    capitalize,\n    chain,\n    count,\n    Curve,\n    delay,\n    dateDifference,\n    dateRange,\n    dateRound,\n    TimeUnit,\n    enumerate,\n    getWeek,\n    hash,\n    loadScript,\n    nextAnimationFrame,\n    Random,\n    range,\n    shuffle,\n    sum,\n    unique,\n    WeekDay,\n    yieldToEventLoop,\n    zip\n\n} from \"./utils/index.js\";\n"],"names":["isBrowser","isNode","_a","isWorker","_b","Exception","_d","_c","message","cause","name","__publicField","error","exc","FatalErrorException","_f","_e","NotImplementedException","_h","_g","FileException","_j","_i","FileExistsException","_l","_k","FileNotFoundException","_n","_m","KeyException","_p","_o","NetworkException","_r","_q","PermissionException","_t","_s","ReferenceException","_v","_u","RuntimeException","_x","_w","EnvironmentException","_z","_y","TimeoutException","_B","_A","TypeException","_D","_C","ValueException","_F","_E","RangeException","_H","_G","SmartIterator","argument","_I","predicate","index","result","iterator","iteratee","reducer","initialValue","accumulator","elements","value","count","limit","values","AggregatedIterator","element","_J","_ReducedIterator","key","_","ReducedIterator","_K","_AggregatedAsyncIterator","SmartAsyncIterator","indexes","finding","keys","counters","map","groups","AggregatedAsyncIterator","_L","generator","next","_value","_M","_AggregatedIterator","SmartFunction","CallableObject","_O","_N","self","_P","_Publisher","scope","propagator","event","args","results","subscribers","subscriber","Publisher","Disabler","SwitchableCallback","_R","_Q","callback","MapView","_T","_S","iterable","size","SetView","_V","_U","_W","JSONStorage","preferPersistence","storage","defaultValue","newValue","encodedValue","persistent","_X","_SmartPromise","executor","_onFulfilled","_onRejected","reason","promise","resolve","reject","onFulfilled","onRejected","onFinally","SmartPromise","DeferredPromise","_Z","_Y","_resolve","_reject","otherPromise","TimedPromise","_$","__","timeout","_timeoutId","PromiseQueue","_ba","_aa","_executor","TimeUnit","WeekDay","dateDifference","start","end","unit","_round","dateRange","step","endTime","unixTime","dateRound","date","getWeek","firstDay","startCorrector","weekDayIndex","firstDayTime","_ca","GameLoop","msIfNotBrowser","elapsedTime","Clock","_ea","_da","tickStep","lastTick","Countdown","_ga","_fa","duration","remainingTime","_ha","Curve","steps","base","_ia","_Random","ratio","min","max","Random","delay","milliseconds","nextAnimationFrame","yieldToEventLoop","loadScript","scriptUrl","scriptType","script","evt","chain","iterables","_count","enumerate","range","shuffle","array","jndex","unique","zip","first","second","firstIterator","secondIterator","firstResult","secondResult","average","weights","_sum","_index","weight","hash","hashedValue","char","sum","capitalize","VERSION"],"mappings":"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"}