@kluntje/services
Advanced tools
+17
-0
@@ -6,2 +6,19 @@ # Change Log | ||
| # [0.9.0](https://github.com/kluntje/kluntje/tree/develop/packages/services/compare/@kluntje/services@0.8.0...@kluntje/services@0.9.0) (2025-03-18) | ||
| ### Code Refactoring | ||
| * **services:** optimized ContextState typing ([603f61c](https://github.com/kluntje/kluntje/tree/develop/packages/services/commit/603f61cb1a1d76d767e7070db2cda194849cd446)) | ||
| ### BREAKING CHANGES | ||
| * **services:** It is no longer possible to force the return type of ContextState.getState via | ||
| generic. | ||
| # [0.8.0](https://github.com/kluntje/kluntje/tree/develop/packages/services/compare/@kluntje/services@0.7.0...@kluntje/services@0.8.0) (2024-12-06) | ||
@@ -8,0 +25,0 @@ |
@@ -1,2 +0,2 @@ | ||
| export declare class ContextState { | ||
| export declare class ContextState<StateDefinition extends Record<string, any> = Record<string, any>> { | ||
| private stateMap; | ||
@@ -10,6 +10,6 @@ private observerService; | ||
| isMatchingContext(contextName: string, consumingElement: HTMLElement): boolean; | ||
| setState<T>(key: string, value: T): void; | ||
| getState<T>(key: string): T | undefined; | ||
| observeState(key: string, callback: () => void): void; | ||
| unobserveState(key: string, callback: () => void): void; | ||
| setState<K extends keyof StateDefinition>(key: K, value: StateDefinition[K]): void; | ||
| getState<K extends keyof StateDefinition>(key: K): StateDefinition[K] | undefined; | ||
| observeState(key: keyof StateDefinition, callback: () => void): void; | ||
| unobserveState(key: keyof StateDefinition, callback: () => void): void; | ||
| } |
@@ -7,5 +7,5 @@ import { ContextState } from './ContextState'; | ||
| private getMatchingContextState; | ||
| getContextState(contextName: string, consumingElement: HTMLElement): Promise<ContextState>; | ||
| createContextState(contextName: string, contextElement: HTMLElement): ContextState; | ||
| getContextState<StateDefinition extends Record<string, any>>(contextName: string, consumingElement: HTMLElement): Promise<ContextState<StateDefinition>>; | ||
| createContextState<StateDefinition extends Record<string, any>>(contextName: string, contextElement: HTMLElement): ContextState<StateDefinition>; | ||
| } | ||
| export declare const ContextStateService: ContextStateServiceImpl; |
| import { ContextState } from './ContextState'; | ||
| export interface IContextStateService { | ||
| getContextState(contextName: string, consumingElement: HTMLElement): Promise<ContextState>; | ||
| createContextState(contextName: string, contextElement: HTMLElement): ContextState; | ||
| getContextState<StateDefinition extends Record<string, any>>(contextName: string, consumingElement: HTMLElement): Promise<ContextState<StateDefinition>>; | ||
| createContextState<StateDefinition extends Record<string, any>>(contextName: string, contextElement: HTMLElement): ContextState<StateDefinition>; | ||
| } |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../src/ViewportObserver.ts","../src/eventNames.ts","../src/MediaQueryService.ts","../src/I18nService.ts","../src/URLSearchParamsService.ts","../src/DebuggerService.ts","../src/LazyConnectService.ts","../src/StorageService/StorageService.ts","../src/CachingService/CachingService.ts","../src/RequestCachingService/RequestCachingService.ts","../src/APIService/APIService.types.ts","../src/APIService/APIService.ts","../src/ObserverService/ObserverService.ts","../src/ContextStateService/ContextState.ts","../src/ContextStateService/ContextStateService.ts","../src/AbortableRequestService/AbortableRequestService.ts"],"sourcesContent":["import { IN_VP_EVENT, OUT_VP_EVENT } from './eventNames';\n\ntype IntersectionEvent = {\n [key: string]: any;\n};\n\nexport class ViewportObserver {\n private static instance: IntersectionObserver;\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private constructor() {}\n\n static getInstance() {\n if (ViewportObserver.instance === undefined) {\n ViewportObserver.instance = new IntersectionObserver(ViewportObserver.handleIntersectionChange);\n }\n return ViewportObserver.instance;\n }\n\n private static handleIntersectionChange(e: IntersectionEvent) {\n Object.keys(e).forEach((key) => {\n const observedEl = e[key];\n const target = observedEl.target;\n\n if (observedEl.isIntersecting) {\n target.dispatchEvent(new CustomEvent(IN_VP_EVENT, { bubbles: false }));\n } else {\n target.dispatchEvent(new CustomEvent(OUT_VP_EVENT, { bubbles: false }));\n }\n });\n }\n}\n","export const MQ_CHANGE_EVENT = 'kl-mq-change';\nexport const IN_VP_EVENT = 'kl-in-vp';\nexport const OUT_VP_EVENT = 'kl-out-vp';\n","import { throttle } from '@kluntje/js-utils/lib/function-helpers/decorators';\nimport { onEvent, getCurrentMQ, MQDefinition } from '@kluntje/js-utils/lib/dom-helpers';\nimport { MQ_CHANGE_EVENT } from './eventNames';\n\nexport class MediaQueryService {\n private static instance: MediaQueryService;\n static mediaQuerys: Array<MQDefinition>;\n eventIdMap: WeakMap<HTMLElement | Function, string>;\n eventBindingMap: {\n [index: string]: EventListenerOrEventListenerObject;\n };\n lastMQ: string;\n\n private constructor() {\n this.eventIdMap = new WeakMap();\n this.eventBindingMap = {};\n this.lastMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n onEvent(window, 'resize', this.handleMQChange, this);\n }\n\n static getInstance(mediaQuerys: Array<MQDefinition>) {\n if (MediaQueryService.instance === undefined) {\n MediaQueryService.mediaQuerys = mediaQuerys;\n MediaQueryService.instance = new MediaQueryService();\n }\n return MediaQueryService.instance;\n }\n\n @throttle(100)\n handleMQChange() {\n const newMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n if (newMQ === this.lastMQ) {\n return;\n }\n\n window.dispatchEvent(\n new CustomEvent(MQ_CHANGE_EVENT, {\n detail: {\n newMQ,\n oldMQ: this.lastMQ,\n },\n }),\n );\n\n this.lastMQ = newMQ;\n }\n}\n","import { fetchJSON } from '@kluntje/js-utils/lib/api-helpers';\nimport { isFilledObject } from '@kluntje/js-utils/lib/object-helpers';\n\nconst resolveSymbol = Symbol('resolve');\nconst rejectSymbol = Symbol('reject');\nconst pendingSymbol = Symbol('pending');\n\n// Promise but with options to resolve/reject from outside\ninterface ExtendedPromise<T> extends Promise<T> {\n [resolveSymbol]: Function;\n [rejectSymbol]: Function;\n [pendingSymbol]: boolean;\n}\n\n/**\n * A service to provide sync/async way to provide internationalization values.\n * With i18n values beeing able to have variable placeholder in them. indexd for arrays e.g. `{0}` or named for objects e.g. `{hour}`\n *\n * @example\n * import I18nService from \"@kluntje/services/I18nService\";\n * // get singleton instance\n * const i18nService = I18nService.getInstance();\n * // provide the url to fetch the dictionary\n * i18nService.setUp({url: \"path/to/i18n/ajax/service\"});\n * // or provide the dictionary itself\n * // i18nService.setUp({dictionary: {\"com.page.filter.notifications\": \"{0} Nachrichten\", ...}});\n * const i18n = i18nService.get;\n * // use API\n * // render markup with i18n value, if the i18n key hasn't been fetched jet, a placeholder `<span class\"kl-i18n-placeholder\"></span>` will be rendered,\n * // with the provided `fallback` text. or the last part of the key.\n * // this `span` will be replaced with the i18n value in den DOM after the keys where successfully fetched from the server\n * render(html`<button>${i18n(\"com.page.filter.notifications\", {fallback: \"Info\", interpolations: [7]})}</button>`, el);\n * // if any actions needs the keys to be ready and shouldn't be replace later in the DOM, the `ready` accessor can be called.\n * // this will automatically trigger the fetch for the keys from the server\n * await i18nService.ready;\n * // the boolean `loaded` can be used to check if the keys have been fetched form the server. This will not trigger the fetch.\n * if (i18nService.loaded) console.log(i18nService.get(\"com.page.filter.submitLabel\"))\n *\n * @export\n * @class I18nService\n */\nexport class I18nService {\n /**\n * class name for the `span`s being used as placeholder for i18n values in the DOM before the actual values have been fetched from the server\n *\n * @readonly\n * @static\n * @memberof I18nService\n */\n static get PLACEHOLDER_SELECTOR() {\n return 'kl-i18n-placeholder';\n }\n\n private static _instance?: I18nService;\n\n /**\n * returns the singleton instance of the I18nService\n *\n * @static\n * @returns\n * @memberof I18nService\n */\n static getInstance() {\n if (I18nService._instance === undefined) {\n I18nService._instance = new I18nService();\n }\n\n return I18nService._instance;\n }\n\n // see `I18nService.loaded` for more information about this property\n private _loaded = false;\n\n // see `I18nService.ready` for more information about this property\n private _ready: ExtendedPromise<undefined>;\n\n // a key-value map of the i18n keys and their internationalizations fetched from the server or provided by the user\n private _dictionary: { [key: string]: string } = {};\n\n // url to the servlet returning the dictionary\n private _url?: string;\n\n /**\n * returns true if the I18nService has been set up already. i.e. has a ajax url or the dictionary provided\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get isSetUp(): boolean {\n return Boolean(this._url || isFilledObject(this._dictionary));\n }\n\n /**\n * `loaded` will be true when the keys have been fetched from the server. and `false` otherwise.\n * reading the `loaded` accessor won't trigger the key fetch. For that use {@see I18nService.ready}\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get loaded(): boolean {\n return this._loaded;\n }\n\n /**\n * a promise will be returned that resolves when the keys have been fetched from the server, or the server rejected the ajax call.\n * reading the `ready` accessor will automatically trigger the dictionary fetch.\n * use this property when you NEED the keys to be already loaded and can't be replaced in the DOM later.\n *\n * @readonly\n * @type {Promise<undefined>}\n * @memberof I18nService\n */\n public get ready(): Promise<undefined> {\n if (!this._ready[pendingSymbol]) this.fetchI18nDictionary();\n\n return this._ready as Promise<undefined>;\n }\n\n /**\n * providing information necessary for the service to retrieve the i18n dictionary.\n * i.e. a ajax url to fetch data, or a static object with the i18n key-value in it\n *\n * @param {{ url: string; dictionary: Record<string, string> }} { url, dictionary }\n * @returns\n * @memberof I18nService\n */\n public setUp({ url, dictionary }: { url?: string; dictionary?: Record<string, string> } = {}) {\n if (this.isSetUp) {\n console.warn(\"@kluntje I18nService: service has already been set up. You can't set it up twice!\");\n return;\n }\n if (url) {\n this._url = url;\n } else if (dictionary) {\n this._dictionary = dictionary;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this._ready[pendingSymbol] = true;\n } else {\n throw new Error('@kluntje I18nService: a \"url\" or \"dictionary\" should have been passed to the setUp function.');\n }\n }\n\n /**\n * returns the internationalized value for the given i18n key when the value have been fetched from the server,\n * or a placeholder `<span>` with a fallback text based on the key or the provided fallback text\n * which will automatically be replaced with the value in the DOM after server response\n *\n * @param {string} key\n * @param {({ fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> })} [{\n * fallback,\n * interpolations,\n * }={}]\n * @returns {string}\n * @memberof I18nService\n */\n public get(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ): string {\n if (this.loaded) {\n if (this._dictionary.hasOwnProperty(key)) {\n let result = this._dictionary[key];\n if (interpolations) {\n Object.entries(interpolations).forEach(([k, v]) => {\n // replaceAll({key}, value)\n result = result.split(`{${k}}`).join(String(v));\n });\n }\n\n return result;\n }\n console.warn(`@kluntje I18nService: i18n for key '${key}' is missing in dictionary!`);\n\n return fallback !== undefined ? fallback : this.getHumanReadableName(key);\n }\n\n if (!this._ready[pendingSymbol]) {\n // add styling for the placeholder first time a placeholder will be added to the DOM\n this.addStyling();\n this.fetchI18nDictionary();\n }\n\n return this.getPlaceholder(key, { fallback, interpolations });\n }\n\n /**\n * Creates an instance of I18nService.\n * @memberof I18nService\n */\n private constructor() {\n this._ready = this.getReadyPromise();\n }\n\n /**\n * returns a Promise like object with properties to allow resolving the promise from the outside\n *\n * @private\n * @returns {ExtendedPromise<undefined>}\n * @memberof I18nService\n */\n private getReadyPromise(): ExtendedPromise<undefined> {\n let resolve: Function;\n let reject: Function;\n\n // @ts-ignore - other properties will be added in next couple of lines\n const _ready: ExtendedPromise<undefined> = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n // @ts-ignore - `resolve` is defined in the promise body from lines above\n _ready[resolveSymbol] = resolve;\n // @ts-ignore - `reject` is defined in the promise body from lines above\n _ready[rejectSymbol] = reject;\n // will be set to true when ajax call is sent\n _ready[pendingSymbol] = false;\n\n return _ready;\n }\n\n /**\n * throws an Error when the service is not set up\n *\n * @private\n * @memberof I18nService\n */\n private ensureSetup(): void {\n if (!this.isSetUp) throw new Error('@kluntje I18nService: should be set up before calling other APIs');\n }\n\n /**\n * add minimal styling for the placeholder to look as much as possible as if they were a text node and not a html element,\n * and without the need of an actual .css file to be loaded\n *\n * @private\n * @memberof I18nService\n */\n private addStyling(): void {\n const head = document.head;\n const style = document.createElement('style');\n style.type = 'text/css';\n style.appendChild(\n document.createTextNode(`\n .${I18nService.PLACEHOLDER_SELECTOR} {\n display: contents;\n }\n `),\n );\n head.appendChild(style);\n }\n\n /**\n * retrieves the i18n key.value pairs, and update instance properties regarding the pending/fulfilled status of the request\n *\n * @private\n * @memberof I18nService\n */\n private fetchI18nDictionary() {\n this.ensureSetup();\n this._ready[pendingSymbol] = true;\n\n fetchJSON(this._url!)\n .then((results: Record<string, string>) => {\n this._dictionary = results;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this.fillInPlaceholders();\n })\n .catch((err: Error) => {\n console.error('@kluntje I18nService: unable to fetch keys from server!', err);\n // ? adding a failed flag\n this._loaded = true;\n this._ready[resolveSymbol]();\n });\n }\n\n /**\n * i18n placeholder in the DOM will be fetched with i18n values been fetched from the server.\n *\n * @private\n * @memberof I18nService\n */\n private fillInPlaceholders() {\n Array.from(document.getElementsByClassName(I18nService.PLACEHOLDER_SELECTOR)).forEach((el) => {\n const { key, fallback, interpolations } = (el as HTMLElement).dataset;\n\n el.replaceWith(\n this.get(key!, {\n fallback,\n interpolations: interpolations ? JSON.parse(interpolations) : undefined,\n }),\n );\n });\n }\n\n /**\n * converts the i18n key names to values that can be used as fallback for the i18n text\n * @example\n * getHumanReadableName(\"org.example.hyphenated_name.filter.submitBtn\") === \"submit btn\"\n *\n * @private\n * @param {string} key\n * @returns\n * @memberof I18nService\n */\n private getHumanReadableName(key: string) {\n return (\n key\n // \"org.example.hyphenated_name.filter.submitBtn\" -> \"submitBtn\"\n .split('.')\n .reverse()[0]\n // \"submitBtn\" -> \"submit btn\"\n .replace(/[A-Z]/g, (letter: string) => ` ${letter.toLowerCase()}`)\n );\n }\n\n /**\n * generates a span element whith the fallback text to be replaced with the correct i18n value after server response\n *\n * @private\n * @param {string} key\n * @param {string} [fallback]\n * @returns\n * @memberof I18nService\n */\n private getPlaceholder(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ) {\n const span = document.createElement('span');\n span.innerText = fallback !== undefined ? fallback : this.getHumanReadableName(key);\n span.classList.add(I18nService.PLACEHOLDER_SELECTOR);\n span.setAttribute('data-key', key);\n if (fallback) span.setAttribute('data-fallback', fallback);\n // use escaping mechanism of setAttribute to store the stringified json\n if (interpolations) span.setAttribute('data-interpolations', JSON.stringify(interpolations));\n\n return span.outerHTML;\n }\n}\n","export class URLSearchParamsService {\n private urlSearchParams: URLSearchParams = new URLSearchParams(window.location.search);\n\n public get(param: string): string | null {\n return this.urlSearchParams.get(param);\n }\n\n public getAll(param: string): string[] | null {\n return this.urlSearchParams.getAll(param);\n }\n\n public getAllKeys(): Array<string> {\n // @ts-ignore\n return Array.from(this.urlSearchParams.keys());\n }\n\n public set(param: string, value: string): void {\n this.urlSearchParams.set(param, value);\n this.updateUrl();\n }\n\n public delete(param: string): void {\n this.urlSearchParams.delete(param);\n this.updateUrl();\n }\n\n public getString(): string {\n return this.urlSearchParams.toString();\n }\n\n public get curUrl() {\n return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;\n }\n\n private updateUrl() {\n const curQueryString = this.getString();\n const curUrl = this.curUrl;\n const hashCache = window.location.hash;\n const newUrl = curQueryString !== '' ? `${curUrl}?${curQueryString}` : curUrl;\n window.history.replaceState({ path: newUrl }, '', newUrl);\n if (hashCache !== '') window.location.hash = hashCache;\n }\n}\n\nexport default new URLSearchParamsService();\n","import URLSearchParamsService from './URLSearchParamsService';\n\nfunction debugModeActive() {\n return URLSearchParamsService.get('js-debug') !== null;\n}\n\nconst handler = {\n get(target: Console, prop: keyof Console) {\n if (debugModeActive()) return target[prop];\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n else return () => {};\n },\n};\n\nexport default new Proxy(console, handler);\n","class LazyConnectService {\n componentMap = new WeakMap();\n intersectionObserver: IntersectionObserver;\n\n constructor() {\n this.intersectionObserver = new IntersectionObserver((entries: any) => this.handleIntersectionChange(entries), {\n rootMargin: '500px 0px',\n });\n }\n\n subscribe(target: HTMLElement, intersectionCallback: () => void) {\n this.componentMap.set(target, intersectionCallback);\n this.intersectionObserver.observe(target);\n }\n\n unsubscribe(target: HTMLElement) {\n this.intersectionObserver.unobserve(target);\n this.componentMap.delete(target);\n }\n\n handleIntersectionChange(entries: Array<IntersectionObserverEntry>) {\n entries.forEach((intersectionEntry: any) => {\n const target = intersectionEntry.target;\n\n if (!intersectionEntry.isIntersecting || !this.componentMap.has(target)) return;\n\n const intersectionCallback = this.componentMap.get(target);\n this.unsubscribe(target as HTMLElement);\n intersectionCallback();\n });\n }\n}\n\nexport default new LazyConnectService();\n","import { IStorageService } from './StorageService.interface';\nimport { StorageServiceOptions, StorageType } from './StorageService.types';\n\nexport class StorageServiceImpl implements IStorageService {\n private observedItemsMap: Map<string, Set<() => void>> = new Map();\n\n constructor() {\n window.addEventListener('storage', (e) => this.handleStorageChange(e));\n }\n\n public addItem(storageKey: string, storageValue: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).setItem(storageKey, storageValue);\n this.fireCallbacks(storageKey);\n }\n\n public getItem(storageKey: string, options: StorageServiceOptions = {}): string | null {\n return this.getStorage(options).getItem(storageKey);\n }\n\n public removeItem(storageKey: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).removeItem(storageKey);\n }\n\n public observeItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.add(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public unobserveItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.delete(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public clearStorage(storageType: StorageType) {\n this.getStorage({ storageType }).clear();\n }\n\n private handleStorageChange(e: StorageEvent) {\n const storageKey = e.key;\n const oldValue = e.oldValue;\n const newValue = e.newValue;\n if (storageKey === null || oldValue === newValue || !this.observedItemsMap.has(storageKey)) return;\n\n this.fireCallbacks(storageKey);\n }\n\n private getKeyCallbacks(storageKey: string): Set<() => void> {\n return this.observedItemsMap.get(storageKey) || new Set();\n }\n\n private fireCallbacks(storageKey: string) {\n const callbacks = this.getKeyCallbacks(storageKey);\n callbacks.forEach((callback) => callback());\n }\n\n private getStorage(options: StorageServiceOptions): Storage {\n const { storageType = 'local' } = options;\n return storageType === 'local' ? localStorage : sessionStorage;\n }\n}\n\nexport const StorageService = new StorageServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { StorageServiceOptions, StorageService, IStorageService } from '../StorageService';\nimport { ICachingService } from './CachingService.interface';\nimport { CacheItem, CacheOptions, CachingServiceConstructorOptions } from './CachingService.types';\n\nexport class CachingServiceImpl implements ICachingService {\n private runtimeCache: Map<string, string> = new Map();\n private storageService: IStorageService = StorageService;\n private storageKeyPrefix = 'kl-caching-service';\n\n constructor(options?: CachingServiceConstructorOptions) {\n const { storageService, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n protected get shouldCache(): boolean {\n return true;\n }\n\n public cacheValue(key: string, value: string, options: CacheOptions) {\n if (this.shouldCache === false) return;\n\n if (options.validFor === 0) {\n this.runtimeCache.set(this.getStorageKey(key), value);\n return;\n }\n\n const cacheItem: CacheItem = {\n value,\n validUntil: Date.now() + options.validFor,\n };\n\n this.storageService.addItem(\n this.getStorageKey(key),\n JSON.stringify(cacheItem),\n this.getStorageServiceOptions(options),\n );\n }\n\n public getCachedValue(key: string, cacheOptions?: CacheOptions): string | null {\n if (this.shouldCache === false) return null;\n\n const storageKey = this.getStorageKey(key);\n\n const runtimeValue = this.runtimeCache.get(storageKey);\n\n if (runtimeValue !== undefined) return runtimeValue;\n\n const cachedItemString = this.storageService.getItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n if (cachedItemString === null) return null;\n\n try {\n const cachedItem: CacheItem = JSON.parse(cachedItemString);\n if (cachedItem.validUntil < Date.now()) {\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n\n return cachedItem.value;\n } catch (e) {\n DebuggerService.warn('CachingService: ', e);\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n }\n\n public getCachedJSON<T>(key: string, cacheOptions?: CacheOptions): T | null {\n const cachedValue = this.getCachedValue(key, cacheOptions);\n if (cachedValue === null) return null;\n try {\n return JSON.parse(cachedValue);\n } catch (error) {\n DebuggerService.error('CachingService: ', error);\n return null;\n }\n }\n\n public clearCachedValue(key: string, cacheOptions?: CacheOptions) {\n const storageKey = this.getStorageKey(key);\n\n if (cacheOptions?.validFor === 0) {\n this.runtimeCache.delete(storageKey);\n return;\n }\n\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n }\n\n private getStorageServiceOptions(cacheOptions?: CacheOptions): StorageServiceOptions {\n return {\n storageType: cacheOptions?.storageType,\n };\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const CachingService = new CachingServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { IStorageService, StorageService, StorageType } from '../StorageService';\nimport { IRequestCachingService } from './RequestCachingService.interface';\nimport { RequestCacheOptions, RequestCachingServiceConstructorOptions } from './RequestCachingService.types';\n\nexport class RequestCachingServiceImpl implements IRequestCachingService {\n private _cache?: Promise<Cache>;\n\n private storageService: IStorageService = StorageService;\n private requestCacheName = 'kl-request-cache';\n private storageKeyPrefix = 'kl-request-caching-service';\n\n constructor(options?: RequestCachingServiceConstructorOptions) {\n const { storageService, requestCacheName, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (requestCacheName !== undefined) {\n this.requestCacheName = requestCacheName;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n private async getCache(): Promise<Cache | null> {\n try {\n if (this._cache === undefined) {\n this._cache = caches.open(this.requestCacheName);\n }\n return await this._cache;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async getCachedResponse(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return null;\n\n const response = await cache.match(request);\n if (response === undefined) return null;\n\n const validUntil = this.storageService.getItem(this.getStorageKey(request.url), { storageType: storage });\n if (validUntil === null) {\n await cache.delete(request);\n return null;\n }\n\n const now = Date.now();\n if (now > parseInt(validUntil, 10)) {\n await cache.delete(request);\n return null;\n }\n return response;\n }\n\n public async getCachedJSON<T>(request: Request, storage?: StorageType) {\n const response = await this.getCachedResponse(request, storage);\n if (response === null) return null;\n try {\n return (await response.json()) as T;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async cacheRequest(options: RequestCacheOptions) {\n const { request, response } = options;\n const cache = await this.getCache();\n if (cache === null) return;\n this.storeExpirationTime(options);\n await cache.put(request, response);\n }\n\n public async clearCachedRequest(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return;\n await cache.delete(request);\n this.storageService.removeItem(this.getStorageKey(request.url), { storageType: storage });\n }\n\n private storeExpirationTime(options: RequestCacheOptions) {\n const { request, maxAge } = options;\n const validUntil = Date.now() + maxAge;\n this.storageService.addItem(this.getStorageKey(request.url), validUntil.toString(), {\n storageType: options.storage,\n });\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const RequestCachingService = new RequestCachingServiceImpl();\n","import { CacheOptions, ICachingService } from '../CachingService';\nimport { IRequestCachingService } from '../RequestCachingService';\n\nexport interface APIServiceCacheOptions extends CacheOptions {\n forceRefetch?: boolean;\n requestBasedCaching?: boolean;\n cacheKeys?: string[];\n}\n\nexport interface APIServiceRequestOptions {\n fetchOptions?: RequestInit;\n cacheOptions?: APIServiceCacheOptions;\n throwError?: boolean;\n}\n\nexport interface APIServiceConstructorOptions {\n cachingService?: ICachingService;\n requestCachingService?: IRequestCachingService;\n}\n\nexport class APIError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n super(response.statusText);\n this.response = response;\n }\n}\n","import { appendQueryObject } from \"@kluntje/js-utils/lib/url-helpers\";\n\nimport DebuggerService from \"../DebuggerService\";\nimport { IRequestCachingService, RequestCachingService } from \"../RequestCachingService\";\nimport { CachingService, ICachingService } from \"../CachingService\";\n\nimport { APIError, APIServiceCacheOptions, APIServiceConstructorOptions, APIServiceRequestOptions } from \"./APIService.types\";\nimport { IAPIService } from \"./APIService.interface\";\n\nexport class APIServiceImpl implements IAPIService {\n private requestPipeline: Map<string, Promise<Response | null>> = new Map();\n\n private cachingService: ICachingService = CachingService;\n private requestCachingService: IRequestCachingService = RequestCachingService;\n\n constructor(options: APIServiceConstructorOptions = {}) {\n const { cachingService, requestCachingService } = options;\n\n if (cachingService !== undefined) this.cachingService = cachingService;\n if (requestCachingService !== undefined) this.requestCachingService = requestCachingService;\n }\n\n public async fetchJSON<T>(url: string, options: APIServiceRequestOptions = {}): Promise<T | null> {\n // eslint-disable-next-line prettier/prettier\n return await this.fetch(url, APIServiceImpl.getJSON<T>, options);\n }\n\n public async fetchHTML(url: string, options: APIServiceRequestOptions = {}): Promise<string | null> {\n return await this.fetch(url, APIServiceImpl.getHTML, options);\n }\n\n private async fetch<T>(\n url: string,\n dataMapper: (response: Response | null) => Promise<T>,\n options: APIServiceRequestOptions = {},\n ): Promise<T | null> {\n const { cacheOptions } = options;\n\n if (cacheOptions?.forceRefetch === true) {\n this.clearCachedValue(url, cacheOptions);\n }\n\n const cachedValue = await this.getCachedValue<T>(url, cacheOptions);\n if (cachedValue !== null) return cachedValue;\n\n try {\n const pipelineRequest = this.requestPipeline.get(url);\n if (pipelineRequest !== undefined) {\n return await dataMapper(await pipelineRequest);\n }\n\n const request = this.fetchData(url, options);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n const responseData = await dataMapper(response);\n this.requestPipeline.delete(url);\n\n if (response === null || responseData === null) return null;\n\n if (cacheOptions === undefined) return responseData;\n await this.cacheResponse(url, response, responseData, cacheOptions);\n\n return responseData;\n } catch (error) {\n DebuggerService.error(\"APIService.fetch: \", error);\n this.requestPipeline.delete(url);\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n public async fetchResponse(url: string, options: APIServiceRequestOptions = {}): Promise<Response | null> {\n const { cacheOptions } = options;\n const { forceRefetch = false } = cacheOptions ?? {};\n\n if (forceRefetch === true) {\n await this.requestCachingService.clearCachedRequest(new Request(url), cacheOptions?.storageType ?? \"session\");\n }\n\n const cachedResponse = await this.requestCachingService.getCachedResponse(\n new Request(url),\n cacheOptions?.storageType ?? \"session\",\n );\n\n if (cachedResponse !== null) return cachedResponse;\n\n const pipelineRequest = this.requestPipeline.get(url);\n\n if (pipelineRequest !== undefined) {\n return await pipelineRequest;\n }\n\n try {\n const request = fetch(url, options.fetchOptions);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n this.requestPipeline.delete(url);\n\n if (cacheOptions === undefined) return response;\n\n await this.requestCachingService.cacheRequest({\n request: new Request(url),\n response,\n storage: cacheOptions.storageType ?? \"session\",\n maxAge: cacheOptions.validFor,\n });\n\n return response;\n } catch (error) {\n DebuggerService.error(\"APIService.fetchResponse: \", error);\n\n this.requestPipeline.delete(url);\n\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n private async fetchData(url: string, options: APIServiceRequestOptions): Promise<Response | null> {\n const response = await fetch(url, options.fetchOptions);\n\n if (!response.ok) throw new APIError(response);\n if (response.status === 204) return null;\n\n return response;\n }\n\n private static async getJSON<T>(response: Response | null): Promise<T | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.json();\n }\n\n private static async getHTML(response: Response | null): Promise<string | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.text();\n }\n\n private async cacheResponse<T>(\n url: string,\n response: Response,\n responseData: T,\n cacheOptions: APIServiceCacheOptions,\n ) {\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (cacheOptions.requestBasedCaching === true) {\n await this.requestCachingService.cacheRequest({\n request: new Request(cacheKey),\n response,\n storage: cacheOptions.storageType ?? \"local\",\n maxAge: cacheOptions.validFor,\n });\n } else {\n this.cachingService.cacheValue(cacheKey, JSON.stringify(responseData), cacheOptions);\n }\n }\n\n private async clearCachedValue(url: string, cacheOptions?: APIServiceCacheOptions) {\n if (cacheOptions === undefined) return;\n const { requestBasedCaching = false } = cacheOptions;\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (requestBasedCaching === true) {\n await this.requestCachingService.clearCachedRequest(new Request(cacheKey), cacheOptions.storageType);\n }\n this.cachingService.clearCachedValue(cacheKey, cacheOptions);\n }\n\n private async getCachedValue<T>(url: string, cacheOptions?: APIServiceCacheOptions): Promise<T | null> {\n if (cacheOptions === undefined) return null;\n const { requestBasedCaching = false } = cacheOptions;\n\n const cacheKey = this.getCacheKey(url, cacheOptions);\n if (requestBasedCaching === true) {\n return await this.requestCachingService.getCachedJSON(new Request(cacheKey), cacheOptions.storageType);\n }\n return this.cachingService.getCachedJSON(cacheKey, cacheOptions);\n }\n\n private getCacheKey(url: string, cacheOptions?: APIServiceCacheOptions): string {\n const cacheKeys = cacheOptions?.cacheKeys ?? [];\n if (cacheKeys.length === 0) return url;\n return appendQueryObject(url, { klCacheKeys: cacheKeys.join(\"_\") });\n }\n}\n\nexport const APIService = new APIServiceImpl();\n","import { IObserverService } from './ObserverService.interface';\nimport { ObserverCallback } from './ObserverService.types';\n\nexport class ObserverServiceImpl implements IObserverService {\n private observerMap: Map<string, Set<ObserverCallback>> = new Map();\n\n public observe(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.add(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public unobserve(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.delete(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public notifyObservers<T>(observedKey: string, data?: T) {\n const callbacks = this.getCallbacks(observedKey);\n callbacks.forEach((callback) => callback(data));\n }\n\n private getCallbacks(observedKey: string): Set<ObserverCallback> {\n return this.observerMap.get(observedKey) || new Set();\n }\n}\n\nexport const ObserverService = new ObserverServiceImpl();\n","import { ObserverServiceImpl } from '../ObserverService';\n\nexport class ContextState {\n private stateMap: Map<string, any> = new Map();\n private observerService = new ObserverServiceImpl();\n private contextName: string;\n private contextElement: HTMLElement;\n\n constructor(contextName: string, contextElement: HTMLElement) {\n this.contextName = contextName;\n this.contextElement = contextElement;\n }\n\n public get name(): string {\n return this.contextName;\n }\n\n public get element(): HTMLElement {\n return this.contextElement;\n }\n\n public isMatchingContext(contextName: string, consumingElement: HTMLElement): boolean {\n if (this.contextName !== contextName) return false;\n\n return this.contextElement.contains(consumingElement);\n }\n\n public setState<T>(key: string, value: T): void {\n if (this.stateMap.get(key) === value) return;\n this.stateMap.set(key, value);\n this.observerService.notifyObservers(key);\n }\n\n public getState<T>(key: string): T | undefined {\n return this.stateMap.get(key) as T;\n }\n\n public observeState(key: string, callback: () => void): void {\n this.observerService.observe(key, callback);\n }\n\n public unobserveState(key: string, callback: () => void): void {\n this.observerService.unobserve(key, callback);\n }\n}\n","import { ContextState } from './ContextState';\nimport { ObserverServiceImpl } from '../ObserverService';\nimport { IContextStateService } from './ContextStateService.interface';\n\nexport class ContextStateServiceImpl implements IContextStateService {\n private contextStateMap: Map<string, ContextState[]> = new Map();\n private contextInitObserver = new ObserverServiceImpl();\n\n private getMatchingContextState(contextName: string, consumingElement: HTMLElement): ContextState | null {\n const contextList = this.contextStateMap.get(contextName) || [];\n const matchingContexts = contextList.filter((context) => context.isMatchingContext(contextName, consumingElement));\n if (matchingContexts.length === 0) return null;\n return matchingContexts[0];\n }\n\n public getContextState(contextName: string, consumingElement: HTMLElement): Promise<ContextState> {\n const matchingContextState = this.getMatchingContextState(contextName, consumingElement);\n if (matchingContextState) return Promise.resolve(matchingContextState);\n return new Promise<ContextState>((resolve) => {\n this.contextInitObserver.observe(contextName, () => {\n const contextState = this.getMatchingContextState(contextName, consumingElement);\n if (contextState) {\n resolve(contextState);\n }\n });\n });\n }\n\n public createContextState(contextName: string, contextElement: HTMLElement): ContextState {\n const contextState = new ContextState(contextName, contextElement);\n const contextList = this.contextStateMap.get(contextName) || [];\n contextList.push(contextState);\n this.contextStateMap.set(contextName, contextList);\n this.contextInitObserver.notifyObservers(contextName);\n return contextState;\n }\n}\n\nexport const ContextStateService = new ContextStateServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { APIService, APIServiceRequestOptions, IAPIService } from '../APIService';\nimport {\n AbortableRequestServiceConstructorOptions,\n AbortableRequestServiceOptions,\n} from './AbortableRequestService.types';\n\nexport class AbortableRequestService {\n private abortController = new AbortController();\n private abortOptions: AbortableRequestServiceOptions | null = null;\n private latestOptions: AbortableRequestServiceOptions | null = null;\n\n protected apiService: IAPIService = APIService;\n\n constructor(options: AbortableRequestServiceConstructorOptions = {}) {\n const { apiService } = options;\n\n if (apiService !== undefined) this.apiService = apiService;\n }\n\n public async fetchJSON<T>(options: AbortableRequestServiceOptions): Promise<T | null> {\n return await this.makeAbortableRequest<T>(options, this.apiService.fetchJSON.bind(this.apiService));\n }\n\n public async fetchResponse(options: AbortableRequestServiceOptions): Promise<Response | null> {\n return await this.makeAbortableRequest<Response>(options, this.apiService.fetchResponse.bind(this.apiService));\n }\n\n private async makeAbortableRequest<R>(\n options: AbortableRequestServiceOptions,\n fetcher: (url: string, options: APIServiceRequestOptions) => Promise<R | null>,\n ): Promise<R | null> {\n if (this.latestOptions !== null) {\n this.abortOptions = options;\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n this.latestOptions = options;\n\n try {\n const response = await fetcher(options.url, {\n cacheOptions: options.options?.cacheOptions,\n throwError: true,\n fetchOptions: {\n ...options.options?.fetchOptions,\n signal: this.abortController.signal,\n },\n });\n this.latestOptions = null;\n return response;\n } catch (error: any) {\n DebuggerService.error('AbortableRequestService.makeAbortableRequest: ', error);\n\n if (error.name === 'AbortError') return this.handleAbortError<R>(this.fetchJSON.bind(this));\n\n if (options.options?.throwError === true) throw error;\n\n return null;\n }\n }\n\n private async handleAbortError<R>(\n nextAction: (options: AbortableRequestServiceOptions) => Promise<R | null>,\n ): Promise<R | null> {\n const latestOptions = this.latestOptions || this.abortOptions;\n if (latestOptions === null) return null;\n this.abortOptions = null;\n this.latestOptions = null;\n return nextAction(latestOptions);\n }\n}\n"],"names":["ViewportObserver","constructor","static","undefined","instance","IntersectionObserver","handleIntersectionChange","e","Object","keys","forEach","key","observedEl","target","isIntersecting","dispatchEvent","CustomEvent","bubbles","MediaQueryService","this","eventIdMap","WeakMap","eventBindingMap","lastMQ","getCurrentMQ","mediaQuerys","onEvent","window","handleMQChange","newMQ","detail","oldMQ","__decorate","throttle","resolveSymbol","Symbol","rejectSymbol","pendingSymbol","I18nService","PLACEHOLDER_SELECTOR","_instance","isSetUp","Boolean","_url","isFilledObject","_dictionary","loaded","_loaded","ready","_ready","fetchI18nDictionary","setUp","url","dictionary","console","warn","Error","get","fallback","interpolations","hasOwnProperty","result","entries","k","v","split","join","String","getHumanReadableName","addStyling","getPlaceholder","getReadyPromise","resolve","reject","Promise","res","rej","ensureSetup","head","document","style","createElement","type","appendChild","createTextNode","fetchJSON","then","results","fillInPlaceholders","catch","err","error","Array","from","getElementsByClassName","el","dataset","replaceWith","JSON","parse","reverse","replace","letter","toLowerCase","span","innerText","classList","add","setAttribute","stringify","outerHTML","URLSearchParams","location","search","param","urlSearchParams","getAll","getAllKeys","set","value","updateUrl","delete","getString","toString","curUrl","protocol","host","pathname","curQueryString","hashCache","hash","newUrl","history","replaceState","path","Proxy","prop","URLSearchParamsService","intersectionObserver","rootMargin","subscribe","intersectionCallback","componentMap","observe","unsubscribe","unobserve","intersectionEntry","has","StorageServiceImpl","Map","addEventListener","handleStorageChange","addItem","storageKey","storageValue","options","getStorage","setItem","fireCallbacks","getItem","removeItem","observeItem","callback","keyCallbacks","getKeyCallbacks","observedItemsMap","unobserveItem","clearStorage","storageType","clear","oldValue","newValue","Set","localStorage","sessionStorage","StorageService","CachingServiceImpl","storageService","storageKeyPrefix","shouldCache","cacheValue","validFor","runtimeCache","getStorageKey","cacheItem","validUntil","Date","now","getStorageServiceOptions","getCachedValue","cacheOptions","runtimeValue","cachedItemString","cachedItem","DebuggerService","getCachedJSON","cachedValue","clearCachedValue","CachingService","RequestCachingServiceImpl","requestCacheName","getCache","_cache","caches","open","getCachedResponse","request","storage","cache","response","match","parseInt","json","cacheRequest","storeExpirationTime","put","clearCachedRequest","maxAge","RequestCachingService","APIError","super","statusText","APIServiceImpl","cachingService","requestCachingService","fetch","fetchHTML","getHTML","dataMapper","forceRefetch","pipelineRequest","requestPipeline","fetchData","responseData","cacheResponse","throwError","fetchResponse","Request","cachedResponse","fetchOptions","ok","status","responseClone","clone","text","cacheKey","getCacheKey","requestBasedCaching","cacheKeys","length","appendQueryObject","klCacheKeys","APIService","ObserverServiceImpl","observedKey","curCallbacks","getCallbacks","observerMap","notifyObservers","data","ObserverService","ContextState","contextName","contextElement","name","element","isMatchingContext","consumingElement","contains","setState","stateMap","observerService","getState","observeState","unobserveState","ContextStateServiceImpl","getMatchingContextState","matchingContexts","contextStateMap","filter","context","getContextState","matchingContextState","contextInitObserver","contextState","createContextState","contextList","push","ContextStateService","AbortController","apiService","makeAbortableRequest","bind","fetcher","latestOptions","abortOptions","abortController","abort","signal","handleAbortError","nextAction"],"mappings":"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"} | ||
| {"version":3,"file":"index.js","sources":["../src/ViewportObserver.ts","../src/eventNames.ts","../src/MediaQueryService.ts","../src/I18nService.ts","../src/URLSearchParamsService.ts","../src/DebuggerService.ts","../src/LazyConnectService.ts","../src/StorageService/StorageService.ts","../src/CachingService/CachingService.ts","../src/RequestCachingService/RequestCachingService.ts","../src/APIService/APIService.types.ts","../src/APIService/APIService.ts","../src/ObserverService/ObserverService.ts","../src/ContextStateService/ContextState.ts","../src/ContextStateService/ContextStateService.ts","../src/AbortableRequestService/AbortableRequestService.ts"],"sourcesContent":["import { IN_VP_EVENT, OUT_VP_EVENT } from './eventNames';\n\ntype IntersectionEvent = {\n [key: string]: any;\n};\n\nexport class ViewportObserver {\n private static instance: IntersectionObserver;\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private constructor() {}\n\n static getInstance() {\n if (ViewportObserver.instance === undefined) {\n ViewportObserver.instance = new IntersectionObserver(ViewportObserver.handleIntersectionChange);\n }\n return ViewportObserver.instance;\n }\n\n private static handleIntersectionChange(e: IntersectionEvent) {\n Object.keys(e).forEach((key) => {\n const observedEl = e[key];\n const target = observedEl.target;\n\n if (observedEl.isIntersecting) {\n target.dispatchEvent(new CustomEvent(IN_VP_EVENT, { bubbles: false }));\n } else {\n target.dispatchEvent(new CustomEvent(OUT_VP_EVENT, { bubbles: false }));\n }\n });\n }\n}\n","export const MQ_CHANGE_EVENT = 'kl-mq-change';\nexport const IN_VP_EVENT = 'kl-in-vp';\nexport const OUT_VP_EVENT = 'kl-out-vp';\n","import { throttle } from '@kluntje/js-utils/lib/function-helpers/decorators';\nimport { onEvent, getCurrentMQ, MQDefinition } from '@kluntje/js-utils/lib/dom-helpers';\nimport { MQ_CHANGE_EVENT } from './eventNames';\n\nexport class MediaQueryService {\n private static instance: MediaQueryService;\n static mediaQuerys: Array<MQDefinition>;\n eventIdMap: WeakMap<HTMLElement | Function, string>;\n eventBindingMap: {\n [index: string]: EventListenerOrEventListenerObject;\n };\n lastMQ: string;\n\n private constructor() {\n this.eventIdMap = new WeakMap();\n this.eventBindingMap = {};\n this.lastMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n onEvent(window, 'resize', this.handleMQChange, this);\n }\n\n static getInstance(mediaQuerys: Array<MQDefinition>) {\n if (MediaQueryService.instance === undefined) {\n MediaQueryService.mediaQuerys = mediaQuerys;\n MediaQueryService.instance = new MediaQueryService();\n }\n return MediaQueryService.instance;\n }\n\n @throttle(100)\n handleMQChange() {\n const newMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n if (newMQ === this.lastMQ) {\n return;\n }\n\n window.dispatchEvent(\n new CustomEvent(MQ_CHANGE_EVENT, {\n detail: {\n newMQ,\n oldMQ: this.lastMQ,\n },\n }),\n );\n\n this.lastMQ = newMQ;\n }\n}\n","import { fetchJSON } from '@kluntje/js-utils/lib/api-helpers';\nimport { isFilledObject } from '@kluntje/js-utils/lib/object-helpers';\n\nconst resolveSymbol = Symbol('resolve');\nconst rejectSymbol = Symbol('reject');\nconst pendingSymbol = Symbol('pending');\n\n// Promise but with options to resolve/reject from outside\ninterface ExtendedPromise<T> extends Promise<T> {\n [resolveSymbol]: Function;\n [rejectSymbol]: Function;\n [pendingSymbol]: boolean;\n}\n\n/**\n * A service to provide sync/async way to provide internationalization values.\n * With i18n values beeing able to have variable placeholder in them. indexd for arrays e.g. `{0}` or named for objects e.g. `{hour}`\n *\n * @example\n * import I18nService from \"@kluntje/services/I18nService\";\n * // get singleton instance\n * const i18nService = I18nService.getInstance();\n * // provide the url to fetch the dictionary\n * i18nService.setUp({url: \"path/to/i18n/ajax/service\"});\n * // or provide the dictionary itself\n * // i18nService.setUp({dictionary: {\"com.page.filter.notifications\": \"{0} Nachrichten\", ...}});\n * const i18n = i18nService.get;\n * // use API\n * // render markup with i18n value, if the i18n key hasn't been fetched jet, a placeholder `<span class\"kl-i18n-placeholder\"></span>` will be rendered,\n * // with the provided `fallback` text. or the last part of the key.\n * // this `span` will be replaced with the i18n value in den DOM after the keys where successfully fetched from the server\n * render(html`<button>${i18n(\"com.page.filter.notifications\", {fallback: \"Info\", interpolations: [7]})}</button>`, el);\n * // if any actions needs the keys to be ready and shouldn't be replace later in the DOM, the `ready` accessor can be called.\n * // this will automatically trigger the fetch for the keys from the server\n * await i18nService.ready;\n * // the boolean `loaded` can be used to check if the keys have been fetched form the server. This will not trigger the fetch.\n * if (i18nService.loaded) console.log(i18nService.get(\"com.page.filter.submitLabel\"))\n *\n * @export\n * @class I18nService\n */\nexport class I18nService {\n /**\n * class name for the `span`s being used as placeholder for i18n values in the DOM before the actual values have been fetched from the server\n *\n * @readonly\n * @static\n * @memberof I18nService\n */\n static get PLACEHOLDER_SELECTOR() {\n return 'kl-i18n-placeholder';\n }\n\n private static _instance?: I18nService;\n\n /**\n * returns the singleton instance of the I18nService\n *\n * @static\n * @returns\n * @memberof I18nService\n */\n static getInstance() {\n if (I18nService._instance === undefined) {\n I18nService._instance = new I18nService();\n }\n\n return I18nService._instance;\n }\n\n // see `I18nService.loaded` for more information about this property\n private _loaded = false;\n\n // see `I18nService.ready` for more information about this property\n private _ready: ExtendedPromise<undefined>;\n\n // a key-value map of the i18n keys and their internationalizations fetched from the server or provided by the user\n private _dictionary: { [key: string]: string } = {};\n\n // url to the servlet returning the dictionary\n private _url?: string;\n\n /**\n * returns true if the I18nService has been set up already. i.e. has a ajax url or the dictionary provided\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get isSetUp(): boolean {\n return Boolean(this._url || isFilledObject(this._dictionary));\n }\n\n /**\n * `loaded` will be true when the keys have been fetched from the server. and `false` otherwise.\n * reading the `loaded` accessor won't trigger the key fetch. For that use {@see I18nService.ready}\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get loaded(): boolean {\n return this._loaded;\n }\n\n /**\n * a promise will be returned that resolves when the keys have been fetched from the server, or the server rejected the ajax call.\n * reading the `ready` accessor will automatically trigger the dictionary fetch.\n * use this property when you NEED the keys to be already loaded and can't be replaced in the DOM later.\n *\n * @readonly\n * @type {Promise<undefined>}\n * @memberof I18nService\n */\n public get ready(): Promise<undefined> {\n if (!this._ready[pendingSymbol]) this.fetchI18nDictionary();\n\n return this._ready as Promise<undefined>;\n }\n\n /**\n * providing information necessary for the service to retrieve the i18n dictionary.\n * i.e. a ajax url to fetch data, or a static object with the i18n key-value in it\n *\n * @param {{ url: string; dictionary: Record<string, string> }} { url, dictionary }\n * @returns\n * @memberof I18nService\n */\n public setUp({ url, dictionary }: { url?: string; dictionary?: Record<string, string> } = {}) {\n if (this.isSetUp) {\n console.warn(\"@kluntje I18nService: service has already been set up. You can't set it up twice!\");\n return;\n }\n if (url) {\n this._url = url;\n } else if (dictionary) {\n this._dictionary = dictionary;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this._ready[pendingSymbol] = true;\n } else {\n throw new Error('@kluntje I18nService: a \"url\" or \"dictionary\" should have been passed to the setUp function.');\n }\n }\n\n /**\n * returns the internationalized value for the given i18n key when the value have been fetched from the server,\n * or a placeholder `<span>` with a fallback text based on the key or the provided fallback text\n * which will automatically be replaced with the value in the DOM after server response\n *\n * @param {string} key\n * @param {({ fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> })} [{\n * fallback,\n * interpolations,\n * }={}]\n * @returns {string}\n * @memberof I18nService\n */\n public get(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ): string {\n if (this.loaded) {\n if (this._dictionary.hasOwnProperty(key)) {\n let result = this._dictionary[key];\n if (interpolations) {\n Object.entries(interpolations).forEach(([k, v]) => {\n // replaceAll({key}, value)\n result = result.split(`{${k}}`).join(String(v));\n });\n }\n\n return result;\n }\n console.warn(`@kluntje I18nService: i18n for key '${key}' is missing in dictionary!`);\n\n return fallback !== undefined ? fallback : this.getHumanReadableName(key);\n }\n\n if (!this._ready[pendingSymbol]) {\n // add styling for the placeholder first time a placeholder will be added to the DOM\n this.addStyling();\n this.fetchI18nDictionary();\n }\n\n return this.getPlaceholder(key, { fallback, interpolations });\n }\n\n /**\n * Creates an instance of I18nService.\n * @memberof I18nService\n */\n private constructor() {\n this._ready = this.getReadyPromise();\n }\n\n /**\n * returns a Promise like object with properties to allow resolving the promise from the outside\n *\n * @private\n * @returns {ExtendedPromise<undefined>}\n * @memberof I18nService\n */\n private getReadyPromise(): ExtendedPromise<undefined> {\n let resolve: Function;\n let reject: Function;\n\n // @ts-ignore - other properties will be added in next couple of lines\n const _ready: ExtendedPromise<undefined> = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n // @ts-ignore - `resolve` is defined in the promise body from lines above\n _ready[resolveSymbol] = resolve;\n // @ts-ignore - `reject` is defined in the promise body from lines above\n _ready[rejectSymbol] = reject;\n // will be set to true when ajax call is sent\n _ready[pendingSymbol] = false;\n\n return _ready;\n }\n\n /**\n * throws an Error when the service is not set up\n *\n * @private\n * @memberof I18nService\n */\n private ensureSetup(): void {\n if (!this.isSetUp) throw new Error('@kluntje I18nService: should be set up before calling other APIs');\n }\n\n /**\n * add minimal styling for the placeholder to look as much as possible as if they were a text node and not a html element,\n * and without the need of an actual .css file to be loaded\n *\n * @private\n * @memberof I18nService\n */\n private addStyling(): void {\n const head = document.head;\n const style = document.createElement('style');\n style.type = 'text/css';\n style.appendChild(\n document.createTextNode(`\n .${I18nService.PLACEHOLDER_SELECTOR} {\n display: contents;\n }\n `),\n );\n head.appendChild(style);\n }\n\n /**\n * retrieves the i18n key.value pairs, and update instance properties regarding the pending/fulfilled status of the request\n *\n * @private\n * @memberof I18nService\n */\n private fetchI18nDictionary() {\n this.ensureSetup();\n this._ready[pendingSymbol] = true;\n\n fetchJSON(this._url!)\n .then((results: Record<string, string>) => {\n this._dictionary = results;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this.fillInPlaceholders();\n })\n .catch((err: Error) => {\n console.error('@kluntje I18nService: unable to fetch keys from server!', err);\n // ? adding a failed flag\n this._loaded = true;\n this._ready[resolveSymbol]();\n });\n }\n\n /**\n * i18n placeholder in the DOM will be fetched with i18n values been fetched from the server.\n *\n * @private\n * @memberof I18nService\n */\n private fillInPlaceholders() {\n Array.from(document.getElementsByClassName(I18nService.PLACEHOLDER_SELECTOR)).forEach((el) => {\n const { key, fallback, interpolations } = (el as HTMLElement).dataset;\n\n el.replaceWith(\n this.get(key!, {\n fallback,\n interpolations: interpolations ? JSON.parse(interpolations) : undefined,\n }),\n );\n });\n }\n\n /**\n * converts the i18n key names to values that can be used as fallback for the i18n text\n * @example\n * getHumanReadableName(\"org.example.hyphenated_name.filter.submitBtn\") === \"submit btn\"\n *\n * @private\n * @param {string} key\n * @returns\n * @memberof I18nService\n */\n private getHumanReadableName(key: string) {\n return (\n key\n // \"org.example.hyphenated_name.filter.submitBtn\" -> \"submitBtn\"\n .split('.')\n .reverse()[0]\n // \"submitBtn\" -> \"submit btn\"\n .replace(/[A-Z]/g, (letter: string) => ` ${letter.toLowerCase()}`)\n );\n }\n\n /**\n * generates a span element whith the fallback text to be replaced with the correct i18n value after server response\n *\n * @private\n * @param {string} key\n * @param {string} [fallback]\n * @returns\n * @memberof I18nService\n */\n private getPlaceholder(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ) {\n const span = document.createElement('span');\n span.innerText = fallback !== undefined ? fallback : this.getHumanReadableName(key);\n span.classList.add(I18nService.PLACEHOLDER_SELECTOR);\n span.setAttribute('data-key', key);\n if (fallback) span.setAttribute('data-fallback', fallback);\n // use escaping mechanism of setAttribute to store the stringified json\n if (interpolations) span.setAttribute('data-interpolations', JSON.stringify(interpolations));\n\n return span.outerHTML;\n }\n}\n","export class URLSearchParamsService {\n private urlSearchParams: URLSearchParams = new URLSearchParams(window.location.search);\n\n public get(param: string): string | null {\n return this.urlSearchParams.get(param);\n }\n\n public getAll(param: string): string[] | null {\n return this.urlSearchParams.getAll(param);\n }\n\n public getAllKeys(): Array<string> {\n // @ts-ignore\n return Array.from(this.urlSearchParams.keys());\n }\n\n public set(param: string, value: string): void {\n this.urlSearchParams.set(param, value);\n this.updateUrl();\n }\n\n public delete(param: string): void {\n this.urlSearchParams.delete(param);\n this.updateUrl();\n }\n\n public getString(): string {\n return this.urlSearchParams.toString();\n }\n\n public get curUrl() {\n return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;\n }\n\n private updateUrl() {\n const curQueryString = this.getString();\n const curUrl = this.curUrl;\n const hashCache = window.location.hash;\n const newUrl = curQueryString !== '' ? `${curUrl}?${curQueryString}` : curUrl;\n window.history.replaceState({ path: newUrl }, '', newUrl);\n if (hashCache !== '') window.location.hash = hashCache;\n }\n}\n\nexport default new URLSearchParamsService();\n","import URLSearchParamsService from './URLSearchParamsService';\n\nfunction debugModeActive() {\n return URLSearchParamsService.get('js-debug') !== null;\n}\n\nconst handler = {\n get(target: Console, prop: keyof Console) {\n if (debugModeActive()) return target[prop];\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n else return () => {};\n },\n};\n\nexport default new Proxy(console, handler);\n","class LazyConnectService {\n componentMap = new WeakMap();\n intersectionObserver: IntersectionObserver;\n\n constructor() {\n this.intersectionObserver = new IntersectionObserver((entries: any) => this.handleIntersectionChange(entries), {\n rootMargin: '500px 0px',\n });\n }\n\n subscribe(target: HTMLElement, intersectionCallback: () => void) {\n this.componentMap.set(target, intersectionCallback);\n this.intersectionObserver.observe(target);\n }\n\n unsubscribe(target: HTMLElement) {\n this.intersectionObserver.unobserve(target);\n this.componentMap.delete(target);\n }\n\n handleIntersectionChange(entries: Array<IntersectionObserverEntry>) {\n entries.forEach((intersectionEntry: any) => {\n const target = intersectionEntry.target;\n\n if (!intersectionEntry.isIntersecting || !this.componentMap.has(target)) return;\n\n const intersectionCallback = this.componentMap.get(target);\n this.unsubscribe(target as HTMLElement);\n intersectionCallback();\n });\n }\n}\n\nexport default new LazyConnectService();\n","import { IStorageService } from './StorageService.interface';\nimport { StorageServiceOptions, StorageType } from './StorageService.types';\n\nexport class StorageServiceImpl implements IStorageService {\n private observedItemsMap: Map<string, Set<() => void>> = new Map();\n\n constructor() {\n window.addEventListener('storage', (e) => this.handleStorageChange(e));\n }\n\n public addItem(storageKey: string, storageValue: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).setItem(storageKey, storageValue);\n this.fireCallbacks(storageKey);\n }\n\n public getItem(storageKey: string, options: StorageServiceOptions = {}): string | null {\n return this.getStorage(options).getItem(storageKey);\n }\n\n public removeItem(storageKey: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).removeItem(storageKey);\n }\n\n public observeItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.add(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public unobserveItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.delete(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public clearStorage(storageType: StorageType) {\n this.getStorage({ storageType }).clear();\n }\n\n private handleStorageChange(e: StorageEvent) {\n const storageKey = e.key;\n const oldValue = e.oldValue;\n const newValue = e.newValue;\n if (storageKey === null || oldValue === newValue || !this.observedItemsMap.has(storageKey)) return;\n\n this.fireCallbacks(storageKey);\n }\n\n private getKeyCallbacks(storageKey: string): Set<() => void> {\n return this.observedItemsMap.get(storageKey) || new Set();\n }\n\n private fireCallbacks(storageKey: string) {\n const callbacks = this.getKeyCallbacks(storageKey);\n callbacks.forEach((callback) => callback());\n }\n\n private getStorage(options: StorageServiceOptions): Storage {\n const { storageType = 'local' } = options;\n return storageType === 'local' ? localStorage : sessionStorage;\n }\n}\n\nexport const StorageService = new StorageServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { StorageServiceOptions, StorageService, IStorageService } from '../StorageService';\nimport { ICachingService } from './CachingService.interface';\nimport { CacheItem, CacheOptions, CachingServiceConstructorOptions } from './CachingService.types';\n\nexport class CachingServiceImpl implements ICachingService {\n private runtimeCache: Map<string, string> = new Map();\n private storageService: IStorageService = StorageService;\n private storageKeyPrefix = 'kl-caching-service';\n\n constructor(options?: CachingServiceConstructorOptions) {\n const { storageService, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n protected get shouldCache(): boolean {\n return true;\n }\n\n public cacheValue(key: string, value: string, options: CacheOptions) {\n if (this.shouldCache === false) return;\n\n if (options.validFor === 0) {\n this.runtimeCache.set(this.getStorageKey(key), value);\n return;\n }\n\n const cacheItem: CacheItem = {\n value,\n validUntil: Date.now() + options.validFor,\n };\n\n this.storageService.addItem(\n this.getStorageKey(key),\n JSON.stringify(cacheItem),\n this.getStorageServiceOptions(options),\n );\n }\n\n public getCachedValue(key: string, cacheOptions?: CacheOptions): string | null {\n if (this.shouldCache === false) return null;\n\n const storageKey = this.getStorageKey(key);\n\n const runtimeValue = this.runtimeCache.get(storageKey);\n\n if (runtimeValue !== undefined) return runtimeValue;\n\n const cachedItemString = this.storageService.getItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n if (cachedItemString === null) return null;\n\n try {\n const cachedItem: CacheItem = JSON.parse(cachedItemString);\n if (cachedItem.validUntil < Date.now()) {\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n\n return cachedItem.value;\n } catch (e) {\n DebuggerService.warn('CachingService: ', e);\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n }\n\n public getCachedJSON<T>(key: string, cacheOptions?: CacheOptions): T | null {\n const cachedValue = this.getCachedValue(key, cacheOptions);\n if (cachedValue === null) return null;\n try {\n return JSON.parse(cachedValue);\n } catch (error) {\n DebuggerService.error('CachingService: ', error);\n return null;\n }\n }\n\n public clearCachedValue(key: string, cacheOptions?: CacheOptions) {\n const storageKey = this.getStorageKey(key);\n\n if (cacheOptions?.validFor === 0) {\n this.runtimeCache.delete(storageKey);\n return;\n }\n\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n }\n\n private getStorageServiceOptions(cacheOptions?: CacheOptions): StorageServiceOptions {\n return {\n storageType: cacheOptions?.storageType,\n };\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const CachingService = new CachingServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { IStorageService, StorageService, StorageType } from '../StorageService';\nimport { IRequestCachingService } from './RequestCachingService.interface';\nimport { RequestCacheOptions, RequestCachingServiceConstructorOptions } from './RequestCachingService.types';\n\nexport class RequestCachingServiceImpl implements IRequestCachingService {\n private _cache?: Promise<Cache>;\n\n private storageService: IStorageService = StorageService;\n private requestCacheName = 'kl-request-cache';\n private storageKeyPrefix = 'kl-request-caching-service';\n\n constructor(options?: RequestCachingServiceConstructorOptions) {\n const { storageService, requestCacheName, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (requestCacheName !== undefined) {\n this.requestCacheName = requestCacheName;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n private async getCache(): Promise<Cache | null> {\n try {\n if (this._cache === undefined) {\n this._cache = caches.open(this.requestCacheName);\n }\n return await this._cache;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async getCachedResponse(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return null;\n\n const response = await cache.match(request);\n if (response === undefined) return null;\n\n const validUntil = this.storageService.getItem(this.getStorageKey(request.url), { storageType: storage });\n if (validUntil === null) {\n await cache.delete(request);\n return null;\n }\n\n const now = Date.now();\n if (now > parseInt(validUntil, 10)) {\n await cache.delete(request);\n return null;\n }\n return response;\n }\n\n public async getCachedJSON<T>(request: Request, storage?: StorageType) {\n const response = await this.getCachedResponse(request, storage);\n if (response === null) return null;\n try {\n return (await response.json()) as T;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async cacheRequest(options: RequestCacheOptions) {\n const { request, response } = options;\n const cache = await this.getCache();\n if (cache === null) return;\n this.storeExpirationTime(options);\n await cache.put(request, response);\n }\n\n public async clearCachedRequest(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return;\n await cache.delete(request);\n this.storageService.removeItem(this.getStorageKey(request.url), { storageType: storage });\n }\n\n private storeExpirationTime(options: RequestCacheOptions) {\n const { request, maxAge } = options;\n const validUntil = Date.now() + maxAge;\n this.storageService.addItem(this.getStorageKey(request.url), validUntil.toString(), {\n storageType: options.storage,\n });\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const RequestCachingService = new RequestCachingServiceImpl();\n","import { CacheOptions, ICachingService } from '../CachingService';\nimport { IRequestCachingService } from '../RequestCachingService';\n\nexport interface APIServiceCacheOptions extends CacheOptions {\n forceRefetch?: boolean;\n requestBasedCaching?: boolean;\n cacheKeys?: string[];\n}\n\nexport interface APIServiceRequestOptions {\n fetchOptions?: RequestInit;\n cacheOptions?: APIServiceCacheOptions;\n throwError?: boolean;\n}\n\nexport interface APIServiceConstructorOptions {\n cachingService?: ICachingService;\n requestCachingService?: IRequestCachingService;\n}\n\nexport class APIError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n super(response.statusText);\n this.response = response;\n }\n}\n","import { appendQueryObject } from \"@kluntje/js-utils/lib/url-helpers\";\n\nimport DebuggerService from \"../DebuggerService\";\nimport { IRequestCachingService, RequestCachingService } from \"../RequestCachingService\";\nimport { CachingService, ICachingService } from \"../CachingService\";\n\nimport { APIError, APIServiceCacheOptions, APIServiceConstructorOptions, APIServiceRequestOptions } from \"./APIService.types\";\nimport { IAPIService } from \"./APIService.interface\";\n\nexport class APIServiceImpl implements IAPIService {\n private requestPipeline: Map<string, Promise<Response | null>> = new Map();\n\n private cachingService: ICachingService = CachingService;\n private requestCachingService: IRequestCachingService = RequestCachingService;\n\n constructor(options: APIServiceConstructorOptions = {}) {\n const { cachingService, requestCachingService } = options;\n\n if (cachingService !== undefined) this.cachingService = cachingService;\n if (requestCachingService !== undefined) this.requestCachingService = requestCachingService;\n }\n\n public async fetchJSON<T>(url: string, options: APIServiceRequestOptions = {}): Promise<T | null> {\n // eslint-disable-next-line prettier/prettier\n return await this.fetch(url, APIServiceImpl.getJSON<T>, options);\n }\n\n public async fetchHTML(url: string, options: APIServiceRequestOptions = {}): Promise<string | null> {\n return await this.fetch(url, APIServiceImpl.getHTML, options);\n }\n\n private async fetch<T>(\n url: string,\n dataMapper: (response: Response | null) => Promise<T>,\n options: APIServiceRequestOptions = {},\n ): Promise<T | null> {\n const { cacheOptions } = options;\n\n if (cacheOptions?.forceRefetch === true) {\n this.clearCachedValue(url, cacheOptions);\n }\n\n const cachedValue = await this.getCachedValue<T>(url, cacheOptions);\n if (cachedValue !== null) return cachedValue;\n\n try {\n const pipelineRequest = this.requestPipeline.get(url);\n if (pipelineRequest !== undefined) {\n return await dataMapper(await pipelineRequest);\n }\n\n const request = this.fetchData(url, options);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n const responseData = await dataMapper(response);\n this.requestPipeline.delete(url);\n\n if (response === null || responseData === null) return null;\n\n if (cacheOptions === undefined) return responseData;\n await this.cacheResponse(url, response, responseData, cacheOptions);\n\n return responseData;\n } catch (error) {\n DebuggerService.error(\"APIService.fetch: \", error);\n this.requestPipeline.delete(url);\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n public async fetchResponse(url: string, options: APIServiceRequestOptions = {}): Promise<Response | null> {\n const { cacheOptions } = options;\n const { forceRefetch = false } = cacheOptions ?? {};\n\n if (forceRefetch === true) {\n await this.requestCachingService.clearCachedRequest(new Request(url), cacheOptions?.storageType ?? \"session\");\n }\n\n const cachedResponse = await this.requestCachingService.getCachedResponse(\n new Request(url),\n cacheOptions?.storageType ?? \"session\",\n );\n\n if (cachedResponse !== null) return cachedResponse;\n\n const pipelineRequest = this.requestPipeline.get(url);\n\n if (pipelineRequest !== undefined) {\n return await pipelineRequest;\n }\n\n try {\n const request = fetch(url, options.fetchOptions);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n this.requestPipeline.delete(url);\n\n if (cacheOptions === undefined) return response;\n\n await this.requestCachingService.cacheRequest({\n request: new Request(url),\n response,\n storage: cacheOptions.storageType ?? \"session\",\n maxAge: cacheOptions.validFor,\n });\n\n return response;\n } catch (error) {\n DebuggerService.error(\"APIService.fetchResponse: \", error);\n\n this.requestPipeline.delete(url);\n\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n private async fetchData(url: string, options: APIServiceRequestOptions): Promise<Response | null> {\n const response = await fetch(url, options.fetchOptions);\n\n if (!response.ok) throw new APIError(response);\n if (response.status === 204) return null;\n\n return response;\n }\n\n private static async getJSON<T>(response: Response | null): Promise<T | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.json();\n }\n\n private static async getHTML(response: Response | null): Promise<string | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.text();\n }\n\n private async cacheResponse<T>(\n url: string,\n response: Response,\n responseData: T,\n cacheOptions: APIServiceCacheOptions,\n ) {\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (cacheOptions.requestBasedCaching === true) {\n await this.requestCachingService.cacheRequest({\n request: new Request(cacheKey),\n response,\n storage: cacheOptions.storageType ?? \"local\",\n maxAge: cacheOptions.validFor,\n });\n } else {\n this.cachingService.cacheValue(cacheKey, JSON.stringify(responseData), cacheOptions);\n }\n }\n\n private async clearCachedValue(url: string, cacheOptions?: APIServiceCacheOptions) {\n if (cacheOptions === undefined) return;\n const { requestBasedCaching = false } = cacheOptions;\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (requestBasedCaching === true) {\n await this.requestCachingService.clearCachedRequest(new Request(cacheKey), cacheOptions.storageType);\n }\n this.cachingService.clearCachedValue(cacheKey, cacheOptions);\n }\n\n private async getCachedValue<T>(url: string, cacheOptions?: APIServiceCacheOptions): Promise<T | null> {\n if (cacheOptions === undefined) return null;\n const { requestBasedCaching = false } = cacheOptions;\n\n const cacheKey = this.getCacheKey(url, cacheOptions);\n if (requestBasedCaching === true) {\n return await this.requestCachingService.getCachedJSON(new Request(cacheKey), cacheOptions.storageType);\n }\n return this.cachingService.getCachedJSON(cacheKey, cacheOptions);\n }\n\n private getCacheKey(url: string, cacheOptions?: APIServiceCacheOptions): string {\n const cacheKeys = cacheOptions?.cacheKeys ?? [];\n if (cacheKeys.length === 0) return url;\n return appendQueryObject(url, { klCacheKeys: cacheKeys.join(\"_\") });\n }\n}\n\nexport const APIService = new APIServiceImpl();\n","import { IObserverService } from './ObserverService.interface';\nimport { ObserverCallback } from './ObserverService.types';\n\nexport class ObserverServiceImpl implements IObserverService {\n private observerMap: Map<string, Set<ObserverCallback>> = new Map();\n\n public observe(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.add(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public unobserve(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.delete(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public notifyObservers<T>(observedKey: string, data?: T) {\n const callbacks = this.getCallbacks(observedKey);\n callbacks.forEach((callback) => callback(data));\n }\n\n private getCallbacks(observedKey: string): Set<ObserverCallback> {\n return this.observerMap.get(observedKey) || new Set();\n }\n}\n\nexport const ObserverService = new ObserverServiceImpl();\n","import { ObserverServiceImpl } from '../ObserverService';\n\nexport class ContextState<StateDefinition extends Record<string, any> = Record<string, any>> {\n private stateMap: Map<keyof StateDefinition, any> = new Map();\n private observerService = new ObserverServiceImpl();\n private contextName: string;\n private contextElement: HTMLElement;\n\n constructor(contextName: string, contextElement: HTMLElement) {\n this.contextName = contextName;\n this.contextElement = contextElement;\n }\n\n public get name(): string {\n return this.contextName;\n }\n\n public get element(): HTMLElement {\n return this.contextElement;\n }\n\n public isMatchingContext(contextName: string, consumingElement: HTMLElement): boolean {\n if (this.contextName !== contextName) return false;\n\n return this.contextElement.contains(consumingElement);\n }\n\n public setState<K extends keyof StateDefinition>(key: K, value: StateDefinition[K]): void {\n if (this.stateMap.get(key) === value) return;\n this.stateMap.set(key, value);\n this.observerService.notifyObservers(key as string);\n }\n\n public getState<K extends keyof StateDefinition>(key: K): StateDefinition[K] | undefined {\n return this.stateMap.get(key);\n }\n\n public observeState(key: keyof StateDefinition, callback: () => void): void {\n this.observerService.observe(key as string, callback);\n }\n\n public unobserveState(key: keyof StateDefinition, callback: () => void): void {\n this.observerService.unobserve(key as string, callback);\n }\n}\n","import { ContextState } from './ContextState';\nimport { ObserverServiceImpl } from '../ObserverService';\nimport { IContextStateService } from './ContextStateService.interface';\n\nexport class ContextStateServiceImpl implements IContextStateService {\n private contextStateMap: Map<string, ContextState[]> = new Map();\n private contextInitObserver = new ObserverServiceImpl();\n\n private getMatchingContextState(contextName: string, consumingElement: HTMLElement): ContextState | null {\n const contextList = this.contextStateMap.get(contextName) || [];\n const matchingContexts = contextList.filter((context) => context.isMatchingContext(contextName, consumingElement));\n if (matchingContexts.length === 0) return null;\n return matchingContexts[0];\n }\n\n public getContextState<StateDefinition extends Record<string, any>>(\n contextName: string,\n consumingElement: HTMLElement,\n ): Promise<ContextState<StateDefinition>> {\n const matchingContextState = this.getMatchingContextState(contextName, consumingElement);\n if (matchingContextState) return Promise.resolve(matchingContextState) as Promise<ContextState<StateDefinition>>;\n return new Promise<ContextState<StateDefinition>>((resolve) => {\n this.contextInitObserver.observe(contextName, () => {\n const contextState = this.getMatchingContextState(contextName, consumingElement);\n if (contextState) {\n resolve(contextState as ContextState<StateDefinition>);\n }\n });\n });\n }\n\n public createContextState<StateDefinition extends Record<string, any>>(\n contextName: string,\n contextElement: HTMLElement,\n ): ContextState<StateDefinition> {\n const contextState = new ContextState(contextName, contextElement);\n const contextList = this.contextStateMap.get(contextName) || [];\n contextList.push(contextState);\n this.contextStateMap.set(contextName, contextList);\n this.contextInitObserver.notifyObservers(contextName);\n return contextState as ContextState<StateDefinition>;\n }\n}\n\nexport const ContextStateService = new ContextStateServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { APIService, APIServiceRequestOptions, IAPIService } from '../APIService';\nimport {\n AbortableRequestServiceConstructorOptions,\n AbortableRequestServiceOptions,\n} from './AbortableRequestService.types';\n\nexport class AbortableRequestService {\n private abortController = new AbortController();\n private abortOptions: AbortableRequestServiceOptions | null = null;\n private latestOptions: AbortableRequestServiceOptions | null = null;\n\n protected apiService: IAPIService = APIService;\n\n constructor(options: AbortableRequestServiceConstructorOptions = {}) {\n const { apiService } = options;\n\n if (apiService !== undefined) this.apiService = apiService;\n }\n\n public async fetchJSON<T>(options: AbortableRequestServiceOptions): Promise<T | null> {\n return await this.makeAbortableRequest<T>(options, this.apiService.fetchJSON.bind(this.apiService));\n }\n\n public async fetchResponse(options: AbortableRequestServiceOptions): Promise<Response | null> {\n return await this.makeAbortableRequest<Response>(options, this.apiService.fetchResponse.bind(this.apiService));\n }\n\n private async makeAbortableRequest<R>(\n options: AbortableRequestServiceOptions,\n fetcher: (url: string, options: APIServiceRequestOptions) => Promise<R | null>,\n ): Promise<R | null> {\n if (this.latestOptions !== null) {\n this.abortOptions = options;\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n this.latestOptions = options;\n\n try {\n const response = await fetcher(options.url, {\n cacheOptions: options.options?.cacheOptions,\n throwError: true,\n fetchOptions: {\n ...options.options?.fetchOptions,\n signal: this.abortController.signal,\n },\n });\n this.latestOptions = null;\n return response;\n } catch (error: any) {\n DebuggerService.error('AbortableRequestService.makeAbortableRequest: ', error);\n\n if (error.name === 'AbortError') return this.handleAbortError<R>(this.fetchJSON.bind(this));\n\n if (options.options?.throwError === true) throw error;\n\n return null;\n }\n }\n\n private async handleAbortError<R>(\n nextAction: (options: AbortableRequestServiceOptions) => Promise<R | null>,\n ): Promise<R | null> {\n const latestOptions = this.latestOptions || this.abortOptions;\n if (latestOptions === null) return null;\n this.abortOptions = null;\n this.latestOptions = null;\n return nextAction(latestOptions);\n }\n}\n"],"names":["ViewportObserver","constructor","static","undefined","instance","IntersectionObserver","handleIntersectionChange","e","Object","keys","forEach","key","observedEl","target","isIntersecting","dispatchEvent","CustomEvent","bubbles","MediaQueryService","this","eventIdMap","WeakMap","eventBindingMap","lastMQ","getCurrentMQ","mediaQuerys","onEvent","window","handleMQChange","newMQ","detail","oldMQ","__decorate","throttle","resolveSymbol","Symbol","rejectSymbol","pendingSymbol","I18nService","PLACEHOLDER_SELECTOR","_instance","isSetUp","Boolean","_url","isFilledObject","_dictionary","loaded","_loaded","ready","_ready","fetchI18nDictionary","setUp","url","dictionary","console","warn","Error","get","fallback","interpolations","hasOwnProperty","result","entries","k","v","split","join","String","getHumanReadableName","addStyling","getPlaceholder","getReadyPromise","resolve","reject","Promise","res","rej","ensureSetup","head","document","style","createElement","type","appendChild","createTextNode","fetchJSON","then","results","fillInPlaceholders","catch","err","error","Array","from","getElementsByClassName","el","dataset","replaceWith","JSON","parse","reverse","replace","letter","toLowerCase","span","innerText","classList","add","setAttribute","stringify","outerHTML","URLSearchParams","location","search","param","urlSearchParams","getAll","getAllKeys","set","value","updateUrl","delete","getString","toString","curUrl","protocol","host","pathname","curQueryString","hashCache","hash","newUrl","history","replaceState","path","Proxy","prop","URLSearchParamsService","intersectionObserver","rootMargin","subscribe","intersectionCallback","componentMap","observe","unsubscribe","unobserve","intersectionEntry","has","StorageServiceImpl","Map","addEventListener","handleStorageChange","addItem","storageKey","storageValue","options","getStorage","setItem","fireCallbacks","getItem","removeItem","observeItem","callback","keyCallbacks","getKeyCallbacks","observedItemsMap","unobserveItem","clearStorage","storageType","clear","oldValue","newValue","Set","localStorage","sessionStorage","StorageService","CachingServiceImpl","storageService","storageKeyPrefix","shouldCache","cacheValue","validFor","runtimeCache","getStorageKey","cacheItem","validUntil","Date","now","getStorageServiceOptions","getCachedValue","cacheOptions","runtimeValue","cachedItemString","cachedItem","DebuggerService","getCachedJSON","cachedValue","clearCachedValue","CachingService","RequestCachingServiceImpl","requestCacheName","getCache","_cache","caches","open","getCachedResponse","request","storage","cache","response","match","parseInt","json","cacheRequest","storeExpirationTime","put","clearCachedRequest","maxAge","RequestCachingService","APIError","super","statusText","APIServiceImpl","cachingService","requestCachingService","fetch","fetchHTML","getHTML","dataMapper","forceRefetch","pipelineRequest","requestPipeline","fetchData","responseData","cacheResponse","throwError","fetchResponse","Request","cachedResponse","fetchOptions","ok","status","responseClone","clone","text","cacheKey","getCacheKey","requestBasedCaching","cacheKeys","length","appendQueryObject","klCacheKeys","APIService","ObserverServiceImpl","observedKey","curCallbacks","getCallbacks","observerMap","notifyObservers","data","ObserverService","ContextState","contextName","contextElement","name","element","isMatchingContext","consumingElement","contains","setState","stateMap","observerService","getState","observeState","unobserveState","ContextStateServiceImpl","getMatchingContextState","matchingContexts","contextStateMap","filter","context","getContextState","matchingContextState","contextInitObserver","contextState","createContextState","contextList","push","ContextStateService","AbortController","apiService","makeAbortableRequest","bind","fetcher","latestOptions","abortOptions","abortController","abort","signal","handleAbortError","nextAction"],"mappings":"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"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.module.js","sources":["../src/eventNames.ts","../src/ViewportObserver.ts","../src/MediaQueryService.ts","../src/I18nService.ts","../src/URLSearchParamsService.ts","../src/DebuggerService.ts","../src/LazyConnectService.ts","../src/StorageService/StorageService.ts","../src/CachingService/CachingService.ts","../src/RequestCachingService/RequestCachingService.ts","../src/APIService/APIService.types.ts","../src/APIService/APIService.ts","../src/AbortableRequestService/AbortableRequestService.ts","../src/ObserverService/ObserverService.ts","../src/ContextStateService/ContextState.ts","../src/ContextStateService/ContextStateService.ts"],"sourcesContent":["export const MQ_CHANGE_EVENT = 'kl-mq-change';\nexport const IN_VP_EVENT = 'kl-in-vp';\nexport const OUT_VP_EVENT = 'kl-out-vp';\n","import { IN_VP_EVENT, OUT_VP_EVENT } from './eventNames';\n\ntype IntersectionEvent = {\n [key: string]: any;\n};\n\nexport class ViewportObserver {\n private static instance: IntersectionObserver;\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private constructor() {}\n\n static getInstance() {\n if (ViewportObserver.instance === undefined) {\n ViewportObserver.instance = new IntersectionObserver(ViewportObserver.handleIntersectionChange);\n }\n return ViewportObserver.instance;\n }\n\n private static handleIntersectionChange(e: IntersectionEvent) {\n Object.keys(e).forEach((key) => {\n const observedEl = e[key];\n const target = observedEl.target;\n\n if (observedEl.isIntersecting) {\n target.dispatchEvent(new CustomEvent(IN_VP_EVENT, { bubbles: false }));\n } else {\n target.dispatchEvent(new CustomEvent(OUT_VP_EVENT, { bubbles: false }));\n }\n });\n }\n}\n","import { throttle } from '@kluntje/js-utils/lib/function-helpers/decorators';\nimport { onEvent, getCurrentMQ, MQDefinition } from '@kluntje/js-utils/lib/dom-helpers';\nimport { MQ_CHANGE_EVENT } from './eventNames';\n\nexport class MediaQueryService {\n private static instance: MediaQueryService;\n static mediaQuerys: Array<MQDefinition>;\n eventIdMap: WeakMap<HTMLElement | Function, string>;\n eventBindingMap: {\n [index: string]: EventListenerOrEventListenerObject;\n };\n lastMQ: string;\n\n private constructor() {\n this.eventIdMap = new WeakMap();\n this.eventBindingMap = {};\n this.lastMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n onEvent(window, 'resize', this.handleMQChange, this);\n }\n\n static getInstance(mediaQuerys: Array<MQDefinition>) {\n if (MediaQueryService.instance === undefined) {\n MediaQueryService.mediaQuerys = mediaQuerys;\n MediaQueryService.instance = new MediaQueryService();\n }\n return MediaQueryService.instance;\n }\n\n @throttle(100)\n handleMQChange() {\n const newMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n if (newMQ === this.lastMQ) {\n return;\n }\n\n window.dispatchEvent(\n new CustomEvent(MQ_CHANGE_EVENT, {\n detail: {\n newMQ,\n oldMQ: this.lastMQ,\n },\n }),\n );\n\n this.lastMQ = newMQ;\n }\n}\n","import { fetchJSON } from '@kluntje/js-utils/lib/api-helpers';\nimport { isFilledObject } from '@kluntje/js-utils/lib/object-helpers';\n\nconst resolveSymbol = Symbol('resolve');\nconst rejectSymbol = Symbol('reject');\nconst pendingSymbol = Symbol('pending');\n\n// Promise but with options to resolve/reject from outside\ninterface ExtendedPromise<T> extends Promise<T> {\n [resolveSymbol]: Function;\n [rejectSymbol]: Function;\n [pendingSymbol]: boolean;\n}\n\n/**\n * A service to provide sync/async way to provide internationalization values.\n * With i18n values beeing able to have variable placeholder in them. indexd for arrays e.g. `{0}` or named for objects e.g. `{hour}`\n *\n * @example\n * import I18nService from \"@kluntje/services/I18nService\";\n * // get singleton instance\n * const i18nService = I18nService.getInstance();\n * // provide the url to fetch the dictionary\n * i18nService.setUp({url: \"path/to/i18n/ajax/service\"});\n * // or provide the dictionary itself\n * // i18nService.setUp({dictionary: {\"com.page.filter.notifications\": \"{0} Nachrichten\", ...}});\n * const i18n = i18nService.get;\n * // use API\n * // render markup with i18n value, if the i18n key hasn't been fetched jet, a placeholder `<span class\"kl-i18n-placeholder\"></span>` will be rendered,\n * // with the provided `fallback` text. or the last part of the key.\n * // this `span` will be replaced with the i18n value in den DOM after the keys where successfully fetched from the server\n * render(html`<button>${i18n(\"com.page.filter.notifications\", {fallback: \"Info\", interpolations: [7]})}</button>`, el);\n * // if any actions needs the keys to be ready and shouldn't be replace later in the DOM, the `ready` accessor can be called.\n * // this will automatically trigger the fetch for the keys from the server\n * await i18nService.ready;\n * // the boolean `loaded` can be used to check if the keys have been fetched form the server. This will not trigger the fetch.\n * if (i18nService.loaded) console.log(i18nService.get(\"com.page.filter.submitLabel\"))\n *\n * @export\n * @class I18nService\n */\nexport class I18nService {\n /**\n * class name for the `span`s being used as placeholder for i18n values in the DOM before the actual values have been fetched from the server\n *\n * @readonly\n * @static\n * @memberof I18nService\n */\n static get PLACEHOLDER_SELECTOR() {\n return 'kl-i18n-placeholder';\n }\n\n private static _instance?: I18nService;\n\n /**\n * returns the singleton instance of the I18nService\n *\n * @static\n * @returns\n * @memberof I18nService\n */\n static getInstance() {\n if (I18nService._instance === undefined) {\n I18nService._instance = new I18nService();\n }\n\n return I18nService._instance;\n }\n\n // see `I18nService.loaded` for more information about this property\n private _loaded = false;\n\n // see `I18nService.ready` for more information about this property\n private _ready: ExtendedPromise<undefined>;\n\n // a key-value map of the i18n keys and their internationalizations fetched from the server or provided by the user\n private _dictionary: { [key: string]: string } = {};\n\n // url to the servlet returning the dictionary\n private _url?: string;\n\n /**\n * returns true if the I18nService has been set up already. i.e. has a ajax url or the dictionary provided\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get isSetUp(): boolean {\n return Boolean(this._url || isFilledObject(this._dictionary));\n }\n\n /**\n * `loaded` will be true when the keys have been fetched from the server. and `false` otherwise.\n * reading the `loaded` accessor won't trigger the key fetch. For that use {@see I18nService.ready}\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get loaded(): boolean {\n return this._loaded;\n }\n\n /**\n * a promise will be returned that resolves when the keys have been fetched from the server, or the server rejected the ajax call.\n * reading the `ready` accessor will automatically trigger the dictionary fetch.\n * use this property when you NEED the keys to be already loaded and can't be replaced in the DOM later.\n *\n * @readonly\n * @type {Promise<undefined>}\n * @memberof I18nService\n */\n public get ready(): Promise<undefined> {\n if (!this._ready[pendingSymbol]) this.fetchI18nDictionary();\n\n return this._ready as Promise<undefined>;\n }\n\n /**\n * providing information necessary for the service to retrieve the i18n dictionary.\n * i.e. a ajax url to fetch data, or a static object with the i18n key-value in it\n *\n * @param {{ url: string; dictionary: Record<string, string> }} { url, dictionary }\n * @returns\n * @memberof I18nService\n */\n public setUp({ url, dictionary }: { url?: string; dictionary?: Record<string, string> } = {}) {\n if (this.isSetUp) {\n console.warn(\"@kluntje I18nService: service has already been set up. You can't set it up twice!\");\n return;\n }\n if (url) {\n this._url = url;\n } else if (dictionary) {\n this._dictionary = dictionary;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this._ready[pendingSymbol] = true;\n } else {\n throw new Error('@kluntje I18nService: a \"url\" or \"dictionary\" should have been passed to the setUp function.');\n }\n }\n\n /**\n * returns the internationalized value for the given i18n key when the value have been fetched from the server,\n * or a placeholder `<span>` with a fallback text based on the key or the provided fallback text\n * which will automatically be replaced with the value in the DOM after server response\n *\n * @param {string} key\n * @param {({ fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> })} [{\n * fallback,\n * interpolations,\n * }={}]\n * @returns {string}\n * @memberof I18nService\n */\n public get(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ): string {\n if (this.loaded) {\n if (this._dictionary.hasOwnProperty(key)) {\n let result = this._dictionary[key];\n if (interpolations) {\n Object.entries(interpolations).forEach(([k, v]) => {\n // replaceAll({key}, value)\n result = result.split(`{${k}}`).join(String(v));\n });\n }\n\n return result;\n }\n console.warn(`@kluntje I18nService: i18n for key '${key}' is missing in dictionary!`);\n\n return fallback !== undefined ? fallback : this.getHumanReadableName(key);\n }\n\n if (!this._ready[pendingSymbol]) {\n // add styling for the placeholder first time a placeholder will be added to the DOM\n this.addStyling();\n this.fetchI18nDictionary();\n }\n\n return this.getPlaceholder(key, { fallback, interpolations });\n }\n\n /**\n * Creates an instance of I18nService.\n * @memberof I18nService\n */\n private constructor() {\n this._ready = this.getReadyPromise();\n }\n\n /**\n * returns a Promise like object with properties to allow resolving the promise from the outside\n *\n * @private\n * @returns {ExtendedPromise<undefined>}\n * @memberof I18nService\n */\n private getReadyPromise(): ExtendedPromise<undefined> {\n let resolve: Function;\n let reject: Function;\n\n // @ts-ignore - other properties will be added in next couple of lines\n const _ready: ExtendedPromise<undefined> = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n // @ts-ignore - `resolve` is defined in the promise body from lines above\n _ready[resolveSymbol] = resolve;\n // @ts-ignore - `reject` is defined in the promise body from lines above\n _ready[rejectSymbol] = reject;\n // will be set to true when ajax call is sent\n _ready[pendingSymbol] = false;\n\n return _ready;\n }\n\n /**\n * throws an Error when the service is not set up\n *\n * @private\n * @memberof I18nService\n */\n private ensureSetup(): void {\n if (!this.isSetUp) throw new Error('@kluntje I18nService: should be set up before calling other APIs');\n }\n\n /**\n * add minimal styling for the placeholder to look as much as possible as if they were a text node and not a html element,\n * and without the need of an actual .css file to be loaded\n *\n * @private\n * @memberof I18nService\n */\n private addStyling(): void {\n const head = document.head;\n const style = document.createElement('style');\n style.type = 'text/css';\n style.appendChild(\n document.createTextNode(`\n .${I18nService.PLACEHOLDER_SELECTOR} {\n display: contents;\n }\n `),\n );\n head.appendChild(style);\n }\n\n /**\n * retrieves the i18n key.value pairs, and update instance properties regarding the pending/fulfilled status of the request\n *\n * @private\n * @memberof I18nService\n */\n private fetchI18nDictionary() {\n this.ensureSetup();\n this._ready[pendingSymbol] = true;\n\n fetchJSON(this._url!)\n .then((results: Record<string, string>) => {\n this._dictionary = results;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this.fillInPlaceholders();\n })\n .catch((err: Error) => {\n console.error('@kluntje I18nService: unable to fetch keys from server!', err);\n // ? adding a failed flag\n this._loaded = true;\n this._ready[resolveSymbol]();\n });\n }\n\n /**\n * i18n placeholder in the DOM will be fetched with i18n values been fetched from the server.\n *\n * @private\n * @memberof I18nService\n */\n private fillInPlaceholders() {\n Array.from(document.getElementsByClassName(I18nService.PLACEHOLDER_SELECTOR)).forEach((el) => {\n const { key, fallback, interpolations } = (el as HTMLElement).dataset;\n\n el.replaceWith(\n this.get(key!, {\n fallback,\n interpolations: interpolations ? JSON.parse(interpolations) : undefined,\n }),\n );\n });\n }\n\n /**\n * converts the i18n key names to values that can be used as fallback for the i18n text\n * @example\n * getHumanReadableName(\"org.example.hyphenated_name.filter.submitBtn\") === \"submit btn\"\n *\n * @private\n * @param {string} key\n * @returns\n * @memberof I18nService\n */\n private getHumanReadableName(key: string) {\n return (\n key\n // \"org.example.hyphenated_name.filter.submitBtn\" -> \"submitBtn\"\n .split('.')\n .reverse()[0]\n // \"submitBtn\" -> \"submit btn\"\n .replace(/[A-Z]/g, (letter: string) => ` ${letter.toLowerCase()}`)\n );\n }\n\n /**\n * generates a span element whith the fallback text to be replaced with the correct i18n value after server response\n *\n * @private\n * @param {string} key\n * @param {string} [fallback]\n * @returns\n * @memberof I18nService\n */\n private getPlaceholder(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ) {\n const span = document.createElement('span');\n span.innerText = fallback !== undefined ? fallback : this.getHumanReadableName(key);\n span.classList.add(I18nService.PLACEHOLDER_SELECTOR);\n span.setAttribute('data-key', key);\n if (fallback) span.setAttribute('data-fallback', fallback);\n // use escaping mechanism of setAttribute to store the stringified json\n if (interpolations) span.setAttribute('data-interpolations', JSON.stringify(interpolations));\n\n return span.outerHTML;\n }\n}\n","export class URLSearchParamsService {\n private urlSearchParams: URLSearchParams = new URLSearchParams(window.location.search);\n\n public get(param: string): string | null {\n return this.urlSearchParams.get(param);\n }\n\n public getAll(param: string): string[] | null {\n return this.urlSearchParams.getAll(param);\n }\n\n public getAllKeys(): Array<string> {\n // @ts-ignore\n return Array.from(this.urlSearchParams.keys());\n }\n\n public set(param: string, value: string): void {\n this.urlSearchParams.set(param, value);\n this.updateUrl();\n }\n\n public delete(param: string): void {\n this.urlSearchParams.delete(param);\n this.updateUrl();\n }\n\n public getString(): string {\n return this.urlSearchParams.toString();\n }\n\n public get curUrl() {\n return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;\n }\n\n private updateUrl() {\n const curQueryString = this.getString();\n const curUrl = this.curUrl;\n const hashCache = window.location.hash;\n const newUrl = curQueryString !== '' ? `${curUrl}?${curQueryString}` : curUrl;\n window.history.replaceState({ path: newUrl }, '', newUrl);\n if (hashCache !== '') window.location.hash = hashCache;\n }\n}\n\nexport default new URLSearchParamsService();\n","import URLSearchParamsService from './URLSearchParamsService';\n\nfunction debugModeActive() {\n return URLSearchParamsService.get('js-debug') !== null;\n}\n\nconst handler = {\n get(target: Console, prop: keyof Console) {\n if (debugModeActive()) return target[prop];\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n else return () => {};\n },\n};\n\nexport default new Proxy(console, handler);\n","class LazyConnectService {\n componentMap = new WeakMap();\n intersectionObserver: IntersectionObserver;\n\n constructor() {\n this.intersectionObserver = new IntersectionObserver((entries: any) => this.handleIntersectionChange(entries), {\n rootMargin: '500px 0px',\n });\n }\n\n subscribe(target: HTMLElement, intersectionCallback: () => void) {\n this.componentMap.set(target, intersectionCallback);\n this.intersectionObserver.observe(target);\n }\n\n unsubscribe(target: HTMLElement) {\n this.intersectionObserver.unobserve(target);\n this.componentMap.delete(target);\n }\n\n handleIntersectionChange(entries: Array<IntersectionObserverEntry>) {\n entries.forEach((intersectionEntry: any) => {\n const target = intersectionEntry.target;\n\n if (!intersectionEntry.isIntersecting || !this.componentMap.has(target)) return;\n\n const intersectionCallback = this.componentMap.get(target);\n this.unsubscribe(target as HTMLElement);\n intersectionCallback();\n });\n }\n}\n\nexport default new LazyConnectService();\n","import { IStorageService } from './StorageService.interface';\nimport { StorageServiceOptions, StorageType } from './StorageService.types';\n\nexport class StorageServiceImpl implements IStorageService {\n private observedItemsMap: Map<string, Set<() => void>> = new Map();\n\n constructor() {\n window.addEventListener('storage', (e) => this.handleStorageChange(e));\n }\n\n public addItem(storageKey: string, storageValue: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).setItem(storageKey, storageValue);\n this.fireCallbacks(storageKey);\n }\n\n public getItem(storageKey: string, options: StorageServiceOptions = {}): string | null {\n return this.getStorage(options).getItem(storageKey);\n }\n\n public removeItem(storageKey: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).removeItem(storageKey);\n }\n\n public observeItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.add(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public unobserveItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.delete(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public clearStorage(storageType: StorageType) {\n this.getStorage({ storageType }).clear();\n }\n\n private handleStorageChange(e: StorageEvent) {\n const storageKey = e.key;\n const oldValue = e.oldValue;\n const newValue = e.newValue;\n if (storageKey === null || oldValue === newValue || !this.observedItemsMap.has(storageKey)) return;\n\n this.fireCallbacks(storageKey);\n }\n\n private getKeyCallbacks(storageKey: string): Set<() => void> {\n return this.observedItemsMap.get(storageKey) || new Set();\n }\n\n private fireCallbacks(storageKey: string) {\n const callbacks = this.getKeyCallbacks(storageKey);\n callbacks.forEach((callback) => callback());\n }\n\n private getStorage(options: StorageServiceOptions): Storage {\n const { storageType = 'local' } = options;\n return storageType === 'local' ? localStorage : sessionStorage;\n }\n}\n\nexport const StorageService = new StorageServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { StorageServiceOptions, StorageService, IStorageService } from '../StorageService';\nimport { ICachingService } from './CachingService.interface';\nimport { CacheItem, CacheOptions, CachingServiceConstructorOptions } from './CachingService.types';\n\nexport class CachingServiceImpl implements ICachingService {\n private runtimeCache: Map<string, string> = new Map();\n private storageService: IStorageService = StorageService;\n private storageKeyPrefix = 'kl-caching-service';\n\n constructor(options?: CachingServiceConstructorOptions) {\n const { storageService, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n protected get shouldCache(): boolean {\n return true;\n }\n\n public cacheValue(key: string, value: string, options: CacheOptions) {\n if (this.shouldCache === false) return;\n\n if (options.validFor === 0) {\n this.runtimeCache.set(this.getStorageKey(key), value);\n return;\n }\n\n const cacheItem: CacheItem = {\n value,\n validUntil: Date.now() + options.validFor,\n };\n\n this.storageService.addItem(\n this.getStorageKey(key),\n JSON.stringify(cacheItem),\n this.getStorageServiceOptions(options),\n );\n }\n\n public getCachedValue(key: string, cacheOptions?: CacheOptions): string | null {\n if (this.shouldCache === false) return null;\n\n const storageKey = this.getStorageKey(key);\n\n const runtimeValue = this.runtimeCache.get(storageKey);\n\n if (runtimeValue !== undefined) return runtimeValue;\n\n const cachedItemString = this.storageService.getItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n if (cachedItemString === null) return null;\n\n try {\n const cachedItem: CacheItem = JSON.parse(cachedItemString);\n if (cachedItem.validUntil < Date.now()) {\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n\n return cachedItem.value;\n } catch (e) {\n DebuggerService.warn('CachingService: ', e);\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n }\n\n public getCachedJSON<T>(key: string, cacheOptions?: CacheOptions): T | null {\n const cachedValue = this.getCachedValue(key, cacheOptions);\n if (cachedValue === null) return null;\n try {\n return JSON.parse(cachedValue);\n } catch (error) {\n DebuggerService.error('CachingService: ', error);\n return null;\n }\n }\n\n public clearCachedValue(key: string, cacheOptions?: CacheOptions) {\n const storageKey = this.getStorageKey(key);\n\n if (cacheOptions?.validFor === 0) {\n this.runtimeCache.delete(storageKey);\n return;\n }\n\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n }\n\n private getStorageServiceOptions(cacheOptions?: CacheOptions): StorageServiceOptions {\n return {\n storageType: cacheOptions?.storageType,\n };\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const CachingService = new CachingServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { IStorageService, StorageService, StorageType } from '../StorageService';\nimport { IRequestCachingService } from './RequestCachingService.interface';\nimport { RequestCacheOptions, RequestCachingServiceConstructorOptions } from './RequestCachingService.types';\n\nexport class RequestCachingServiceImpl implements IRequestCachingService {\n private _cache?: Promise<Cache>;\n\n private storageService: IStorageService = StorageService;\n private requestCacheName = 'kl-request-cache';\n private storageKeyPrefix = 'kl-request-caching-service';\n\n constructor(options?: RequestCachingServiceConstructorOptions) {\n const { storageService, requestCacheName, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (requestCacheName !== undefined) {\n this.requestCacheName = requestCacheName;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n private async getCache(): Promise<Cache | null> {\n try {\n if (this._cache === undefined) {\n this._cache = caches.open(this.requestCacheName);\n }\n return await this._cache;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async getCachedResponse(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return null;\n\n const response = await cache.match(request);\n if (response === undefined) return null;\n\n const validUntil = this.storageService.getItem(this.getStorageKey(request.url), { storageType: storage });\n if (validUntil === null) {\n await cache.delete(request);\n return null;\n }\n\n const now = Date.now();\n if (now > parseInt(validUntil, 10)) {\n await cache.delete(request);\n return null;\n }\n return response;\n }\n\n public async getCachedJSON<T>(request: Request, storage?: StorageType) {\n const response = await this.getCachedResponse(request, storage);\n if (response === null) return null;\n try {\n return (await response.json()) as T;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async cacheRequest(options: RequestCacheOptions) {\n const { request, response } = options;\n const cache = await this.getCache();\n if (cache === null) return;\n this.storeExpirationTime(options);\n await cache.put(request, response);\n }\n\n public async clearCachedRequest(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return;\n await cache.delete(request);\n this.storageService.removeItem(this.getStorageKey(request.url), { storageType: storage });\n }\n\n private storeExpirationTime(options: RequestCacheOptions) {\n const { request, maxAge } = options;\n const validUntil = Date.now() + maxAge;\n this.storageService.addItem(this.getStorageKey(request.url), validUntil.toString(), {\n storageType: options.storage,\n });\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const RequestCachingService = new RequestCachingServiceImpl();\n","import { CacheOptions, ICachingService } from '../CachingService';\nimport { IRequestCachingService } from '../RequestCachingService';\n\nexport interface APIServiceCacheOptions extends CacheOptions {\n forceRefetch?: boolean;\n requestBasedCaching?: boolean;\n cacheKeys?: string[];\n}\n\nexport interface APIServiceRequestOptions {\n fetchOptions?: RequestInit;\n cacheOptions?: APIServiceCacheOptions;\n throwError?: boolean;\n}\n\nexport interface APIServiceConstructorOptions {\n cachingService?: ICachingService;\n requestCachingService?: IRequestCachingService;\n}\n\nexport class APIError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n super(response.statusText);\n this.response = response;\n }\n}\n","import { appendQueryObject } from \"@kluntje/js-utils/lib/url-helpers\";\n\nimport DebuggerService from \"../DebuggerService\";\nimport { IRequestCachingService, RequestCachingService } from \"../RequestCachingService\";\nimport { CachingService, ICachingService } from \"../CachingService\";\n\nimport { APIError, APIServiceCacheOptions, APIServiceConstructorOptions, APIServiceRequestOptions } from \"./APIService.types\";\nimport { IAPIService } from \"./APIService.interface\";\n\nexport class APIServiceImpl implements IAPIService {\n private requestPipeline: Map<string, Promise<Response | null>> = new Map();\n\n private cachingService: ICachingService = CachingService;\n private requestCachingService: IRequestCachingService = RequestCachingService;\n\n constructor(options: APIServiceConstructorOptions = {}) {\n const { cachingService, requestCachingService } = options;\n\n if (cachingService !== undefined) this.cachingService = cachingService;\n if (requestCachingService !== undefined) this.requestCachingService = requestCachingService;\n }\n\n public async fetchJSON<T>(url: string, options: APIServiceRequestOptions = {}): Promise<T | null> {\n // eslint-disable-next-line prettier/prettier\n return await this.fetch(url, APIServiceImpl.getJSON<T>, options);\n }\n\n public async fetchHTML(url: string, options: APIServiceRequestOptions = {}): Promise<string | null> {\n return await this.fetch(url, APIServiceImpl.getHTML, options);\n }\n\n private async fetch<T>(\n url: string,\n dataMapper: (response: Response | null) => Promise<T>,\n options: APIServiceRequestOptions = {},\n ): Promise<T | null> {\n const { cacheOptions } = options;\n\n if (cacheOptions?.forceRefetch === true) {\n this.clearCachedValue(url, cacheOptions);\n }\n\n const cachedValue = await this.getCachedValue<T>(url, cacheOptions);\n if (cachedValue !== null) return cachedValue;\n\n try {\n const pipelineRequest = this.requestPipeline.get(url);\n if (pipelineRequest !== undefined) {\n return await dataMapper(await pipelineRequest);\n }\n\n const request = this.fetchData(url, options);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n const responseData = await dataMapper(response);\n this.requestPipeline.delete(url);\n\n if (response === null || responseData === null) return null;\n\n if (cacheOptions === undefined) return responseData;\n await this.cacheResponse(url, response, responseData, cacheOptions);\n\n return responseData;\n } catch (error) {\n DebuggerService.error(\"APIService.fetch: \", error);\n this.requestPipeline.delete(url);\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n public async fetchResponse(url: string, options: APIServiceRequestOptions = {}): Promise<Response | null> {\n const { cacheOptions } = options;\n const { forceRefetch = false } = cacheOptions ?? {};\n\n if (forceRefetch === true) {\n await this.requestCachingService.clearCachedRequest(new Request(url), cacheOptions?.storageType ?? \"session\");\n }\n\n const cachedResponse = await this.requestCachingService.getCachedResponse(\n new Request(url),\n cacheOptions?.storageType ?? \"session\",\n );\n\n if (cachedResponse !== null) return cachedResponse;\n\n const pipelineRequest = this.requestPipeline.get(url);\n\n if (pipelineRequest !== undefined) {\n return await pipelineRequest;\n }\n\n try {\n const request = fetch(url, options.fetchOptions);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n this.requestPipeline.delete(url);\n\n if (cacheOptions === undefined) return response;\n\n await this.requestCachingService.cacheRequest({\n request: new Request(url),\n response,\n storage: cacheOptions.storageType ?? \"session\",\n maxAge: cacheOptions.validFor,\n });\n\n return response;\n } catch (error) {\n DebuggerService.error(\"APIService.fetchResponse: \", error);\n\n this.requestPipeline.delete(url);\n\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n private async fetchData(url: string, options: APIServiceRequestOptions): Promise<Response | null> {\n const response = await fetch(url, options.fetchOptions);\n\n if (!response.ok) throw new APIError(response);\n if (response.status === 204) return null;\n\n return response;\n }\n\n private static async getJSON<T>(response: Response | null): Promise<T | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.json();\n }\n\n private static async getHTML(response: Response | null): Promise<string | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.text();\n }\n\n private async cacheResponse<T>(\n url: string,\n response: Response,\n responseData: T,\n cacheOptions: APIServiceCacheOptions,\n ) {\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (cacheOptions.requestBasedCaching === true) {\n await this.requestCachingService.cacheRequest({\n request: new Request(cacheKey),\n response,\n storage: cacheOptions.storageType ?? \"local\",\n maxAge: cacheOptions.validFor,\n });\n } else {\n this.cachingService.cacheValue(cacheKey, JSON.stringify(responseData), cacheOptions);\n }\n }\n\n private async clearCachedValue(url: string, cacheOptions?: APIServiceCacheOptions) {\n if (cacheOptions === undefined) return;\n const { requestBasedCaching = false } = cacheOptions;\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (requestBasedCaching === true) {\n await this.requestCachingService.clearCachedRequest(new Request(cacheKey), cacheOptions.storageType);\n }\n this.cachingService.clearCachedValue(cacheKey, cacheOptions);\n }\n\n private async getCachedValue<T>(url: string, cacheOptions?: APIServiceCacheOptions): Promise<T | null> {\n if (cacheOptions === undefined) return null;\n const { requestBasedCaching = false } = cacheOptions;\n\n const cacheKey = this.getCacheKey(url, cacheOptions);\n if (requestBasedCaching === true) {\n return await this.requestCachingService.getCachedJSON(new Request(cacheKey), cacheOptions.storageType);\n }\n return this.cachingService.getCachedJSON(cacheKey, cacheOptions);\n }\n\n private getCacheKey(url: string, cacheOptions?: APIServiceCacheOptions): string {\n const cacheKeys = cacheOptions?.cacheKeys ?? [];\n if (cacheKeys.length === 0) return url;\n return appendQueryObject(url, { klCacheKeys: cacheKeys.join(\"_\") });\n }\n}\n\nexport const APIService = new APIServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { APIService, APIServiceRequestOptions, IAPIService } from '../APIService';\nimport {\n AbortableRequestServiceConstructorOptions,\n AbortableRequestServiceOptions,\n} from './AbortableRequestService.types';\n\nexport class AbortableRequestService {\n private abortController = new AbortController();\n private abortOptions: AbortableRequestServiceOptions | null = null;\n private latestOptions: AbortableRequestServiceOptions | null = null;\n\n protected apiService: IAPIService = APIService;\n\n constructor(options: AbortableRequestServiceConstructorOptions = {}) {\n const { apiService } = options;\n\n if (apiService !== undefined) this.apiService = apiService;\n }\n\n public async fetchJSON<T>(options: AbortableRequestServiceOptions): Promise<T | null> {\n return await this.makeAbortableRequest<T>(options, this.apiService.fetchJSON.bind(this.apiService));\n }\n\n public async fetchResponse(options: AbortableRequestServiceOptions): Promise<Response | null> {\n return await this.makeAbortableRequest<Response>(options, this.apiService.fetchResponse.bind(this.apiService));\n }\n\n private async makeAbortableRequest<R>(\n options: AbortableRequestServiceOptions,\n fetcher: (url: string, options: APIServiceRequestOptions) => Promise<R | null>,\n ): Promise<R | null> {\n if (this.latestOptions !== null) {\n this.abortOptions = options;\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n this.latestOptions = options;\n\n try {\n const response = await fetcher(options.url, {\n cacheOptions: options.options?.cacheOptions,\n throwError: true,\n fetchOptions: {\n ...options.options?.fetchOptions,\n signal: this.abortController.signal,\n },\n });\n this.latestOptions = null;\n return response;\n } catch (error: any) {\n DebuggerService.error('AbortableRequestService.makeAbortableRequest: ', error);\n\n if (error.name === 'AbortError') return this.handleAbortError<R>(this.fetchJSON.bind(this));\n\n if (options.options?.throwError === true) throw error;\n\n return null;\n }\n }\n\n private async handleAbortError<R>(\n nextAction: (options: AbortableRequestServiceOptions) => Promise<R | null>,\n ): Promise<R | null> {\n const latestOptions = this.latestOptions || this.abortOptions;\n if (latestOptions === null) return null;\n this.abortOptions = null;\n this.latestOptions = null;\n return nextAction(latestOptions);\n }\n}\n","import { IObserverService } from './ObserverService.interface';\nimport { ObserverCallback } from './ObserverService.types';\n\nexport class ObserverServiceImpl implements IObserverService {\n private observerMap: Map<string, Set<ObserverCallback>> = new Map();\n\n public observe(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.add(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public unobserve(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.delete(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public notifyObservers<T>(observedKey: string, data?: T) {\n const callbacks = this.getCallbacks(observedKey);\n callbacks.forEach((callback) => callback(data));\n }\n\n private getCallbacks(observedKey: string): Set<ObserverCallback> {\n return this.observerMap.get(observedKey) || new Set();\n }\n}\n\nexport const ObserverService = new ObserverServiceImpl();\n","import { ObserverServiceImpl } from '../ObserverService';\n\nexport class ContextState {\n private stateMap: Map<string, any> = new Map();\n private observerService = new ObserverServiceImpl();\n private contextName: string;\n private contextElement: HTMLElement;\n\n constructor(contextName: string, contextElement: HTMLElement) {\n this.contextName = contextName;\n this.contextElement = contextElement;\n }\n\n public get name(): string {\n return this.contextName;\n }\n\n public get element(): HTMLElement {\n return this.contextElement;\n }\n\n public isMatchingContext(contextName: string, consumingElement: HTMLElement): boolean {\n if (this.contextName !== contextName) return false;\n\n return this.contextElement.contains(consumingElement);\n }\n\n public setState<T>(key: string, value: T): void {\n if (this.stateMap.get(key) === value) return;\n this.stateMap.set(key, value);\n this.observerService.notifyObservers(key);\n }\n\n public getState<T>(key: string): T | undefined {\n return this.stateMap.get(key) as T;\n }\n\n public observeState(key: string, callback: () => void): void {\n this.observerService.observe(key, callback);\n }\n\n public unobserveState(key: string, callback: () => void): void {\n this.observerService.unobserve(key, callback);\n }\n}\n","import { ContextState } from './ContextState';\nimport { ObserverServiceImpl } from '../ObserverService';\nimport { IContextStateService } from './ContextStateService.interface';\n\nexport class ContextStateServiceImpl implements IContextStateService {\n private contextStateMap: Map<string, ContextState[]> = new Map();\n private contextInitObserver = new ObserverServiceImpl();\n\n private getMatchingContextState(contextName: string, consumingElement: HTMLElement): ContextState | null {\n const contextList = this.contextStateMap.get(contextName) || [];\n const matchingContexts = contextList.filter((context) => context.isMatchingContext(contextName, consumingElement));\n if (matchingContexts.length === 0) return null;\n return matchingContexts[0];\n }\n\n public getContextState(contextName: string, consumingElement: HTMLElement): Promise<ContextState> {\n const matchingContextState = this.getMatchingContextState(contextName, consumingElement);\n if (matchingContextState) return Promise.resolve(matchingContextState);\n return new Promise<ContextState>((resolve) => {\n this.contextInitObserver.observe(contextName, () => {\n const contextState = this.getMatchingContextState(contextName, consumingElement);\n if (contextState) {\n resolve(contextState);\n }\n });\n });\n }\n\n public createContextState(contextName: string, contextElement: HTMLElement): ContextState {\n const contextState = new ContextState(contextName, contextElement);\n const contextList = this.contextStateMap.get(contextName) || [];\n contextList.push(contextState);\n this.contextStateMap.set(contextName, contextList);\n this.contextInitObserver.notifyObservers(contextName);\n return contextState;\n }\n}\n\nexport const ContextStateService = new ContextStateServiceImpl();\n"],"names":["MQ_CHANGE_EVENT","IN_VP_EVENT","OUT_VP_EVENT","ViewportObserver","constructor","static","undefined","instance","IntersectionObserver","handleIntersectionChange","e","Object","keys","forEach","key","observedEl","target","isIntersecting","dispatchEvent","CustomEvent","bubbles","MediaQueryService","this","eventIdMap","WeakMap","eventBindingMap","lastMQ","getCurrentMQ","mediaQuerys","onEvent","window","handleMQChange","newMQ","detail","oldMQ","__decorate","throttle","resolveSymbol","Symbol","rejectSymbol","pendingSymbol","I18nService","PLACEHOLDER_SELECTOR","_instance","isSetUp","Boolean","_url","isFilledObject","_dictionary","loaded","_loaded","ready","_ready","fetchI18nDictionary","setUp","url","dictionary","console","warn","Error","get","fallback","interpolations","hasOwnProperty","result","entries","k","v","split","join","String","getHumanReadableName","addStyling","getPlaceholder","getReadyPromise","resolve","reject","Promise","res","rej","ensureSetup","head","document","style","createElement","type","appendChild","createTextNode","fetchJSON","then","results","fillInPlaceholders","catch","err","error","Array","from","getElementsByClassName","el","dataset","replaceWith","JSON","parse","reverse","replace","letter","toLowerCase","span","innerText","classList","add","setAttribute","stringify","outerHTML","URLSearchParams","location","search","param","urlSearchParams","getAll","getAllKeys","set","value","updateUrl","delete","getString","toString","curUrl","protocol","host","pathname","curQueryString","hashCache","hash","newUrl","history","replaceState","path","Proxy","prop","URLSearchParamsService","intersectionObserver","rootMargin","subscribe","intersectionCallback","componentMap","observe","unsubscribe","unobserve","intersectionEntry","has","StorageServiceImpl","Map","addEventListener","handleStorageChange","addItem","storageKey","storageValue","options","getStorage","setItem","fireCallbacks","getItem","removeItem","observeItem","callback","keyCallbacks","getKeyCallbacks","observedItemsMap","unobserveItem","clearStorage","storageType","clear","oldValue","newValue","Set","localStorage","sessionStorage","StorageService","CachingServiceImpl","storageService","storageKeyPrefix","shouldCache","cacheValue","validFor","runtimeCache","getStorageKey","cacheItem","validUntil","Date","now","getStorageServiceOptions","getCachedValue","cacheOptions","runtimeValue","cachedItemString","cachedItem","DebuggerService","getCachedJSON","cachedValue","clearCachedValue","CachingService","RequestCachingServiceImpl","requestCacheName","getCache","_cache","caches","open","getCachedResponse","request","storage","cache","response","match","parseInt","json","cacheRequest","storeExpirationTime","put","clearCachedRequest","maxAge","RequestCachingService","APIError","super","statusText","APIServiceImpl","cachingService","requestCachingService","fetch","fetchHTML","getHTML","dataMapper","forceRefetch","pipelineRequest","requestPipeline","fetchData","responseData","cacheResponse","throwError","fetchResponse","Request","cachedResponse","fetchOptions","ok","status","responseClone","clone","text","cacheKey","getCacheKey","requestBasedCaching","cacheKeys","length","appendQueryObject","klCacheKeys","APIService","AbortableRequestService","AbortController","apiService","makeAbortableRequest","bind","fetcher","latestOptions","abortOptions","abortController","abort","signal","name","handleAbortError","nextAction","ObserverServiceImpl","observedKey","curCallbacks","getCallbacks","observerMap","notifyObservers","data","ObserverService","ContextState","contextName","contextElement","element","isMatchingContext","consumingElement","contains","setState","stateMap","observerService","getState","observeState","unobserveState","ContextStateServiceImpl","getMatchingContextState","matchingContexts","contextStateMap","filter","context","getContextState","matchingContextState","contextInitObserver","contextState","createContextState","contextList","push","ContextStateService"],"mappings":"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"} | ||
| {"version":3,"file":"index.module.js","sources":["../src/eventNames.ts","../src/ViewportObserver.ts","../src/MediaQueryService.ts","../src/I18nService.ts","../src/URLSearchParamsService.ts","../src/DebuggerService.ts","../src/LazyConnectService.ts","../src/StorageService/StorageService.ts","../src/CachingService/CachingService.ts","../src/RequestCachingService/RequestCachingService.ts","../src/APIService/APIService.types.ts","../src/APIService/APIService.ts","../src/AbortableRequestService/AbortableRequestService.ts","../src/ObserverService/ObserverService.ts","../src/ContextStateService/ContextState.ts","../src/ContextStateService/ContextStateService.ts"],"sourcesContent":["export const MQ_CHANGE_EVENT = 'kl-mq-change';\nexport const IN_VP_EVENT = 'kl-in-vp';\nexport const OUT_VP_EVENT = 'kl-out-vp';\n","import { IN_VP_EVENT, OUT_VP_EVENT } from './eventNames';\n\ntype IntersectionEvent = {\n [key: string]: any;\n};\n\nexport class ViewportObserver {\n private static instance: IntersectionObserver;\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private constructor() {}\n\n static getInstance() {\n if (ViewportObserver.instance === undefined) {\n ViewportObserver.instance = new IntersectionObserver(ViewportObserver.handleIntersectionChange);\n }\n return ViewportObserver.instance;\n }\n\n private static handleIntersectionChange(e: IntersectionEvent) {\n Object.keys(e).forEach((key) => {\n const observedEl = e[key];\n const target = observedEl.target;\n\n if (observedEl.isIntersecting) {\n target.dispatchEvent(new CustomEvent(IN_VP_EVENT, { bubbles: false }));\n } else {\n target.dispatchEvent(new CustomEvent(OUT_VP_EVENT, { bubbles: false }));\n }\n });\n }\n}\n","import { throttle } from '@kluntje/js-utils/lib/function-helpers/decorators';\nimport { onEvent, getCurrentMQ, MQDefinition } from '@kluntje/js-utils/lib/dom-helpers';\nimport { MQ_CHANGE_EVENT } from './eventNames';\n\nexport class MediaQueryService {\n private static instance: MediaQueryService;\n static mediaQuerys: Array<MQDefinition>;\n eventIdMap: WeakMap<HTMLElement | Function, string>;\n eventBindingMap: {\n [index: string]: EventListenerOrEventListenerObject;\n };\n lastMQ: string;\n\n private constructor() {\n this.eventIdMap = new WeakMap();\n this.eventBindingMap = {};\n this.lastMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n onEvent(window, 'resize', this.handleMQChange, this);\n }\n\n static getInstance(mediaQuerys: Array<MQDefinition>) {\n if (MediaQueryService.instance === undefined) {\n MediaQueryService.mediaQuerys = mediaQuerys;\n MediaQueryService.instance = new MediaQueryService();\n }\n return MediaQueryService.instance;\n }\n\n @throttle(100)\n handleMQChange() {\n const newMQ = getCurrentMQ(MediaQueryService.mediaQuerys);\n if (newMQ === this.lastMQ) {\n return;\n }\n\n window.dispatchEvent(\n new CustomEvent(MQ_CHANGE_EVENT, {\n detail: {\n newMQ,\n oldMQ: this.lastMQ,\n },\n }),\n );\n\n this.lastMQ = newMQ;\n }\n}\n","import { fetchJSON } from '@kluntje/js-utils/lib/api-helpers';\nimport { isFilledObject } from '@kluntje/js-utils/lib/object-helpers';\n\nconst resolveSymbol = Symbol('resolve');\nconst rejectSymbol = Symbol('reject');\nconst pendingSymbol = Symbol('pending');\n\n// Promise but with options to resolve/reject from outside\ninterface ExtendedPromise<T> extends Promise<T> {\n [resolveSymbol]: Function;\n [rejectSymbol]: Function;\n [pendingSymbol]: boolean;\n}\n\n/**\n * A service to provide sync/async way to provide internationalization values.\n * With i18n values beeing able to have variable placeholder in them. indexd for arrays e.g. `{0}` or named for objects e.g. `{hour}`\n *\n * @example\n * import I18nService from \"@kluntje/services/I18nService\";\n * // get singleton instance\n * const i18nService = I18nService.getInstance();\n * // provide the url to fetch the dictionary\n * i18nService.setUp({url: \"path/to/i18n/ajax/service\"});\n * // or provide the dictionary itself\n * // i18nService.setUp({dictionary: {\"com.page.filter.notifications\": \"{0} Nachrichten\", ...}});\n * const i18n = i18nService.get;\n * // use API\n * // render markup with i18n value, if the i18n key hasn't been fetched jet, a placeholder `<span class\"kl-i18n-placeholder\"></span>` will be rendered,\n * // with the provided `fallback` text. or the last part of the key.\n * // this `span` will be replaced with the i18n value in den DOM after the keys where successfully fetched from the server\n * render(html`<button>${i18n(\"com.page.filter.notifications\", {fallback: \"Info\", interpolations: [7]})}</button>`, el);\n * // if any actions needs the keys to be ready and shouldn't be replace later in the DOM, the `ready` accessor can be called.\n * // this will automatically trigger the fetch for the keys from the server\n * await i18nService.ready;\n * // the boolean `loaded` can be used to check if the keys have been fetched form the server. This will not trigger the fetch.\n * if (i18nService.loaded) console.log(i18nService.get(\"com.page.filter.submitLabel\"))\n *\n * @export\n * @class I18nService\n */\nexport class I18nService {\n /**\n * class name for the `span`s being used as placeholder for i18n values in the DOM before the actual values have been fetched from the server\n *\n * @readonly\n * @static\n * @memberof I18nService\n */\n static get PLACEHOLDER_SELECTOR() {\n return 'kl-i18n-placeholder';\n }\n\n private static _instance?: I18nService;\n\n /**\n * returns the singleton instance of the I18nService\n *\n * @static\n * @returns\n * @memberof I18nService\n */\n static getInstance() {\n if (I18nService._instance === undefined) {\n I18nService._instance = new I18nService();\n }\n\n return I18nService._instance;\n }\n\n // see `I18nService.loaded` for more information about this property\n private _loaded = false;\n\n // see `I18nService.ready` for more information about this property\n private _ready: ExtendedPromise<undefined>;\n\n // a key-value map of the i18n keys and their internationalizations fetched from the server or provided by the user\n private _dictionary: { [key: string]: string } = {};\n\n // url to the servlet returning the dictionary\n private _url?: string;\n\n /**\n * returns true if the I18nService has been set up already. i.e. has a ajax url or the dictionary provided\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get isSetUp(): boolean {\n return Boolean(this._url || isFilledObject(this._dictionary));\n }\n\n /**\n * `loaded` will be true when the keys have been fetched from the server. and `false` otherwise.\n * reading the `loaded` accessor won't trigger the key fetch. For that use {@see I18nService.ready}\n *\n * @readonly\n * @type {boolean}\n * @memberof I18nService\n */\n public get loaded(): boolean {\n return this._loaded;\n }\n\n /**\n * a promise will be returned that resolves when the keys have been fetched from the server, or the server rejected the ajax call.\n * reading the `ready` accessor will automatically trigger the dictionary fetch.\n * use this property when you NEED the keys to be already loaded and can't be replaced in the DOM later.\n *\n * @readonly\n * @type {Promise<undefined>}\n * @memberof I18nService\n */\n public get ready(): Promise<undefined> {\n if (!this._ready[pendingSymbol]) this.fetchI18nDictionary();\n\n return this._ready as Promise<undefined>;\n }\n\n /**\n * providing information necessary for the service to retrieve the i18n dictionary.\n * i.e. a ajax url to fetch data, or a static object with the i18n key-value in it\n *\n * @param {{ url: string; dictionary: Record<string, string> }} { url, dictionary }\n * @returns\n * @memberof I18nService\n */\n public setUp({ url, dictionary }: { url?: string; dictionary?: Record<string, string> } = {}) {\n if (this.isSetUp) {\n console.warn(\"@kluntje I18nService: service has already been set up. You can't set it up twice!\");\n return;\n }\n if (url) {\n this._url = url;\n } else if (dictionary) {\n this._dictionary = dictionary;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this._ready[pendingSymbol] = true;\n } else {\n throw new Error('@kluntje I18nService: a \"url\" or \"dictionary\" should have been passed to the setUp function.');\n }\n }\n\n /**\n * returns the internationalized value for the given i18n key when the value have been fetched from the server,\n * or a placeholder `<span>` with a fallback text based on the key or the provided fallback text\n * which will automatically be replaced with the value in the DOM after server response\n *\n * @param {string} key\n * @param {({ fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> })} [{\n * fallback,\n * interpolations,\n * }={}]\n * @returns {string}\n * @memberof I18nService\n */\n public get(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ): string {\n if (this.loaded) {\n if (this._dictionary.hasOwnProperty(key)) {\n let result = this._dictionary[key];\n if (interpolations) {\n Object.entries(interpolations).forEach(([k, v]) => {\n // replaceAll({key}, value)\n result = result.split(`{${k}}`).join(String(v));\n });\n }\n\n return result;\n }\n console.warn(`@kluntje I18nService: i18n for key '${key}' is missing in dictionary!`);\n\n return fallback !== undefined ? fallback : this.getHumanReadableName(key);\n }\n\n if (!this._ready[pendingSymbol]) {\n // add styling for the placeholder first time a placeholder will be added to the DOM\n this.addStyling();\n this.fetchI18nDictionary();\n }\n\n return this.getPlaceholder(key, { fallback, interpolations });\n }\n\n /**\n * Creates an instance of I18nService.\n * @memberof I18nService\n */\n private constructor() {\n this._ready = this.getReadyPromise();\n }\n\n /**\n * returns a Promise like object with properties to allow resolving the promise from the outside\n *\n * @private\n * @returns {ExtendedPromise<undefined>}\n * @memberof I18nService\n */\n private getReadyPromise(): ExtendedPromise<undefined> {\n let resolve: Function;\n let reject: Function;\n\n // @ts-ignore - other properties will be added in next couple of lines\n const _ready: ExtendedPromise<undefined> = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n // @ts-ignore - `resolve` is defined in the promise body from lines above\n _ready[resolveSymbol] = resolve;\n // @ts-ignore - `reject` is defined in the promise body from lines above\n _ready[rejectSymbol] = reject;\n // will be set to true when ajax call is sent\n _ready[pendingSymbol] = false;\n\n return _ready;\n }\n\n /**\n * throws an Error when the service is not set up\n *\n * @private\n * @memberof I18nService\n */\n private ensureSetup(): void {\n if (!this.isSetUp) throw new Error('@kluntje I18nService: should be set up before calling other APIs');\n }\n\n /**\n * add minimal styling for the placeholder to look as much as possible as if they were a text node and not a html element,\n * and without the need of an actual .css file to be loaded\n *\n * @private\n * @memberof I18nService\n */\n private addStyling(): void {\n const head = document.head;\n const style = document.createElement('style');\n style.type = 'text/css';\n style.appendChild(\n document.createTextNode(`\n .${I18nService.PLACEHOLDER_SELECTOR} {\n display: contents;\n }\n `),\n );\n head.appendChild(style);\n }\n\n /**\n * retrieves the i18n key.value pairs, and update instance properties regarding the pending/fulfilled status of the request\n *\n * @private\n * @memberof I18nService\n */\n private fetchI18nDictionary() {\n this.ensureSetup();\n this._ready[pendingSymbol] = true;\n\n fetchJSON(this._url!)\n .then((results: Record<string, string>) => {\n this._dictionary = results;\n this._loaded = true;\n this._ready[resolveSymbol]();\n this.fillInPlaceholders();\n })\n .catch((err: Error) => {\n console.error('@kluntje I18nService: unable to fetch keys from server!', err);\n // ? adding a failed flag\n this._loaded = true;\n this._ready[resolveSymbol]();\n });\n }\n\n /**\n * i18n placeholder in the DOM will be fetched with i18n values been fetched from the server.\n *\n * @private\n * @memberof I18nService\n */\n private fillInPlaceholders() {\n Array.from(document.getElementsByClassName(I18nService.PLACEHOLDER_SELECTOR)).forEach((el) => {\n const { key, fallback, interpolations } = (el as HTMLElement).dataset;\n\n el.replaceWith(\n this.get(key!, {\n fallback,\n interpolations: interpolations ? JSON.parse(interpolations) : undefined,\n }),\n );\n });\n }\n\n /**\n * converts the i18n key names to values that can be used as fallback for the i18n text\n * @example\n * getHumanReadableName(\"org.example.hyphenated_name.filter.submitBtn\") === \"submit btn\"\n *\n * @private\n * @param {string} key\n * @returns\n * @memberof I18nService\n */\n private getHumanReadableName(key: string) {\n return (\n key\n // \"org.example.hyphenated_name.filter.submitBtn\" -> \"submitBtn\"\n .split('.')\n .reverse()[0]\n // \"submitBtn\" -> \"submit btn\"\n .replace(/[A-Z]/g, (letter: string) => ` ${letter.toLowerCase()}`)\n );\n }\n\n /**\n * generates a span element whith the fallback text to be replaced with the correct i18n value after server response\n *\n * @private\n * @param {string} key\n * @param {string} [fallback]\n * @returns\n * @memberof I18nService\n */\n private getPlaceholder(\n key: string,\n {\n fallback,\n interpolations,\n }: { fallback?: string; interpolations?: Array<string | number> | Record<string, string | number> } = {},\n ) {\n const span = document.createElement('span');\n span.innerText = fallback !== undefined ? fallback : this.getHumanReadableName(key);\n span.classList.add(I18nService.PLACEHOLDER_SELECTOR);\n span.setAttribute('data-key', key);\n if (fallback) span.setAttribute('data-fallback', fallback);\n // use escaping mechanism of setAttribute to store the stringified json\n if (interpolations) span.setAttribute('data-interpolations', JSON.stringify(interpolations));\n\n return span.outerHTML;\n }\n}\n","export class URLSearchParamsService {\n private urlSearchParams: URLSearchParams = new URLSearchParams(window.location.search);\n\n public get(param: string): string | null {\n return this.urlSearchParams.get(param);\n }\n\n public getAll(param: string): string[] | null {\n return this.urlSearchParams.getAll(param);\n }\n\n public getAllKeys(): Array<string> {\n // @ts-ignore\n return Array.from(this.urlSearchParams.keys());\n }\n\n public set(param: string, value: string): void {\n this.urlSearchParams.set(param, value);\n this.updateUrl();\n }\n\n public delete(param: string): void {\n this.urlSearchParams.delete(param);\n this.updateUrl();\n }\n\n public getString(): string {\n return this.urlSearchParams.toString();\n }\n\n public get curUrl() {\n return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;\n }\n\n private updateUrl() {\n const curQueryString = this.getString();\n const curUrl = this.curUrl;\n const hashCache = window.location.hash;\n const newUrl = curQueryString !== '' ? `${curUrl}?${curQueryString}` : curUrl;\n window.history.replaceState({ path: newUrl }, '', newUrl);\n if (hashCache !== '') window.location.hash = hashCache;\n }\n}\n\nexport default new URLSearchParamsService();\n","import URLSearchParamsService from './URLSearchParamsService';\n\nfunction debugModeActive() {\n return URLSearchParamsService.get('js-debug') !== null;\n}\n\nconst handler = {\n get(target: Console, prop: keyof Console) {\n if (debugModeActive()) return target[prop];\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n else return () => {};\n },\n};\n\nexport default new Proxy(console, handler);\n","class LazyConnectService {\n componentMap = new WeakMap();\n intersectionObserver: IntersectionObserver;\n\n constructor() {\n this.intersectionObserver = new IntersectionObserver((entries: any) => this.handleIntersectionChange(entries), {\n rootMargin: '500px 0px',\n });\n }\n\n subscribe(target: HTMLElement, intersectionCallback: () => void) {\n this.componentMap.set(target, intersectionCallback);\n this.intersectionObserver.observe(target);\n }\n\n unsubscribe(target: HTMLElement) {\n this.intersectionObserver.unobserve(target);\n this.componentMap.delete(target);\n }\n\n handleIntersectionChange(entries: Array<IntersectionObserverEntry>) {\n entries.forEach((intersectionEntry: any) => {\n const target = intersectionEntry.target;\n\n if (!intersectionEntry.isIntersecting || !this.componentMap.has(target)) return;\n\n const intersectionCallback = this.componentMap.get(target);\n this.unsubscribe(target as HTMLElement);\n intersectionCallback();\n });\n }\n}\n\nexport default new LazyConnectService();\n","import { IStorageService } from './StorageService.interface';\nimport { StorageServiceOptions, StorageType } from './StorageService.types';\n\nexport class StorageServiceImpl implements IStorageService {\n private observedItemsMap: Map<string, Set<() => void>> = new Map();\n\n constructor() {\n window.addEventListener('storage', (e) => this.handleStorageChange(e));\n }\n\n public addItem(storageKey: string, storageValue: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).setItem(storageKey, storageValue);\n this.fireCallbacks(storageKey);\n }\n\n public getItem(storageKey: string, options: StorageServiceOptions = {}): string | null {\n return this.getStorage(options).getItem(storageKey);\n }\n\n public removeItem(storageKey: string, options: StorageServiceOptions = {}) {\n this.getStorage(options).removeItem(storageKey);\n }\n\n public observeItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.add(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public unobserveItem(storageKey: string, callback: () => void) {\n const keyCallbacks = this.getKeyCallbacks(storageKey);\n keyCallbacks.delete(callback);\n this.observedItemsMap.set(storageKey, keyCallbacks);\n }\n\n public clearStorage(storageType: StorageType) {\n this.getStorage({ storageType }).clear();\n }\n\n private handleStorageChange(e: StorageEvent) {\n const storageKey = e.key;\n const oldValue = e.oldValue;\n const newValue = e.newValue;\n if (storageKey === null || oldValue === newValue || !this.observedItemsMap.has(storageKey)) return;\n\n this.fireCallbacks(storageKey);\n }\n\n private getKeyCallbacks(storageKey: string): Set<() => void> {\n return this.observedItemsMap.get(storageKey) || new Set();\n }\n\n private fireCallbacks(storageKey: string) {\n const callbacks = this.getKeyCallbacks(storageKey);\n callbacks.forEach((callback) => callback());\n }\n\n private getStorage(options: StorageServiceOptions): Storage {\n const { storageType = 'local' } = options;\n return storageType === 'local' ? localStorage : sessionStorage;\n }\n}\n\nexport const StorageService = new StorageServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { StorageServiceOptions, StorageService, IStorageService } from '../StorageService';\nimport { ICachingService } from './CachingService.interface';\nimport { CacheItem, CacheOptions, CachingServiceConstructorOptions } from './CachingService.types';\n\nexport class CachingServiceImpl implements ICachingService {\n private runtimeCache: Map<string, string> = new Map();\n private storageService: IStorageService = StorageService;\n private storageKeyPrefix = 'kl-caching-service';\n\n constructor(options?: CachingServiceConstructorOptions) {\n const { storageService, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n protected get shouldCache(): boolean {\n return true;\n }\n\n public cacheValue(key: string, value: string, options: CacheOptions) {\n if (this.shouldCache === false) return;\n\n if (options.validFor === 0) {\n this.runtimeCache.set(this.getStorageKey(key), value);\n return;\n }\n\n const cacheItem: CacheItem = {\n value,\n validUntil: Date.now() + options.validFor,\n };\n\n this.storageService.addItem(\n this.getStorageKey(key),\n JSON.stringify(cacheItem),\n this.getStorageServiceOptions(options),\n );\n }\n\n public getCachedValue(key: string, cacheOptions?: CacheOptions): string | null {\n if (this.shouldCache === false) return null;\n\n const storageKey = this.getStorageKey(key);\n\n const runtimeValue = this.runtimeCache.get(storageKey);\n\n if (runtimeValue !== undefined) return runtimeValue;\n\n const cachedItemString = this.storageService.getItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n if (cachedItemString === null) return null;\n\n try {\n const cachedItem: CacheItem = JSON.parse(cachedItemString);\n if (cachedItem.validUntil < Date.now()) {\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n\n return cachedItem.value;\n } catch (e) {\n DebuggerService.warn('CachingService: ', e);\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n return null;\n }\n }\n\n public getCachedJSON<T>(key: string, cacheOptions?: CacheOptions): T | null {\n const cachedValue = this.getCachedValue(key, cacheOptions);\n if (cachedValue === null) return null;\n try {\n return JSON.parse(cachedValue);\n } catch (error) {\n DebuggerService.error('CachingService: ', error);\n return null;\n }\n }\n\n public clearCachedValue(key: string, cacheOptions?: CacheOptions) {\n const storageKey = this.getStorageKey(key);\n\n if (cacheOptions?.validFor === 0) {\n this.runtimeCache.delete(storageKey);\n return;\n }\n\n this.storageService.removeItem(storageKey, this.getStorageServiceOptions(cacheOptions));\n }\n\n private getStorageServiceOptions(cacheOptions?: CacheOptions): StorageServiceOptions {\n return {\n storageType: cacheOptions?.storageType,\n };\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const CachingService = new CachingServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { IStorageService, StorageService, StorageType } from '../StorageService';\nimport { IRequestCachingService } from './RequestCachingService.interface';\nimport { RequestCacheOptions, RequestCachingServiceConstructorOptions } from './RequestCachingService.types';\n\nexport class RequestCachingServiceImpl implements IRequestCachingService {\n private _cache?: Promise<Cache>;\n\n private storageService: IStorageService = StorageService;\n private requestCacheName = 'kl-request-cache';\n private storageKeyPrefix = 'kl-request-caching-service';\n\n constructor(options?: RequestCachingServiceConstructorOptions) {\n const { storageService, requestCacheName, storageKeyPrefix } = options ?? {};\n\n if (storageService !== undefined) {\n this.storageService = storageService;\n }\n\n if (requestCacheName !== undefined) {\n this.requestCacheName = requestCacheName;\n }\n\n if (storageKeyPrefix !== undefined) {\n this.storageKeyPrefix = storageKeyPrefix;\n }\n }\n\n private async getCache(): Promise<Cache | null> {\n try {\n if (this._cache === undefined) {\n this._cache = caches.open(this.requestCacheName);\n }\n return await this._cache;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async getCachedResponse(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return null;\n\n const response = await cache.match(request);\n if (response === undefined) return null;\n\n const validUntil = this.storageService.getItem(this.getStorageKey(request.url), { storageType: storage });\n if (validUntil === null) {\n await cache.delete(request);\n return null;\n }\n\n const now = Date.now();\n if (now > parseInt(validUntil, 10)) {\n await cache.delete(request);\n return null;\n }\n return response;\n }\n\n public async getCachedJSON<T>(request: Request, storage?: StorageType) {\n const response = await this.getCachedResponse(request, storage);\n if (response === null) return null;\n try {\n return (await response.json()) as T;\n } catch (error) {\n DebuggerService.error('RequestCachingService: ', error);\n return null;\n }\n }\n\n public async cacheRequest(options: RequestCacheOptions) {\n const { request, response } = options;\n const cache = await this.getCache();\n if (cache === null) return;\n this.storeExpirationTime(options);\n await cache.put(request, response);\n }\n\n public async clearCachedRequest(request: Request, storage?: StorageType) {\n const cache = await this.getCache();\n if (cache === null) return;\n await cache.delete(request);\n this.storageService.removeItem(this.getStorageKey(request.url), { storageType: storage });\n }\n\n private storeExpirationTime(options: RequestCacheOptions) {\n const { request, maxAge } = options;\n const validUntil = Date.now() + maxAge;\n this.storageService.addItem(this.getStorageKey(request.url), validUntil.toString(), {\n storageType: options.storage,\n });\n }\n\n private getStorageKey(key: string) {\n return `${this.storageKeyPrefix}_${key}`;\n }\n}\n\nexport const RequestCachingService = new RequestCachingServiceImpl();\n","import { CacheOptions, ICachingService } from '../CachingService';\nimport { IRequestCachingService } from '../RequestCachingService';\n\nexport interface APIServiceCacheOptions extends CacheOptions {\n forceRefetch?: boolean;\n requestBasedCaching?: boolean;\n cacheKeys?: string[];\n}\n\nexport interface APIServiceRequestOptions {\n fetchOptions?: RequestInit;\n cacheOptions?: APIServiceCacheOptions;\n throwError?: boolean;\n}\n\nexport interface APIServiceConstructorOptions {\n cachingService?: ICachingService;\n requestCachingService?: IRequestCachingService;\n}\n\nexport class APIError extends Error {\n public response: Response;\n\n constructor(response: Response) {\n super(response.statusText);\n this.response = response;\n }\n}\n","import { appendQueryObject } from \"@kluntje/js-utils/lib/url-helpers\";\n\nimport DebuggerService from \"../DebuggerService\";\nimport { IRequestCachingService, RequestCachingService } from \"../RequestCachingService\";\nimport { CachingService, ICachingService } from \"../CachingService\";\n\nimport { APIError, APIServiceCacheOptions, APIServiceConstructorOptions, APIServiceRequestOptions } from \"./APIService.types\";\nimport { IAPIService } from \"./APIService.interface\";\n\nexport class APIServiceImpl implements IAPIService {\n private requestPipeline: Map<string, Promise<Response | null>> = new Map();\n\n private cachingService: ICachingService = CachingService;\n private requestCachingService: IRequestCachingService = RequestCachingService;\n\n constructor(options: APIServiceConstructorOptions = {}) {\n const { cachingService, requestCachingService } = options;\n\n if (cachingService !== undefined) this.cachingService = cachingService;\n if (requestCachingService !== undefined) this.requestCachingService = requestCachingService;\n }\n\n public async fetchJSON<T>(url: string, options: APIServiceRequestOptions = {}): Promise<T | null> {\n // eslint-disable-next-line prettier/prettier\n return await this.fetch(url, APIServiceImpl.getJSON<T>, options);\n }\n\n public async fetchHTML(url: string, options: APIServiceRequestOptions = {}): Promise<string | null> {\n return await this.fetch(url, APIServiceImpl.getHTML, options);\n }\n\n private async fetch<T>(\n url: string,\n dataMapper: (response: Response | null) => Promise<T>,\n options: APIServiceRequestOptions = {},\n ): Promise<T | null> {\n const { cacheOptions } = options;\n\n if (cacheOptions?.forceRefetch === true) {\n this.clearCachedValue(url, cacheOptions);\n }\n\n const cachedValue = await this.getCachedValue<T>(url, cacheOptions);\n if (cachedValue !== null) return cachedValue;\n\n try {\n const pipelineRequest = this.requestPipeline.get(url);\n if (pipelineRequest !== undefined) {\n return await dataMapper(await pipelineRequest);\n }\n\n const request = this.fetchData(url, options);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n const responseData = await dataMapper(response);\n this.requestPipeline.delete(url);\n\n if (response === null || responseData === null) return null;\n\n if (cacheOptions === undefined) return responseData;\n await this.cacheResponse(url, response, responseData, cacheOptions);\n\n return responseData;\n } catch (error) {\n DebuggerService.error(\"APIService.fetch: \", error);\n this.requestPipeline.delete(url);\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n public async fetchResponse(url: string, options: APIServiceRequestOptions = {}): Promise<Response | null> {\n const { cacheOptions } = options;\n const { forceRefetch = false } = cacheOptions ?? {};\n\n if (forceRefetch === true) {\n await this.requestCachingService.clearCachedRequest(new Request(url), cacheOptions?.storageType ?? \"session\");\n }\n\n const cachedResponse = await this.requestCachingService.getCachedResponse(\n new Request(url),\n cacheOptions?.storageType ?? \"session\",\n );\n\n if (cachedResponse !== null) return cachedResponse;\n\n const pipelineRequest = this.requestPipeline.get(url);\n\n if (pipelineRequest !== undefined) {\n return await pipelineRequest;\n }\n\n try {\n const request = fetch(url, options.fetchOptions);\n this.requestPipeline.set(url, request);\n\n const response = await request;\n this.requestPipeline.delete(url);\n\n if (cacheOptions === undefined) return response;\n\n await this.requestCachingService.cacheRequest({\n request: new Request(url),\n response,\n storage: cacheOptions.storageType ?? \"session\",\n maxAge: cacheOptions.validFor,\n });\n\n return response;\n } catch (error) {\n DebuggerService.error(\"APIService.fetchResponse: \", error);\n\n this.requestPipeline.delete(url);\n\n if (options.throwError === true) throw error;\n return null;\n }\n }\n\n private async fetchData(url: string, options: APIServiceRequestOptions): Promise<Response | null> {\n const response = await fetch(url, options.fetchOptions);\n\n if (!response.ok) throw new APIError(response);\n if (response.status === 204) return null;\n\n return response;\n }\n\n private static async getJSON<T>(response: Response | null): Promise<T | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.json();\n }\n\n private static async getHTML(response: Response | null): Promise<string | null> {\n if (response === null) return null;\n\n const responseClone = response.clone();\n return await responseClone.text();\n }\n\n private async cacheResponse<T>(\n url: string,\n response: Response,\n responseData: T,\n cacheOptions: APIServiceCacheOptions,\n ) {\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (cacheOptions.requestBasedCaching === true) {\n await this.requestCachingService.cacheRequest({\n request: new Request(cacheKey),\n response,\n storage: cacheOptions.storageType ?? \"local\",\n maxAge: cacheOptions.validFor,\n });\n } else {\n this.cachingService.cacheValue(cacheKey, JSON.stringify(responseData), cacheOptions);\n }\n }\n\n private async clearCachedValue(url: string, cacheOptions?: APIServiceCacheOptions) {\n if (cacheOptions === undefined) return;\n const { requestBasedCaching = false } = cacheOptions;\n const cacheKey = this.getCacheKey(url, cacheOptions);\n\n if (requestBasedCaching === true) {\n await this.requestCachingService.clearCachedRequest(new Request(cacheKey), cacheOptions.storageType);\n }\n this.cachingService.clearCachedValue(cacheKey, cacheOptions);\n }\n\n private async getCachedValue<T>(url: string, cacheOptions?: APIServiceCacheOptions): Promise<T | null> {\n if (cacheOptions === undefined) return null;\n const { requestBasedCaching = false } = cacheOptions;\n\n const cacheKey = this.getCacheKey(url, cacheOptions);\n if (requestBasedCaching === true) {\n return await this.requestCachingService.getCachedJSON(new Request(cacheKey), cacheOptions.storageType);\n }\n return this.cachingService.getCachedJSON(cacheKey, cacheOptions);\n }\n\n private getCacheKey(url: string, cacheOptions?: APIServiceCacheOptions): string {\n const cacheKeys = cacheOptions?.cacheKeys ?? [];\n if (cacheKeys.length === 0) return url;\n return appendQueryObject(url, { klCacheKeys: cacheKeys.join(\"_\") });\n }\n}\n\nexport const APIService = new APIServiceImpl();\n","import DebuggerService from '../DebuggerService';\nimport { APIService, APIServiceRequestOptions, IAPIService } from '../APIService';\nimport {\n AbortableRequestServiceConstructorOptions,\n AbortableRequestServiceOptions,\n} from './AbortableRequestService.types';\n\nexport class AbortableRequestService {\n private abortController = new AbortController();\n private abortOptions: AbortableRequestServiceOptions | null = null;\n private latestOptions: AbortableRequestServiceOptions | null = null;\n\n protected apiService: IAPIService = APIService;\n\n constructor(options: AbortableRequestServiceConstructorOptions = {}) {\n const { apiService } = options;\n\n if (apiService !== undefined) this.apiService = apiService;\n }\n\n public async fetchJSON<T>(options: AbortableRequestServiceOptions): Promise<T | null> {\n return await this.makeAbortableRequest<T>(options, this.apiService.fetchJSON.bind(this.apiService));\n }\n\n public async fetchResponse(options: AbortableRequestServiceOptions): Promise<Response | null> {\n return await this.makeAbortableRequest<Response>(options, this.apiService.fetchResponse.bind(this.apiService));\n }\n\n private async makeAbortableRequest<R>(\n options: AbortableRequestServiceOptions,\n fetcher: (url: string, options: APIServiceRequestOptions) => Promise<R | null>,\n ): Promise<R | null> {\n if (this.latestOptions !== null) {\n this.abortOptions = options;\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n this.latestOptions = options;\n\n try {\n const response = await fetcher(options.url, {\n cacheOptions: options.options?.cacheOptions,\n throwError: true,\n fetchOptions: {\n ...options.options?.fetchOptions,\n signal: this.abortController.signal,\n },\n });\n this.latestOptions = null;\n return response;\n } catch (error: any) {\n DebuggerService.error('AbortableRequestService.makeAbortableRequest: ', error);\n\n if (error.name === 'AbortError') return this.handleAbortError<R>(this.fetchJSON.bind(this));\n\n if (options.options?.throwError === true) throw error;\n\n return null;\n }\n }\n\n private async handleAbortError<R>(\n nextAction: (options: AbortableRequestServiceOptions) => Promise<R | null>,\n ): Promise<R | null> {\n const latestOptions = this.latestOptions || this.abortOptions;\n if (latestOptions === null) return null;\n this.abortOptions = null;\n this.latestOptions = null;\n return nextAction(latestOptions);\n }\n}\n","import { IObserverService } from './ObserverService.interface';\nimport { ObserverCallback } from './ObserverService.types';\n\nexport class ObserverServiceImpl implements IObserverService {\n private observerMap: Map<string, Set<ObserverCallback>> = new Map();\n\n public observe(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.add(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public unobserve(observedKey: string, callback: ObserverCallback) {\n const curCallbacks = this.getCallbacks(observedKey);\n curCallbacks.delete(callback);\n this.observerMap.set(observedKey, curCallbacks);\n }\n\n public notifyObservers<T>(observedKey: string, data?: T) {\n const callbacks = this.getCallbacks(observedKey);\n callbacks.forEach((callback) => callback(data));\n }\n\n private getCallbacks(observedKey: string): Set<ObserverCallback> {\n return this.observerMap.get(observedKey) || new Set();\n }\n}\n\nexport const ObserverService = new ObserverServiceImpl();\n","import { ObserverServiceImpl } from '../ObserverService';\n\nexport class ContextState<StateDefinition extends Record<string, any> = Record<string, any>> {\n private stateMap: Map<keyof StateDefinition, any> = new Map();\n private observerService = new ObserverServiceImpl();\n private contextName: string;\n private contextElement: HTMLElement;\n\n constructor(contextName: string, contextElement: HTMLElement) {\n this.contextName = contextName;\n this.contextElement = contextElement;\n }\n\n public get name(): string {\n return this.contextName;\n }\n\n public get element(): HTMLElement {\n return this.contextElement;\n }\n\n public isMatchingContext(contextName: string, consumingElement: HTMLElement): boolean {\n if (this.contextName !== contextName) return false;\n\n return this.contextElement.contains(consumingElement);\n }\n\n public setState<K extends keyof StateDefinition>(key: K, value: StateDefinition[K]): void {\n if (this.stateMap.get(key) === value) return;\n this.stateMap.set(key, value);\n this.observerService.notifyObservers(key as string);\n }\n\n public getState<K extends keyof StateDefinition>(key: K): StateDefinition[K] | undefined {\n return this.stateMap.get(key);\n }\n\n public observeState(key: keyof StateDefinition, callback: () => void): void {\n this.observerService.observe(key as string, callback);\n }\n\n public unobserveState(key: keyof StateDefinition, callback: () => void): void {\n this.observerService.unobserve(key as string, callback);\n }\n}\n","import { ContextState } from './ContextState';\nimport { ObserverServiceImpl } from '../ObserverService';\nimport { IContextStateService } from './ContextStateService.interface';\n\nexport class ContextStateServiceImpl implements IContextStateService {\n private contextStateMap: Map<string, ContextState[]> = new Map();\n private contextInitObserver = new ObserverServiceImpl();\n\n private getMatchingContextState(contextName: string, consumingElement: HTMLElement): ContextState | null {\n const contextList = this.contextStateMap.get(contextName) || [];\n const matchingContexts = contextList.filter((context) => context.isMatchingContext(contextName, consumingElement));\n if (matchingContexts.length === 0) return null;\n return matchingContexts[0];\n }\n\n public getContextState<StateDefinition extends Record<string, any>>(\n contextName: string,\n consumingElement: HTMLElement,\n ): Promise<ContextState<StateDefinition>> {\n const matchingContextState = this.getMatchingContextState(contextName, consumingElement);\n if (matchingContextState) return Promise.resolve(matchingContextState) as Promise<ContextState<StateDefinition>>;\n return new Promise<ContextState<StateDefinition>>((resolve) => {\n this.contextInitObserver.observe(contextName, () => {\n const contextState = this.getMatchingContextState(contextName, consumingElement);\n if (contextState) {\n resolve(contextState as ContextState<StateDefinition>);\n }\n });\n });\n }\n\n public createContextState<StateDefinition extends Record<string, any>>(\n contextName: string,\n contextElement: HTMLElement,\n ): ContextState<StateDefinition> {\n const contextState = new ContextState(contextName, contextElement);\n const contextList = this.contextStateMap.get(contextName) || [];\n contextList.push(contextState);\n this.contextStateMap.set(contextName, contextList);\n this.contextInitObserver.notifyObservers(contextName);\n return contextState as ContextState<StateDefinition>;\n }\n}\n\nexport const ContextStateService = new ContextStateServiceImpl();\n"],"names":["MQ_CHANGE_EVENT","IN_VP_EVENT","OUT_VP_EVENT","ViewportObserver","constructor","static","undefined","instance","IntersectionObserver","handleIntersectionChange","e","Object","keys","forEach","key","observedEl","target","isIntersecting","dispatchEvent","CustomEvent","bubbles","MediaQueryService","this","eventIdMap","WeakMap","eventBindingMap","lastMQ","getCurrentMQ","mediaQuerys","onEvent","window","handleMQChange","newMQ","detail","oldMQ","__decorate","throttle","resolveSymbol","Symbol","rejectSymbol","pendingSymbol","I18nService","PLACEHOLDER_SELECTOR","_instance","isSetUp","Boolean","_url","isFilledObject","_dictionary","loaded","_loaded","ready","_ready","fetchI18nDictionary","setUp","url","dictionary","console","warn","Error","get","fallback","interpolations","hasOwnProperty","result","entries","k","v","split","join","String","getHumanReadableName","addStyling","getPlaceholder","getReadyPromise","resolve","reject","Promise","res","rej","ensureSetup","head","document","style","createElement","type","appendChild","createTextNode","fetchJSON","then","results","fillInPlaceholders","catch","err","error","Array","from","getElementsByClassName","el","dataset","replaceWith","JSON","parse","reverse","replace","letter","toLowerCase","span","innerText","classList","add","setAttribute","stringify","outerHTML","URLSearchParams","location","search","param","urlSearchParams","getAll","getAllKeys","set","value","updateUrl","delete","getString","toString","curUrl","protocol","host","pathname","curQueryString","hashCache","hash","newUrl","history","replaceState","path","Proxy","prop","URLSearchParamsService","intersectionObserver","rootMargin","subscribe","intersectionCallback","componentMap","observe","unsubscribe","unobserve","intersectionEntry","has","StorageServiceImpl","Map","addEventListener","handleStorageChange","addItem","storageKey","storageValue","options","getStorage","setItem","fireCallbacks","getItem","removeItem","observeItem","callback","keyCallbacks","getKeyCallbacks","observedItemsMap","unobserveItem","clearStorage","storageType","clear","oldValue","newValue","Set","localStorage","sessionStorage","StorageService","CachingServiceImpl","storageService","storageKeyPrefix","shouldCache","cacheValue","validFor","runtimeCache","getStorageKey","cacheItem","validUntil","Date","now","getStorageServiceOptions","getCachedValue","cacheOptions","runtimeValue","cachedItemString","cachedItem","DebuggerService","getCachedJSON","cachedValue","clearCachedValue","CachingService","RequestCachingServiceImpl","requestCacheName","getCache","_cache","caches","open","getCachedResponse","request","storage","cache","response","match","parseInt","json","cacheRequest","storeExpirationTime","put","clearCachedRequest","maxAge","RequestCachingService","APIError","super","statusText","APIServiceImpl","cachingService","requestCachingService","fetch","fetchHTML","getHTML","dataMapper","forceRefetch","pipelineRequest","requestPipeline","fetchData","responseData","cacheResponse","throwError","fetchResponse","Request","cachedResponse","fetchOptions","ok","status","responseClone","clone","text","cacheKey","getCacheKey","requestBasedCaching","cacheKeys","length","appendQueryObject","klCacheKeys","APIService","AbortableRequestService","AbortController","apiService","makeAbortableRequest","bind","fetcher","latestOptions","abortOptions","abortController","abort","signal","name","handleAbortError","nextAction","ObserverServiceImpl","observedKey","curCallbacks","getCallbacks","observerMap","notifyObservers","data","ObserverService","ContextState","contextName","contextElement","element","isMatchingContext","consumingElement","contains","setState","stateMap","observerService","getState","observeState","unobserveState","ContextStateServiceImpl","getMatchingContextState","matchingContexts","contextStateMap","filter","context","getContextState","matchingContextState","contextInitObserver","contextState","createContextState","contextList","push","ContextStateService"],"mappings":"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"} |
+2
-2
| { | ||
| "name": "@kluntje/services", | ||
| "version": "0.8.0", | ||
| "version": "0.9.0", | ||
| "description": "Collection of useful services, when creating kluntje-components", | ||
@@ -28,3 +28,3 @@ "author": "Frederik Riewerts <frederik.riewerts@gmail.com>", | ||
| }, | ||
| "gitHead": "864d754bb4da3e8c2a52e9969a65544b3ebfe02e" | ||
| "gitHead": "3e524f72b4c55dcbef2d3b860b4e2e5d441e319c" | ||
| } |
+23
-1
@@ -430,3 +430,3 @@ # `@kluntje/services` | ||
| const stateValue = contextState.getState<string>("myStateItem"); | ||
| const stateValue = contextState.getState("myStateItem"); | ||
| ``` | ||
@@ -442,2 +442,24 @@ | ||
| #### Advanced Usage | ||
| For better type safety, it is possible to define a type for the state. | ||
| ```typescript | ||
| import { ContextStateService } from "@kluntje/services"; | ||
| interface MyStateDefinition { | ||
| myStateItem: string; | ||
| myOtherStateItem: number; | ||
| } | ||
| const contextState = ContextStateService.createContextState<MyStateDefinition>("my-context-state", this); | ||
| contextState.setState("myStateItem", "myStateValue"); | ||
| contextState.setState("myOtherStateItem", "myStateValue"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'. | ||
| contextState.setState("myOtherStateItem", 42); | ||
| const stringValue = contextState.getState("myStateItem"); // stateValue is of type string | ||
| const numberValue = contextState.getState("myOtherStateItem"); // stateValue is of type number | ||
| ``` | ||
| --- |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
207570
1.31%464
4.98%