{"version":3,"sources":["../../src/core/collection.ts"],"sourcesContent":["import assertNever from '../errors/asserts/asserts';\r\nimport IOObject from \"./internet-object\";\r\n\r\n/**\r\n * IOCollection is an ordered, index-accessible collection of items.\r\n *\r\n * Features:\r\n * - Array-like operations (push, pop, insert, deleteAt)\r\n * - Functional methods (map, filter, reduce, forEach, find, some, every)\r\n * - Iterable support for for..of loops\r\n * - JSON serialization with error handling options\r\n * - Proxy-based index access (collection[0])\r\n *\r\n * @template T The type of items stored in the collection (defaults to IOObject)\r\n *\r\n * @example\r\n * ```typescript\r\n * const collection = new IOCollection<Person>();\r\n * collection.push({ name: 'Alice', age: 30 });\r\n * collection.push({ name: 'Bob', age: 25 });\r\n *\r\n * // Iteration\r\n * for (const person of collection) {\r\n *   console.log(person.name);\r\n * }\r\n *\r\n * // Functional operations\r\n * const names = collection.map(p => p.name);\r\n * ```\r\n */\r\nclass IOCollection<T = IOObject> {\r\n  private _items: T[];\r\n  public errors: Error[] = [];\r\n\r\n  /**\r\n   * Constructs a new IOCollection instance.\r\n   * @param items - An optional array of items to initialize the collection with.\r\n   */\r\n  constructor(items: T[] = []) {\r\n    this._items = items;\r\n  }\r\n\r\n  /**\r\n   * Pushes one or more items to the IOCollection\r\n   * @param items - The items to push.\r\n   * @returns The updated IOCollection.\r\n   */\r\n  public push(...items: T[]): IOCollection<T> {\r\n    this._items.push(...items);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Gets the item at the specified index.\r\n   * @param index - The index of the item to retrieve.\r\n   * @throws {Error} If the index is out of range.\r\n   * @returns The item at the specified index.\r\n   */\r\n  public getAt(index: number): T {\r\n    if (index < 0 || index >= this._items.length) {\r\n      throw new Error('Index out of range');\r\n    }\r\n    return this._items[index];\r\n  }\r\n\r\n  /**\r\n   * Sets the item at the specified index.\r\n   * @param index - The index at which to set the item.\r\n   * @param item - The item to set.\r\n   * @throws {Error} If the index is negative.\r\n   * @returns The updated IOCollection.\r\n   */\r\n  public setAt(index: number, item: T): IOCollection<T> {\r\n    if (index < 0) {\r\n      throw new Error('Index cannot be negative.');\r\n    }\r\n    if (index >= this._items.length) {\r\n      this._items.push(item);\r\n    } else {\r\n      this._items[index] = item;\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Deletes an item from the IOCollection at the specified index.\r\n   * @param index - The index of the item to delete.\r\n   * @throws {Error} If the index is out of range.\r\n   * @returns The updated IOCollection.\r\n   */\r\n  public deleteAt(index: number): IOCollection<T> {\r\n    if (index < 0 || index >= this._items.length) {\r\n      throw new Error('Index out of range');\r\n    }\r\n    this._items.splice(index, 1);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Gets the length of the IOCollection.\r\n   * @returns The number of items in the IOCollection.\r\n   */\r\n  public get length(): number {\r\n    return this._items.length;\r\n  }\r\n\r\n  /**\r\n   * Checks if the IOCollection is empty.\r\n   * @returns True if the IOCollection is empty, otherwise false.\r\n   */\r\n  public get isEmpty(): boolean {\r\n    return this.length === 0;\r\n  }\r\n\r\n  /**\r\n   * Creates a new IOCollection with the results of calling a provided function on every element.\r\n   * @param callback - Function that produces an element of the new IOCollection.\r\n   * @returns A new IOCollection with each element being the result of the callback function.\r\n   */\r\n  public map<U>(callback: (item: T, index: number, array: T[]) => U): IOCollection<U> {\r\n    const mappedItems = this._items.map(callback);\r\n    return new IOCollection<U>(mappedItems);\r\n  }\r\n\r\n  /**\r\n   * Creates a new IOCollection with all elements that pass the test implemented by the provided function.\r\n   * @param callback - Function to test each element of the IOCollection.\r\n   * @returns A new IOCollection with the elements that pass the test.\r\n   */\r\n  public filter(callback: (item: T, index: number, array: T[]) => boolean): IOCollection<T> {\r\n    const filteredItems = this._items.filter(callback);\r\n    return new IOCollection<T>(filteredItems);\r\n  }\r\n\r\n  /**\r\n   * Applies a function against an accumulator and each element in the IOCollection to reduce it to a single value.\r\n   * @param callback - Function to execute on each element in the IOCollection.\r\n   * @param initialValue - Initial value to start the reduction.\r\n   * @returns The single value that results from the reduction.\r\n   */\r\n  public reduce<U>(callback: (accumulator: U, item: T, index: number, array: T[]) => U, initialValue: U): U {\r\n    return this._items.reduce(callback, initialValue);\r\n  }\r\n\r\n  /**\r\n   * Executes a provided function once for each IOCollection element.\r\n   * @param callback - Function to execute on each element.\r\n   */\r\n  public forEach(callback: (item: T, index: number, array: T[]) => void): void {\r\n    this._items.forEach(callback);\r\n  }\r\n\r\n  /**\r\n   * Tests whether at least one element in the IOCollection passes the test implemented by the provided function.\r\n   * @param callback - Function to test each element.\r\n   * @returns True if the callback function returns a truthy value for at least one element, otherwise false.\r\n   */\r\n  public some(callback: (item: T, index: number, array: T[]) => boolean): boolean {\r\n    return this._items.some(callback);\r\n  }\r\n\r\n  /**\r\n   * Tests whether all elements in the IOCollection pass the test implemented by the provided function.\r\n   * @param callback - Function to test each element.\r\n   * @returns True if the callback returns a truthy value for all elements, otherwise false.\r\n   */\r\n  public every(callback: (item: T, index: number, array: T[]) => boolean): boolean {\r\n    return this._items.every(callback);\r\n  }\r\n\r\n  /**\r\n   * Returns the value of the first element in the IOCollection that satisfies the provided testing function.\r\n   * @param callback - Function to execute on each element.\r\n   * @returns The first element that satisfies the testing function, or undefined if no elements satisfy it.\r\n   */\r\n  public find(callback: (item: T, index: number, array: T[]) => boolean): T | undefined {\r\n    return this._items.find(callback);\r\n  }\r\n\r\n  /**\r\n   * Returns the index of the first element in the IOCollection that satisfies the provided testing function.\r\n   * @param callback - Function to execute on each element.\r\n   * @returns The index of the first element that satisfies the testing function, or -1 if no elements satisfy it.\r\n   */\r\n  public findIndex(callback: (item: T, index: number, array: T[]) => boolean): number {\r\n    return this._items.findIndex(callback);\r\n  }\r\n\r\n  /**\r\n   * Inserts one or more items into the IOCollection at the specified index.\r\n   * @param index - The index at which to insert the items.\r\n   * @param items - The items to insert.\r\n   * @returns The new length of the IOCollection.\r\n   */\r\n  public insert(index: number, ...items: T[]): number {\r\n    this._items.splice(index, 0, ...items);\r\n    return this._items.length;\r\n  }\r\n\r\n  /**\r\n   * Removes the last item from the IOCollection.\r\n   * @returns The removed item, or undefined if the IOCollection is empty.\r\n   */\r\n  public pop(): T | undefined {\r\n    return this._items.pop();\r\n  }\r\n\r\n  /**\r\n   * Converts the collection to a plain JavaScript array.\r\n   * Recursively calls `toObject()` on items that support it.\r\n   *\r\n   * @param options Optional configuration for conversion\r\n   * @param options.skipErrors If true, excludes error objects from output (default: false)\r\n   * @returns An array of plain JavaScript values.\r\n   */\r\n  public toObject(options?: { skipErrors?: boolean }): any {\r\n    const skipErrors = options?.skipErrors ?? false;\r\n\r\n    return this._items\r\n      .filter((item) => {\r\n        // If skipErrors is true, filter out items with toValue that return __error\r\n        if (skipErrors && typeof item === 'object' && item !== null) {\r\n          if (typeof (item as any).toValue === 'function') {\r\n            const value = (item as any).toValue();\r\n            if (value && value.__error === true) {\r\n              return false; // Skip this error item\r\n            }\r\n          }\r\n        }\r\n        return true; // Keep this item\r\n      })\r\n      .map((item) => {\r\n        if (item instanceof IOObject) {\r\n          return item.toObject();\r\n        } else if (typeof item === 'object' && item !== null) {\r\n          // Check if item has toValue method (e.g., ErrorNode)\r\n          if (typeof (item as any).toValue === 'function') {\r\n            return (item as any).toValue();\r\n          }\r\n           // Check if item has toObject method\r\n          if (typeof (item as any).toObject === 'function') {\r\n            return (item as any).toObject();\r\n          }\r\n          // Check if item has toJSON method\r\n          if (typeof (item as any).toJSON === 'function') {\r\n            return (item as any).toJSON();\r\n          }\r\n          return JSON.stringify(item); // TODO: Should this be parsed back to object or left as string?\r\n        }\r\n        return item;\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Alias for `toObject()`.\r\n   * Provides compatibility with `JSON.stringify()`.\r\n   */\r\n  public toJSON(options?: { skipErrors?: boolean }): any {\r\n    return this.toObject(options);\r\n  }\r\n\r\n  /**\r\n   * Custom inspector for Node.js `console.log`.\r\n   * Returns the plain object representation for better readability.\r\n   */\r\n  [Symbol.for('nodejs.util.inspect.custom')]() {\r\n    return this.toObject();\r\n  }\r\n\r\n  /**\r\n   * Returns all Error objects contained within this collection's ErrorNodes.\r\n   *\r\n   * Note: This method is primarily useful when working with collections directly.\r\n   * When using Document.getErrors(), all errors (parser + validation) are already\r\n   * aggregated at the document level.\r\n   *\r\n   * @returns Array of Error objects from ErrorNode items in this collection\r\n   */\r\n  public getErrors(): Error[] {\r\n    const errors: Error[] = [];\r\n    for (const item of this._items) {\r\n      // ErrorNode-like shape: has an `error` property of type Error\r\n      if (item && typeof item === 'object' && (item as any).error instanceof Error) {\r\n        errors.push((item as any).error as Error);\r\n      }\r\n    }\r\n    return errors;\r\n  }\r\n\r\n  /**\r\n   * Allows iteration over the IOCollection using for..of syntax.\r\n   * @returns An iterator for the IOCollection.\r\n   */\r\n  *[Symbol.iterator](): IterableIterator<T> {\r\n    yield* this._items;\r\n  }\r\n\r\n  /**\r\n   * Returns an iterator of [index, item] pairs.\r\n   * @returns An iterator of index-item pairs.\r\n   */\r\n  *entries(): IterableIterator<[number, T]> {\r\n    for (let index = 0; index < this._items.length; index++) {\r\n      yield [index, this._items[index]];\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns an iterator of item indices.\r\n   * @returns An iterator of item indices.\r\n   */\r\n  *keys(): IterableIterator<number> {\r\n    for (let index = 0; index < this._items.length; index++) {\r\n      yield index;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Returns an iterator of IOCollection items.\r\n   * @returns An iterator of IOCollection items.\r\n   */\r\n  *values(): IterableIterator<T> {\r\n    yield* this._items;\r\n  }\r\n}\r\n\r\nconst proxy = {\r\n  get: (target: IOCollection<any>, property: string | symbol) => {\r\n    if (property in target) {\r\n      return Reflect.get(target, property);\r\n    }\r\n\r\n    if (typeof property === 'string' && /^[0-9]+$/.test(property)) {\r\n      return target.getAt(Number(property));\r\n    }\r\n\r\n    assertNever(property as never);\r\n  },\r\n\r\n  set: (target: IOCollection<any>, property: string | number | symbol, value: any) => {\r\n    if (typeof property === 'string' && /^[0-9]+$/.test(property)) {\r\n      target.setAt(Number(property), value);\r\n      return true;\r\n    }\r\n\r\n    throw new Error('Cannot set a value on a Collection');\r\n  },\r\n\r\n  deleteProperty: (target: IOCollection<any>, property: string | symbol) => {\r\n    if (typeof property === 'string' && /^[0-9]+$/.test(property)) {\r\n      const index = Number(property);\r\n      target.deleteAt(index);\r\n      return true;\r\n    }\r\n\r\n    throw new Error('Cannot delete a value on a Collection');\r\n  }\r\n};\r\n\r\nexport default IOCollection;\r\n"],"mappings":"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","names":["IOObject","assertNever"]}