@aegis-framework/artemis 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +555 -96
  2. package/dist/artemis.browser.js +2 -2
  3. package/dist/artemis.browser.js.map +19 -18
  4. package/dist/artemis.js +2 -2
  5. package/dist/artemis.js.map +18 -17
  6. package/dist/types/DOM.d.ts +190 -207
  7. package/dist/types/DOM.d.ts.map +1 -1
  8. package/dist/types/Debug.d.ts +73 -2
  9. package/dist/types/Debug.d.ts.map +1 -1
  10. package/dist/types/FileSystem.d.ts +55 -38
  11. package/dist/types/FileSystem.d.ts.map +1 -1
  12. package/dist/types/Form.d.ts +41 -16
  13. package/dist/types/Form.d.ts.map +1 -1
  14. package/dist/types/Platform.d.ts +62 -63
  15. package/dist/types/Platform.d.ts.map +1 -1
  16. package/dist/types/Preload.d.ts +70 -11
  17. package/dist/types/Preload.d.ts.map +1 -1
  18. package/dist/types/Request.d.ts +111 -47
  19. package/dist/types/Request.d.ts.map +1 -1
  20. package/dist/types/Space.d.ts +19 -6
  21. package/dist/types/Space.d.ts.map +1 -1
  22. package/dist/types/SpaceAdapter/IndexedDB.d.ts +10 -7
  23. package/dist/types/SpaceAdapter/IndexedDB.d.ts.map +1 -1
  24. package/dist/types/SpaceAdapter/LocalStorage.d.ts +18 -8
  25. package/dist/types/SpaceAdapter/LocalStorage.d.ts.map +1 -1
  26. package/dist/types/SpaceAdapter/RemoteStorage.d.ts +15 -2
  27. package/dist/types/SpaceAdapter/RemoteStorage.d.ts.map +1 -1
  28. package/dist/types/SpaceAdapter/SessionStorage.d.ts +21 -2
  29. package/dist/types/SpaceAdapter/SessionStorage.d.ts.map +1 -1
  30. package/dist/types/SpaceAdapter/types.d.ts +32 -1
  31. package/dist/types/SpaceAdapter/types.d.ts.map +1 -1
  32. package/dist/types/Text.d.ts +34 -23
  33. package/dist/types/Text.d.ts.map +1 -1
  34. package/dist/types/Util.d.ts +18 -14
  35. package/dist/types/Util.d.ts.map +1 -1
  36. package/dist/types/browser.d.ts.map +1 -1
  37. package/package.json +10 -11
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/Debug.ts", "../src/DOM.ts", "../src/Request.ts", "../src/FileSystem.ts", "../src/Form.ts", "../src/Platform.ts", "../src/Preload.ts", "../src/SpaceAdapter/LocalStorage.ts", "../src/SpaceAdapter/SessionStorage.ts", "../src/SpaceAdapter/IndexedDB.ts", "../src/SpaceAdapter/RemoteStorage.ts", "../src/Space.ts", "../src/Text.ts", "../src/Util.ts", "../src/browser.ts"],
3
+ "sources": ["../src/Debug.ts", "../src/DOM.ts", "../src/Request.ts", "../src/FileSystem.ts", "../src/Form.ts", "../src/Platform.ts", "../src/Preload.ts", "../src/SpaceAdapter/types.ts", "../src/SpaceAdapter/LocalStorage.ts", "../src/SpaceAdapter/SessionStorage.ts", "../src/SpaceAdapter/IndexedDB.ts", "../src/SpaceAdapter/RemoteStorage.ts", "../src/Space.ts", "../src/Text.ts", "../src/Util.ts", "../src/browser.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * ==============================\n * Debug\n * ==============================\n */\n\n\n/**\n * Debug level enum\n */\nexport enum DebugLevel {\n\tNONE = 0,\n\tERROR = 1,\n\tWARNING = 2,\n\tINFO = 3,\n\tDEBUG = 4,\n\tALL = 5\n}\n\n/**\n * This class acts as a proxy for the console. It shares the same methods as the\n * web console but they are conditioned to a debug level.\n */\nexport class Debug {\n\tprivate static _level: DebugLevel = DebugLevel.NONE;\n\n\t/**\n\t * Set or get the log level\n\t *\n\t * @param level - The debug level to use\n\t * @returns The current debug level\n\t */\n\tstatic level(level?: DebugLevel): DebugLevel {\n\t\tif (typeof level === 'number') {\n\t\t\tthis._level = level;\n\t\t}\n\t\treturn this._level;\n\t}\n\n\t/**\n\t * Log the given elements.\n\t * Logs will only be made if the level is set to DEBUG or above\n\t *\n\t * @param args - Arguments to log\n\t */\n\tstatic log(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.log(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Show a debugging log\n\t * Logs will only be made if the level is set DEBUG or above\n\t *\n\t * @param args - Arguments to log\n\t */\n\tstatic debug(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.debug(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Show an info log\n\t * Logs will only be made if the level is set to INFO or above\n\t *\n\t * @param args - Arguments to log\n\t */\n\tstatic info(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.INFO) {\n\t\t\tconsole.info(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Show an error log\n\t * Logs will only be made if the level is set to ERROR or above\n\t *\n\t * @param args - Arguments to log\n\t */\n\tstatic error(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.ERROR) {\n\t\t\tconsole.error(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Show a warning log\n\t * Logs will only be made if the level is set to WARNING or above\n\t *\n\t * @param args - Arguments to log\n\t */\n\tstatic warning(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.WARNING) {\n\t\t\tconsole.warn(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Show data as a table\n\t * Table will only be made if the level is set to DEBUG or above\n\t *\n\t * @param args - Arguments to display as table\n\t */\n\tstatic table(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.table(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Start an indented group\n\t *\n\t * @param args - Group label arguments\n\t */\n\tstatic group(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.group(...args);\n\t\t}\n\t}\n\n\t/**\n\t * Start an indented group collapsed by default\n\t *\n\t * @param args - Group label arguments\n\t */\n\tstatic groupCollapsed(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.groupCollapsed(...args);\n\t\t}\n\t}\n\n\t/**\n\t * End a previously started group\n\t */\n\tstatic groupEnd(): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.groupEnd();\n\t\t}\n\t}\n\n\t/**\n\t * Start a timer\n\t * The timer will only start if the level is set to DEBUG or above\n\t *\n\t * @param label - Timer label\n\t */\n\tstatic time(label?: string): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.time(label);\n\t\t}\n\t}\n\n\t/**\n\t * Log the time a timer has been running for\n\t * The time will only be logged if the level is set to DEBUG or above\n\t *\n\t * @param label - Timer label\n\t * @param args - Additional arguments to log\n\t */\n\tstatic timeLog(label?: string, ...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.timeLog(label, ...args);\n\t\t}\n\t}\n\n\t/**\n\t * End a timer\n\t * The timer will only be available if the level is set to DEBUG or above\n\t *\n\t * @param label - Timer label\n\t */\n\tstatic timeEnd(label?: string): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.timeEnd(label);\n\t\t}\n\t}\n\n\t/**\n\t * Show the stack trace\n\t * The stack trace will only be available if the level is set to DEBUG or above\n\t *\n\t * @param args - Arguments to log with trace\n\t */\n\tstatic trace(...args: unknown[]): void {\n\t\tif (this.level() >= DebugLevel.DEBUG) {\n\t\t\tconsole.trace(...args);\n\t\t}\n\t}\n}\n\n",
6
- "/**\n * ==============================\n * DOM\n * ==============================\n */\n\n/**\n * Type for elements that can be used as a selector\n */\nexport type DOMSelector = string | Element | Element[] | NodeList | NodeListOf<Element> | HTMLElement[] | DOM | null;\n\n/**\n * Type for style properties object\n */\nexport type StyleProperties = Record<string, string | number>;\n\n/**\n * Type for offset object\n */\nexport interface DOMOffset {\n\ttop: number;\n\tleft: number;\n}\n\n/**\n * Event callback type\n */\nexport type EventCallback = (event: Event) => void;\n\n/**\n * Element callback type\n */\nexport type ElementCallback = (element: Element) => void;\n\n/**\n * Simple DOM manipulation functions\n */\nexport class DOM {\n\tpublic collection: Element[] | NodeListOf<Element>;\n\tpublic length: number;\n\tpublic _selector: DOMSelector;\n\n\t/**\n\t * Create a new DOM object\n\t *\n\t * @param selector - Selector or DOM element to use\n\t */\n\tconstructor(selector: DOMSelector) {\n\t\tif (selector === null) {\n\t\t\tthis.collection = [];\n\t\t\tthis.length = 0;\n\t\t\tthis._selector = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof selector === 'string') {\n\t\t\tthis.collection = document.querySelectorAll(selector);\n\t\t\tthis.length = this.collection.length;\n\t\t\tthis._selector = selector;\n\t\t} else if (selector instanceof NodeList) {\n\t\t\tthis.collection = selector as NodeListOf<Element>;\n\t\t\tthis.length = selector.length;\n\t\t\tthis._selector = selector;\n\t\t} else if (selector instanceof DOM) {\n\t\t\tthis.collection = selector.collection;\n\t\t\tthis.length = this.collection.length;\n\t\t\tthis._selector = selector._selector;\n\t\t} else if (selector instanceof HTMLElement) {\n\t\t\tthis.collection = [selector];\n\t\t\tthis.length = this.collection.length;\n\t\t\tthis._selector = selector;\n\t\t} else if (Array.isArray(selector)) {\n\t\t\tthis.collection = selector;\n\t\t\tthis.length = selector.length;\n\t\t\tthis._selector = selector;\n\t\t} else {\n\t\t\tthis.collection = [];\n\t\t\tthis.length = 0;\n\t\t\tthis._selector = null;\n\t\t}\n\t}\n\n\t/**\n\t * Hide elements by setting their `display` property to 'none'.\n\t *\n\t * @returns Current instance\n\t */\n\thide(): this {\n\t\tfor (const element of this.collection) {\n\t\t\t(element as HTMLElement).style.display = 'none';\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Show elements by setting their `display` property to the given value.\n\t *\n\t * @param display - Display property to set\n\t * @returns Current instance\n\t */\n\tshow(display: string = 'block'): this {\n\t\tfor (const element of this.collection) {\n\t\t\t(element as HTMLElement).style.display = display;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a class to the classList object\n\t *\n\t * @param newClass - Class name to add\n\t * @returns Current instance\n\t */\n\taddClass(newClass: string): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.classList.add(newClass);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove a given class from the classList object\n\t *\n\t * @param oldClass - Class to remove. If it's empty or null, all classes will be removed\n\t * @returns Current instance\n\t */\n\tremoveClass(oldClass: string | null = null): this {\n\t\tif (oldClass !== null) {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\telement.classList.remove(oldClass);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\twhile (element.classList.length > 0) {\n\t\t\t\t\tconst className = element.classList.item(0);\n\t\t\t\t\tif (className) {\n\t\t\t\t\t\telement.classList.remove(className);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Toggle between two classes\n\t *\n\t * @param classes - Space separated class names\n\t * @returns Current instance\n\t */\n\ttoggleClass(classes: string): this {\n\t\tconst classList = classes.split(' ');\n\t\tfor (const element of this.collection) {\n\t\t\tfor (const className of classList) {\n\t\t\t\telement.classList.toggle(className);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Check if ALL elements in the collection have the given class\n\t *\n\t * @param classToCheck - Class name to check for\n\t * @returns Whether all elements have the class\n\t */\n\thasClass(classToCheck: string): boolean {\n\t\tfor (const element of this.collection) {\n\t\t\tif (!element.classList.contains(classToCheck)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get or set the value from the elements\n\t *\n\t * @param value - Value to set to the elements\n\t * @returns If a value is provided, returns current instance. Otherwise returns the value(s) - single value if one element, array if multiple.\n\t */\n\tvalue(value?: string): this | string | string[] | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\t(element as HTMLInputElement).value = value;\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn (this.collection[0] as HTMLInputElement).value;\n\t\t\t}\n\t\t\tconst values: string[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push((element as HTMLInputElement).value);\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\t}\n\n\t/**\n\t * Focus on the first element matching the selector\n\t *\n\t * @returns Current instance\n\t */\n\tfocus(): this {\n\t\tif (this.length > 0) {\n\t\t\t(this.collection[0] as HTMLElement).focus();\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'click' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tclick(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('click', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'keyup' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tkeyup(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('keyup', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'keydown' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tkeydown(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('keydown', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'submit' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tsubmit(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('submit', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'change' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tchange(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('change', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback for the 'scroll' event on every element matching the selector\n\t *\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\tscroll(callback: EventCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.addEventListener('scroll', callback, false);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a callback function to a given event\n\t *\n\t * @param event - Event to add the listener to\n\t * @param target - Target element on which to detect the event or callback function\n\t * @param callback - Callback function to run when the event is triggered\n\t * @returns Current instance\n\t */\n\ton(event: string, target: string | EventCallback, callback?: EventCallback): this {\n\t\tconst events = event.split(' ');\n\t\tfor (const element of this.collection) {\n\t\t\tfor (const evt of events) {\n\t\t\t\t// Check if no target was defined and just a function was provided\n\t\t\t\tif (typeof target === 'function') {\n\t\t\t\t\telement.addEventListener(evt, target, false);\n\t\t\t\t} else if (typeof target === 'string' && typeof callback === 'function') {\n\t\t\t\t\telement.addEventListener(evt, (e: Event) => {\n\t\t\t\t\t\tif (!e.target) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst domInstance = new DOM(e.target as Element);\n\t\t\t\t\t\tconst targetElement = domInstance.closestParent(target, this._selector as string);\n\n\t\t\t\t\t\tif (targetElement.exists()) {\n\t\t\t\t\t\t\tcallback.call(targetElement.get(0), e);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, false);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Filter from the current collection to only those matching the new selector\n\t * Applies to ALL elements in the collection\n\t *\n\t * @param selector - Selector to filter the collection with\n\t * @returns New DOM instance with the filtered collection\n\t */\n\tfilter(selector: string): DOM {\n\t\tconst filtered: HTMLElement[] = [];\n\t\tfor (const element of this.collection) {\n\t\t\tif (element.matches(selector)) {\n\t\t\t\tfiltered.push(element as HTMLElement);\n\t\t\t}\n\t\t}\n\t\treturn new DOM(filtered.length > 0 ? filtered : null);\n\t}\n\n\t/**\n\t * Check if there are any elements that match the selector.\n\t *\n\t * @returns Whether elements matching the selector existed or not\n\t */\n\texists(): boolean {\n\t\treturn this.length > 0;\n\t}\n\n\t/**\n\t * Get or set a `data` property\n\t *\n\t * @param name - Name of the data property\n\t * @param value - Value of the property\n\t * @returns If no value is provided, returns the value(s) - single value if one element, array if multiple.\n\t */\n\tdata(name: string, value?: string): this | string | string[] | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\t(element as HTMLElement).dataset[name] = value;\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn (this.collection[0] as HTMLElement).dataset[name];\n\t\t\t}\n\t\t\tconst values: (string | undefined)[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push((element as HTMLElement).dataset[name]);\n\t\t\t}\n\t\t\treturn values as string[];\n\t\t}\n\t}\n\n\t/**\n\t * Remove a data property from all the elements on the collection given its name.\n\t *\n\t * @param name - Name of the data property to remove\n\t * @returns Current instance\n\t */\n\tremoveData(name: string): this {\n\t\tfor (const element of this.collection) {\n\t\t\tdelete (element as HTMLElement).dataset[name];\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get or set the text of elements\n\t *\n\t * @param value - Value to set the text to\n\t * @returns If no value is provided, returns the text(s) - single value if one element, array if multiple.\n\t */\n\ttext(value?: string): this | string | (string | null)[] | null | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\telement.textContent = value;\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn this.collection[0].textContent;\n\t\t\t}\n\t\t\tconst values: (string | null)[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push(element.textContent);\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\t}\n\n\t/**\n\t * Get or set the inner HTML of elements\n\t *\n\t * @param value - Value to set the HTML to\n\t * @returns If no value is provided, returns the HTML(s) - single value if one element, array if multiple.\n\t */\n\thtml(value?: string): this | string | string[] | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\telement.innerHTML = value;\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn this.collection[0].innerHTML;\n\t\t\t}\n\t\t\tconst values: string[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push(element.innerHTML);\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\t}\n\n\t/**\n\t * Append an element to ALL elements in the collection\n\t *\n\t * @param element - String representation of the element to add or an Element\n\t * @returns Current instance\n\t */\n\tappend(element: string | Element): this {\n\t\tlet isFirstElement = true;\n\t\tfor (const el of this.collection) {\n\t\t\tif (typeof element === 'string') {\n\t\t\t\tconst div = document.createElement('div');\n\t\t\t\tdiv.innerHTML = element.trim();\n\t\t\t\tif (div.firstChild) {\n\t\t\t\t\tel.appendChild(div.firstChild.cloneNode(true));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// For the first target, append the original element to preserve\n\t\t\t\t// custom element state/props. For subsequent targets, clone.\n\t\t\t\t// Note: Cloned custom elements will have their constructor re-run,\n\t\t\t\t// which may reset state/props to defaults.\n\t\t\t\tif (isFirstElement) {\n\t\t\t\t\tel.appendChild(element);\n\t\t\t\t\tisFirstElement = false;\n\t\t\t\t} else {\n\t\t\t\t\tel.appendChild(element.cloneNode(true));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Prepend an element to ALL elements in the collection\n\t *\n\t * @param element - String representation of the element to add or an Element\n\t * @returns Current instance\n\t */\n\tprepend(element: string | Element): this {\n\t\tlet isFirstElement = true;\n\n\t\tfor (const el of this.collection) {\n\t\t\tif (typeof element === 'string') {\n\t\t\t\tconst div = document.createElement('div');\n\t\t\t\tdiv.innerHTML = element.trim();\n\t\t\t\tif (div.firstChild) {\n\t\t\t\t\tif (el.childNodes.length > 0) {\n\t\t\t\t\t\tel.insertBefore(div.firstChild.cloneNode(true), el.childNodes[0]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tel.appendChild(div.firstChild.cloneNode(true));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// For the first target, use the original element to preserve\n\t\t\t\t// custom element state/props. For subsequent targets, clone.\n\t\t\t\t// Note: Cloned custom elements will have their constructor re-run,\n\t\t\t\t// which may reset state/props to defaults.\n\t\t\t\tconst nodeToInsert = isFirstElement ? element : element.cloneNode(true);\n\t\t\t\tif (isFirstElement) {\n\t\t\t\t\tisFirstElement = false;\n\t\t\t\t}\n\n\t\t\t\tif (el.childNodes.length > 0) {\n\t\t\t\t\tel.insertBefore(nodeToInsert, el.childNodes[0]);\n\t\t\t\t} else {\n\t\t\t\t\tel.appendChild(nodeToInsert);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Iterate over the collection of elements matching the selector\n\t *\n\t * @param callback - Callback to run for every element\n\t * @returns Current instance\n\t */\n\teach(callback: ElementCallback): this {\n\t\tfor (const element of this.collection) {\n\t\t\tcallback(element);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get an element from the collection given its index\n\t *\n\t * @param index - Index of the element to retrieve\n\t * @returns HTML Element in the position indicated by the index\n\t */\n\tget(index: number): Element | undefined {\n\t\treturn this.collection[index];\n\t}\n\n\t/**\n\t * Get the first element in the collection\n\t *\n\t * @returns DOM instance with the first element\n\t */\n\tfirst(): DOM {\n\t\tif (this.length > 0) {\n\t\t\treturn new DOM(this.collection[0] as HTMLElement);\n\t\t}\n\t\treturn new DOM(null);\n\t}\n\n\t/**\n\t * Get the last element in the collection\n\t *\n\t * @returns DOM instance with the last element\n\t */\n\tlast(): DOM {\n\t\tif (this.length > 0) {\n\t\t\treturn new DOM(this.collection[this.collection.length - 1] as HTMLElement);\n\t\t}\n\t\treturn new DOM(null);\n\t}\n\n\t/**\n\t * Check if any element in the collection is visible by checking their\n\t * display, offsetWidth and offsetHeight properties\n\t *\n\t * @returns Whether any element is visible\n\t */\n\tisVisible(): boolean {\n\t\tfor (const element of this.collection) {\n\t\t\tconst el = element as HTMLElement;\n\t\t\tif (el.style.display !== 'none' && el.offsetWidth > 0 && el.offsetHeight > 0) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get the parents of ALL elements in the collection\n\t *\n\t * @returns DOM instance of the parent elements\n\t */\n\tparent(): DOM {\n\t\tconst parents: HTMLElement[] = [];\n\t\tfor (const element of this.collection) {\n\t\t\tif (element.parentElement && !parents.includes(element.parentElement)) {\n\t\t\t\tparents.push(element.parentElement);\n\t\t\t}\n\t\t}\n\t\treturn new DOM(parents.length > 0 ? parents : null);\n\t}\n\n\t/**\n\t * Find elements that match the given selector in ALL elements of the collection\n\t *\n\t * @param selector - Selector to find elements with\n\t * @returns DOM instance with found elements\n\t */\n\tfind(selector: string): DOM {\n\t\tconst found: HTMLElement[] = [];\n\t\tfor (const element of this.collection) {\n\t\t\tconst results = element.querySelectorAll(selector);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (!found.includes(result as HTMLElement)) {\n\t\t\t\t\tfound.push(result as HTMLElement);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn new DOM(found.length > 0 ? found : null);\n\t}\n\n\t/**\n\t * Get the top and left offsets of elements in the collection\n\t *\n\t * @returns Single offset object if one element, array of offset objects if multiple\n\t */\n\toffset(): DOMOffset | DOMOffset[] | undefined {\n\t\tif (this.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (this.length === 1) {\n\t\t\tconst rect = this.collection[0].getBoundingClientRect();\n\t\t\treturn {\n\t\t\t\ttop: rect.top + document.body.scrollTop,\n\t\t\t\tleft: rect.left + document.body.scrollLeft\n\t\t\t};\n\t\t}\n\t\tconst offsets: DOMOffset[] = [];\n\t\tfor (const element of this.collection) {\n\t\t\tconst rect = element.getBoundingClientRect();\n\t\t\toffsets.push({\n\t\t\t\ttop: rect.top + document.body.scrollTop,\n\t\t\t\tleft: rect.left + document.body.scrollLeft\n\t\t\t});\n\t\t}\n\t\treturn offsets;\n\t}\n\n\t/**\n\t * Find the closest element matching the given selector for ALL elements.\n\t * This bubbles up from the initial object and then follows to its parents.\n\t *\n\t * @param selector - Selector to match the closest element with\n\t * @returns DOM instance with the closest HTML elements matching the selector\n\t */\n\tclosest(selector: string): DOM {\n\t\tconst found: HTMLElement[] = [];\n\t\tfor (const element of this.collection) {\n\t\t\tconst closest = element.closest(selector) as HTMLElement | null;\n\t\t\tif (closest && !found.includes(closest)) {\n\t\t\t\tfound.push(closest);\n\t\t\t}\n\t\t}\n\t\treturn new DOM(found.length > 0 ? found : null);\n\t}\n\n\t/**\n\t * Find the closest parent element matching the given selector. This bubbles up\n\t * from the initial object and then follows to its parents.\n\t *\n\t * @param selector - Selector to match the closest element with\n\t * @param limit - Selector for limit element. If the limit is reached and no element matching the provided selector was found, it will cause an early return.\n\t * @returns DOM instance with the closest HTML element matching the selector\n\t */\n\tclosestParent(selector: string, limit?: string): DOM {\n\t\tif (this.length === 0) {\n\t\t\treturn new DOM(null);\n\t\t}\n\n\t\tlet current: Element | null = this.collection[0];\n\t\twhile (current) {\n\t\t\t// Check if the current element matches the selector\n\t\t\tif (current.matches(selector)) {\n\t\t\t\treturn new DOM(current as HTMLElement);\n\t\t\t}\n\n\t\t\t// Check if we hit the limit\n\t\t\tif (typeof limit === 'string' && current.matches(limit)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcurrent = current.parentElement;\n\t\t}\n\t\treturn new DOM(null);\n\t}\n\n\t/**\n\t * Get or set the value of a given attribute\n\t *\n\t * @param attribute - Attribute's name\n\t * @param value - Value to set the attribute to\n\t * @returns If no value is provided, returns the attribute value(s) - single value if one element, array if multiple.\n\t */\n\tattribute(attribute: string, value?: string | number): this | string | (string | null)[] | null | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\telement.setAttribute(attribute, String(value));\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn this.collection[0].getAttribute(attribute);\n\t\t\t}\n\t\t\tconst values: (string | null)[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push(element.getAttribute(attribute));\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\t}\n\n\t/**\n\t * Check whether ALL elements have an attribute\n\t *\n\t * @param attribute - The name of the attribute to check existence for\n\t * @returns Whether all elements have the attribute\n\t */\n\thasAttribute(attribute: string): boolean {\n\t\tfor (const element of this.collection) {\n\t\t\tif (!element.hasAttribute(attribute)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Insert content after all elements in the collection\n\t *\n\t * @param content - String representation of the content to add\n\t * @returns Current instance\n\t */\n\tafter(content: string): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.insertAdjacentHTML('afterend', content);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Insert content before all elements in the collection\n\t *\n\t * @param content - String representation of the content to add\n\t * @returns Current instance\n\t */\n\tbefore(content: string): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.insertAdjacentHTML('beforebegin', content);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get or modify the `style` properties of the elements matching the selector\n\t *\n\t * @param properties - Properties to change or get. Can be either an individual property or a JSON object with key-value pairs\n\t * @param value - Value to set the property to when only changing one property\n\t * @returns If a property is given but not a value for it, returns the style value(s) - single value if one element, array if multiple.\n\t */\n\tstyle(properties: string | StyleProperties, value?: string): this | string | string[] | undefined {\n\t\t// Getting a style property\n\t\tif (typeof properties === 'string' && typeof value === 'undefined') {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn (this.collection[0] as HTMLElement).style.getPropertyValue(properties);\n\t\t\t}\n\t\t\tconst values: string[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push((element as HTMLElement).style.getPropertyValue(properties));\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\n\t\t// Setting style properties\n\t\tfor (const element of this.collection) {\n\t\t\tconst el = element as HTMLElement;\n\t\t\tif (typeof properties === 'string' && typeof value !== 'undefined') {\n\t\t\t\tel.style.setProperty(properties, value);\n\t\t\t} else if (typeof properties === 'object') {\n\t\t\t\tfor (const property in properties) {\n\t\t\t\t\tel.style.setProperty(property, String(properties[property]));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Animate the given `style` properties on all elements in the collection\n\t * with a given time duration\n\t *\n\t * @param style - JSON object with the key-value pairs of properties to animate\n\t * @param time - Time in milliseconds during which the properties will be animated\n\t * @returns Current instance\n\t */\n\tanimate(style: Record<string, number>, time: number): this {\n\t\tfor (let i = 0; i < this.collection.length; i++) {\n\t\t\tconst element = this.collection[i] as HTMLElement;\n\t\t\tfor (const property in style) {\n\t\t\t\tconst start = Date.now();\n\t\t\t\tlet initialValue: number;\n\n\t\t\t\tif (typeof element.style.getPropertyValue(property) !== 'undefined' && element.style.getPropertyValue(property) !== '') {\n\t\t\t\t\tinitialValue = parseFloat(element.style.getPropertyValue(property));\n\n\t\t\t\t\tconst timer = setInterval(() => {\n\t\t\t\t\t\tconst step = Math.min(1, (Date.now() - start) / time);\n\t\t\t\t\t\telement.style.setProperty(property, String(initialValue + step * (style[property] - initialValue)));\n\n\t\t\t\t\t\tif (step === 1) {\n\t\t\t\t\t\t\tclearInterval(timer);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 25);\n\t\t\t\t\telement.style.setProperty(property, String(initialValue));\n\t\t\t\t} else if (typeof (element as unknown as Record<string, number>)[property] !== 'undefined') {\n\t\t\t\t\tinitialValue = (element as unknown as Record<string, number>)[property];\n\n\t\t\t\t\tconst timer = setInterval(() => {\n\t\t\t\t\t\tconst step = Math.min(1, (Date.now() - start) / time);\n\t\t\t\t\t\t(element as unknown as Record<string, number>)[property] = initialValue + step * (style[property] - initialValue);\n\n\t\t\t\t\t\tif (step === 1) {\n\t\t\t\t\t\t\tclearInterval(timer);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 25);\n\t\t\t\t\t(element as unknown as Record<string, number>)[property] = initialValue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Use a fade in animation on ALL elements in the collection\n\t *\n\t * @param time - Time duration for the animation\n\t * @param callback - Callback function to run once all animations are over\n\t * @returns Current instance\n\t */\n\tfadeIn(time: number = 400, callback?: () => void): this {\n\t\tlet completed = 0;\n\t\tconst total = this.collection.length;\n\n\t\tfor (const el of this.collection) {\n\t\t\tconst element = el as HTMLElement;\n\t\t\telement.style.opacity = '0';\n\n\t\t\tlet last = Date.now();\n\n\t\t\tconst tick = (): void => {\n\t\t\t\telement.style.opacity = String(parseFloat(element.style.opacity) + (Date.now() - last) / time);\n\t\t\t\tlast = Date.now();\n\n\t\t\t\tif (parseFloat(element.style.opacity) < 1) {\n\t\t\t\t\trequestAnimationFrame(tick);\n\t\t\t\t} else {\n\t\t\t\t\tcompleted++;\n\t\t\t\t\tif (completed === total && typeof callback === 'function') {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttick();\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Use a fade out animation on ALL elements in the collection\n\t *\n\t * @param time - Time duration for the animation\n\t * @param callback - Callback function to run once all animations are over\n\t * @returns Current instance\n\t */\n\tfadeOut(time: number = 400, callback?: () => void): this {\n\t\tlet completed = 0;\n\t\tconst total = this.collection.length;\n\n\t\tfor (const el of this.collection) {\n\t\t\tconst element = el as HTMLElement;\n\t\t\tlet last = Date.now();\n\n\t\t\tconst tick = (): void => {\n\t\t\t\telement.style.opacity = String(parseFloat(element.style.opacity) - (Date.now() - last) / time);\n\t\t\t\tlast = Date.now();\n\n\t\t\t\tif (parseFloat(element.style.opacity) > 0) {\n\t\t\t\t\trequestAnimationFrame(tick);\n\t\t\t\t} else {\n\t\t\t\t\tcompleted++;\n\t\t\t\t\tif (completed === total && typeof callback === 'function') {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttick();\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Check if ALL elements in the collection match a given selector\n\t *\n\t * @param selector - Selector to match\n\t * @returns Whether all elements match the selector\n\t */\n\tmatches(selector: string): boolean {\n\t\tif (this.length === 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (const element of this.collection) {\n\t\t\tif (!element.matches(selector)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove all elements in the collection\n\t *\n\t * @returns Current instance\n\t */\n\tremove(): this {\n\t\tfor (const element of this.collection) {\n\t\t\telement.parentNode?.removeChild(element);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Replace ALL elements in the collection with a new element\n\t *\n\t * @param newElement - The replacement element or HTML string\n\t * @returns Current instance\n\t */\n\treplaceWith(newElement: string | Element): this {\n\t\tfor (const element of this.collection) {\n\t\t\tlet replaceElement: Element;\n\n\t\t\tif (typeof newElement === 'string') {\n\t\t\t\tconst div = document.createElement('div');\n\t\t\t\tdiv.innerHTML = newElement;\n\t\t\t\treplaceElement = div.firstChild as Element;\n\t\t\t} else {\n\t\t\t\treplaceElement = newElement.cloneNode(true) as Element;\n\t\t\t}\n\n\t\t\telement.parentElement?.replaceChild(replaceElement, element);\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Reset every element in the collection (for form elements)\n\t *\n\t * @returns Current instance\n\t */\n\treset(): this {\n\t\tfor (const element of this.collection) {\n\t\t\tif ((element as HTMLFormElement).reset) {\n\t\t\t\t(element as HTMLFormElement).reset();\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Get or set a property for elements in the collection\n\t *\n\t * @param property - Property name to set or get\n\t * @param value - Value to set the property to\n\t * @returns If no value is provided, returns the property value(s) - single value if one element, array if multiple.\n\t */\n\tproperty<T = unknown>(property: string, value?: T): this | T | T[] | undefined {\n\t\tif (typeof value !== 'undefined') {\n\t\t\tfor (const element of this.collection) {\n\t\t\t\t(element as unknown as Record<string, T>)[property] = value;\n\t\t\t}\n\t\t\treturn this;\n\t\t} else {\n\t\t\tif (this.length === 0) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (this.length === 1) {\n\t\t\t\treturn (this.collection[0] as unknown as Record<string, T>)[property];\n\t\t\t}\n\t\t\tconst values: T[] = [];\n\t\t\tfor (const element of this.collection) {\n\t\t\t\tvalues.push((element as unknown as Record<string, T>)[property]);\n\t\t\t}\n\t\t\treturn values;\n\t\t}\n\t}\n}\n\n/**\n * Simple wrapper function to use the DOM library\n *\n * @param selector - Selector or DOM element to use\n * @returns DOM instance\n */\nexport function $_(selector: DOMSelector): DOM {\n\treturn new DOM(selector);\n}\n\n/**\n * Utility function to attach the 'load' listener to the window\n *\n * @param callback - Callback function to run when the window is ready\n */\nexport function $_ready(callback: EventListener): void {\n\twindow.addEventListener('load', callback);\n}\n\n",
7
- "/**\n * ==============================\n * Request\n * ==============================\n */\n\n/**\n * Type for request data object\n */\nexport type RequestData = Record<string, string | number | boolean>;\n\n/**\n * Type for request options\n */\nexport interface RequestOptions extends Omit<RequestInit, 'headers'> {\n\theaders?: Record<string, string>;\n}\n\n/**\n * Simple Wrapper for the fetch API, providing simple functions to handle requests\n */\nexport class Request {\n\t/**\n\t * Serialize an object of data into a URI encoded format\n\t *\n\t * @param data - Key-value object of data to serialize\n\t * @returns Serialized Data\n\t */\n\tstatic serialize(data: RequestData): string {\n\t\treturn Object.keys(data).map((key) => {\n\t\t\treturn encodeURIComponent(key) + '=' + encodeURIComponent(String(data[key]));\n\t\t}).join('&');\n\t}\n\n\t/**\n\t * Make a GET request to a given URL with the provided data parameters\n\t * and an optional configuration object for the request.\n\t *\n\t * @param url - URL to make the request to\n\t * @param data - Parameters to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the response of the request\n\t */\n\tstatic get(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Response> {\n\t\tconst query = Request.serialize(data);\n\n\t\t// Check if there is actually any data parameters and join them to the\n\t\t// url as query parameters\n\t\tif (query !== '') {\n\t\t\turl = `${url}?${query}`;\n\t\t}\n\n\t\treturn fetch(url, options as RequestInit);\n\t}\n\n\t/**\n\t * Make a POST request to a given URL with the provided data and an optional\n\t * configuration object for the request.\n\t *\n\t * @param url - URL to make the request\n\t * @param data - Set of data to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the response of the request\n\t */\n\tstatic post(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n\t\tlet formData: FormData | string;\n\n\t\tconst contentType = options.headers?.['Content-Type'];\n\t\tif (contentType !== undefined) {\n\t\t\tif (contentType === 'multipart/form-data') {\n\t\t\t\tformData = new FormData();\n\t\t\t\tfor (const value in data) {\n\t\t\t\t\tformData.append(value, String(data[value]));\n\t\t\t\t}\n\t\t\t} else if (contentType === 'application/json') {\n\t\t\t\tformData = JSON.stringify(data);\n\t\t\t} else {\n\t\t\t\tformData = Request.serialize(data);\n\t\t\t}\n\t\t} else {\n\t\t\tformData = Request.serialize(data);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {\n\t\t\t'Content-Type': 'application/x-www-form-urlencoded',\n\t\t\t...options.headers\n\t\t};\n\n\t\t// Delete the explicit multipart/form-data header to allow boundary automatic filling\n\t\tif (headers['Content-Type'] === 'multipart/form-data') {\n\t\t\tdelete headers['Content-Type'];\n\t\t}\n\n\t\tconst props: RequestInit = {\n\t\t\t...options,\n\t\t\tmethod: 'POST',\n\t\t\theaders,\n\t\t\tbody: formData\n\t\t};\n\n\t\treturn fetch(url, props);\n\t}\n\n\t/**\n\t * Make a PUT request to a given URL with the provided data and an optional\n\t * configuration object for the request.\n\t *\n\t * @param url - URL to make the request\n\t * @param data - Set of data to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the response of the request\n\t */\n\tstatic put(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n\t\treturn Request.post(url, data, Object.assign({}, { method: 'PUT' }, options));\n\t}\n\n\t/**\n\t * Make a DELETE request to a given URL with the provided data and an optional\n\t * configuration object for the request.\n\t *\n\t * @param url - URL to make the request\n\t * @param data - Parameters to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the response of the request\n\t */\n\tstatic delete(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n\t\treturn Request.get(url, data, Object.assign({}, { method: 'DELETE' }, options));\n\t}\n\n\t/**\n\t * Request a JSON object from a given URL through a GET request\n\t *\n\t * @param url - URL to make the request to\n\t * @param data - Parameters to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the json object obtained from the request response\n\t */\n\tstatic json<T = unknown>(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<T> {\n\t\treturn Request.get(url, data, options).then((response) => {\n\t\t\treturn response.json() as Promise<T>;\n\t\t});\n\t}\n\n\t/**\n\t * Request a Blob from a given URL through a GET request\n\t *\n\t * @param url - URL to make the request to\n\t * @param data - Parameters to send in the URL, represented as a JSON object\n\t * @param options - Options object for configurations you want to use in the fetch request\n\t * @returns Resolves to the blob obtained from the request response\n\t */\n\tstatic blob(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Blob> {\n\t\treturn Request.get(url, data, options).then((response) => {\n\t\t\treturn response.blob();\n\t\t});\n\t}\n}\n\n",
8
- "/**\n * ==============================\n * File System\n * ==============================\n */\n\nimport { Request, RequestOptions } from './Request';\n\n/**\n * File read type options\n */\nexport type FileReadType = 'text' | 'base64' | 'buffer';\n\n/**\n * File read result type based on read type\n */\nexport interface FileReadResult {\n\tevent: ProgressEvent<FileReader>;\n\tcontent: string | ArrayBuffer | null;\n}\n\n/**\n * A simple class wrapper for the File and FileReader web API, while this class\n * doesn't actually provide access to the host file system, it does provide useful\n * utilities for form file inputs and remote content loading.\n */\nexport class FileSystem {\n\t/**\n\t * Read a file from a remote location given a URL. This function will fetch\n\t * the file blob using the Request class and then use the read() function\n\t * to read the blob in the format required.\n\t *\n\t * @param url - URL to fetch the file from\n\t * @param type - Type of data to be read, values can be 'text', 'base64' and 'buffer'\n\t * @param props - Props to send to the Request object\n\t * @returns Content of the file. The format depends on the type parameter used.\n\t */\n\tstatic readRemote(url: string, type: FileReadType = 'base64', props: RequestOptions = {}): Promise<FileReadResult> {\n\t\treturn Request.blob(url, {}, props).then((file) => {\n\t\t\treturn FileSystem.read(file, type);\n\t\t});\n\t}\n\n\t/**\n\t * Read a given File or Blob object.\n\t *\n\t * @param file - File to read\n\t * @param type - Type of data to be read, values can be 'text', 'base64' and 'buffer'\n\t * @returns Promise that resolves to the load event and content of the file\n\t */\n\tstatic read(file: File | Blob, type: FileReadType = 'text'): Promise<FileReadResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst reader = new FileReader();\n\n\t\t\treader.onload = (event: ProgressEvent<FileReader>) => {\n\t\t\t\t// Pass down the event object and the content\n\t\t\t\tresolve({\n\t\t\t\t\tevent,\n\t\t\t\t\tcontent: event.target?.result ?? null\n\t\t\t\t});\n\t\t\t};\n\n\t\t\treader.onerror = (error) => {\n\t\t\t\treject(error);\n\t\t\t};\n\n\t\t\tif (type === 'base64') {\n\t\t\t\treader.readAsDataURL(file);\n\t\t\t} else if (type === 'buffer') {\n\t\t\t\treader.readAsArrayBuffer(file);\n\t\t\t} else {\n\t\t\t\treader.readAsText(file, 'UTF-8');\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Create a new File, this uses the File API and will not actually create\n\t * a file in the user's file system, however using it with other features,\n\t * that may be possible\n\t *\n\t * @param name - Name of the file (Including extension)\n\t * @param content - Content to save in the file\n\t * @param type - Mime Type for the file\n\t * @returns Promise resolving to the created File\n\t */\n\tstatic create(name: string, content: BlobPart, type: string = 'text/plain'): Promise<File> {\n\t\treturn Promise.resolve(new File([content], name, { type }));\n\t}\n\n\t/**\n\t * Returns the extension of a file given its file name.\n\t *\n\t * @param name - Name or full path of the file\n\t * @returns File extension without the leading dot (.)\n\t */\n\tstatic extension(name: string): string {\n\t\treturn name.split('.').pop() ?? '';\n\t}\n\n\t/**\n\t * Check if a file is an image by its extension.\n\t *\n\t * @param name - Name or full path of the file\n\t * @returns Whether the file is an image\n\t */\n\tstatic isImage(name: string): boolean {\n\t\tconst extensions = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp', 'bmp'];\n\t\treturn extensions.indexOf(FileSystem.extension(name).toLowerCase()) > -1;\n\t}\n}\n\n",
9
- "/**\n * ==============================\n * Form\n * ==============================\n */\n\nimport { $_ } from './DOM';\n\n/**\n * Form data object type\n */\nexport type FormData = Record<string, string | File | FileList | undefined>;\n\n/**\n * Utility class that provides simple functions for filling and retrieving values\n * from forms. This class requires the use of the `data-form` attribute.\n */\nexport class Form {\n\t/**\n\t * Fill a form's inputs with the given values. Each key in the provided object\n\t * must match the `name` attribute of the input to fill.\n\t *\n\t * @param name - Form name. Must match the `data-form` attribute of the Form.\n\t * @param data - JSON object with key-value pairs to fill the inputs.\n\t */\n\tstatic fill(name: string, data: Record<string, string>): void {\n\t\tfor (const field in data) {\n\t\t\tconst element = $_(`form[data-form='${name}'] [name='${field}']`).get(0) as HTMLInputElement | undefined;\n\t\t\tif (typeof element !== 'undefined') {\n\t\t\t\tswitch (element.type) {\n\t\t\t\t\tcase 'file':\n\t\t\t\t\tcase 'file[]':\n\t\t\t\t\t\t// Cannot programmatically set file input values\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\telement.value = data[field];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get all the values from a form's inputs. The keys are mapped using the\n\t * `name` attribute of each input.\n\t *\n\t * @param name - Form name. Must match the `data-form` attribute of the Form.\n\t * @returns Key-value JSON object\n\t */\n\tstatic values(name: string): FormData {\n\t\tconst data: FormData = {};\n\t\t$_(`form[data-form='${name}'] [name]`).each((el: Element) => {\n\t\t\tconst element = el as HTMLInputElement;\n\t\t\tlet value: string | File | FileList | undefined;\n\t\t\tswitch (element.type) {\n\t\t\t\tcase 'file[]':\n\t\t\t\t\tvalue = element.files ?? undefined;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'file':\n\t\t\t\t\tvalue = element.files?.[0];\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tvalue = element.value;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (typeof value !== 'undefined' && value !== null) {\n\t\t\t\tdata[element.name] = value;\n\t\t\t}\n\t\t});\n\n\t\treturn data;\n\t}\n}\n\n",
10
- "/**\n * ==============================\n * Platform\n * ==============================\n */\n\n/**\n * Desktop platform types\n */\nexport type DesktopPlatform = 'Windows' | 'macOS' | 'Linux' | 'FreeBSD' | 'webOS' | 'Any';\n\n/**\n * Mobile platform types\n */\nexport type MobilePlatform = 'Android' | 'iOS' | 'Opera' | 'Windows' | 'BlackBerry' | 'Any';\n\n/**\n * Orientation types\n */\nexport type Orientation = 'portrait' | 'landscape';\n\n/**\n * Extended Navigator interface for userAgentData\n */\ninterface NavigatorUAData {\n\tplatform?: string;\n\tbrands?: { brand: string; version: string }[];\n\tmobile?: boolean;\n}\n\ndeclare global {\n\tinterface Navigator {\n\t\tuserAgentData?: NavigatorUAData;\n\t}\n}\n\n/**\n * Extended window interface for process (Electron)\n */\ninterface ElectronWindow extends Window {\n\tprocess?: {\n\t\ttype?: string;\n\t\tversions?: {\n\t\t\telectron?: string;\n\t\t};\n\t};\n\tcordova?: unknown;\n}\n\n/**\n * General checks for what kind of platform is being used to run the app.\n */\nexport class Platform {\n\t/**\n\t * Check if the screen has a retina pixel ratio\n\t * @returns Whether the screen is retina\n\t */\n\tstatic retina(): boolean {\n\t\treturn window.devicePixelRatio >= 2;\n\t}\n\n\t/**\n\t * Check if the device is on portrait orientation\n\t * @returns Whether device is in portrait mode\n\t */\n\tstatic portrait(): boolean {\n\t\treturn window.screen.orientation.type === 'portrait-primary' || window.screen.orientation.type === 'portrait-secondary';\n\t}\n\n\t/**\n\t * Check if the device is on landscape orientation\n\t * @returns Whether device is in landscape mode\n\t */\n\tstatic landscape(): boolean {\n\t\treturn window.screen.orientation.type === 'landscape-primary' || window.screen.orientation.type === 'landscape-secondary';\n\t}\n\n\t/**\n\t * Get device Orientation\n\t * @returns 'portrait' or 'landscape'\n\t */\n\tstatic orientation(): Orientation {\n\t\treturn Platform.portrait() ? 'portrait' : 'landscape';\n\t}\n\n\t/**\n\t * Check if the app is running over Electron\n\t * @returns Whether running in Electron\n\t */\n\tstatic electron(): boolean {\n\t\tconst win = window as ElectronWindow;\n\n\t\t// Renderer process\n\t\tif (typeof win !== 'undefined' && typeof win.process === 'object' && win.process?.type === 'renderer') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Main process (Node.js/Electron environment)\n\t\tconst nodeProcess = typeof globalThis !== 'undefined' ? (globalThis as { process?: { versions?: { electron?: string } } }).process : undefined;\n\t\tif (nodeProcess && typeof nodeProcess.versions === 'object' && !!nodeProcess.versions?.electron) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Detect the user agent when the `nodeIntegration` option is set to true\n\t\tif (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Check if the app is running over Cordova\n\t * @returns Whether running in Cordova\n\t */\n\tstatic cordova(): boolean {\n\t\treturn !!(window as ElectronWindow).cordova;\n\t}\n\n\t/**\n\t * Get the platform string using modern userAgentData API with fallback\n\t * @returns Platform string\n\t */\n\tprivate static getPlatformString(): string {\n\t\t// Try modern userAgentData first\n\t\tif (navigator.userAgentData?.platform) {\n\t\t\treturn navigator.userAgentData.platform;\n\t\t}\n\t\t// Fallback to userAgent parsing\n\t\tconst ua = navigator.userAgent;\n\t\tif (ua.includes('Win')) return 'Windows';\n\t\tif (ua.includes('Mac')) return 'macOS';\n\t\tif (ua.includes('Linux')) return 'Linux';\n\t\tif (ua.includes('FreeBSD')) return 'FreeBSD';\n\t\tif (ua.includes('WebTV')) return 'webOS';\n\t\treturn '';\n\t}\n\n\t/**\n\t * Check if the app is running in a desktop platform\n\t * @param platform - Check for a specific desktop platform\n\t * @returns Whether running on specified desktop platform\n\t */\n\tstatic desktop(platform: DesktopPlatform = 'Any'): boolean {\n\t\tconst platformString = Platform.getPlatformString();\n\n\t\tswitch (platform) {\n\t\t\tcase 'Windows':\n\t\t\t\treturn platformString === 'Windows' || platformString.includes('Win');\n\n\t\t\tcase 'macOS':\n\t\t\t\treturn platformString === 'macOS' || platformString.includes('Mac');\n\n\t\t\tcase 'Linux':\n\t\t\t\treturn platformString === 'Linux' || platformString.includes('Linux');\n\n\t\t\tcase 'FreeBSD':\n\t\t\t\treturn platformString === 'FreeBSD' || platformString.includes('FreeBSD');\n\n\t\t\tcase 'webOS':\n\t\t\t\treturn platformString === 'webOS' || platformString.includes('WebTV');\n\n\t\t\tcase 'Any':\n\t\t\tdefault:\n\t\t\t\treturn ['Windows', 'macOS', 'Linux', 'FreeBSD', 'webOS'].some(p =>\n\t\t\t\t\tplatformString === p || platformString.includes(p.replace('macOS', 'Mac').replace('webOS', 'WebTV'))\n\t\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the app is running in a mobile platform\n\t * @param platform - Check for a specific mobile platform\n\t * @returns Whether running on specified mobile platform\n\t */\n\tstatic mobile(platform: MobilePlatform = 'Any'): boolean {\n\t\t// Try modern userAgentData first for general mobile detection\n\t\tif (navigator.userAgentData?.mobile !== undefined && platform === 'Any') {\n\t\t\treturn navigator.userAgentData.mobile;\n\t\t}\n\n\t\t// Fallback to userAgent for specific platform detection\n\t\tconst ua = navigator.userAgent;\n\n\t\tswitch (platform) {\n\t\t\tcase 'Android':\n\t\t\t\treturn /Android/i.test(ua);\n\n\t\t\tcase 'iOS':\n\t\t\t\treturn /iPhone|iPad|iPod/i.test(ua);\n\n\t\t\tcase 'Opera':\n\t\t\t\treturn /Opera Mini/i.test(ua);\n\n\t\t\tcase 'Windows':\n\t\t\t\treturn /Windows Phone|IEMobile|WPDesktop/i.test(ua);\n\n\t\t\tcase 'BlackBerry':\n\t\t\t\treturn /BlackBerry|BB10/i.test(ua);\n\n\t\t\tcase 'Any':\n\t\t\tdefault:\n\t\t\t\treturn /Android|iPhone|iPad|iPod|Windows Phone|IEMobile|WPDesktop|BlackBerry|BB10/i.test(ua);\n\t\t}\n\t}\n\n\t/**\n\t * Check if the platform allows the use of service workers\n\t *\n\t * @returns Whether service workers are supported\n\t */\n\tstatic serviceWorkers(): boolean {\n\t\tif (typeof navigator !== 'undefined') {\n\t\t\tif ('serviceWorker' in navigator && location.protocol.indexOf('http') > -1) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\n",
11
- "/**\n * ==============================\n * Preload\n * ==============================\n */\n\nimport { Request } from './Request';\n\n/**\n * A simple class for asset preloading. This class assumes you have a service\n * worker set up that will be caching all requests.\n */\nexport class Preload {\n\t/**\n\t * Preload an image file\n\t *\n\t * @param route - Route to the image\n\t * @returns Resolves to the image object or gets rejected with the rejection event\n\t */\n\tstatic image(route: string): Promise<HTMLImageElement> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst image = new Image();\n\n\t\t\timage.onload = () => {\n\t\t\t\tresolve(image);\n\t\t\t};\n\n\t\t\timage.onerror = (e) => {\n\t\t\t\treject(e);\n\t\t\t};\n\n\t\t\timage.src = route;\n\t\t});\n\t}\n\n\t/**\n\t * Preload any kind of file\n\t *\n\t * @param route - Route to the file\n\t * @returns Resolves or rejects depending on request success\n\t */\n\tstatic file(route: string): Promise<Blob> {\n\t\treturn Request.blob(route);\n\t}\n}\n\n",
12
- "/**\n * ==============================\n * Local Storage Adapter\n * ==============================\n */\n\nimport type { LocalStorageConfiguration, StorageValue, KeyValueResult, UpgradeCallback } from './types';\n\n/**\n * The Local Storage Adapter provides the Space Class the ability to interact\n * with the localStorage API found in most modern browsers.\n */\nexport class LocalStorage {\n\tpublic name: string;\n\tpublic version: string;\n\tpublic store: string;\n\tpublic id: string;\n\tpublic numericVersion: number;\n\tpublic upgrades: Record<string, UpgradeCallback<LocalStorage>>;\n\tpublic storage: Storage | Promise<LocalStorage> | undefined;\n\n\t/**\n\t * Create a new LocalStorage. If no configuration is provided, the LocalStorage\n\t * global object is used. The LocalStorage Adapter can provide independency\n\t * by store name and space name.\n\t *\n\t * @param configuration - Configuration Object for the Adapter\n\t */\n\tconstructor({ name = '', version = '', store = '' }: LocalStorageConfiguration) {\n\t\tthis.name = name;\n\t\tthis.version = version;\n\t\tthis.store = store;\n\t\tthis.upgrades = {};\n\n\t\tif (this.version === '') {\n\t\t\tthis.numericVersion = 0;\n\t\t} else {\n\t\t\tthis.numericVersion = parseInt(version.replace(/\\./g, ''));\n\t\t}\n\n\t\tif (name !== '' && version !== '' && store !== '') {\n\t\t\tthis.id = `${this.name}::${this.store}::${this.version}_`;\n\t\t} else if (name !== '' && version !== '') {\n\t\t\tthis.id = `${this.name}::${this.version}_`;\n\t\t} else if (name !== '') {\n\t\t\tthis.id = `${this.name}::_`;\n\t\t} else {\n\t\t\tthis.id = '';\n\t\t}\n\t}\n\n\t/**\n\t * Modify the configuration\n\t *\n\t * @param config - Configuration object to set up\n\t */\n\tconfiguration(config: LocalStorageConfiguration): void {\n\t\tif (config.name) this.name = config.name;\n\t\tif (config.version) this.version = config.version;\n\t\tif (config.store) this.store = config.store;\n\t}\n\n\t/**\n\t * Open the Storage Object\n\t *\n\t * @returns Promise resolving to this adapter\n\t */\n\topen(): Promise<this> {\n\t\tif (this.storage instanceof Storage) {\n\t\t\treturn Promise.resolve(this);\n\t\t} else if (this.storage instanceof Promise) {\n\t\t\treturn this.storage as Promise<this>;\n\t\t} else {\n\t\t\tconst openPromise: Promise<this> = new Promise<{ upgrades: string[] }>((resolve) => {\n\t\t\t\tlet upgradesToApply: string[] = [];\n\n\t\t\t\t// Check if this space is versioned\n\t\t\t\tif (this.version !== '') {\n\t\t\t\t\t// Get the versionless part of the ID\n\t\t\t\t\tlet versionless = '';\n\t\t\t\t\tif (this.name !== '' && this.version !== '' && this.store !== '') {\n\t\t\t\t\t\tversionless = `${this.name}::${this.store}::`;\n\t\t\t\t\t} else if (this.name !== '' && this.version !== '') {\n\t\t\t\t\t\tversionless = `${this.name}::`;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get all the currently stored keys that contain the versionless ID\n\t\t\t\t\tconst storedVersions = Object.keys(window.localStorage).filter((key) => {\n\t\t\t\t\t\treturn key.indexOf(versionless) === 0;\n\t\t\t\t\t}).map((key) => {\n\t\t\t\t\t\treturn key.replace(versionless, '').split('_')[0];\n\t\t\t\t\t}).filter((key) => {\n\t\t\t\t\t\treturn key.indexOf('::') === -1;\n\t\t\t\t\t}).sort();\n\n\t\t\t\t\tif (storedVersions.length > 0) {\n\t\t\t\t\t\tconst oldVersion = storedVersions[0];\n\t\t\t\t\t\tconst oldVersionNumeric = parseInt(oldVersion.replace(/\\./g, ''));\n\n\t\t\t\t\t\tif (oldVersionNumeric < this.numericVersion) {\n\t\t\t\t\t\t\tconst availableUpgrades = Object.keys(this.upgrades).sort();\n\n\t\t\t\t\t\t\tconst startFrom = availableUpgrades.findIndex((u) => {\n\t\t\t\t\t\t\t\tconst [old] = u.split('::');\n\t\t\t\t\t\t\t\treturn parseInt(old) === oldVersionNumeric;\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (startFrom > -1) {\n\t\t\t\t\t\t\t\tupgradesToApply = availableUpgrades.slice(startFrom).filter((u) => {\n\t\t\t\t\t\t\t\t\tconst [old, next] = u.split('::');\n\t\t\t\t\t\t\t\t\treturn parseInt(old) < this.numericVersion && parseInt(next) <= this.numericVersion;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Get the previous ID using the old version\n\t\t\t\t\t\t\tlet previousId = `${this.name}::${oldVersion}_`;\n\n\t\t\t\t\t\t\tif (this.name !== '' && this.version !== '' && this.store !== '') {\n\t\t\t\t\t\t\t\tpreviousId = `${this.name}::${this.store}::${oldVersion}_`;\n\t\t\t\t\t\t\t} else if (this.name !== '' && this.version !== '') {\n\t\t\t\t\t\t\t\tpreviousId = `${this.name}::${oldVersion}_`;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Get all keys from the previous version\n\t\t\t\t\t\t\tconst keys = Object.keys(window.localStorage).filter((key) => {\n\t\t\t\t\t\t\t\treturn key.indexOf(previousId) === 0;\n\t\t\t\t\t\t\t}).map((key) => {\n\t\t\t\t\t\t\t\treturn key.replace(previousId, '');\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tfor (const key of keys) {\n\t\t\t\t\t\t\t\tconst previous = window.localStorage.getItem(`${previousId}${key}`);\n\t\t\t\t\t\t\t\tif (previous !== null) {\n\t\t\t\t\t\t\t\t\twindow.localStorage.setItem(this.id + key, previous);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.localStorage.removeItem(`${previousId}${key}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresolve({ upgrades: upgradesToApply });\n\t\t\t}).then(({ upgrades }) => {\n\t\t\t\tthis.storage = window.localStorage;\n\t\t\t\treturn new Promise<this>((resolve) => {\n\t\t\t\t\tconst res = () => resolve(this);\n\t\t\t\t\tthis._upgrade(upgrades, res);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.storage = openPromise as unknown as Promise<LocalStorage>;\n\t\t\treturn openPromise;\n\t\t}\n\t}\n\n\t/**\n\t * Store a key-value pair\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tset(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.open().then(() => {\n\t\t\tif (typeof value === 'object') {\n\t\t\t\t(this.storage as Storage).setItem(this.id + key, JSON.stringify(value));\n\t\t\t} else {\n\t\t\t\t(this.storage as Storage).setItem(this.id + key, String(value));\n\t\t\t}\n\t\t\treturn Promise.resolve({ key, value });\n\t\t});\n\t}\n\n\t/**\n\t * Update a key-value pair. The update method will use Object.assign()\n\t * in the case of objects so no value is lost.\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tupdate(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.get(key).then((currentValue) => {\n\t\t\tif (typeof currentValue === 'object' && currentValue !== null) {\n\t\t\t\tif (typeof value === 'object' && value !== null) {\n\t\t\t\t\tvalue = Object.assign({}, currentValue as object, value as object);\n\t\t\t\t}\n\t\t\t\t(this.storage as Storage).setItem(this.id + key, JSON.stringify(value));\n\t\t\t} else {\n\t\t\t\t(this.storage as Storage).setItem(this.id + key, String(value));\n\t\t\t}\n\t\t\treturn Promise.resolve({ key, value });\n\t\t}).catch(() => {\n\t\t\treturn this.set(key, value);\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves a value from storage given its key\n\t *\n\t * @param key - Key with which the value was saved\n\t * @returns Promise resolving to the retrieved value\n\t */\n\tget(key: string): Promise<StorageValue> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tlet value: StorageValue = (this.storage as Storage).getItem(this.id + key);\n\t\t\t\ttry {\n\t\t\t\t\tconst o = JSON.parse(value as string);\n\t\t\t\t\tif (o && typeof o === 'object') {\n\t\t\t\t\t\tvalue = o;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Unable to parse to JSON\n\t\t\t\t}\n\n\t\t\t\tif (typeof value !== 'undefined' && value !== null) {\n\t\t\t\t\tresolve(value);\n\t\t\t\t} else {\n\t\t\t\t\treject();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves all the values in the space in a key-value JSON object\n\t *\n\t * @returns Promise resolving to all values\n\t */\n\tgetAll(): Promise<Record<string, StorageValue>> {\n\t\treturn this.keys().then((keys) => {\n\t\t\tconst values: Record<string, StorageValue> = {};\n\t\t\tconst promises: Promise<void>[] = [];\n\t\t\tfor (const key of keys) {\n\t\t\t\tpromises.push(this.get(key).then((value) => {\n\t\t\t\t\tvalues[key] = value;\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn Promise.all(promises).then(() => values);\n\t\t});\n\t}\n\n\t/**\n\t * Check if the space contains a given key.\n\t *\n\t * @param key - Key to look for\n\t * @returns Promise that resolves if key exists\n\t */\n\tcontains(key: string): Promise<void> {\n\t\treturn this.keys().then((keys) => {\n\t\t\tif (keys.includes(key)) {\n\t\t\t\treturn Promise.resolve();\n\t\t\t} else {\n\t\t\t\treturn Promise.reject();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Upgrade a Space Version\n\t *\n\t * @param oldVersion - The version of the storage to be upgraded\n\t * @param newVersion - The version to be upgraded to\n\t * @param callback - Function to transform the old stored values\n\t * @returns Promise\n\t */\n\tupgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback<LocalStorage>): Promise<void> {\n\t\tconst key = `${parseInt(oldVersion.replace(/\\./g, ''))}::${parseInt(newVersion.replace(/\\./g, ''))}`;\n\t\tthis.upgrades[key] = callback;\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * Helper for the upgrade progress by executing callbacks in order\n\t */\n\tprivate _upgrade(upgradesToApply: string[], resolve: () => void): void {\n\t\tif (upgradesToApply.length > 0) {\n\t\t\tthis.upgrades[upgradesToApply[0]].call(this, this).then(() => {\n\t\t\t\tthis._upgrade(upgradesToApply.slice(1), resolve);\n\t\t\t}).catch((e) => console.error(e));\n\t\t} else {\n\t\t\tresolve();\n\t\t}\n\t}\n\n\t/**\n\t * Rename a Space\n\t *\n\t * @param name - New name to be used\n\t * @returns Promise for the rename operation\n\t */\n\trename(name: string): Promise<void> {\n\t\tif (this.name !== name) {\n\t\t\treturn this.keys().then((keys) => {\n\t\t\t\tconst oldId = this.id;\n\t\t\t\tthis.name = name;\n\n\t\t\t\tif (this.name !== '' && this.version !== '' && this.store !== '') {\n\t\t\t\t\tthis.id = `${this.name}::${this.store}::${this.version}_`;\n\t\t\t\t} else if (this.name !== '' && this.version !== '') {\n\t\t\t\t\tthis.id = `${this.name}::${this.version}_`;\n\t\t\t\t} else if (this.name !== '') {\n\t\t\t\t\tthis.id = `${this.name}::_`;\n\t\t\t\t} else {\n\t\t\t\t\tthis.id = '';\n\t\t\t\t}\n\n\t\t\t\tconst promises: Promise<void>[] = [];\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst value = (this.storage as Storage).getItem(`${oldId}${key}`);\n\t\t\t\t\tif (value !== null) {\n\t\t\t\t\t\tpromises.push(this.set(key, value).then(() => {\n\t\t\t\t\t\t\t(this.storage as Storage).removeItem(`${oldId}${key}`);\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Promise.all(promises).then(() => {});\n\t\t\t});\n\t\t} else {\n\t\t\treturn Promise.reject();\n\t\t}\n\t}\n\n\t/**\n\t * Get the key that corresponds to a given index in the storage\n\t *\n\t * @param index - Index to get the key from\n\t * @param full - Whether to return the full key name including space id\n\t * @returns Promise resolving to the key's name\n\t */\n\tkey(index: number, full: boolean = false): Promise<string> {\n\t\treturn this.open().then(() => {\n\t\t\tconst keyValue = (this.storage as Storage).key(index);\n\t\t\tif (full === true) {\n\t\t\t\treturn Promise.resolve(keyValue ?? '');\n\t\t\t} else {\n\t\t\t\treturn Promise.resolve((keyValue ?? '').replace(this.id, ''));\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Return all keys stored in the space.\n\t *\n\t * @param full - Whether to return the full key name including space id\n\t * @returns Promise resolving to array of keys\n\t */\n\tkeys(full: boolean = false): Promise<string[]> {\n\t\treturn this.open().then(() => {\n\t\t\treturn Promise.resolve(Object.keys(this.storage as Storage).filter((key) => {\n\t\t\t\treturn key.indexOf(this.id) === 0;\n\t\t\t}).map((key) => {\n\t\t\t\tif (full === true) {\n\t\t\t\t\treturn key;\n\t\t\t\t} else {\n\t\t\t\t\treturn key.replace(this.id, '');\n\t\t\t\t}\n\t\t\t}));\n\t\t});\n\t}\n\n\t/**\n\t * Delete a value from the space given its key\n\t *\n\t * @param key - Key of the item to delete\n\t * @returns Promise resolving to the value of the deleted object\n\t */\n\tremove(key: string): Promise<StorageValue> {\n\t\treturn this.get(key).then((value) => {\n\t\t\t(this.storage as Storage).removeItem(this.id + key);\n\t\t\treturn Promise.resolve(value);\n\t\t});\n\t}\n\n\t/**\n\t * Clear the entire space\n\t *\n\t * @returns Promise for the clear operation\n\t */\n\tclear(): Promise<void> {\n\t\treturn this.keys().then((keys) => {\n\t\t\tfor (const key of keys) {\n\t\t\t\tthis.remove(key);\n\t\t\t}\n\t\t\treturn Promise.resolve();\n\t\t});\n\t}\n}\n\n",
13
- "/**\n * ==============================\n * Session Storage Adapter\n * ==============================\n */\n\nimport { LocalStorage } from './LocalStorage';\nimport type { LocalStorageConfiguration } from './types';\n\n/**\n * The Session Storage Adapter provides the Space Class the ability to interact\n * with the sessionStorage API found in most modern browsers. Since this API\n * shares pretty much the same methods as the local storage one, this class\n * inherits from the LocalStorage adapter.\n */\nexport class SessionStorage extends LocalStorage {\n\t/**\n\t * Create a new SessionStorage. If no configuration is provided, the SessionStorage\n\t * global object is used. The SessionStorage Adapter can provide independency\n\t * by store name and space name.\n\t *\n\t * @param configuration - Configuration Object for the Adapter\n\t */\n\tconstructor({ name = '', version = '', store = '' }: LocalStorageConfiguration) {\n\t\tsuper({ name, version, store });\n\t}\n\n\t/**\n\t * Open the Storage Object\n\t *\n\t * @returns Promise resolving to this adapter\n\t */\n\topen(): Promise<this> {\n\t\tif (typeof this.storage === 'undefined') {\n\t\t\tthis.storage = window.sessionStorage;\n\t\t}\n\t\treturn Promise.resolve(this);\n\t}\n}\n\n",
14
- "/**\n * ==============================\n * IndexedDB Adapter\n * ==============================\n */\n\nimport type { IndexedDBConfiguration, StorageValue, KeyValueResult, UpgradeCallback } from './types';\n\n/**\n * The IndexedDB Adapter provides the Space Class the ability to interact\n * with the IndexedDB API found in most modern browsers.\n */\nexport class IndexedDB {\n\tpublic name: string;\n\tpublic version: string;\n\tpublic store: string;\n\tpublic props: IDBObjectStoreParameters;\n\tpublic index: Record<string, { name: string; field: string; props?: IDBIndexParameters }>;\n\tpublic keyPath: string;\n\tpublic numericVersion: number;\n\tpublic upgrades: Record<string, UpgradeCallback<IndexedDB>>;\n\tpublic storage: IDBDatabase | Promise<IDBDatabase> | undefined;\n\n\t/**\n\t * Create a new IndexedDB. Differently from Local and Session Storages, the\n\t * IndexedDB Adapter requires a mandatory name, version and store name.\n\t *\n\t * @param configuration - Configuration Object for the Adapter\n\t */\n\tconstructor({ name = '', version = '', store = '', props = {}, index = {} }: IndexedDBConfiguration) {\n\t\tthis.name = name;\n\t\tthis.version = version;\n\t\tthis.store = store;\n\t\tthis.props = props || {};\n\t\tthis.index = index;\n\n\t\tthis.keyPath = (props?.keyPath as string) || 'id';\n\t\tthis.upgrades = {};\n\n\t\tif (this.version === '') {\n\t\t\tthis.numericVersion = 0;\n\t\t} else {\n\t\t\tthis.numericVersion = parseInt(version.replace(/\\./g, ''));\n\t\t}\n\t}\n\n\t/**\n\t * Modify the configuration\n\t *\n\t * @param config - Configuration object to set up\n\t */\n\tconfiguration(config: IndexedDBConfiguration): void {\n\t\tif (config.name) this.name = config.name;\n\t\tif (config.version) this.version = config.version;\n\t\tif (config.store) this.store = config.store;\n\t}\n\n\t/**\n\t * Open the Storage Object\n\t *\n\t * @returns Promise resolving to this adapter\n\t */\n\topen(): Promise<this> {\n\t\tif (this.name === '') {\n\t\t\tconsole.error('No name has been defined for IndexedDB space.');\n\t\t\treturn Promise.reject();\n\t\t}\n\n\t\tif (this.store === '') {\n\t\t\tconsole.error('No store has been defined for IndexedDB space.');\n\t\t\treturn Promise.reject();\n\t\t}\n\n\t\tif (this.storage instanceof IDBDatabase) {\n\t\t\treturn Promise.resolve(this);\n\t\t} else if (this.storage instanceof Promise) {\n\t\t\treturn this.storage as unknown as Promise<this>;\n\t\t} else {\n\t\t\tlet upgradeEvent: IDBVersionChangeEvent | undefined;\n\n\t\t\tconst openPromise = new Promise<{ storage: IDBDatabase; upgrades: string[] }>((resolve, reject) => {\n\t\t\t\tlet upgradesToApply: string[] = [];\n\t\t\t\tconst request = window.indexedDB.open(this.name, this.numericVersion);\n\n\t\t\t\trequest.onerror = (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t};\n\n\t\t\t\trequest.onsuccess = (event) => {\n\t\t\t\t\tresolve({ storage: (event.target as IDBOpenDBRequest).result, upgrades: upgradesToApply });\n\t\t\t\t};\n\n\t\t\t\trequest.onupgradeneeded = (event: IDBVersionChangeEvent) => {\n\t\t\t\t\tupgradeEvent = event;\n\t\t\t\t\tconst db = (event.target as IDBOpenDBRequest).result;\n\n\t\t\t\t\tif (event.oldVersion < 1) {\n\t\t\t\t\t\t// Create all the needed Stores\n\t\t\t\t\t\tconst store = db.createObjectStore(this.store, this.props);\n\t\t\t\t\t\tfor (const indexKey of Object.keys(this.index)) {\n\t\t\t\t\t\t\tconst idx = this.index[indexKey];\n\t\t\t\t\t\t\tstore.createIndex(idx.name, idx.field, idx.props);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Check what upgrade functions have been declared\n\t\t\t\t\t\tconst availableUpgrades = Object.keys(this.upgrades).sort();\n\n\t\t\t\t\t\tconst startFrom = availableUpgrades.findIndex((u) => {\n\t\t\t\t\t\t\tconst [old] = u.split('::');\n\t\t\t\t\t\t\treturn parseInt(old) === event.oldVersion;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (startFrom > -1) {\n\t\t\t\t\t\t\tupgradesToApply = availableUpgrades.slice(startFrom).filter((u) => {\n\t\t\t\t\t\t\t\tconst [old, next] = u.split('::');\n\t\t\t\t\t\t\t\treturn parseInt(old) < this.numericVersion && parseInt(next) <= this.numericVersion;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Once the transaction is done, resolve the storage object\n\t\t\t\t\tconst transaction = (event.target as IDBOpenDBRequest).transaction;\n\t\t\t\t\tif (transaction) {\n\t\t\t\t\t\ttransaction.addEventListener('complete', () => {\n\t\t\t\t\t\t\tresolve({ storage: db, upgrades: upgradesToApply });\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}).then(({ storage, upgrades }) => {\n\t\t\t\tthis.storage = storage;\n\t\t\t\treturn new Promise<this>((resolve) => {\n\t\t\t\t\tconst res = () => resolve(this);\n\t\t\t\t\tthis._upgrade(upgrades, res, upgradeEvent);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.storage = openPromise as unknown as Promise<IDBDatabase>;\n\t\t\treturn openPromise;\n\t\t}\n\t}\n\n\t/**\n\t * Store a key-value pair. Because of the nature of IndexedDB,\n\t * stored values must be JSON objects.\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tset(key: string | null = null, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store, 'readwrite')\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tlet op: IDBRequest;\n\n\t\t\t\tif (key !== null) {\n\t\t\t\t\tconst temp: Record<string, unknown> = {};\n\t\t\t\t\ttemp[this.keyPath] = key;\n\t\t\t\t\top = transaction.put(Object.assign({}, temp, value as object));\n\t\t\t\t} else {\n\t\t\t\t\top = transaction.add(value);\n\t\t\t\t}\n\n\t\t\t\top.addEventListener('success', (event) => {\n\t\t\t\t\tresolve({ key: String((event.target as IDBRequest).result), value });\n\t\t\t\t});\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Update a key-value pair. The update method will use Object.assign()\n\t * in the case of objects so no value is lost.\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tupdate(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.get(key).then((currentValue) => {\n\t\t\tif (typeof currentValue === 'undefined') {\n\t\t\t\treturn this.set(key, value);\n\t\t\t}\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store, 'readwrite')\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.put(Object.assign({}, currentValue as object, value as object));\n\n\t\t\t\top.addEventListener('success', (event) => {\n\t\t\t\t\tresolve({ key: String((event.target as IDBRequest).result), value });\n\t\t\t\t});\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves a value from storage given its key\n\t *\n\t * @param key - Key with which the value was saved\n\t * @returns Promise resolving to the retrieved value\n\t */\n\tget(key: string): Promise<StorageValue> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store)\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.get(key);\n\n\t\t\t\top.addEventListener('success', (event) => {\n\t\t\t\t\tconst value = (event.target as IDBRequest).result;\n\t\t\t\t\tif (typeof value !== 'undefined' && value !== null) {\n\t\t\t\t\t\tresolve(value);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves all the values in the space in a key-value JSON object\n\t *\n\t * @returns Promise resolving to all values\n\t */\n\tgetAll(): Promise<Record<string, StorageValue>> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store)\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.getAll();\n\n\t\t\t\top.addEventListener('success', (event) => {\n\t\t\t\t\tconst results: Record<string, StorageValue> = {};\n\t\t\t\t\tconst items = (event.target as IDBRequest).result as Record<string, unknown>[];\n\t\t\t\t\titems.forEach((item) => {\n\t\t\t\t\t\tconst id = item[this.keyPath] as string;\n\t\t\t\t\t\tdelete item[this.keyPath];\n\t\t\t\t\t\tresults[id] = item;\n\t\t\t\t\t});\n\t\t\t\t\tresolve(results);\n\t\t\t\t});\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Check if the space contains a given key.\n\t *\n\t * @param key - Key to look for\n\t * @returns Promise that resolves if key exists\n\t */\n\tcontains(key: string): Promise<void> {\n\t\treturn this.get(key).then(() => {\n\t\t\treturn Promise.resolve();\n\t\t});\n\t}\n\n\t/**\n\t * Upgrade a Space Version. Upgrades must be declared before the open()\n\t * method is executed.\n\t *\n\t * @param oldVersion - The version to be upgraded\n\t * @param newVersion - The version to be upgraded to\n\t * @param callback - Function to transform the old stored values\n\t * @returns Promise\n\t */\n\tupgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback<IndexedDB>): Promise<void> {\n\t\tconst key = `${parseInt(oldVersion.replace(/\\./g, ''))}::${parseInt(newVersion.replace(/\\./g, ''))}`;\n\t\tthis.upgrades[key] = callback;\n\t\treturn Promise.resolve();\n\t}\n\n\t/**\n\t * Helper for the upgrade progress by executing callbacks in order\n\t */\n\tprivate _upgrade(upgradesToApply: string[], resolve: () => void, event?: IDBVersionChangeEvent): void {\n\t\tif (upgradesToApply.length > 0) {\n\t\t\tthis.upgrades[upgradesToApply[0]].call(this, this, event).then(() => {\n\t\t\t\tthis._upgrade(upgradesToApply.slice(1), resolve, event);\n\t\t\t}).catch((e) => console.error(e));\n\t\t} else {\n\t\t\tresolve();\n\t\t}\n\t}\n\n\t/**\n\t * Renaming the space is not possible with the IndexedDB adapter therefore\n\t * this function always gets rejected.\n\t *\n\t * @returns Promise rejection\n\t */\n\trename(): Promise<never> {\n\t\treturn Promise.reject();\n\t}\n\n\t/**\n\t * Getting a key by its index is not possible in this adapter, therefore this\n\t * function always gets rejected.\n\t *\n\t * @returns Promise rejection\n\t */\n\tkey(): Promise<never> {\n\t\treturn Promise.reject();\n\t}\n\n\t/**\n\t * Return all keys stored in the space.\n\t *\n\t * @returns Promise resolving to array of keys\n\t */\n\tkeys(): Promise<string[]> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store, 'readwrite')\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.getAllKeys();\n\n\t\t\t\top.addEventListener('success', (event) => {\n\t\t\t\t\tresolve((event.target as IDBRequest).result.map(String));\n\t\t\t\t}, false);\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t}, false);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Delete a value from the space given its key\n\t *\n\t * @param key - Key of the item to delete\n\t * @returns Promise resolving to the value of the deleted object\n\t */\n\tremove(key: string): Promise<StorageValue> {\n\t\treturn this.get(key).then((value) => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store, 'readwrite')\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.delete(key);\n\n\t\t\t\top.addEventListener('success', () => {\n\t\t\t\t\tresolve(value);\n\t\t\t\t}, false);\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t}, false);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Clear the entire space\n\t *\n\t * @returns Promise for the clear operation\n\t */\n\tclear(): Promise<void> {\n\t\treturn this.open().then(() => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst transaction = (this.storage as IDBDatabase)\n\t\t\t\t\t.transaction(this.store, 'readwrite')\n\t\t\t\t\t.objectStore(this.store);\n\t\t\t\tconst op = transaction.clear();\n\n\t\t\t\top.addEventListener('success', () => {\n\t\t\t\t\tresolve();\n\t\t\t\t}, false);\n\t\t\t\top.addEventListener('error', (event) => {\n\t\t\t\t\treject(event);\n\t\t\t\t}, false);\n\t\t\t});\n\t\t});\n\t}\n}\n\n",
15
- "/**\n * ==============================\n * Remote Storage Adapter\n * ==============================\n */\n\nimport { Request } from '../Request';\nimport type { RequestOptions } from '../Request';\nimport type { RemoteStorageConfiguration, StorageValue, KeyValueResult } from './types';\n\n/**\n * The Remote Storage Adapter provides the Space Class the ability to interact\n * with a server in order to handle data persistence. The server's implementation\n * is up to the developer but it will need to respond to this adapter's request\n * formatting. This adapter uses the Request class to perform its tasks.\n */\nexport class RemoteStorage {\n\tpublic name: string;\n\tpublic version: string;\n\tpublic store: string;\n\tpublic endpoint: string;\n\tpublic props: RequestOptions;\n\tpublic storage: typeof Request | undefined;\n\n\t/**\n\t * Create a new Remote Storage. This adapter requires an endpoint URL where\n\t * it will make the requests.\n\t *\n\t * @param configuration - Configuration Object for the Adapter\n\t */\n\tconstructor({ name = '', version = '', store = '', endpoint = '', props = {} }: RemoteStorageConfiguration) {\n\t\tthis.name = name;\n\t\tthis.version = version;\n\t\tthis.store = store;\n\t\tthis.endpoint = `${endpoint}${store}/`;\n\t\tthis.props = props;\n\t}\n\n\t/**\n\t * Modify the configuration\n\t *\n\t * @param config - Configuration object to set up\n\t */\n\tconfiguration(config: RemoteStorageConfiguration): void {\n\t\tif (config.name) this.name = config.name;\n\t\tif (config.version) this.version = config.version;\n\t\tif (config.store) this.store = config.store;\n\t}\n\n\t/**\n\t * Open the Storage Object\n\t *\n\t * @returns Promise resolving to this adapter\n\t */\n\topen(): Promise<this> {\n\t\tif (typeof this.storage === 'undefined') {\n\t\t\tthis.storage = Request;\n\t\t}\n\t\treturn Promise.resolve(this);\n\t}\n\n\t/**\n\t * Store a key-value pair. This function sends a POST request to the server\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and response\n\t */\n\tset(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.post(this.endpoint + key, value as Record<string, string | number | boolean>, this.props).then((response) => {\n\t\t\t\treturn Promise.resolve({ key, value: response.json() });\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Update a key-value pair. The update method will use Object.assign()\n\t * in the case of objects so no value is lost. This function sends a PUT\n\t * request to the server.\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and response\n\t */\n\tupdate(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\treturn this.get(key).then((currentValue) => {\n\t\t\tconst merged = Object.assign({}, currentValue as object, value as object);\n\t\t\treturn this.storage!.put(this.endpoint + key, merged as Record<string, string | number | boolean>, this.props).then((response) => {\n\t\t\t\treturn Promise.resolve({ key, value: response.json() });\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves a value from storage given its key\n\t *\n\t * @param key - Key with which the value was saved\n\t * @returns Promise resolving to the retrieved value\n\t */\n\tget(key: string): Promise<StorageValue> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.json(this.endpoint + key, {}, this.props);\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves all the values in the space in a key-value JSON object\n\t *\n\t * @returns Promise resolving to all values\n\t */\n\tgetAll(): Promise<Record<string, StorageValue>> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.json(this.endpoint, {}, this.props);\n\t\t});\n\t}\n\n\t/**\n\t * Check if a space contains a given key.\n\t *\n\t * @param key - Key to look for\n\t * @returns Promise that resolves if key exists\n\t */\n\tcontains(key: string): Promise<void> {\n\t\treturn this.keys().then((keys) => {\n\t\t\tif (keys.includes(key)) {\n\t\t\t\treturn Promise.resolve();\n\t\t\t} else {\n\t\t\t\treturn Promise.reject();\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Upgrading the Storage must be done on the server side, therefore this\n\t * function always gets rejected.\n\t *\n\t * @returns Promise rejection\n\t */\n\tupgrade(): Promise<never> {\n\t\treturn Promise.reject();\n\t}\n\n\t/**\n\t * Renaming the Storage must be done on the server side, therefore this\n\t * function always gets rejected.\n\t *\n\t * @returns Promise rejection\n\t */\n\trename(): Promise<never> {\n\t\treturn Promise.reject();\n\t}\n\n\t/**\n\t * Getting a key by its index is not possible in this adapter, therefore\n\t * this function always gets rejected.\n\t *\n\t * @returns Promise rejection\n\t */\n\tkey(): Promise<never> {\n\t\treturn Promise.reject();\n\t}\n\n\t/**\n\t * Return all keys stored in the space. This makes a GET request to the\n\t * full endpoint with a keys query parameter.\n\t *\n\t * @returns Promise resolving to array of keys\n\t */\n\tkeys(): Promise<string[]> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.json<string[]>(this.endpoint, { keys: true }, this.props);\n\t\t});\n\t}\n\n\t/**\n\t * Delete a value from the space given its key. This function sends a\n\t * DELETE request to the server.\n\t *\n\t * @param key - Key of the item to delete\n\t * @returns Promise resolving to the key and response\n\t */\n\tremove(key: string): Promise<StorageValue> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.delete(this.endpoint + key, {}, this.props).then((response) => {\n\t\t\t\treturn response.json();\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Clear the entire space. This function sends a DELETE request to the server.\n\t *\n\t * @returns Promise for the clear operation\n\t */\n\tclear(): Promise<void> {\n\t\treturn this.open().then(() => {\n\t\t\treturn this.storage!.delete(this.endpoint, {}, this.props).then(() => {});\n\t\t});\n\t}\n}\n\n",
16
- "/**\n * ==============================\n * Space\n * ==============================\n */\n\nimport { LocalStorage } from './SpaceAdapter/LocalStorage';\nimport { SessionStorage } from './SpaceAdapter/SessionStorage';\nimport { IndexedDB } from './SpaceAdapter/IndexedDB';\nimport { RemoteStorage } from './SpaceAdapter/RemoteStorage';\nimport type { SpaceConfiguration, StorageValue, KeyValueResult, UpgradeCallback } from './SpaceAdapter/types';\n\n/**\n * List of Adapters Available\n */\nexport const SpaceAdapter = {\n\tLocalStorage,\n\tSessionStorage,\n\tIndexedDB,\n\tRemoteStorage\n};\n\n/**\n * Space adapter type (any of the available adapters)\n */\nexport type SpaceAdapterType = LocalStorage | SessionStorage | IndexedDB | RemoteStorage;\n\n/**\n * Space adapter constructor type\n */\nexport type SpaceAdapterConstructor = typeof LocalStorage | typeof SessionStorage | typeof IndexedDB | typeof RemoteStorage;\n\n/**\n * Callback function type for space events\n */\nexport type SpaceCallback = (key: string, value: StorageValue) => void;\n\n/**\n * Transformation function type\n */\nexport type TransformationFunction = (key: string, value: StorageValue) => StorageValue;\n\n/**\n * Transformation configuration\n */\nexport interface Transformation {\n\tid: string;\n\tget?: TransformationFunction | null;\n\tset?: TransformationFunction | null;\n}\n\n/**\n * Space provides a simple wrapper for different Storage APIs. It aims to\n * provide data independence through storage namespaces and versioning, allowing\n * transparent data formatting and content modifications through versions.\n */\nexport class Space {\n\tprivate _configuration: SpaceConfiguration;\n\tpublic adapter: SpaceAdapterType;\n\tpublic callbacks: {\n\t\tcreate: SpaceCallback[];\n\t\tupdate: SpaceCallback[];\n\t\tdelete: SpaceCallback[];\n\t};\n\tpublic transformations: Record<string, Transformation>;\n\n\t/**\n\t * Create a new Space Object. If no name and version is defined, the global\n\t * LocalSpace space is used.\n\t *\n\t * @param adapter - Space Adapter to use\n\t * @param configuration - Configuration object for the space\n\t */\n\tconstructor(adapter: SpaceAdapterConstructor = SpaceAdapter.LocalStorage, configuration: SpaceConfiguration = {}) {\n\t\t// Assign the provided configuration to the default one\n\t\tthis._configuration = Object.assign({}, { name: '', version: '', store: '' }, configuration);\n\n\t\t// Set up the adapter instance to use\n\t\tthis.adapter = new adapter(this._configuration);\n\n\t\t// This object stores all the callbacks the user can define for the space operations\n\t\tthis.callbacks = {\n\t\t\tcreate: [],\n\t\t\tupdate: [],\n\t\t\tdelete: []\n\t\t};\n\n\t\t// A transformation is an object that can contain set and get functions\n\t\tthis.transformations = {};\n\t}\n\n\t/**\n\t * Modify the space configuration, it will also be passed down to the adapter\n\t * using its configuration() function.\n\t *\n\t * @param object - Configuration object to set up\n\t * @returns Configuration object if no param was passed\n\t */\n\tconfiguration(object: SpaceConfiguration | null = null): SpaceConfiguration | void {\n\t\tif (object !== null) {\n\t\t\tthis._configuration = Object.assign({}, this._configuration, object);\n\t\t\tif (this.adapter.configuration) {\n\t\t\t\tthis.adapter.configuration(object);\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._configuration;\n\t\t}\n\t}\n\n\t/**\n\t * Open the Storage Object to be used depending on the SpaceAdapter\n\t *\n\t * @returns Promise resolving to this Space\n\t */\n\topen(): Promise<this> {\n\t\treturn this.adapter.open().then(() => {\n\t\t\treturn Promise.resolve(this);\n\t\t});\n\t}\n\n\t/**\n\t * Store a key-value pair\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tset(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\t// Apply all set transformations to the value\n\t\tfor (const id of Object.keys(this.transformations)) {\n\t\t\tif (typeof this.transformations[id].set === 'function') {\n\t\t\t\tvalue = this.transformations[id].set!(key, value);\n\t\t\t}\n\t\t}\n\n\t\treturn this.adapter.set(key, value).then(({ key, value }) => {\n\t\t\tfor (const callback of this.callbacks.create) {\n\t\t\t\tcallback.call(null, key, value);\n\t\t\t}\n\t\t\treturn Promise.resolve({ key, value });\n\t\t});\n\t}\n\n\t/**\n\t * Update a key-value pair. In difference with the set() method, the update\n\t * method will use Object.assign() in the case of objects so no value is lost.\n\t *\n\t * @param key - Key with which this value will be saved\n\t * @param value - Value to save\n\t * @returns Promise with key and value\n\t */\n\tupdate(key: string, value: StorageValue): Promise<KeyValueResult> {\n\t\t// Apply all set transformations to the value\n\t\tfor (const id of Object.keys(this.transformations)) {\n\t\t\tif (typeof this.transformations[id].set === 'function') {\n\t\t\t\tvalue = this.transformations[id].set!(key, value);\n\t\t\t}\n\t\t}\n\n\t\treturn this.adapter.update(key, value).then(({ key, value }) => {\n\t\t\tfor (const callback of this.callbacks.update) {\n\t\t\t\tcallback.call(null, key, value);\n\t\t\t}\n\t\t\treturn Promise.resolve({ key, value });\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves a value from storage given its key\n\t *\n\t * @param key - Key with which the value was saved\n\t * @returns Promise resolving to the retrieved value\n\t */\n\tget(key: string): Promise<StorageValue> {\n\t\treturn this.adapter.get(key).then((value) => {\n\t\t\t// Apply all get transformations to the value\n\t\t\tfor (const id of Object.keys(this.transformations)) {\n\t\t\t\tif (typeof this.transformations[id].get === 'function') {\n\t\t\t\t\tvalue = this.transformations[id].get!(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t});\n\t}\n\n\t/**\n\t * Retrieves all the values in the space in a key-value JSON object\n\t *\n\t * @returns Promise resolving to all values\n\t */\n\tgetAll(): Promise<Record<string, StorageValue>> {\n\t\treturn this.adapter.getAll().then((values) => {\n\t\t\t// Apply all get transformations to the values\n\t\t\tfor (const key of Object.keys(values)) {\n\t\t\t\tfor (const id of Object.keys(this.transformations)) {\n\t\t\t\t\tif (typeof this.transformations[id].get === 'function') {\n\t\t\t\t\t\tvalues[key] = this.transformations[id].get!(key, values[key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn values;\n\t\t});\n\t}\n\n\t/**\n\t * Iterate over every value in the space\n\t *\n\t * @param callback - A callback function receiving the key and value\n\t * @returns Promise resolving when all callbacks have been resolved\n\t */\n\teach(callback: (key: string, value: StorageValue) => unknown): Promise<unknown[]> {\n\t\treturn this.getAll().then((values) => {\n\t\t\tconst promises: unknown[] = [];\n\t\t\tfor (const i of Object.keys(values)) {\n\t\t\t\tpromises.push(callback.call(this, i, values[i]));\n\t\t\t}\n\t\t\treturn Promise.all(promises);\n\t\t});\n\t}\n\n\t/**\n\t * Check if a space contains a given key. Not all adapters may give this information\n\t *\n\t * @param key - Key to look for\n\t * @returns Promise that resolves if key exists\n\t */\n\tcontains(key: string): Promise<void> {\n\t\treturn this.adapter.contains(key);\n\t}\n\n\t/**\n\t * Upgrade a Space Version. Not all adapters may provide this functionality\n\t *\n\t * @param oldVersion - The version of the storage to be upgraded\n\t * @param newVersion - The version to be upgraded to\n\t * @param callback - Function to transform the old stored values\n\t * @returns Promise for the upgrade operation\n\t */\n\tupgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback): Promise<this> {\n\t\treturn this.adapter.upgrade(oldVersion, newVersion, callback).then(() => {\n\t\t\treturn Promise.resolve(this);\n\t\t});\n\t}\n\n\t/**\n\t * Rename a Space. Not all adapters may provide this functionality\n\t *\n\t * @param name - New name to be used\n\t * @returns Promise for the rename operation\n\t */\n\trename(name: string): Promise<void> {\n\t\treturn this.adapter.rename(name);\n\t}\n\n\t/**\n\t * Add a callback function to be run every time a value is created.\n\t *\n\t * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n\t */\n\tonCreate(callback: SpaceCallback): void {\n\t\tthis.callbacks.create.push(callback);\n\t}\n\n\t/**\n\t * Add a callback function to be run every time a value is updated.\n\t *\n\t * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n\t */\n\tonUpdate(callback: SpaceCallback): void {\n\t\tthis.callbacks.update.push(callback);\n\t}\n\n\t/**\n\t * Add a callback function to be run every time a value is deleted.\n\t *\n\t * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n\t */\n\tonDelete(callback: SpaceCallback): void {\n\t\tthis.callbacks.delete.push(callback);\n\t}\n\n\t/**\n\t * Add a transformation function to the space.\n\t *\n\t * @param transformation - Transformation configuration with id, get, and set functions\n\t */\n\taddTransformation({ id, get, set }: Transformation): void {\n\t\tthis.transformations[id] = { id, get, set };\n\t}\n\n\t/**\n\t * Remove a transformation function given its id\n\t *\n\t * @param id - Name or identifier of the transformation to remove\n\t */\n\tremoveTransformation(id: string): void {\n\t\tdelete this.transformations[id];\n\t}\n\n\t/**\n\t * Get the key that corresponds to a given index in the storage.\n\t * Not all adapters may provide this functionality\n\t *\n\t * @param index - Index to get the key from\n\t * @param full - Whether to return the full key name including space id\n\t * @returns Promise resolving to the key's name\n\t */\n\tkey(index: number, full: boolean = false): Promise<string> {\n\t\treturn this.adapter.key(index, full);\n\t}\n\n\t/**\n\t * Return all keys stored in the space. Not all adapters may provide this functionality\n\t *\n\t * @param full - Whether to return the full key name including space id\n\t * @returns Promise resolving to array of keys\n\t */\n\tkeys(full: boolean = false): Promise<string[]> {\n\t\treturn this.adapter.keys(full);\n\t}\n\n\t/**\n\t * Delete a value from the space given its key\n\t *\n\t * @param key - Key of the item to delete\n\t * @returns Promise that resolves after deletion\n\t */\n\tremove(key: string): Promise<void> {\n\t\treturn this.adapter.remove(key).then((value) => {\n\t\t\t// Run the callback for deletions\n\t\t\tfor (const callback of this.callbacks.delete) {\n\t\t\t\tcallback.call(null, key, value);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Clear the entire space\n\t *\n\t * @returns Promise for the clear operation\n\t */\n\tclear(): Promise<void> {\n\t\treturn this.adapter.clear();\n\t}\n}\n\n// Re-export adapter types\nexport { LocalStorage } from './SpaceAdapter/LocalStorage';\nexport { SessionStorage } from './SpaceAdapter/SessionStorage';\nexport { IndexedDB } from './SpaceAdapter/IndexedDB';\nexport { RemoteStorage } from './SpaceAdapter/RemoteStorage';\nexport type { SpaceConfiguration, StorageValue, KeyValueResult, UpgradeCallback } from './SpaceAdapter/types';\n\n",
17
- "/**\n * ==============================\n * Text\n * ==============================\n */\n\n/**\n * Provides utility functions for texts\n */\nexport class Text {\n\t/**\n\t * Capitalizes every word in a string\n\t *\n\t * @param text - Text string to capitalize\n\t * @returns Capitalized string\n\t */\n\tstatic capitalize(text: string): string {\n\t\treturn text.replace(/\\w\\S*/g, (txt) => {\n\t\t\treturn txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase();\n\t\t});\n\t}\n\n\t/**\n\t * Gets the suffix of a string given a key\n\t *\n\t * @param key - Key part of the string\n\t * @param text - Full string to extract the suffix from\n\t * @returns Suffix\n\t */\n\tstatic suffix(key: string, text: string): string {\n\t\tlet suffix = '';\n\t\tlet position = text.indexOf(key);\n\t\tif (position !== -1) {\n\t\t\tposition += key.length;\n\t\t\tsuffix = text.substring(position);\n\t\t}\n\t\treturn suffix;\n\t}\n\n\t/**\n\t * Get the currently selected text\n\t *\n\t * @returns Text selection\n\t */\n\tstatic selection(): string {\n\t\tconst selection = window.getSelection();\n\t\tif (selection) {\n\t\t\treturn selection.toString();\n\t\t}\n\t\treturn '';\n\t}\n\n\t/**\n\t * Gets the prefix of a string given a key\n\t *\n\t * @param key - Key part of the string\n\t * @param text - Full string to extract the prefix from\n\t * @returns Prefix\n\t */\n\tstatic prefix(key: string, text: string): string {\n\t\tlet prefix = '';\n\t\tconst position = text.indexOf(key);\n\t\tif (position !== -1) {\n\t\t\tprefix = text.substring(0, position);\n\t\t}\n\t\treturn prefix;\n\t}\n\n\t/**\n\t * Transforms a given text into a friendly URL string replacing all special characters\n\t *\n\t * @param text - The text to build the url from\n\t * @returns Friendly URL\n\t */\n\tstatic friendly(text: string): string {\n\t\tconst regex: RegExp[] = [\n\t\t\t/[áàâãªä]/g,\n\t\t\t/[ÁÀÂÃÄ]/g,\n\t\t\t/[ÍÌÎÏ]/g,\n\t\t\t/[íìîï]/g,\n\t\t\t/[éèêë]/g,\n\t\t\t/[ÉÈÊË]/g,\n\t\t\t/[óòôõºö]/g,\n\t\t\t/[ÓÒÔÕÖ]/g,\n\t\t\t/[úùûü]/g,\n\t\t\t/[ÚÙÛÜ]/g,\n\t\t\t/ç/g,\n\t\t\t/Ç/g,\n\t\t\t/ñ/g,\n\t\t\t/Ñ/g,\n\t\t\t/_/g,\n\t\t\t/[''‹›<>']/g,\n\t\t\t/[\"\"«»„\"]/g,\n\t\t\t/[(){}[\\]]/g,\n\t\t\t/[?¿!¡#$%&^*´`~/°|]/g,\n\t\t\t/[,.:;]/g,\n\t\t\t/ /g\n\t\t];\n\n\t\tconst replacements: string[] = [\n\t\t\t'a',\n\t\t\t'A',\n\t\t\t'I',\n\t\t\t'i',\n\t\t\t'e',\n\t\t\t'E',\n\t\t\t'o',\n\t\t\t'O',\n\t\t\t'u',\n\t\t\t'U',\n\t\t\t'c',\n\t\t\t'C',\n\t\t\t'n',\n\t\t\t'N',\n\t\t\t'-',\n\t\t\t'',\n\t\t\t'',\n\t\t\t'',\n\t\t\t'',\n\t\t\t'',\n\t\t\t'-'\n\t\t];\n\n\t\tlet result = text;\n\t\tfor (let i = 0; i < regex.length; i++) {\n\t\t\tresult = result.replace(regex[i], replacements[i]);\n\t\t}\n\n\t\treturn result;\n\t}\n}\n\n",
18
- "/**\n * ==============================\n * Util\n * ==============================\n */\n\n/**\n * Callable function type\n */\nexport type Callable<T = unknown> = (...args: unknown[]) => T | Promise<T>;\n\n/**\n * Provides diverse utility functions\n */\nexport class Util {\n\t/**\n\t * Calls any function using promises to keep a standard behavior between\n\t * async and sync functions.\n\t *\n\t * @param callable - The function to run\n\t * @param context - The object `this` will be mapped to\n\t * @param args - List of parameters to pass to the function when called\n\t * @returns A promise that resolves to the result of the function\n\t */\n\tstatic callAsync<T = unknown>(callable: Callable<T>, context: unknown, ...args: unknown[]): Promise<T> {\n\t\ttry {\n\t\t\t// Call the provided function using the context and arguments given\n\t\t\tconst result = callable.apply(context, args);\n\n\t\t\t// Check if the function returned a simple value or a Promise\n\t\t\tif (result instanceof Promise) {\n\t\t\t\treturn result;\n\t\t\t} else {\n\t\t\t\treturn Promise.resolve(result);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treturn Promise.reject(e);\n\t\t}\n\t}\n\n\t/**\n\t * Creates a UUID. These UUIDs should not be trusted for uniqueness\n\t *\n\t * @returns Generated UUID\n\t */\n\tstatic uuid(): string {\n\t\tif (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n\t\t\treturn '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => {\n\t\t\t\tconst num = parseInt(c, 10);\n\t\t\t\treturn (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);\n\t\t\t});\n\t\t} else {\n\t\t\tconst generate = (): string => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\n\t\t\treturn generate() + generate() + '-' + generate() + '-' + generate() + '-' +\n\t\t\t\tgenerate() + '-' + generate() + generate() + generate();\n\t\t}\n\t}\n}\n\n",
19
- "// This file is basically just a hack to expose the Artemis namespace in the\n// window object. Once/if bun adds support for this, we can remove this file.\n\nimport * as Artemis from './index';\n\ndeclare global {\n\tinterface Window {\n\t\tArtemis: typeof Artemis;\n\t}\n}\n\nif (typeof window === 'object') {\n\twindow.Artemis = Artemis;\n}\n\n"
5
+ "/**\n * ==============================\n * Debug\n * ==============================\n */\n\n/**\n * Debug level enum\n */\nexport enum DebugLevel {\n NONE = 0,\n ERROR = 1,\n WARNING = 2,\n INFO = 3,\n DEBUG = 4,\n ALL = 5\n}\n\n/**\n * This class acts as a proxy for the console. It shares the same methods as the\n * web console but they are conditioned to a debug level.\n */\nexport class Debug {\n private static _level: DebugLevel = DebugLevel.NONE;\n\n /**\n * Get the current debug level\n */\n static get currentLevel(): DebugLevel {\n return this._level;\n }\n\n /**\n * Set or get the log level\n *\n * @param level - The debug level to use\n * @returns The current debug level\n */\n static level(level?: DebugLevel): DebugLevel {\n if (typeof level === 'number') {\n this._level = level;\n }\n return this._level;\n }\n\n /**\n * Set the debug level\n *\n * @param level - The debug level to set\n */\n static setLevel(level: DebugLevel): void {\n this._level = level;\n }\n\n /**\n * Check if a specific level is enabled\n *\n * @param level - The level to check\n */\n static isEnabled(level: DebugLevel): boolean {\n return this._level >= level;\n }\n\n /**\n * Log the given elements.\n * Logs will only be made if the level is set to DEBUG or above\n *\n * @param args - Arguments to log\n */\n static log(...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.log(...args);\n }\n }\n\n /**\n * Show a debugging log\n * Logs will only be made if the level is set DEBUG or above\n *\n * @param args - Arguments to log\n */\n static debug(...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.debug(...args);\n }\n }\n\n /**\n * Show an info log\n * Logs will only be made if the level is set to INFO or above\n *\n * @param args - Arguments to log\n */\n static info(...args: unknown[]): void {\n if (this._level >= DebugLevel.INFO) {\n console.info(...args);\n }\n }\n\n /**\n * Show an error log\n * Logs will only be made if the level is set to ERROR or above\n *\n * @param args - Arguments to log\n */\n static error(...args: unknown[]): void {\n if (this._level >= DebugLevel.ERROR) {\n console.error(...args);\n }\n }\n\n /**\n * Show a warning log\n * Logs will only be made if the level is set to WARNING or above\n *\n * @param args - Arguments to log\n */\n static warning(...args: unknown[]): void {\n if (this._level >= DebugLevel.WARNING) {\n console.warn(...args);\n }\n }\n\n /**\n * Alias for warning()\n *\n * @param args - Arguments to log\n */\n static warn(...args: unknown[]): void {\n this.warning(...args);\n }\n\n /**\n * Show data as a table\n * Table will only be made if the level is set to DEBUG or above\n *\n * @param data - Data to display as table\n * @param columns - Optional column names to include\n */\n static table(data: unknown, columns?: string[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.table(data, columns);\n }\n }\n\n /**\n * Start an indented group\n *\n * @param args - Group label arguments\n */\n static group(...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.group(...args);\n }\n }\n\n /**\n * Start an indented group collapsed by default\n *\n * @param args - Group label arguments\n */\n static groupCollapsed(...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.groupCollapsed(...args);\n }\n }\n\n /**\n * End a previously started group\n */\n static groupEnd(): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.groupEnd();\n }\n }\n\n /**\n * Start a timer\n * The timer will only start if the level is set to DEBUG or above\n *\n * @param label - Timer label\n */\n static time(label?: string): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.time(label);\n }\n }\n\n /**\n * Log the time a timer has been running for\n * The time will only be logged if the level is set to DEBUG or above\n *\n * @param label - Timer label\n * @param args - Additional arguments to log\n */\n static timeLog(label?: string, ...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.timeLog(label, ...args);\n }\n }\n\n /**\n * End a timer\n * The timer will only be available if the level is set to DEBUG or above\n *\n * @param label - Timer label\n */\n static timeEnd(label?: string): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.timeEnd(label);\n }\n }\n\n /**\n * Show the stack trace\n * The stack trace will only be available if the level is set to DEBUG or above\n *\n * @param args - Arguments to log with trace\n */\n static trace(...args: unknown[]): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.trace(...args);\n }\n }\n\n /**\n * Log a message if a condition is false\n * Only logs if the level is set to ERROR or above\n *\n * @param condition - Condition to check\n * @param args - Arguments to log if condition is false\n */\n static assert(condition: boolean, ...args: unknown[]): void {\n if (this._level >= DebugLevel.ERROR) {\n console.assert(condition, ...args);\n }\n }\n\n /**\n * Clear the console\n * Only clears if the level is set to DEBUG or above\n */\n static clear(): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.clear();\n }\n }\n\n /**\n * Increment a counter with the given label\n * Only counts if the level is set to DEBUG or above\n *\n * @param label - Counter label\n */\n static count(label?: string): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.count(label);\n }\n }\n\n /**\n * Reset a counter with the given label\n * Only resets if the level is set to DEBUG or above\n *\n * @param label - Counter label\n */\n static countReset(label?: string): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.countReset(label);\n }\n }\n\n /**\n * Display an interactive listing of the properties of an object\n * Only displays if the level is set to DEBUG or above\n *\n * @param data - Object to display\n */\n static dir(data: unknown): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.dir(data);\n }\n }\n\n /**\n * Display XML/HTML element representation\n * Only displays if the level is set to DEBUG or above\n *\n * @param data - Element to display\n */\n static dirxml(data: unknown): void {\n if (this._level >= DebugLevel.DEBUG) {\n console.dirxml(data);\n }\n }\n\n /**\n * Create a formatted string with substitution values\n *\n * @param format - Format string\n * @param args - Substitution values\n */\n static format(format: string, ...args: unknown[]): string {\n let result = format;\n let argIndex = 0;\n\n result = result.replace(/%[sdioOcj%]/g, (match) => {\n if (match === '%%') return '%';\n if (argIndex >= args.length) return match;\n\n const arg = args[argIndex++];\n\n switch (match) {\n case '%s': return String(arg);\n case '%d':\n case '%i': return String(parseInt(String(arg), 10));\n case '%o':\n case '%O': return JSON.stringify(arg);\n case '%c': return ''; // CSS styling not supported in string format\n case '%j': return JSON.stringify(arg);\n default: return match;\n }\n });\n\n return result;\n }\n}\n",
6
+ "/**\n * ==============================\n * DOM\n * ==============================\n */\n\nexport type DOMSelector = string | Element | Element[] | NodeList | NodeListOf<Element> | HTMLElement[] | DOM | null;\n\nexport type StyleProperties = Record<string, string | number>;\n\nexport interface DOMOffset {\n top: number;\n left: number;\n}\n\nexport type EventCallback = (event: Event) => void;\nexport type ElementCallback = (element: HTMLElement, index: number) => void;\n\ninterface StoredHandler {\n selector: string | null;\n originalCallback: EventCallback;\n wrappedListener: EventListener;\n}\n\nconst eventHandlers = new WeakMap<Element, Map<string, StoredHandler[]>>();\n\n/**\n * Simple DOM manipulation functions\n */\nexport class DOM {\n public collection: HTMLElement[];\n public length: number;\n\n constructor(selector: DOMSelector) {\n if (!selector) {\n this.collection = [];\n } else if (typeof selector === 'string') {\n this.collection = Array.from(document.querySelectorAll(selector)) as HTMLElement[];\n } else if (selector instanceof NodeList) {\n this.collection = Array.from(selector) as HTMLElement[];\n } else if (selector instanceof DOM) {\n this.collection = selector.collection;\n } else if (selector instanceof Element) {\n this.collection = [selector as HTMLElement];\n } else if (Array.isArray(selector)) {\n this.collection = selector as HTMLElement[];\n } else {\n this.collection = [];\n }\n\n this.length = this.collection.length;\n }\n\n /**\n * Hide elements by setting display to none\n */\n hide(): this {\n return this.style('display', 'none');\n }\n\n /**\n * Show elements by setting display property\n *\n * @param display - Display value (default: 'block')\n */\n show(display: string = 'block'): this {\n return this.style('display', display);\n }\n\n /**\n * Add a class to all elements\n *\n * @param newClass - Class name to add\n */\n addClass(newClass: string): this {\n this.collection.forEach(element => element.classList.add(newClass));\n return this;\n }\n\n /**\n * Remove a class or all classes from all elements\n *\n * @param oldClass - Class name to remove (if omitted, removes all classes)\n */\n removeClass(oldClass?: string): this {\n this.collection.forEach(element => {\n if (!oldClass) {\n element.className = '';\n } else {\n element.classList.remove(oldClass);\n }\n });\n\n return this;\n }\n\n /**\n * Toggle one or more classes on all elements\n *\n * @param classes - Space-separated class names to toggle\n */\n toggleClass(classes: string): this {\n const classList = classes.split(' ');\n\n this.collection.forEach(element => {\n classList.forEach(c => element.classList.toggle(c));\n });\n\n return this;\n }\n\n /**\n * Check if all elements have a given class\n *\n * @param classToCheck - Class name to check\n */\n hasClass(classToCheck: string): boolean {\n return this.collection.every(element => element.classList.contains(classToCheck));\n }\n\n /**\n * Get or set the value of form elements\n */\n value(value: string | number): this;\n value(): string | undefined;\n value(value?: string | number): this | string | undefined {\n if (value !== undefined) {\n const valueString = String(value);\n for (const element of this.collection) {\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLButtonElement ||\n element instanceof HTMLOptionElement\n ) {\n element.value = valueString;\n }\n }\n\n return this;\n }\n\n if (this.length === 0) {\n return undefined;\n }\n\n const first = this.collection[0];\n\n if (\n first instanceof HTMLInputElement ||\n first instanceof HTMLTextAreaElement ||\n first instanceof HTMLSelectElement ||\n first instanceof HTMLButtonElement ||\n first instanceof HTMLOptionElement\n ) {\n return first.value;\n }\n\n return undefined;\n }\n\n /**\n * Focus the first element in the collection\n */\n focus(): this {\n if (this.length > 0) {\n this.collection[0].focus();\n }\n\n return this;\n }\n\n /**\n * Blur (unfocus) the first element in the collection\n */\n blur(): this {\n if (this.length > 0) {\n this.collection[0].blur();\n }\n\n return this;\n }\n\n /**\n * Attach a click event handler\n */\n click(callback: EventCallback): this {\n return this.on('click', callback);\n }\n\n /**\n * Attach a keyup event handler\n */\n keyup(callback: EventCallback): this {\n return this.on('keyup', callback);\n }\n\n /**\n * Attach a keydown event handler\n */\n keydown(callback: EventCallback): this {\n return this.on('keydown', callback);\n }\n\n /**\n * Attach a submit event handler\n */\n submit(callback: EventCallback): this {\n return this.on('submit', callback);\n }\n\n /**\n * Attach a change event handler\n */\n change(callback: EventCallback): this {\n return this.on('change', callback);\n }\n\n /**\n * Attach a scroll event handler\n */\n scroll(callback: EventCallback): this {\n return this.on('scroll', callback);\n }\n\n /**\n * Attach an input event handler\n */\n input(callback: EventCallback): this {\n return this.on('input', callback);\n }\n\n /**\n * Attach event handlers to elements\n *\n * @param eventNames - Space-separated event names\n * @param targetOrCallback - Either a selector for delegation or a callback\n * @param callback - Callback function (required if using delegation)\n */\n on(eventNames: string, targetOrCallback: string | EventCallback, callback?: EventCallback): this {\n const events = eventNames.split(' ');\n const isDelegation = typeof targetOrCallback === 'string';\n const callbackFunction = isDelegation ? callback : (targetOrCallback as EventCallback);\n const selector = isDelegation ? (targetOrCallback as string) : null;\n\n if (!callbackFunction) {\n return this;\n }\n\n this.collection.forEach(element => {\n events.forEach(eventName => {\n const listener: EventListener = isDelegation && selector\n ? (e: Event) => {\n const target = e.target;\n if (target instanceof Element) {\n const match = target.closest(selector);\n if (match && element.contains(match)) {\n callbackFunction.call(match, e);\n }\n }\n }\n : callbackFunction;\n\n if (!eventHandlers.has(element)) {\n eventHandlers.set(element, new Map());\n }\n\n const elementHandlers = eventHandlers.get(element)!;\n\n\n if (!elementHandlers.has(eventName)) {\n elementHandlers.set(eventName, []);\n }\n\n elementHandlers.get(eventName)!.push({\n selector,\n originalCallback: callbackFunction,\n wrappedListener: listener\n });\n\n element.addEventListener(eventName, listener, false);\n });\n });\n\n return this;\n }\n\n /**\n * Remove event handlers from elements\n *\n * @param eventNames - Space-separated event names (optional - omit to remove all)\n * @param targetOrCallback - Either a selector for delegation or a callback (optional)\n * @param callback - Callback function (required if using delegation removal)\n */\n off(eventNames?: string, targetOrCallback?: string | EventCallback, callback?: EventCallback): this {\n this.collection.forEach(element => {\n const elementHandlers = eventHandlers.get(element);\n\n if (!elementHandlers) {\n return;\n }\n\n const events = eventNames ? eventNames.split(' ') : Array.from(elementHandlers.keys());\n const isDelegation = typeof targetOrCallback === 'string';\n const selector = isDelegation ? targetOrCallback : null;\n const callbackToRemove = isDelegation ? callback : (targetOrCallback as EventCallback | undefined);\n\n events.forEach(eventName => {\n const handlers = elementHandlers.get(eventName);\n\n if (!handlers) {\n return;\n }\n\n // Find all the handlers we need to remove\n const toRemove = handlers.filter(handler => {\n if (callbackToRemove && handler.originalCallback !== callbackToRemove) {\n return false;\n }\n\n if (selector !== undefined && handler.selector !== selector) {\n return false;\n }\n\n return true;\n });\n\n toRemove.forEach(handler => {\n element.removeEventListener(eventName, handler.wrappedListener);\n });\n\n const remaining = handlers.filter(handler => !toRemove.includes(handler));\n\n if (remaining.length > 0) {\n elementHandlers.set(eventName, remaining);\n } else {\n elementHandlers.delete(eventName);\n }\n });\n\n if (elementHandlers.size === 0) {\n eventHandlers.delete(element);\n }\n });\n\n return this;\n }\n\n /**\n * Trigger events on elements\n *\n * @param eventNames - Space-separated event names\n * @param detail - Custom event detail data\n */\n trigger(eventNames: string, detail?: unknown): this {\n const events = eventNames.split(' ');\n\n this.collection.forEach(element => {\n events.forEach(eventName => {\n const customEvent = detail !== undefined\n ? new CustomEvent(eventName, { detail, bubbles: true, cancelable: true })\n : new Event(eventName, { bubbles: true, cancelable: true });\n\n element.dispatchEvent(customEvent);\n });\n });\n\n return this;\n }\n\n /**\n * Filter elements by a selector\n *\n * @param selector - CSS selector to match\n */\n filter(selector: string): DOM {\n return new DOM(this.collection.filter(element => element.matches(selector)));\n }\n\n /**\n * Check if the collection contains any elements\n */\n exists(): boolean {\n return this.length > 0;\n }\n\n /**\n * Get or set data attributes\n *\n * @param name - Data attribute name (without 'data-' prefix)\n * @param value - Value to set (if omitted, returns current value)\n */\n data(name: string): string | undefined;\n data(name: string, value: string): this;\n data(name: string, value?: string): this | string | undefined {\n if (value !== undefined) {\n this.collection.forEach(element => element.dataset[name] = value);\n return this;\n }\n\n return this.length > 0 ? this.collection[0].dataset[name] : undefined;\n }\n\n /**\n * Remove a data attribute from all elements\n *\n * @param name - Data attribute name to remove\n */\n removeData(name: string): this {\n this.collection.forEach(element => delete element.dataset[name]);\n return this;\n }\n\n /**\n * Get or set text content\n */\n text(value: string | number): this;\n text(): string | undefined;\n text(value?: string | number): this | string | undefined {\n if (value !== undefined) {\n const valueString = String(value);\n\n for (const element of this.collection) {\n element.textContent = valueString;\n }\n\n return this;\n }\n\n if (this.length === 0) {\n return undefined;\n }\n\n return this.collection[0].textContent || '';\n }\n\n /**\n * Get or set HTML content\n */\n html(value: string | number): this;\n html(): string | undefined;\n html(value?: string | number): this | string | undefined {\n if (value !== undefined) {\n const valueString = String(value);\n\n for (const element of this.collection) {\n element.innerHTML = valueString;\n }\n return this;\n }\n\n if (this.length === 0) {\n return undefined;\n }\n\n return this.collection[0].innerHTML;\n }\n\n /**\n * Append content to the end of each element\n *\n * @param content - HTML string or Element to append\n */\n append(content: string | Element): this {\n this.collection.forEach((element, index) => {\n if (typeof content === 'string') {\n element.insertAdjacentHTML('beforeend', content);\n } else {\n // Clone if not the first iteration to allow appending one element to multiple parents\n const node = (index === 0) ? content : content.cloneNode(true);\n element.appendChild(node as Node);\n }\n });\n\n return this;\n }\n\n /**\n * Prepend content to the beginning of each element\n *\n * @param content - HTML string or Element to prepend\n */\n prepend(content: string | Element): this {\n this.collection.forEach((element, index) => {\n if (typeof content === 'string') {\n element.insertAdjacentHTML('afterbegin', content);\n } else {\n const node = (index === 0) ? content : content.cloneNode(true);\n element.prepend(node as Node);\n }\n });\n\n return this;\n }\n\n /**\n * Iterate over each element in the collection\n *\n * @param callback - Function to call for each element\n */\n each(callback: ElementCallback): this {\n this.collection.forEach((element, i) => callback(element, i));\n return this;\n }\n\n /**\n * Get an element by index\n *\n * @param index - Zero-based index\n */\n get(index: number): HTMLElement | undefined {\n return this.collection[index];\n }\n\n /**\n * Get the first element wrapped in a new DOM instance\n */\n first(): DOM {\n return new DOM(this.collection[0] ?? null);\n }\n\n /**\n * Get the last element wrapped in a new DOM instance\n */\n last(): DOM {\n return new DOM(this.collection[this.collection.length - 1] ?? null);\n }\n\n /**\n * Get element at index wrapped in a new DOM instance\n *\n * @param index - Zero-based index (negative counts from end)\n */\n eq(index: number): DOM {\n const actualIndex = index < 0 ? this.collection.length + index : index;\n return new DOM(this.collection[actualIndex] ?? null);\n }\n\n /**\n * Check if any element in the collection is visible\n */\n isVisible(): boolean {\n return this.collection.some(element =>\n element.style.display !== 'none' && element.offsetWidth > 0 && element.offsetHeight > 0\n );\n }\n\n /**\n * Get the parent elements of all elements in the collection\n */\n parent(): DOM {\n const parents = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n if (element.parentElement) {\n parents.add(element.parentElement);\n }\n });\n\n return new DOM(Array.from(parents));\n }\n\n /**\n * Get all parent/ancestor elements up to the document\n */\n parents(): DOM {\n const ancestors = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n let parent = element.parentElement;\n while (parent) {\n ancestors.add(parent);\n parent = parent.parentElement;\n }\n });\n\n return new DOM(Array.from(ancestors));\n }\n\n /**\n * Find descendant elements matching a selector\n *\n * @param selector - CSS selector\n */\n find(selector: string): DOM {\n const found = new Set<HTMLElement>();\n\n for (const element of this.collection) {\n const results = element.querySelectorAll(selector);\n\n for (const result of results) {\n found.add(result as HTMLElement);\n }\n }\n\n return new DOM(Array.from(found));\n }\n\n /**\n * Get the offset position of the first element\n */\n offset(): DOMOffset | undefined {\n if (this.length === 0) {\n return undefined;\n }\n\n const rect = this.collection[0].getBoundingClientRect();\n\n return {\n top: rect.top + window.scrollY,\n left: rect.left + window.scrollX\n };\n }\n\n /**\n * Get the width of the first element\n */\n width(): number {\n if (this.length === 0) {\n return 0;\n }\n\n return this.collection[0].getBoundingClientRect().width;\n }\n\n /**\n * Get the height of the first element\n */\n height(): number {\n if (this.length === 0) {\n return 0;\n }\n\n return this.collection[0].getBoundingClientRect().height;\n }\n\n /**\n * Get the closest ancestor matching a selector\n *\n * @param selector - CSS selector\n */\n closest(selector: string): DOM {\n const found = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n const match = element.closest(selector);\n\n if (match) {\n found.add(match as HTMLElement);\n }\n });\n\n return new DOM(Array.from(found));\n }\n\n /**\n * Get or set an attribute\n *\n * @param attr - Attribute name\n * @param value - Value to set (if omitted, returns current value)\n */\n attribute(attr: string): string | null | undefined;\n attribute(attr: string, value: string | number): this;\n attribute(attr: string, value?: string | number): this | string | null | undefined {\n if (value !== undefined) {\n this.collection.forEach(element => element.setAttribute(attr, String(value)));\n return this;\n }\n\n return this.length > 0 ? this.collection[0].getAttribute(attr) : undefined;\n }\n\n /**\n * Remove an attribute from all elements\n *\n * @param attr - Attribute name to remove\n */\n removeAttribute(attr: string): this {\n this.collection.forEach(element => element.removeAttribute(attr));\n return this;\n }\n\n /**\n * Check if all elements have a given attribute\n *\n * @param attribute - Attribute name\n */\n hasAttribute(attribute: string): boolean {\n return this.collection.every(element => element.hasAttribute(attribute));\n }\n\n /**\n * Insert HTML after each element\n *\n * @param content - HTML string to insert\n */\n after(content: string): this {\n this.collection.forEach(element => element.insertAdjacentHTML('afterend', content));\n return this;\n }\n\n /**\n * Insert HTML before each element\n *\n * @param content - HTML string to insert\n */\n before(content: string): this {\n this.collection.forEach(element => element.insertAdjacentHTML('beforebegin', content));\n return this;\n }\n\n /**\n * Get or set CSS styles\n */\n style(prop: string): string;\n style(prop: StyleProperties): this;\n style(prop: string, value: string): this;\n style(properties: string | StyleProperties, value?: string): this | string {\n if (typeof properties === 'string' && value === undefined) {\n return this.length > 0 ? this.collection[0].style.getPropertyValue(properties) : '';\n }\n\n this.collection.forEach(element => {\n if (typeof properties === 'string' && value !== undefined) {\n element.style.setProperty(properties, value);\n } else if (typeof properties === 'object') {\n Object.entries(properties).forEach(([k, v]) => {\n element.style.setProperty(k, String(v));\n });\n }\n });\n\n return this;\n }\n\n /**\n * Animate elements using the Web Animations API\n *\n * @param keyframes - Animation keyframes\n * @param options - Animation options\n */\n animate(keyframes: Keyframe[] | PropertyIndexedKeyframes, options: number | KeyframeAnimationOptions): this {\n this.collection.forEach(element => element.animate(keyframes, options));\n return this;\n }\n\n /**\n * Fade elements in\n *\n * @param duration - Animation duration in ms\n * @param callback - Function to call after animation completes\n */\n fadeIn(duration: number = 400, callback?: () => void): this {\n this.collection.forEach((element, index) => {\n if (getComputedStyle(element).display === 'none') {\n element.style.display = 'block';\n }\n\n const animation = element.animate([{ opacity: 0 }, { opacity: 1 }], {\n duration: duration,\n fill: 'forwards',\n });\n\n // Trigger callback only once after the last element finishes\n if (callback && index === this.collection.length - 1) {\n animation.onfinish = () => callback();\n }\n });\n\n return this;\n }\n\n /**\n * Fade elements out\n *\n * @param duration - Animation duration in ms\n * @param callback - Function to call after animation completes\n */\n fadeOut(duration: number = 400, callback?: () => void): this {\n this.collection.forEach((element, index) => {\n const animation = element.animate([{ opacity: 1 }, { opacity: 0 }], {\n duration: duration,\n fill: 'forwards',\n });\n\n animation.onfinish = () => {\n element.style.display = 'none';\n if (callback && index === this.collection.length - 1) {\n callback();\n }\n };\n });\n\n return this;\n }\n\n /**\n * Check if all elements match a selector\n *\n * @param selector - CSS selector\n */\n matches(selector: string): boolean {\n if (this.length === 0) {\n return false;\n }\n\n return this.collection.every(element => element.matches(selector));\n }\n\n /**\n * Remove all elements from the DOM\n */\n remove(): this {\n this.collection.forEach(element => element.remove());\n return this;\n }\n\n /**\n * Remove all child elements\n */\n empty(): this {\n this.collection.forEach(element => {\n element.innerHTML = '';\n });\n\n return this;\n }\n\n /**\n * Clone all elements in the collection\n *\n * @param deep - Whether to clone child nodes (default: true)\n */\n clone(deep: boolean = true): DOM {\n const clones = this.collection.map(element => element.cloneNode(deep) as HTMLElement);\n return new DOM(clones);\n }\n\n /**\n * Replace elements with new content\n *\n * @param newContent - HTML string or Element to replace with\n */\n replaceWith(newContent: string | Element): this {\n for (let i = this.collection.length - 1; i >= 0; i--) {\n const element = this.collection[i];\n\n if (typeof newContent === 'string') {\n element.outerHTML = newContent;\n } else {\n const nodeToInsert = (i === 0) ? newContent : newContent.cloneNode(true);\n element.replaceWith(nodeToInsert);\n }\n }\n\n return this;\n }\n\n /**\n * Reset form elements\n */\n reset(): this {\n this.collection.forEach(element => {\n if (element instanceof HTMLFormElement) {\n element.reset();\n }\n });\n\n return this;\n }\n\n /**\n * Get or set a DOM property\n *\n * @param name - Property name\n * @param value - Value to set (if omitted, returns current value)\n */\n property<K extends keyof HTMLElement>(name: K, value: HTMLElement[K]): this;\n property<K extends keyof HTMLElement>(name: K): HTMLElement[K] | undefined;\n property<K extends keyof HTMLElement>(name: K, value?: HTMLElement[K]): this | HTMLElement[K] | undefined {\n if (value !== undefined) {\n this.collection.forEach(element => {\n (element as HTMLElement)[name] = value;\n });\n return this;\n }\n\n if (this.length === 0) {\n return undefined;\n }\n\n return this.collection[0][name];\n }\n\n /**\n * Get sibling elements\n */\n siblings(): DOM {\n const siblings = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n if (element.parentElement) {\n Array.from(element.parentElement.children).forEach(sibling => {\n if (sibling !== element && sibling instanceof HTMLElement) {\n siblings.add(sibling);\n }\n });\n }\n });\n\n return new DOM(Array.from(siblings));\n }\n\n /**\n * Get the next sibling element\n */\n next(): DOM {\n const nexts = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n const next = element.nextElementSibling;\n if (next instanceof HTMLElement) {\n nexts.add(next);\n }\n });\n\n return new DOM(Array.from(nexts));\n }\n\n /**\n * Get the previous sibling element\n */\n prev(): DOM {\n const prevs = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n const prev = element.previousElementSibling;\n if (prev instanceof HTMLElement) {\n prevs.add(prev);\n }\n });\n\n return new DOM(Array.from(prevs));\n }\n\n /**\n * Get all child elements\n */\n children(): DOM {\n const allChildren = new Set<HTMLElement>();\n\n this.collection.forEach(element => {\n Array.from(element.children).forEach(child => {\n if (child instanceof HTMLElement) {\n allChildren.add(child);\n }\n });\n });\n\n return new DOM(Array.from(allChildren));\n }\n\n /**\n * Scroll element into view\n *\n * @param options - Scroll options\n */\n scrollIntoView(options?: ScrollIntoViewOptions): this {\n if (this.length > 0) {\n this.collection[0].scrollIntoView(options);\n }\n return this;\n }\n}\n\n/**\n * Create a new DOM instance\n *\n * @param selector - CSS selector, Element, or collection\n */\nexport function $_(selector: DOMSelector): DOM {\n return new DOM(selector);\n}\n\n/**\n * Execute a callback when the DOM is ready\n *\n * @param callback - Function to execute\n */\nexport function $_ready(callback: () => void): void {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', callback);\n } else {\n callback();\n }\n}\n\n/**\n * Create a new element\n *\n * @param tagName - HTML tag name\n * @param attributes - Optional attributes to set\n */\nexport function $_create<K extends keyof HTMLElementTagNameMap>(\n tagName: K,\n attributes?: Record<string, string>\n): DOM {\n const element = document.createElement(tagName);\n\n if (attributes) {\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n }\n\n return new DOM(element);\n}\n",
7
+ "/**\n * ==============================\n * Request\n * ==============================\n */\n\nexport type RequestData = Record<string, unknown> | FormData;\n\nexport interface RequestOptions extends Omit<RequestInit, 'body' | 'method'> {\n headers?: Record<string, string>;\n timeout?: number; // Timeout in milliseconds\n}\n\n/**\n * Error thrown when a request fails\n */\nexport class RequestError extends Error {\n public status: number;\n public statusText: string;\n public response: Response;\n\n constructor(response: Response, message?: string) {\n super(message || `Request failed: ${response.status} ${response.statusText}`);\n this.name = 'RequestError';\n this.status = response.status;\n this.statusText = response.statusText;\n this.response = response;\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class RequestTimeoutError extends Error {\n constructor(url: string, timeout: number) {\n super(`Request to \"${url}\" timed out after ${timeout}ms`);\n this.name = 'RequestTimeoutError';\n }\n}\n\nexport class Request {\n /**\n * Serialize data to URL query string\n * Handles nested objects and arrays\n *\n * @param data - Data to serialize\n * @param prefix - Key prefix for nested objects\n */\n static serialize(data: RequestData, prefix?: string): string {\n if (data instanceof FormData) {\n const params = new URLSearchParams();\n data.forEach((value, key) => {\n if (typeof value === 'string') {\n params.append(key, value);\n }\n });\n return params.toString();\n }\n\n const params: string[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n if (value === undefined || value === null) continue;\n\n const paramKey = prefix ? `${prefix}[${key}]` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n params.push(Request.serialize(item as Record<string, unknown>, `${paramKey}[${index}]`));\n } else {\n params.push(`${encodeURIComponent(paramKey)}[]=${encodeURIComponent(String(item))}`);\n }\n });\n } else if (typeof value === 'object') {\n params.push(Request.serialize(value as Record<string, unknown>, paramKey));\n } else {\n params.push(`${encodeURIComponent(paramKey)}=${encodeURIComponent(String(value))}`);\n }\n }\n\n return params.filter(Boolean).join('&');\n }\n\n /**\n * Parse a URL safely\n *\n * @param url - URL to parse\n */\n private static parseUrl(url: string): URL {\n try {\n return new URL(url);\n } catch {\n try {\n return new URL(url, window.location.origin);\n } catch (e) {\n throw new Error(`Invalid URL: \"${url}\"`);\n }\n }\n }\n\n /**\n * Create an AbortController with timeout\n *\n * @param timeout - Timeout in milliseconds\n * @param url - URL for error message\n */\n private static createTimeoutController(timeout: number | undefined, url: string): { controller: AbortController; timeoutId?: ReturnType<typeof setTimeout> } {\n const controller = new AbortController();\n\n if (!timeout) {\n return { controller };\n }\n\n const timeoutId = setTimeout(() => {\n controller.abort(new RequestTimeoutError(url, timeout));\n }, timeout);\n\n return { controller, timeoutId };\n }\n\n private static async send(\n method: string,\n url: string,\n data: RequestData = {},\n options: RequestOptions = {}\n ): Promise<Response> {\n const { timeout, ...fetchOptions } = options;\n const urlObj = Request.parseUrl(url);\n let body: BodyInit | undefined = undefined;\n const headers = { ...fetchOptions.headers };\n\n if (['GET', 'DELETE', 'HEAD'].includes(method.toUpperCase())) {\n if (data && typeof data === 'object' && !(data instanceof FormData)) {\n Object.entries(data).forEach(([key, val]) => {\n if (val !== undefined && val !== null) {\n urlObj.searchParams.append(key, String(val));\n }\n });\n }\n } else {\n const contentType = headers['Content-Type'] || headers['content-type'];\n\n if (data instanceof FormData) {\n // Browser automatically sets Content-Type to multipart/form-data with boundary\n // Removing both cases to let the browser do its job\n delete headers['Content-Type'];\n delete headers['content-type'];\n body = data;\n } else if (contentType === 'application/json') {\n body = JSON.stringify(data);\n } else {\n if (!contentType) {\n headers['Content-Type'] = 'application/x-www-form-urlencoded';\n }\n\n const params = new URLSearchParams();\n Object.entries(data).forEach(([k, v]) => params.append(k, String(v)));\n body = params;\n }\n }\n\n const { controller, timeoutId } = Request.createTimeoutController(timeout, url);\n\n try {\n const response = await fetch(urlObj.toString(), {\n ...fetchOptions,\n method,\n headers,\n body,\n signal: controller.signal\n });\n\n return response;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n /**\n * Make a GET request\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n */\n static get(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Response> {\n return Request.send('GET', url, data, options);\n }\n\n /**\n * Make a POST request\n *\n * @param url - Request URL\n * @param data - Request body\n * @param options - Request options\n */\n static post(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n return Request.send('POST', url, data, options);\n }\n\n /**\n * Make a PUT request\n *\n * @param url - Request URL\n * @param data - Request body\n * @param options - Request options\n */\n static put(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n return Request.send('PUT', url, data, options);\n }\n\n /**\n * Make a PATCH request\n *\n * @param url - Request URL\n * @param data - Request body\n * @param options - Request options\n */\n static patch(url: string, data: RequestData, options: RequestOptions = {}): Promise<Response> {\n return Request.send('PATCH', url, data, options);\n }\n\n /**\n * Make a DELETE request\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n */\n static delete(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Response> {\n return Request.send('DELETE', url, data, options);\n }\n\n /**\n * Make a HEAD request\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n */\n static head(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Response> {\n return Request.send('HEAD', url, data, options);\n }\n\n /**\n * Make a GET request and parse JSON response\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n * @throws {RequestError} If the response is not ok\n */\n static async json<T = unknown>(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<T> {\n const response = await Request.get(url, data, options);\n\n if (!response.ok) {\n throw new RequestError(response);\n }\n\n return response.json();\n }\n\n /**\n * Make a POST request with JSON body and parse JSON response\n *\n * @param url - Request URL\n * @param data - Request body\n * @param options - Request options\n * @throws {RequestError} If the response is not ok\n */\n static async postJson<T = unknown>(url: string, data: RequestData, options: RequestOptions = {}): Promise<T> {\n const headers = { ...options.headers, 'Content-Type': 'application/json' };\n const response = await Request.post(url, data, { ...options, headers });\n\n if (!response.ok) {\n throw new RequestError(response);\n }\n\n return response.json();\n }\n\n /**\n * Make a GET request and return as Blob\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n * @throws {RequestError} If the response is not ok\n */\n static async blob(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<Blob> {\n const response = await Request.get(url, data, options);\n\n if (!response.ok) {\n throw new RequestError(response);\n }\n\n return response.blob();\n }\n\n /**\n * Make a GET request and return as text\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n * @throws {RequestError} If the response is not ok\n */\n static async text(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<string> {\n const response = await Request.get(url, data, options);\n\n if (!response.ok) {\n throw new RequestError(response);\n }\n\n return response.text();\n }\n\n /**\n * Make a GET request and return as ArrayBuffer\n *\n * @param url - Request URL\n * @param data - Query parameters\n * @param options - Request options\n * @throws {RequestError} If the response is not ok\n */\n static async arrayBuffer(url: string, data: RequestData = {}, options: RequestOptions = {}): Promise<ArrayBuffer> {\n const response = await Request.get(url, data, options);\n\n if (!response.ok) {\n throw new RequestError(response);\n }\n\n return response.arrayBuffer();\n }\n\n /**\n * Check if a URL exists (returns 2xx status)\n *\n * @param url - URL to check\n * @param options - Request options\n */\n static async exists(url: string, options: RequestOptions = {}): Promise<boolean> {\n try {\n const response = await Request.head(url, {}, options);\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n",
8
+ "/**\n * ==============================\n * File System\n * ==============================\n */\n\nimport { Request, RequestOptions } from './Request';\n\nexport type FileReadType = 'text' | 'base64' | 'buffer' | 'binary';\n\n/**\n * Return type mapping for file read operations\n */\nexport interface FileReadResult {\n text: string;\n base64: string;\n buffer: ArrayBuffer;\n binary: string;\n}\n\n/**\n * A utility wrapper for File/Blob operations\n */\nexport class FileSystem {\n\n /**\n * Read a file from a remote URL.\n *\n * @param url - The URL to fetch\n * @param type - The format to return ('text', 'base64', 'buffer', 'binary')\n * @param options - Request options\n */\n static async readRemote<T extends FileReadType>(\n url: string,\n type: T = 'base64' as T,\n options: RequestOptions = {}\n ): Promise<FileReadResult[T]> {\n const blob = await Request.blob(url, {}, options);\n return FileSystem.read(blob, type);\n }\n\n /**\n * Read a local File or Blob.\n *\n * @param file - The File or Blob to read\n * @param type - The format to return\n */\n static async read<T extends FileReadType>(file: File | Blob, type: T = 'text' as T): Promise<FileReadResult[T]> {\n switch (type) {\n case 'text':\n return file.text() as Promise<FileReadResult[T]>;\n\n case 'buffer':\n return file.arrayBuffer() as Promise<FileReadResult[T]>;\n\n case 'base64':\n return new Promise<FileReadResult[T]>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as FileReadResult[T]);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n\n case 'binary':\n return new Promise<FileReadResult[T]>((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const buffer = reader.result as ArrayBuffer;\n let binary = '';\n const bytes = new Uint8Array(buffer);\n const length = bytes.byteLength;\n for (let i = 0; i < length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n resolve(binary as FileReadResult[T]);\n };\n reader.onerror = () => reject(reader.error);\n reader.readAsArrayBuffer(file);\n });\n\n default: {\n const exhaustiveCheck: never = type;\n throw new Error(`FileSystem.read: Unknown type ${exhaustiveCheck}`);\n }\n }\n }\n\n /**\n * Create a File object.\n * This is a synchronous operation.\n *\n * @param name - Filename\n * @param content - Data (String, Blob, ArrayBuffer)\n * @param mimeType - MIME type (e.g. 'application/json')\n */\n static create(name: string, content: BlobPart, mimeType: string = 'text/plain'): File {\n return new File([content], name, { type: mimeType });\n }\n\n /**\n * Trigger a browser download for a specific File or Blob.\n * This will creates a temporary anchor tag to force the download.\n *\n * @param file - The file to download\n * @param name - Optional rename for the downloaded file\n */\n static download(file: File | Blob, name?: string): void {\n const url = URL.createObjectURL(file);\n const a = document.createElement('a');\n\n a.href = url;\n\n // Determine filename: use provided name, or File.name if available, or fallback\n let filename: string;\n if (name !== undefined && name !== '') {\n filename = name;\n } else if (file instanceof File && file.name !== '') {\n filename = file.name;\n } else {\n filename = 'download';\n }\n\n a.download = filename;\n\n document.body.appendChild(a);\n a.click();\n\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }\n\n /**\n * Get the file extension safely\n *\n * @param name - Filename or path\n * @returns Lowercase extension without the dot, or empty string\n */\n static extension(name: string, allowHiddenFiles: boolean = false): string {\n const parts = name.split('.');\n\n // No extension: \"file\" or hidden file \".gitignore\"\n if (parts.length === 1 || (parts[0] === '' && parts.length === 2 && !allowHiddenFiles)) {\n return '';\n }\n\n return parts.pop()?.toLowerCase() ?? '';\n }\n\n /**\n * Check if a file is an image based on extension.\n *\n * @param name - Filename to check\n */\n static isImage(name: string): boolean {\n const ext = FileSystem.extension(name);\n const valid = new Set([\n 'jpg', 'jpeg', 'png', 'gif', 'svg',\n 'webp', 'avif', 'bmp', 'ico', 'tiff', 'heic'\n ]);\n return valid.has(ext);\n }\n\n /**\n * Check if a file is a video based on extension.\n *\n * @param name - Filename to check\n */\n static isVideo(name: string): boolean {\n const ext = FileSystem.extension(name);\n const valid = new Set([\n 'mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv', 'm4v'\n ]);\n return valid.has(ext);\n }\n\n /**\n * Check if a file is audio based on extension.\n *\n * @param name - Filename to check\n */\n static isAudio(name: string): boolean {\n const ext = FileSystem.extension(name);\n const valid = new Set([\n 'mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a', 'wma'\n ]);\n return valid.has(ext);\n }\n\n /**\n * Convert bytes to human-readable size.\n *\n * @param bytes - Size in bytes\n * @param decimals - Number of decimal places\n */\n static humanSize(bytes: number, decimals: number = 2): string {\n if (bytes === 0) return '0 Bytes';\n\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i];\n }\n}\n",
9
+ "/**\n * ==============================\n * Form\n * ==============================\n */\n\nexport type FormValue = string | number | boolean | File | null;\nexport type FormValues = Record<string, FormValue | FormValue[]>;\n\n/**\n * Options for parsing form values\n */\nexport interface FormParseOptions {\n parseNumbers?: boolean; // Whether to parse numeric strings as numbers\n parseBooleans?: boolean; // Whether to parse checkbox values as booleans for single checkboxes\n}\n\nexport class Form {\n\n /**\n * Fill a form with data.\n *\n * @param formName - The data-form attribute value\n * @param data - Key-value pairs to fill\n */\n static fill(formName: string, data: Record<string, unknown>): void {\n const form = document.querySelector(`form[data-form='${formName}']`) as HTMLFormElement;\n\n if (!form) {\n console.warn(`Form [data-form='${formName}'] not found.`);\n return;\n }\n\n Object.entries(data).forEach(([name, value]) => {\n const elements = form.querySelectorAll(`[name='${name}']`);\n\n if (elements.length === 0) return;\n\n const firstElement = elements[0] as HTMLInputElement;\n const type = firstElement.type;\n const valString = String(value);\n\n switch (type) {\n case 'radio':\n elements.forEach((el) => {\n const input = el as HTMLInputElement;\n if (input.value === valString) {\n input.checked = true;\n }\n });\n break;\n\n case 'checkbox':\n if (elements.length === 1) {\n // Single checkbox: treat as boolean\n (elements[0] as HTMLInputElement).checked = !!value;\n } else if (Array.isArray(value)) {\n // Multiple checkboxes: check those whose value is in the array\n const stringValues = value.map(String);\n elements.forEach((el) => {\n const input = el as HTMLInputElement;\n input.checked = stringValues.includes(input.value);\n });\n }\n break;\n\n case 'file':\n // File inputs cannot be programmatically filled for security reasons\n break;\n\n default:\n (elements[0] as HTMLInputElement | HTMLSelectElement).value = valString;\n break;\n }\n });\n }\n\n /**\n * Get all values from a form.\n *\n * @param formName - The data-form attribute value\n * @param options - Parsing options\n * @returns Form values as a record\n */\n static values(formName: string, options: FormParseOptions = {}): FormValues {\n const { parseNumbers = true, parseBooleans = true } = options;\n\n const form = document.querySelector(`form[data-form='${formName}']`) as HTMLFormElement;\n\n if (!form) {\n console.warn(`Form [data-form='${formName}'] not found.`);\n return {};\n }\n\n const formData = new FormData(form);\n const data: FormValues = {};\n\n const keys = Array.from(new Set(formData.keys()));\n\n for (const key of keys) {\n const allValues = formData.getAll(key);\n const element = form.querySelector(`[name='${key}']`) as HTMLInputElement | null;\n const inputType = element?.type;\n\n // Handle file inputs\n if (inputType === 'file') {\n const files = allValues.filter((v): v is File => v instanceof File);\n if (element?.multiple || files.length > 1) {\n data[key] = files;\n } else {\n data[key] = files[0] || null;\n }\n continue;\n }\n\n // Handle checkboxes\n if (inputType === 'checkbox') {\n const checkboxes = form.querySelectorAll(`[name='${key}']`);\n if (checkboxes.length === 1 && parseBooleans) {\n // Single checkbox: return boolean\n data[key] = (checkboxes[0] as HTMLInputElement).checked;\n continue;\n }\n // Multiple checkboxes: return array of checked values\n data[key] = allValues.map((v) => Form.parseValue(String(v), parseNumbers));\n continue;\n }\n\n // Handle number inputs\n if (inputType === 'number' && parseNumbers) {\n if (allValues.length > 1) {\n data[key] = allValues.map((v) => parseFloat(String(v)));\n } else {\n data[key] = parseFloat(String(allValues[0]));\n }\n continue;\n }\n\n // Handle other inputs\n if (allValues.length > 1) {\n data[key] = allValues.map((v) => Form.parseValue(String(v), parseNumbers));\n } else {\n data[key] = Form.parseValue(String(allValues[0]), parseNumbers);\n }\n }\n\n return data;\n }\n\n /**\n * Parse a string value, optionally converting to number.\n *\n * @param value - String value to parse\n * @param parseNumbers - Whether to parse numeric strings\n */\n private static parseValue(value: string, parseNumbers: boolean): string | number {\n if (parseNumbers && value !== '' && !isNaN(Number(value))) {\n return Number(value);\n }\n return value;\n }\n\n /**\n * Reset a form to its initial state.\n *\n * @param formName - The data-form attribute value\n */\n static reset(formName: string): void {\n const form = document.querySelector(`form[data-form='${formName}']`) as HTMLFormElement;\n\n if (!form) {\n console.warn(`Form [data-form='${formName}'] not found.`);\n return;\n }\n\n form.reset();\n }\n\n /**\n * Check if a form is valid according to HTML5 validation.\n *\n * @param formName - The data-form attribute value\n */\n static isValid(formName: string): boolean {\n const form = document.querySelector(`form[data-form='${formName}']`) as HTMLFormElement;\n\n if (!form) {\n console.warn(`Form [data-form='${formName}'] not found.`);\n return false;\n }\n\n return form.checkValidity();\n }\n\n /**\n * Report validity and show browser validation messages.\n *\n * @param formName - The data-form attribute value\n */\n static reportValidity(formName: string): boolean {\n const form = document.querySelector(`form[data-form='${formName}']`) as HTMLFormElement;\n\n if (!form) {\n console.warn(`Form [data-form='${formName}'] not found.`);\n return false;\n }\n\n return form.reportValidity();\n }\n}\n",
10
+ "/**\n * ==============================\n * Platform\n * ==============================\n */\n\nexport type DesktopPlatform = 'Windows' | 'macOS' | 'Linux' | 'FreeBSD' | 'Any' | 'ChromeOS';\nexport type MobilePlatform = 'Android' | 'iOS' | 'iPadOS' | 'WindowsMobile' | 'BlackBerry' | 'Any';\nexport type Orientation = 'portrait' | 'landscape';\n\ninterface NavigatorUAData {\n platform: string;\n mobile: boolean;\n brands: { brand: string; version: string }[];\n}\n\ninterface NavigatorWithStandalone extends Navigator {\n standalone?: boolean;\n userAgentData?: NavigatorUAData;\n}\n\ninterface ExtendedWindow extends Window {\n process?: {\n type?: string;\n versions?: { electron?: string };\n };\n cordova?: unknown;\n}\n\nexport class Platform {\n /**\n * Check if the screen has a high pixel density (Retina)\n */\n static get retina(): boolean {\n return window.devicePixelRatio >= 2;\n }\n\n /**\n * Check if the device is in portrait orientation.\n * Uses matchMedia to align perfectly with CSS media queries.\n */\n static get portrait(): boolean {\n return window.matchMedia('(orientation: portrait)').matches;\n }\n\n /**\n * Check if the device is in landscape orientation.\n */\n static get landscape(): boolean {\n return window.matchMedia('(orientation: landscape)').matches;\n }\n\n /**\n * Get current device orientation as a string.\n */\n static get orientation(): Orientation {\n return Platform.portrait ? 'portrait' : 'landscape';\n }\n\n /**\n * Check if the user prefers Dark Mode\n */\n static get darkMode(): boolean {\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n\n /**\n * Check if the user prefers reduced motion\n */\n static get reducedMotion(): boolean {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /**\n * Check if the device supports touch events.\n * Useful for distinguishing hybrid laptops from tablets.\n */\n static get touch(): boolean {\n return (\n 'ontouchstart' in window ||\n navigator.maxTouchPoints > 0\n );\n }\n\n /**\n * Check if the app is running in \"Standalone\" mode (Installed PWA).\n */\n static get standalone(): boolean {\n const nav = navigator as NavigatorWithStandalone;\n return (\n window.matchMedia('(display-mode: standalone)').matches ||\n nav.standalone === true // iOS fallback\n );\n }\n\n /**\n * Check if the app is running inside Electron.\n * Checks both Renderer process and Main process contexts.\n */\n static get electron(): boolean {\n const win = window as ExtendedWindow;\n\n if (navigator.userAgent.toLowerCase().includes(' electron/')) {\n return true;\n }\n\n if (win.process?.type === 'renderer') {\n return true;\n }\n\n if (win.process?.versions?.electron) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Check if the app is running inside Cordova / PhoneGap.\n */\n static get cordova(): boolean {\n return !!(window as ExtendedWindow).cordova;\n }\n\n /**\n * Internal helper to normalize platform detection\n */\n private static get userAgent(): string {\n return navigator.userAgent.toLowerCase();\n }\n\n /**\n * Check if the app is running on a Desktop platform.\n *\n * @param os - Specific desktop OS to check for, or 'Any' for any desktop\n */\n static desktop(os: DesktopPlatform = 'Any'): boolean {\n const nav = navigator as NavigatorWithStandalone;\n\n if (nav.userAgentData?.mobile === true) {\n return false;\n }\n\n if (Platform.isIpadOS()) {\n return false;\n }\n\n const ua = Platform.userAgent;\n const dataPlatform = nav.userAgentData?.platform?.toLowerCase() || '';\n\n const checks: Record<Exclude<DesktopPlatform, 'Any'>, boolean> = {\n 'ChromeOS': dataPlatform.includes('cros') || ua.includes('cros'),\n 'Windows': dataPlatform.includes('windows') || ua.includes('windows'),\n 'macOS': dataPlatform.includes('macos') || ua.includes('macintosh'),\n 'Linux': !ua.includes('android') && (dataPlatform.includes('linux') || ua.includes('linux')),\n 'FreeBSD': dataPlatform.includes('freebsd') || ua.includes('freebsd'),\n };\n\n if (os === 'Any') {\n return Object.values(checks).some(val => val);\n }\n\n return checks[os] || false;\n }\n\n /**\n * Check if the app is running on a Mobile platform.\n *\n * @param os - Specific mobile OS to check for, or 'Any' for any mobile\n */\n static mobile(os: MobilePlatform = 'Any'): boolean {\n const nav = navigator as NavigatorWithStandalone;\n\n if (nav.userAgentData?.mobile === true && os === 'Any') {\n return true;\n }\n\n const ua = Platform.userAgent;\n\n const checks: Record<Exclude<MobilePlatform, 'Any'>, boolean> = {\n 'Android': ua.includes('android'),\n 'iOS': /iphone|ipod/.test(ua),\n 'iPadOS': Platform.isIpadOS(),\n 'WindowsMobile': /windows phone|iemobile|wpdesktop/.test(ua),\n 'BlackBerry': /blackberry|bb10/.test(ua),\n };\n\n if (os === 'Any') {\n return Object.values(checks).some(val => val);\n }\n\n return checks[os] || false;\n }\n\n /**\n * Detect iPadOS explicitly.\n * Modern iPads send a \"Macintosh\" User Agent, but have Touch Points.\n */\n private static isIpadOS(): boolean {\n const ua = Platform.userAgent;\n\n if (ua.includes('ipad')) {\n return true;\n }\n\n if (ua.includes('macintosh') && navigator.maxTouchPoints > 0) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Check if the platform supports Service Workers.\n * Uses `isSecureContext` to accurately allow localhost/HTTPS.\n */\n static get serviceWorkers(): boolean {\n return 'serviceWorker' in navigator && window.isSecureContext;\n }\n\n /**\n * Check if the device has a coarse pointer (touch) as primary input.\n */\n static get coarsePointer(): boolean {\n return window.matchMedia('(pointer: coarse)').matches;\n }\n\n /**\n * Check if the device has a fine pointer (mouse) as primary input.\n */\n static get finePointer(): boolean {\n return window.matchMedia('(pointer: fine)').matches;\n }\n\n /**\n * Check if the device supports hover interactions.\n */\n static get canHover(): boolean {\n return window.matchMedia('(hover: hover)').matches;\n }\n}\n",
11
+ "/**\n * ==============================\n * Preload\n * ==============================\n */\n\ninterface RequestInitWithPriority extends RequestInit {\n priority?: 'high' | 'low' | 'auto';\n}\n\nexport class Preload {\n /**\n * Preload and decode an image. Decoding prevents the image from still having\n * a delay when it is displayed.\n *\n * @param route - URL of the image\n * @returns Promise<HTMLImageElement>\n */\n static async image(route: string): Promise<HTMLImageElement> {\n const img = new Image();\n img.src = route;\n\n await img.decode();\n\n return img;\n }\n\n /**\n * Preload multiple images in parallel.\n *\n * @param routes - Array of image URLs\n * @returns Promise<HTMLImageElement[]>\n */\n static async images(routes: string[]): Promise<HTMLImageElement[]> {\n return Promise.all(routes.map(route => Preload.image(route)));\n }\n\n /**\n * Preload a generic file by fetching it.\n *\n * @param route - URL of the file\n * @param priority - Fetch priority hint (default: 'low')\n * @returns Promise<Response>\n */\n static async file(route: string, priority: 'high' | 'low' | 'auto' = 'low'): Promise<Response> {\n const options: RequestInitWithPriority = { priority };\n const response = await fetch(route, options as RequestInit);\n\n if (!response.ok) {\n throw new Error(`Preload failed for \"${route}\": ${response.status} ${response.statusText}`);\n }\n\n return response;\n }\n\n /**\n * Preload multiple files in parallel.\n *\n * @param routes - Array of file URLs\n * @param priority - Fetch priority hint\n * @returns Promise<Response[]>\n */\n static async files(routes: string[], priority: 'high' | 'low' | 'auto' = 'low'): Promise<Response[]> {\n return Promise.all(routes.map(route => Preload.file(route, priority)));\n }\n\n /**\n * Check if a URL is cached in a specific cache.\n *\n * @param cacheName - Name of the cache to check\n * @param url - URL to look for\n * @returns Whether the URL is cached\n */\n static async isCached(cacheName: string, url: string): Promise<boolean> {\n if (!('caches' in window)) {\n return false;\n }\n\n try {\n const cache = await caches.open(cacheName);\n const match = await cache.match(url);\n return !!match;\n } catch {\n // Cache API may throw in private browsing mode or other restricted contexts\n return false;\n }\n }\n\n /**\n * Add a URL to a cache.\n *\n * @param cacheName - Name of the cache\n * @param url - URL to cache\n * @returns Promise<void>\n */\n static async addToCache(cacheName: string, url: string): Promise<void> {\n if (!('caches' in window)) {\n throw new Error('Cache API is not supported in this browser');\n }\n\n try {\n const cache = await caches.open(cacheName);\n await cache.add(url);\n } catch (error) {\n throw new Error(`Failed to cache \"${url}\": ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Add multiple URLs to a cache.\n *\n * @param cacheName - Name of the cache\n * @param urls - URLs to cache\n * @returns Promise<void>\n */\n static async addAllToCache(cacheName: string, urls: string[]): Promise<void> {\n if (!('caches' in window)) {\n throw new Error('Cache API is not supported in this browser');\n }\n\n try {\n const cache = await caches.open(cacheName);\n await cache.addAll(urls);\n } catch (error) {\n throw new Error(`Failed to cache URLs: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n /**\n * Preload a CSS stylesheet.\n *\n * @param url - URL of the stylesheet\n * @returns Promise<void>\n */\n static async stylesheet(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n\n link.rel = 'preload';\n link.as = 'style';\n link.href = url;\n\n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to preload stylesheet: ${url}`));\n\n document.head.appendChild(link);\n });\n }\n\n /**\n * Preload a JavaScript file.\n *\n * @param url - URL of the script\n * @returns Promise<void>\n */\n static async script(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n\n link.rel = 'preload';\n link.as = 'script';\n link.href = url;\n\n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to preload script: ${url}`));\n\n document.head.appendChild(link);\n });\n }\n\n /**\n * Preload a font file.\n *\n * @param url - URL of the font\n * @param crossOrigin - Whether to use crossorigin attribute (default: true for fonts)\n * @returns Promise<void>\n */\n static async font(url: string, crossOrigin: boolean = true): Promise<void> {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n\n link.rel = 'preload';\n link.as = 'font';\n link.href = url;\n\n if (crossOrigin) {\n link.crossOrigin = 'anonymous';\n }\n\n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to preload font: ${url}`));\n\n document.head.appendChild(link);\n });\n }\n}\n",
12
+ "/**\n * ==============================\n * Space Adapter Types\n * ==============================\n */\n\n/**\n * Base configuration for all space adapters\n */\nexport interface SpaceConfiguration {\n name?: string;\n version?: string;\n store?: string;\n}\n\n/**\n * LocalStorage/SessionStorage configuration\n */\nexport type LocalStorageConfiguration = SpaceConfiguration;\n\n/**\n * IndexedDB configuration with additional options\n */\nexport interface IndexedDBConfiguration extends SpaceConfiguration {\n props?: IDBObjectStoreParameters;\n index?: Record<string, {\n name: string;\n field: string;\n props?: IDBIndexParameters;\n }>;\n}\n\n/**\n * RemoteStorage configuration\n */\nexport interface RemoteStorageConfiguration extends SpaceConfiguration {\n endpoint?: string;\n props?: Record<string, unknown>;\n}\n\n/**\n * Generic storage value type\n */\nexport type StorageValue = unknown;\n\n/**\n * Key-value result type\n */\nexport interface KeyValueResult {\n key: string;\n value: StorageValue;\n}\n\n/**\n * Upgrade callback function type\n */\nexport type UpgradeCallback<T = unknown> = (adapter: T, event?: IDBVersionChangeEvent) => Promise<void>;\n\n/**\n * Base interface for all space adapters\n */\nexport interface SpaceAdapterInterface {\n name: string;\n version: string;\n store: string;\n\n open(): Promise<this>;\n set(key: string | null, value: StorageValue): Promise<KeyValueResult>;\n update(key: string, value: StorageValue): Promise<KeyValueResult>;\n get(key: string): Promise<StorageValue>;\n getAll(): Promise<Record<string, StorageValue>>;\n contains(key: string): Promise<void>;\n upgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback): Promise<void>;\n rename(name: string): Promise<void>;\n key(index: number, full?: boolean): Promise<string>;\n keys(full?: boolean): Promise<string[]>;\n remove(key: string): Promise<StorageValue>;\n clear(): Promise<void>;\n configuration?(config: SpaceConfiguration): void;\n}\n\n/**\n * Space adapter constructor type\n */\nexport type SpaceAdapterConstructor = new (config: SpaceConfiguration) => SpaceAdapterInterface;\n\n/**\n * Convert a version string to a numeric value for comparison.\n * Each segment is padded to 5 digits to support versions up to 99999.x.x\n *\n * @param version - Version string (e.g., \"1.0.0\", \"10.2.15\")\n * @returns Numeric version for comparison\n */\nexport function versionToNumber(version: string): number {\n if (version === '') {\n return 0;\n }\n\n const segments = version.split('.');\n let result = 0;\n const multipliers = [1000000000000, 100000000, 10000]; // Support up to 4 segments\n\n for (let i = 0; i < Math.min(segments.length, multipliers.length); i++) {\n const segment = parseInt(segments[i], 10) || 0;\n result += segment * multipliers[i];\n }\n\n return result;\n}\n\n/**\n * Compare two version strings\n *\n * @param v1 - First version string\n * @param v2 - Second version string\n * @returns -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: string, v2: string): number {\n const n1 = versionToNumber(v1);\n const n2 = versionToNumber(v2);\n\n if (n1 < n2) return -1;\n if (n1 > n2) return 1;\n return 0;\n}\n\n/**\n * Deep clone a value to prevent mutation\n *\n * @param value - Value to clone\n * @returns Cloned value\n */\nexport function cloneValue<T>(value: T): T {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map(item => cloneValue(item)) as T;\n }\n\n const cloned: Record<string, unknown> = {};\n for (const key of Object.keys(value as object)) {\n cloned[key] = cloneValue((value as Record<string, unknown>)[key]);\n }\n return cloned as T;\n}\n\n/**\n * Normalize a URL by ensuring proper slash handling\n *\n * @param base - Base URL\n * @param path - Path to append\n * @returns Normalized URL\n */\nexport function normalizeUrl(base: string, path: string): string {\n const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n return `${normalizedBase}${normalizedPath}`;\n}\n",
13
+ "/**\n * ==============================\n * Local Storage Adapter\n * ==============================\n */\n\nimport type { LocalStorageConfiguration, StorageValue, KeyValueResult, UpgradeCallback, SpaceAdapterInterface } from './types';\nimport { versionToNumber } from './types';\n\n/**\n * Error thrown when a key is not found in storage\n */\nexport class KeyNotFoundError extends Error {\n constructor(key: string) {\n super(`Key \"${key}\" not found in storage`);\n this.name = 'KeyNotFoundError';\n }\n}\n\n/**\n * The Local Storage Adapter provides the Space Class the ability to interact\n * with the localStorage API found in most modern browsers.\n */\nexport class LocalStorage implements SpaceAdapterInterface {\n public name: string;\n public version: string;\n public store: string;\n public id: string;\n public numericVersion: number;\n public upgrades: Record<string, UpgradeCallback<LocalStorage>>;\n public storage: Storage | undefined;\n private _openPromise: Promise<this> | undefined;\n\n /**\n * Create a new LocalStorage. If no configuration is provided, the LocalStorage\n * global object is used. The LocalStorage Adapter can provide independency\n * by store name and space name.\n *\n * @param configuration - Configuration Object for the Adapter\n */\n constructor({ name = '', version = '', store = '' }: LocalStorageConfiguration) {\n this.name = name;\n this.version = version;\n this.store = store;\n this.upgrades = {};\n\n this.numericVersion = versionToNumber(version);\n this.id = this.computeId();\n }\n\n /**\n * Compute the storage ID based on current name, version, and store\n *\n * @returns The computed ID string\n */\n private computeId(): string {\n if (this.name !== '' && this.version !== '' && this.store !== '') {\n return `${this.name}::${this.store}::${this.version}_`;\n } else if (this.name !== '' && this.version !== '') {\n return `${this.name}::${this.version}_`;\n } else if (this.name !== '') {\n return `${this.name}::_`;\n } else {\n return '';\n }\n }\n\n /**\n * Modify the configuration\n *\n * @param config - Configuration object to set up\n */\n configuration(config: LocalStorageConfiguration): void {\n if (config.name !== undefined) this.name = config.name;\n if (config.version !== undefined) {\n this.version = config.version;\n this.numericVersion = versionToNumber(config.version);\n }\n if (config.store !== undefined) this.store = config.store;\n\n // Recalculate the ID after configuration changes\n this.id = this.computeId();\n }\n\n /**\n * Open the Storage Object\n *\n * @returns Promise resolving to this adapter\n */\n async open(): Promise<this> {\n // Already opened\n if (this.storage instanceof Storage) {\n return this;\n }\n\n // Currently opening - wait for it\n if (this._openPromise) {\n return this._openPromise;\n }\n\n // Start opening\n this._openPromise = (async () => {\n let upgradesToApply: string[] = [];\n\n // Check if this space is versioned\n if (this.version !== '') {\n // Get the versionless part of the ID\n let versionless = '';\n if (this.name !== '' && this.version !== '' && this.store !== '') {\n versionless = `${this.name}::${this.store}::`;\n } else if (this.name !== '' && this.version !== '') {\n versionless = `${this.name}::`;\n }\n\n // Get all the currently stored keys that contain the versionless ID\n const storedVersions = Object.keys(window.localStorage).filter((key) => {\n return key.indexOf(versionless) === 0;\n }).map((key) => {\n return key.replace(versionless, '').split('_')[0];\n }).filter((key) => {\n return key.indexOf('::') === -1;\n }).sort();\n\n if (storedVersions.length > 0) {\n const oldVersion = storedVersions[0];\n const oldVersionNumeric = versionToNumber(oldVersion);\n\n if (oldVersionNumeric < this.numericVersion) {\n const availableUpgrades = Object.keys(this.upgrades).sort((a, b) => {\n const [aOld] = a.split('::').map(Number);\n const [bOld] = b.split('::').map(Number);\n return aOld - bOld;\n });\n\n const startFrom = availableUpgrades.findIndex((u) => {\n const [old] = u.split('::');\n return parseInt(old) === oldVersionNumeric;\n });\n\n if (startFrom > -1) {\n upgradesToApply = availableUpgrades.slice(startFrom).filter((u) => {\n const [old, next] = u.split('::');\n return parseInt(old) < this.numericVersion && parseInt(next) <= this.numericVersion;\n });\n }\n\n // Get the previous ID using the old version\n let previousId = `${this.name}::${oldVersion}_`;\n\n if (this.name !== '' && this.version !== '' && this.store !== '') {\n previousId = `${this.name}::${this.store}::${oldVersion}_`;\n } else if (this.name !== '' && this.version !== '') {\n previousId = `${this.name}::${oldVersion}_`;\n }\n\n // Get all keys from the previous version\n const keys = Object.keys(window.localStorage).filter((key) => {\n return key.indexOf(previousId) === 0;\n }).map((key) => {\n return key.replace(previousId, '');\n });\n\n for (const key of keys) {\n const previous = window.localStorage.getItem(`${previousId}${key}`);\n if (previous !== null) {\n window.localStorage.setItem(this.id + key, previous);\n }\n window.localStorage.removeItem(`${previousId}${key}`);\n }\n }\n }\n }\n\n this.storage = window.localStorage;\n\n // Apply upgrades\n for (const upgradeKey of upgradesToApply) {\n try {\n await this.upgrades[upgradeKey].call(this, this);\n } catch (e) {\n console.error(e);\n }\n }\n\n return this;\n })();\n\n try {\n return await this._openPromise;\n } finally {\n this._openPromise = undefined;\n }\n }\n\n /**\n * Store a key-value pair\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async set(key: string, value: StorageValue): Promise<KeyValueResult> {\n await this.open();\n if (typeof value === 'object') {\n (this.storage as Storage).setItem(this.id + key, JSON.stringify(value));\n } else {\n (this.storage as Storage).setItem(this.id + key, String(value));\n }\n return { key, value };\n }\n\n /**\n * Update a key-value pair. The update method will use Object.assign()\n * in the case of objects so no value is lost.\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async update(key: string, value: StorageValue): Promise<KeyValueResult> {\n try {\n const currentValue = await this.get(key);\n if (typeof currentValue === 'object' && currentValue !== null) {\n if (typeof value === 'object' && value !== null) {\n value = { ...(currentValue as object), ...(value as object) };\n }\n (this.storage as Storage).setItem(this.id + key, JSON.stringify(value));\n } else {\n (this.storage as Storage).setItem(this.id + key, String(value));\n }\n return { key, value };\n } catch {\n return this.set(key, value);\n }\n }\n\n /**\n * Retrieves a value from storage given its key\n *\n * @param key - Key with which the value was saved\n * @returns Promise resolving to the retrieved value\n */\n async get(key: string): Promise<StorageValue> {\n await this.open();\n const rawValue = (this.storage as Storage).getItem(this.id + key);\n\n if (rawValue === null) {\n throw new KeyNotFoundError(key);\n }\n\n try {\n const parsed = JSON.parse(rawValue);\n if (parsed && typeof parsed === 'object') {\n return parsed;\n }\n return rawValue;\n } catch {\n // Unable to parse to JSON, return raw value\n return rawValue;\n }\n }\n\n /**\n * Retrieves all the values in the space in a key-value JSON object\n *\n * @returns Promise resolving to all values\n */\n async getAll(): Promise<Record<string, StorageValue>> {\n const keys = await this.keys();\n const values: Record<string, StorageValue> = {};\n\n for (const key of keys) {\n try {\n values[key] = await this.get(key);\n } catch {\n // Skip keys that fail to retrieve\n }\n }\n\n return values;\n }\n\n /**\n * Check if the space contains a given key.\n *\n * @param key - Key to look for\n * @returns Promise that resolves if key exists\n */\n async contains(key: string): Promise<void> {\n const keys = await this.keys();\n if (keys.includes(key)) {\n return;\n } else {\n throw new KeyNotFoundError(key);\n }\n }\n\n /**\n * Upgrade a Space Version\n *\n * @param oldVersion - The version of the storage to be upgraded\n * @param newVersion - The version to be upgraded to\n * @param callback - Function to transform the old stored values\n * @returns Promise\n */\n async upgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback<LocalStorage>): Promise<void> {\n const key = `${versionToNumber(oldVersion)}::${versionToNumber(newVersion)}`;\n this.upgrades[key] = callback;\n return Promise.resolve();\n }\n\n /**\n * Rename a Space\n *\n * @param name - New name to be used\n * @returns Promise for the rename operation\n */\n async rename(name: string): Promise<void> {\n if (this.name === name) {\n throw new Error('Cannot rename: new name is identical to current name');\n }\n\n const keys = await this.keys();\n const oldId = this.id;\n this.name = name;\n this.id = this.computeId();\n\n for (const key of keys) {\n const rawValue = (this.storage as Storage).getItem(`${oldId}${key}`);\n if (rawValue !== null) {\n // Directly copy the raw value to avoid double-encoding\n (this.storage as Storage).setItem(this.id + key, rawValue);\n (this.storage as Storage).removeItem(`${oldId}${key}`);\n }\n }\n }\n\n /**\n * Get the key that corresponds to a given index in the storage.\n * Only considers keys belonging to this space.\n *\n * @param index - Index to get the key from\n * @param full - Whether to return the full key name including space id\n * @returns Promise resolving to the key's name\n */\n async key(index: number, full: boolean = false): Promise<string> {\n const spaceKeys = await this.keys(full);\n\n if (index < 0 || index >= spaceKeys.length) {\n throw new Error(`Index ${index} out of bounds. Space has ${spaceKeys.length} keys.`);\n }\n\n return spaceKeys[index];\n }\n\n /**\n * Return all keys stored in the space.\n *\n * @param full - Whether to return the full key name including space id\n * @returns Promise resolving to array of keys\n */\n async keys(full: boolean = false): Promise<string[]> {\n await this.open();\n return Object.keys(this.storage as Storage).filter((key) => {\n return key.indexOf(this.id) === 0;\n }).map((key) => {\n if (full === true) {\n return key;\n } else {\n return key.replace(this.id, '');\n }\n });\n }\n\n /**\n * Delete a value from the space given its key\n *\n * @param key - Key of the item to delete\n * @returns Promise resolving to the value of the deleted object\n */\n async remove(key: string): Promise<StorageValue> {\n const value = await this.get(key);\n (this.storage as Storage).removeItem(this.id + key);\n return value;\n }\n\n /**\n * Clear the entire space\n *\n * @returns Promise for the clear operation\n */\n async clear(): Promise<void> {\n const keys = await this.keys();\n\n for (const key of keys) {\n (this.storage as Storage).removeItem(this.id + key);\n }\n }\n}\n",
14
+ "/**\n * ==============================\n * Session Storage Adapter\n * ==============================\n */\n\nimport { LocalStorage } from './LocalStorage';\nimport type { LocalStorageConfiguration, UpgradeCallback } from './types';\n\n/**\n * The Session Storage Adapter provides the Space Class the ability to interact\n * with the sessionStorage API found in most modern browsers. Since this API\n * shares pretty much the same methods as the local storage one, this class\n * inherits from the LocalStorage adapter.\n *\n * Note: SessionStorage does not support versioning and upgrades because session\n * data is inherently temporary and cleared when the browser session ends.\n * Any declared upgrades will be ignored.\n */\nexport class SessionStorage extends LocalStorage {\n /**\n * Create a new SessionStorage. If no configuration is provided, the SessionStorage\n * global object is used. The SessionStorage Adapter can provide independency\n * by store name and space name.\n *\n * Note: Version is accepted for API compatibility but upgrades are not supported.\n *\n * @param configuration - Configuration Object for the Adapter\n */\n constructor({ name = '', version = '', store = '' }: LocalStorageConfiguration) {\n super({ name, version, store });\n }\n\n /**\n * Open the Storage Object.\n *\n * Unlike LocalStorage, SessionStorage does not perform upgrade migrations\n * because session data is temporary and cleared when the session ends.\n *\n * @returns Promise resolving to this adapter\n */\n async open(): Promise<this> {\n if (this.storage instanceof Storage) {\n return this;\n }\n\n this.storage = window.sessionStorage;\n return this;\n }\n\n /**\n * Upgrade is not supported for SessionStorage.\n * Session data is temporary and should not require migrations.\n *\n * @param _oldVersion - Ignored\n * @param _newVersion - Ignored\n * @param _callback - Ignored\n * @returns Promise that resolves immediately (no-op)\n */\n async upgrade(_oldVersion: string, _newVersion: string, _callback: UpgradeCallback<SessionStorage>): Promise<void> {\n console.warn('SessionStorage.upgrade() is a no-op. Session data is temporary and does not support migrations.');\n return Promise.resolve();\n }\n}\n",
15
+ "/**\n * ==============================\n * IndexedDB Adapter\n * ==============================\n */\n\nimport type { IndexedDBConfiguration, StorageValue, KeyValueResult, UpgradeCallback, SpaceAdapterInterface } from './types';\nimport { versionToNumber } from './types';\n\n/**\n * Error thrown when a key is not found in storage\n */\nexport class KeyNotFoundError extends Error {\n constructor(key: string) {\n super(`Key \"${key}\" not found in IndexedDB`);\n this.name = 'KeyNotFoundError';\n }\n}\n\n/**\n * The IndexedDB Adapter provides the Space Class the ability to interact\n * with the IndexedDB API found in most modern browsers.\n */\nexport class IndexedDB implements SpaceAdapterInterface {\n public name: string;\n public version: string;\n public store: string;\n public props: IDBObjectStoreParameters;\n public index: Record<string, { name: string; field: string; props?: IDBIndexParameters }>;\n public keyPath: string;\n public numericVersion: number;\n public upgrades: Record<string, UpgradeCallback<IndexedDB>>;\n public storage: IDBDatabase | Promise<IDBDatabase> | undefined;\n\n /**\n * Create a new IndexedDB. Differently from Local and Session Storages, the\n * IndexedDB Adapter requires a mandatory name, version and store name.\n *\n * @param configuration - Configuration Object for the Adapter\n */\n constructor({ name = '', version = '', store = '', props = {}, index = {} }: IndexedDBConfiguration) {\n this.name = name;\n this.version = version;\n this.store = store;\n this.props = props || {};\n this.index = index;\n\n this.keyPath = (props?.keyPath as string) || 'id';\n this.upgrades = {};\n\n this.numericVersion = versionToNumber(version);\n }\n\n /**\n * Modify the configuration\n *\n * @param config - Configuration object to set up\n */\n configuration(config: IndexedDBConfiguration): void {\n if (config.name !== undefined) this.name = config.name;\n if (config.version !== undefined) {\n this.version = config.version;\n this.numericVersion = versionToNumber(config.version);\n }\n if (config.store !== undefined) this.store = config.store;\n }\n\n /**\n * Open the Storage Object\n *\n * @returns Promise resolving to this adapter\n */\n async open(): Promise<this> {\n if (this.name === '') {\n throw new Error('IndexedDB requires a name. No name has been defined for this space.');\n }\n\n if (this.store === '') {\n throw new Error('IndexedDB requires a store name. No store has been defined for this space.');\n }\n\n if (this.storage instanceof IDBDatabase) {\n return this;\n } else if (this.storage instanceof Promise) {\n return await (this.storage as unknown as Promise<this>);\n } else {\n const openTask = (async () => {\n let upgradeEvent: IDBVersionChangeEvent | undefined;\n let upgradesToApply: string[] = [];\n\n const db = await new Promise<IDBDatabase>((resolve, reject) => {\n const request = window.indexedDB.open(this.name, this.numericVersion);\n\n request.onerror = (event) => {\n reject(new Error(`Failed to open IndexedDB \"${this.name}\": ${(event.target as IDBOpenDBRequest).error?.message}`));\n };\n\n request.onsuccess = (event) => {\n resolve((event.target as IDBOpenDBRequest).result);\n };\n\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\n upgradeEvent = event;\n const db = (event.target as IDBOpenDBRequest).result;\n\n if (event.oldVersion < 1) {\n // Create all the needed Stores\n const store = db.createObjectStore(this.store, this.props);\n for (const indexKey of Object.keys(this.index)) {\n const idx = this.index[indexKey];\n store.createIndex(idx.name, idx.field, idx.props);\n }\n } else {\n // Check what upgrade functions have been declared\n const availableUpgrades = Object.keys(this.upgrades).sort((a, b) => {\n const [aOld] = a.split('::').map(Number);\n const [bOld] = b.split('::').map(Number);\n return aOld - bOld;\n });\n\n const startFrom = availableUpgrades.findIndex((u) => {\n const [old] = u.split('::');\n return parseInt(old) === event.oldVersion;\n });\n\n if (startFrom > -1) {\n upgradesToApply = availableUpgrades.slice(startFrom).filter((u) => {\n const [old, next] = u.split('::');\n return parseInt(old) < this.numericVersion && parseInt(next) <= this.numericVersion;\n });\n }\n }\n\n // Once the transaction is done, resolve the storage object\n const transaction = (event.target as IDBOpenDBRequest).transaction;\n if (transaction) {\n transaction.addEventListener('complete', () => {\n // Transaction completed\n });\n }\n };\n });\n\n this.storage = db;\n\n // Apply upgrades\n for (const upgradeKey of upgradesToApply) {\n try {\n await this.upgrades[upgradeKey].call(this, this, upgradeEvent);\n } catch (e) {\n console.error(e);\n }\n }\n\n return this;\n })();\n\n this.storage = openTask as unknown as Promise<IDBDatabase>;\n return await openTask;\n }\n }\n\n /**\n * Store a key-value pair. Because of the nature of IndexedDB,\n * stored values must be JSON objects.\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async set(key: string | null = null, value: StorageValue): Promise<KeyValueResult> {\n await this.open();\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readwrite')\n .objectStore(this.store);\n\n let op: IDBRequest;\n\n if (key !== null) {\n const temp: Record<string, unknown> = {};\n\n temp[this.keyPath] = key;\n op = transaction.put({ ...temp, ...(value as object) });\n } else {\n op = transaction.add(value);\n }\n\n op.addEventListener('success', (event) => {\n resolve({ key: String((event.target as IDBRequest).result), value });\n });\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to set key \"${key}\": ${(event.target as IDBRequest).error?.message}`));\n });\n });\n }\n\n /**\n * Update a key-value pair. The update method will use Object.assign()\n * in the case of objects so no value is lost.\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async update(key: string, value: StorageValue): Promise<KeyValueResult> {\n try {\n const currentValue = await this.get(key);\n\n if (typeof currentValue === 'undefined') {\n return this.set(key, value);\n }\n\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readwrite')\n .objectStore(this.store);\n\n const op = transaction.put({ ...(currentValue as object), ...(value as object) });\n\n op.addEventListener('success', (event) => {\n resolve({ key: String((event.target as IDBRequest).result), value });\n });\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to update key \"${key}\": ${(event.target as IDBRequest).error?.message}`));\n });\n });\n } catch {\n return this.set(key, value);\n }\n }\n\n /**\n * Retrieves a value from storage given its key\n *\n * @param key - Key with which the value was saved\n * @returns Promise resolving to the retrieved value\n */\n async get(key: string): Promise<StorageValue> {\n await this.open();\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readonly')\n .objectStore(this.store);\n\n const op = transaction.get(key);\n\n op.addEventListener('success', (event) => {\n const value = (event.target as IDBRequest).result;\n if (typeof value !== 'undefined' && value !== null) {\n resolve(value);\n } else {\n reject(new KeyNotFoundError(key));\n }\n });\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to get key \"${key}\": ${(event.target as IDBRequest).error?.message}`));\n });\n });\n }\n\n /**\n * Retrieves all the values in the space in a key-value JSON object.\n * Note: The keyPath property is preserved in the returned items.\n *\n * @returns Promise resolving to all values\n */\n async getAll(): Promise<Record<string, StorageValue>> {\n await this.open();\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readonly')\n .objectStore(this.store);\n\n const op = transaction.getAll();\n\n op.addEventListener('success', (event) => {\n const results: Record<string, StorageValue> = {};\n const items = (event.target as IDBRequest).result as Record<string, unknown>[];\n\n items.forEach((item) => {\n const id = item[this.keyPath] as string;\n // Create a shallow copy to avoid mutating the original item\n const itemCopy = { ...item };\n delete itemCopy[this.keyPath];\n results[id] = itemCopy;\n });\n\n resolve(results);\n });\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to get all items: ${(event.target as IDBRequest).error?.message}`));\n });\n });\n }\n\n /**\n * Check if the space contains a given key.\n *\n * @param key - Key to look for\n * @returns Promise that resolves if key exists\n */\n async contains(key: string): Promise<void> {\n await this.get(key);\n }\n\n /**\n * Upgrade a Space Version. Upgrades must be declared before the open()\n * method is executed.\n *\n * @param oldVersion - The version to be upgraded\n * @param newVersion - The version to be upgraded to\n * @param callback - Function to transform the old stored values\n * @returns Promise\n */\n async upgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback<IndexedDB>): Promise<void> {\n const key = `${versionToNumber(oldVersion)}::${versionToNumber(newVersion)}`;\n this.upgrades[key] = callback;\n return Promise.resolve();\n }\n\n /**\n * Renaming the space is not possible with the IndexedDB adapter therefore\n * this function always gets rejected.\n *\n * @returns Promise rejection\n */\n rename(): Promise<never> {\n return Promise.reject(new Error('IndexedDB does not support renaming databases. Create a new database and migrate data manually.'));\n }\n\n /**\n * Getting a key by its index is not possible in this adapter, therefore this\n * function always gets rejected.\n *\n * @returns Promise rejection\n */\n key(): Promise<never> {\n return Promise.reject(new Error('IndexedDB does not support getting keys by index. Use keys() to get all keys.'));\n }\n\n /**\n * Return all keys stored in the space.\n *\n * @returns Promise resolving to array of keys\n */\n async keys(): Promise<string[]> {\n await this.open();\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readonly')\n .objectStore(this.store);\n\n const op = transaction.getAllKeys();\n\n op.addEventListener('success', (event) => {\n resolve((event.target as IDBRequest).result.map(String));\n }, false);\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to get keys: ${(event.target as IDBRequest).error?.message}`));\n }, false);\n });\n }\n\n /**\n * Delete a value from the space given its key\n *\n * @param key - Key of the item to delete\n * @returns Promise resolving to the value of the deleted object\n */\n async remove(key: string): Promise<StorageValue> {\n const value = await this.get(key);\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readwrite')\n .objectStore(this.store);\n\n const op = transaction.delete(key);\n\n op.addEventListener('success', () => {\n resolve(value);\n }, false);\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to delete key \"${key}\": ${(event.target as IDBRequest).error?.message}`));\n }, false);\n });\n }\n\n /**\n * Clear the entire space\n *\n * @returns Promise for the clear operation\n */\n async clear(): Promise<void> {\n await this.open();\n return new Promise((resolve, reject) => {\n const transaction = (this.storage as IDBDatabase)\n .transaction(this.store, 'readwrite')\n .objectStore(this.store);\n\n const op = transaction.clear();\n\n op.addEventListener('success', () => {\n resolve();\n }, false);\n\n op.addEventListener('error', (event) => {\n reject(new Error(`Failed to clear store: ${(event.target as IDBRequest).error?.message}`));\n }, false);\n });\n }\n}\n",
16
+ "/**\n * ==============================\n * Remote Storage Adapter\n * ==============================\n */\n\nimport { Request } from '../Request';\nimport type { RequestOptions } from '../Request';\nimport type { RemoteStorageConfiguration, StorageValue, KeyValueResult, SpaceAdapterInterface } from './types';\nimport { normalizeUrl } from './types';\n\n/**\n * Error thrown when a key is not found in storage\n */\nexport class KeyNotFoundError extends Error {\n constructor(key: string) {\n super(`Key \"${key}\" not found in remote storage`);\n this.name = 'KeyNotFoundError';\n }\n}\n\n/**\n * The Remote Storage Adapter provides the Space Class the ability to interact\n * with a server in order to handle data persistence. The server's implementation\n * is up to the developer but it will need to respond to this adapter's request\n * formatting. This adapter uses the Request class to perform its tasks.\n */\nexport class RemoteStorage implements SpaceAdapterInterface {\n public name: string;\n public version: string;\n public store: string;\n public baseEndpoint: string;\n public endpoint: string;\n public props: RequestOptions;\n public storage: typeof Request | undefined;\n\n /**\n * Create a new Remote Storage. This adapter requires an endpoint URL where\n * it will make the requests.\n *\n * @param configuration - Configuration Object for the Adapter\n */\n constructor({ name = '', version = '', store = '', endpoint = '', props = {} }: RemoteStorageConfiguration) {\n this.name = name;\n this.version = version;\n this.store = store;\n this.baseEndpoint = endpoint;\n this.endpoint = this.computeEndpoint();\n this.props = props;\n }\n\n /**\n * Compute the full endpoint URL\n *\n * @returns The computed endpoint URL\n */\n private computeEndpoint(): string {\n if (this.store) {\n return normalizeUrl(this.baseEndpoint, `${this.store}/`);\n }\n return this.baseEndpoint.endsWith('/') ? this.baseEndpoint : `${this.baseEndpoint}/`;\n }\n\n /**\n * Modify the configuration\n *\n * @param config - Configuration object to set up\n */\n configuration(config: RemoteStorageConfiguration): void {\n if (config.name !== undefined) this.name = config.name;\n if (config.version !== undefined) this.version = config.version;\n if (config.store !== undefined) this.store = config.store;\n if (config.endpoint !== undefined) this.baseEndpoint = config.endpoint;\n\n // Recalculate the endpoint after configuration changes\n this.endpoint = this.computeEndpoint();\n }\n\n /**\n * Open the Storage Object\n *\n * @returns Promise resolving to this adapter\n */\n async open(): Promise<this> {\n if (typeof this.storage === 'undefined') {\n this.storage = Request;\n }\n\n return this;\n }\n\n /**\n * Store a key-value pair. This function sends a POST request to the server\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and response\n */\n async set(key: string, value: StorageValue): Promise<KeyValueResult> {\n await this.open();\n\n const response = await this.storage!.post(this.endpoint + key, value as Record<string, unknown>, this.props);\n const json = await response.json();\n\n return { key, value: json };\n }\n\n /**\n * Update a key-value pair. The update method will use Object.assign()\n * in the case of objects so no value is lost. This function sends a PUT\n * request to the server.\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and response\n */\n async update(key: string, value: StorageValue): Promise<KeyValueResult> {\n await this.open();\n const currentValue = await this.get(key);\n const merged = { ...(currentValue as object), ...(value as object) };\n const response = await this.storage!.put(this.endpoint + key, merged as Record<string, unknown>, this.props);\n const json = await response.json();\n\n return { key, value: json };\n }\n\n /**\n * Retrieves a value from storage given its key\n *\n * @param key - Key with which the value was saved\n * @returns Promise resolving to the retrieved value\n */\n async get(key: string): Promise<StorageValue> {\n await this.open();\n return this.storage!.json(this.endpoint + key, {}, this.props);\n }\n\n /**\n * Retrieves all the values in the space in a key-value JSON object\n *\n * @returns Promise resolving to all values\n */\n async getAll(): Promise<Record<string, StorageValue>> {\n await this.open();\n return this.storage!.json(this.endpoint, {}, this.props);\n }\n\n /**\n * Check if a space contains a given key.\n *\n * @param key - Key to look for\n * @returns Promise that resolves if key exists\n */\n async contains(key: string): Promise<void> {\n const keys = await this.keys();\n if (keys.includes(key)) {\n return;\n } else {\n throw new KeyNotFoundError(key);\n }\n }\n\n /**\n * Upgrading the Storage must be done on the server side, therefore this\n * function always gets rejected.\n *\n * @returns Promise rejection\n */\n upgrade(): Promise<never> {\n return Promise.reject(new Error('RemoteStorage cannot be upgraded from the client. Upgrades must be performed server-side.'));\n }\n\n /**\n * Renaming the Storage must be done on the server side, therefore this\n * function always gets rejected.\n *\n * @returns Promise rejection\n */\n rename(): Promise<never> {\n return Promise.reject(new Error('RemoteStorage cannot be renamed from the client. Renaming must be performed server-side.'));\n }\n\n /**\n * Getting a key by its index is not possible in this adapter, therefore\n * this function always gets rejected.\n *\n * @returns Promise rejection\n */\n key(): Promise<never> {\n return Promise.reject(new Error('RemoteStorage does not support getting keys by index. Use keys() to get all keys.'));\n }\n\n /**\n * Return all keys stored in the space. This makes a GET request to the\n * full endpoint with a keys query parameter.\n *\n * @returns Promise resolving to array of keys\n */\n async keys(): Promise<string[]> {\n await this.open();\n return this.storage!.json<string[]>(this.endpoint, { keys: true }, this.props);\n }\n\n /**\n * Delete a value from the space given its key. This function sends a\n * DELETE request to the server.\n *\n * @param key - Key of the item to delete\n * @returns Promise resolving to the key and response\n */\n async remove(key: string): Promise<StorageValue> {\n await this.open();\n const response = await this.storage!.delete(this.endpoint + key, {}, this.props);\n return response.json();\n }\n\n /**\n * Clear the entire space. This function sends a DELETE request to the server.\n *\n * @returns Promise for the clear operation\n */\n async clear(): Promise<void> {\n await this.open();\n await this.storage!.delete(this.endpoint, {}, this.props);\n }\n}\n",
17
+ "/**\n * ==============================\n * Space\n * ==============================\n */\n\nimport { LocalStorage } from './SpaceAdapter/LocalStorage';\nimport { SessionStorage } from './SpaceAdapter/SessionStorage';\nimport { IndexedDB } from './SpaceAdapter/IndexedDB';\nimport { RemoteStorage } from './SpaceAdapter/RemoteStorage';\nimport type { SpaceConfiguration, StorageValue, KeyValueResult, UpgradeCallback, SpaceAdapterInterface } from './SpaceAdapter/types';\nimport { cloneValue } from './SpaceAdapter/types';\n\n/**\n * List of Adapters Available\n */\nexport const SpaceAdapter = {\n LocalStorage,\n SessionStorage,\n IndexedDB,\n RemoteStorage\n};\n\n/**\n * Space adapter type (any of the available adapters)\n */\nexport type SpaceAdapterType = SpaceAdapterInterface;\n\nexport type SpaceAdapterConstructor = typeof LocalStorage | typeof SessionStorage | typeof IndexedDB | typeof RemoteStorage;\n\n/**\n * Callback function type for space events\n */\nexport type SpaceCallback = (key: string, value: StorageValue) => void;\n\n/**\n * Transformation function type\n */\nexport type TransformationFunction = (key: string, value: StorageValue) => StorageValue;\n\n/**\n * Transformation configuration\n */\nexport interface Transformation {\n id: string;\n get?: TransformationFunction | null;\n set?: TransformationFunction | null;\n}\n\n/**\n * Space provides a simple wrapper for different Storage APIs. It aims to\n * provide data independence through storage namespaces and versioning, allowing\n * transparent data formatting and content modifications through versions.\n */\nexport class Space {\n private _configuration: SpaceConfiguration;\n public adapter: SpaceAdapterType;\n public callbacks: {\n create: SpaceCallback[];\n update: SpaceCallback[];\n delete: SpaceCallback[];\n };\n public transformations: Record<string, Transformation>;\n\n /**\n * Create a new Space Object. If no name and version is defined, the global\n * LocalSpace space is used.\n *\n * @param adapter - Space Adapter to use\n * @param configuration - Configuration object for the space\n */\n constructor(adapter: SpaceAdapterConstructor = SpaceAdapter.LocalStorage, configuration: SpaceConfiguration = {}) {\n // Assign the provided configuration to the default one\n this._configuration = { name: '', version: '', store: '', ...configuration };\n\n // Set up the adapter instance to use\n this.adapter = new adapter(this._configuration);\n\n // This object stores all the callbacks the user can define for the space operations\n this.callbacks = {\n create: [],\n update: [],\n delete: []\n };\n\n // A transformation is an object that can contain set and get functions\n this.transformations = {};\n }\n\n /**\n * Modify the space configuration, it will also be passed down to the adapter\n * using its configuration() function.\n *\n * @param object - Configuration object to set up\n * @returns Configuration object if no param was passed\n */\n configuration(object: SpaceConfiguration | null = null): SpaceConfiguration | undefined {\n if (object !== null) {\n this._configuration = { ...this._configuration, ...object };\n if (this.adapter.configuration) {\n this.adapter.configuration(object);\n }\n return undefined;\n } else {\n return this._configuration;\n }\n }\n\n /**\n * Open the Storage Object to be used depending on the SpaceAdapter\n *\n * @returns Promise resolving to this Space\n */\n async open(): Promise<this> {\n await this.adapter.open();\n return this;\n }\n\n /**\n * Apply set transformations to a value\n *\n * @param key - The key being set\n * @param value - The value to transform\n * @returns The transformed value\n */\n private applySetTransformations(key: string, value: StorageValue): StorageValue {\n let transformedValue = cloneValue(value);\n for (const transformation of Object.values(this.transformations)) {\n if (typeof transformation.set === 'function') {\n transformedValue = transformation.set(key, transformedValue);\n }\n }\n return transformedValue;\n }\n\n /**\n * Apply get transformations to a value\n *\n * @param key - The key being retrieved\n * @param value - The value to transform\n * @returns The transformed value\n */\n private applyGetTransformations(key: string, value: StorageValue): StorageValue {\n let transformedValue = value;\n for (const transformation of Object.values(this.transformations)) {\n if (typeof transformation.get === 'function') {\n transformedValue = transformation.get(key, transformedValue);\n }\n }\n return transformedValue;\n }\n\n /**\n * Store a key-value pair\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async set(key: string, value: StorageValue): Promise<KeyValueResult> {\n const transformedValue = this.applySetTransformations(key, value);\n const result = await this.adapter.set(key, transformedValue);\n for (const callback of this.callbacks.create) {\n callback.call(null, result.key, result.value);\n }\n return result;\n }\n\n /**\n * Update a key-value pair. In difference with the set() method, the update\n * method will use Object.assign() in the case of objects so no value is lost.\n *\n * @param key - Key with which this value will be saved\n * @param value - Value to save\n * @returns Promise with key and value\n */\n async update(key: string, value: StorageValue): Promise<KeyValueResult> {\n const transformedValue = this.applySetTransformations(key, value);\n const result = await this.adapter.update(key, transformedValue);\n for (const callback of this.callbacks.update) {\n callback.call(null, result.key, result.value);\n }\n return result;\n }\n\n /**\n * Retrieves a value from storage given its key\n *\n * @param key - Key with which the value was saved\n * @returns Promise resolving to the retrieved value\n */\n async get(key: string): Promise<StorageValue> {\n const value = await this.adapter.get(key);\n return this.applyGetTransformations(key, value);\n }\n\n /**\n * Retrieves all the values in the space in a key-value JSON object\n *\n * @returns Promise resolving to all values\n */\n async getAll(): Promise<Record<string, StorageValue>> {\n const values = await this.adapter.getAll();\n const transformedValues: Record<string, StorageValue> = {};\n\n for (const key of Object.keys(values)) {\n transformedValues[key] = this.applyGetTransformations(key, values[key]);\n }\n\n return transformedValues;\n }\n\n /**\n * Iterate over every value in the space\n *\n * @param callback - A callback function receiving the key and value\n * @returns Promise resolving when all callbacks have been resolved\n */\n async each(callback: (key: string, value: StorageValue) => unknown): Promise<unknown[]> {\n const values = await this.getAll();\n const promises: unknown[] = [];\n for (const [key, value] of Object.entries(values)) {\n promises.push(callback.call(this, key, value));\n }\n return Promise.all(promises);\n }\n\n /**\n * Check if a space contains a given key. Not all adapters may give this information\n *\n * @param key - Key to look for\n * @returns Promise that resolves if key exists\n */\n contains(key: string): Promise<void> {\n return this.adapter.contains(key);\n }\n\n /**\n * Upgrade a Space Version. Not all adapters may provide this functionality\n *\n * @param oldVersion - The version of the storage to be upgraded\n * @param newVersion - The version to be upgraded to\n * @param callback - Function to transform the old stored values\n * @returns Promise for the upgrade operation\n */\n async upgrade(oldVersion: string, newVersion: string, callback: UpgradeCallback): Promise<this> {\n await this.adapter.upgrade(oldVersion, newVersion, callback);\n return this;\n }\n\n /**\n * Rename a Space. Not all adapters may provide this functionality\n *\n * @param name - New name to be used\n * @returns Promise for the rename operation\n */\n rename(name: string): Promise<void> {\n return this.adapter.rename(name);\n }\n\n /**\n * Add a callback function to be run every time a value is created.\n *\n * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n */\n onCreate(callback: SpaceCallback): void {\n this.callbacks.create.push(callback);\n }\n\n /**\n * Add a callback function to be run every time a value is updated.\n *\n * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n */\n onUpdate(callback: SpaceCallback): void {\n this.callbacks.update.push(callback);\n }\n\n /**\n * Add a callback function to be run every time a value is deleted.\n *\n * @param callback - Callback Function. Key and Value pair will be sent as parameters.\n */\n onDelete(callback: SpaceCallback): void {\n this.callbacks.delete.push(callback);\n }\n\n /**\n * Add a transformation function to the space.\n *\n * @param transformation - Transformation configuration with id, get, and set functions\n */\n addTransformation({ id, get, set }: Transformation): void {\n this.transformations[id] = { id, get, set };\n }\n\n /**\n * Remove a transformation function given its id\n *\n * @param id - Name or identifier of the transformation to remove\n */\n removeTransformation(id: string): void {\n delete this.transformations[id];\n }\n\n /**\n * Get the key that corresponds to a given index in the storage.\n * Not all adapters may provide this functionality\n *\n * @param index - Index to get the key from\n * @param full - Whether to return the full key name including space id\n * @returns Promise resolving to the key's name\n */\n key(index: number, full: boolean = false): Promise<string> {\n return this.adapter.key(index, full);\n }\n\n /**\n * Return all keys stored in the space. Not all adapters may provide this functionality\n *\n * @param full - Whether to return the full key name including space id\n * @returns Promise resolving to array of keys\n */\n keys(full: boolean = false): Promise<string[]> {\n return this.adapter.keys(full);\n }\n\n /**\n * Delete a value from the space given its key\n *\n * @param key - Key of the item to delete\n * @returns Promise that resolves after deletion\n */\n async remove(key: string): Promise<void> {\n const value = await this.adapter.remove(key);\n // Run the callback for deletions\n for (const callback of this.callbacks.delete) {\n callback.call(null, key, value);\n }\n }\n\n /**\n * Clear the entire space\n *\n * @returns Promise for the clear operation\n */\n clear(): Promise<void> {\n return this.adapter.clear();\n }\n}\n\n// Re-export adapter types\nexport { LocalStorage } from './SpaceAdapter/LocalStorage';\nexport { SessionStorage } from './SpaceAdapter/SessionStorage';\nexport { IndexedDB } from './SpaceAdapter/IndexedDB';\nexport { RemoteStorage } from './SpaceAdapter/RemoteStorage';\nexport type { SpaceConfiguration, StorageValue, KeyValueResult, UpgradeCallback } from './SpaceAdapter/types';\n",
18
+ "/**\n * ==============================\n * Text\n * ==============================\n */\n\nexport interface CapitalizeOptions {\n preserveCase?: boolean; // Wether to preserve the case of letters after the first character\n}\n\nexport class Text {\n\n /**\n * Capitalize the first letter of each word.\n *\n * @param text - Text to capitalize\n * @param options - Capitalization options\n * @returns Capitalized text\n */\n static capitalize(text: string, options: CapitalizeOptions = {}): string {\n const { preserveCase = false } = options;\n\n return text.replace(/\\w\\S*/g, (word) => {\n const firstChar = word.charAt(0).toUpperCase();\n const rest = preserveCase ? word.substring(1) : word.substring(1).toLowerCase();\n return firstChar + rest;\n });\n }\n\n /**\n * Get the currently selected text in the document.\n */\n static selection(): string {\n return window.getSelection()?.toString() || '';\n }\n\n /**\n * Get the text after a given key/substring.\n *\n * @param key - The substring to search for\n * @param text - The text to search in\n * @returns Text after the key, or empty string if not found\n */\n static suffix(key: string, text: string): string {\n const index = text.indexOf(key);\n\n if (index === -1) {\n return '';\n }\n\n return text.slice(index + key.length);\n }\n\n /**\n * Get the text before a given key/substring.\n *\n * @param key - The substring to search for\n * @param text - The text to search in\n * @returns Text before the key, or empty string if not found\n */\n static prefix(key: string, text: string): string {\n const index = text.indexOf(key);\n\n if (index === -1) {\n return '';\n }\n\n return text.slice(0, index);\n }\n\n /**\n * Convert text to a URL-friendly slug.\n *\n * @param text - Text to convert\n * @returns URL-friendly slug\n */\n static friendly(text: string): string {\n return text\n .toString() // Ensure it's a string\n .normalize('NFD') // Split accents from letters (e.g. é -> e + ´)\n .replace(/[\\u0300-\\u036f]/g, '') // Remove the separated accents\n .toLowerCase() // Standardize to lowercase\n .trim() // Remove leading/trailing whitespace\n .replace(/\\s+/g, '-') // Replace spaces with -\n .replace(/[^\\w-]+/g, '') // Remove all non-word chars (except -)\n .replace(/--+/g, '-'); // Replace multiple - with single -\n }\n\n /**\n * Truncate text to a maximum length with ellipsis.\n *\n * @param text - Text to truncate\n * @param maxLength - Maximum length (including ellipsis)\n * @param ellipsis - Ellipsis string to append (default: '...')\n */\n static truncate(text: string, maxLength: number, ellipsis: string = '...'): string {\n if (text.length <= maxLength) {\n return text;\n }\n\n return text.slice(0, maxLength - ellipsis.length).trimEnd() + ellipsis;\n }\n\n /**\n * Check if a string is empty or contains only whitespace.\n */\n static isBlank(text: string | null | undefined): boolean {\n return text === null || text === undefined || text.trim() === '';\n }\n}\n",
19
+ "/**\n * ==============================\n * Util\n * ==============================\n */\n\nexport type Callable<T = unknown> = (...args: unknown[]) => T | Promise<T>;\n\nexport class Util {\n /**\n * Calls a function and ensures it returns a Promise.\n *\n * @param callable - The function to run\n * @param context - The `this` context\n * @param args - Arguments to pass\n */\n static async callAsync<T = unknown>(callable: Callable<T>, context: unknown, ...args: unknown[]): Promise<T> {\n try {\n return await callable.apply(context, args);\n } catch (error) {\n return Promise.reject(error);\n }\n }\n\n /**\n * Generates a UUID v4.\n */\n static uuid(): string {\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return crypto.randomUUID();\n }\n\n // Fallback using crypto.getRandomValues\n if (typeof crypto !== 'undefined' && 'getRandomValues' in crypto) {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => {\n const num = parseInt(c, 10);\n const random = crypto.getRandomValues(new Uint8Array(1))[0];\n const shifted = 15 >> Math.floor(num / 4);\n return (num ^ (random & shifted)).toString(16);\n });\n }\n\n // Insecure Fallback, pretty sure no current browser should need this\n const generate = (): string => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\n return `${generate()}${generate()}-${generate()}-${generate()}-${generate()}-${generate()}${generate()}${generate()}`;\n }\n\n /**\n * Debounce a function call.\n *\n * @param fn - Function to debounce\n * @param delay - Delay in milliseconds\n */\n static debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): (...args: Parameters<T>) => void {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n fn(...args);\n timeoutId = null;\n }, delay);\n };\n }\n\n /**\n * Throttle a function call.\n *\n * @param fn - Function to throttle\n * @param limit - Minimum time between calls in milliseconds\n */\n static throttle<T extends (...args: unknown[]) => unknown>(fn: T, limit: number): (...args: Parameters<T>) => void {\n let inThrottle = false;\n\n return (...args: Parameters<T>): void => {\n if (!inThrottle) {\n fn(...args);\n inThrottle = true;\n setTimeout(() => {\n inThrottle = false;\n }, limit);\n }\n };\n }\n}\n",
20
+ "// This file is basically just a hack to expose the Artemis namespace in the\n// window object. Once/if bun adds support for this, we can remove this file.\n\nimport * as Artemis from './index';\n\ndeclare global {\n interface Window {\n Artemis: typeof Artemis;\n }\n}\n\nif (typeof window === 'object') {\n window.Artemis = Artemis;\n}\n\n"
20
21
  ],
21
- "mappings": "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",
22
- "debugId": "9718D4631B30A69A64756E2164756E21",
22
+ "mappings": "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",
23
+ "debugId": "8FAFB15BD5215AFD64756E2164756E21",
23
24
  "names": []
24
25
  }