{"version":3,"file":"bespunky-angular-zen-async.mjs","sources":["../../../../libs/angular-zen/async/src/async.module.ts","../../../../libs/angular-zen/async/src/lazy-loader/lazy-loader.service.ts","../../../../libs/angular-zen/async/src/utils/promiseLater.ts","../../../../libs/angular-zen/async/src/bespunky-angular-zen-async.ts"],"sourcesContent":["import { NgModule } from '@angular/core';\n\nimport { CoreModule } from '@bespunky/angular-zen/core';\nimport { UniversalModule } from '@bespunky/angular-zen/universal';\n\n@NgModule({\n    declarations: [],\n    imports: [ CoreModule, UniversalModule ],\n    exports: [ CoreModule ]\n})\nexport class AsyncModule { }\n","import { Observable, of } from 'rxjs';\nimport { Injectable, ElementRef } from '@angular/core';\n\nimport { HeadService       } from '@bespunky/angular-zen/core';\nimport { UniversalService  } from '@bespunky/angular-zen/universal';\nimport { ScriptLoadOptions } from './script-load-options';\nimport { LoadOptions       } from './load-options';\nimport { LazyLoadedFile    } from './lazy-loaded-file';\n\ntype ElementCreator = (url: string, onLoad: () => void, onError: (error: any) => void, options: LoadOptions) => ElementRef;\n\n/**\n * Provides methods for lazy loading scripts and styles programatically.\n * The service keeps track of loaded files to skip reloading unless specified otherwise in the options of `loadScript()` or `loadStyle()`.\n */\n@Injectable({\n    providedIn: 'root'\n})\nexport class LazyLoaderService\n{\n    /**\n     * Defines the default options when calling the `LazyLoaderService.loadScript()` method.\n     */\n    private defaultScriptOptions: ScriptLoadOptions = {\n        async: true,\n        defer: true,\n        alreadyLoaded: (url) => this.isCached(url) || this.isScriptPresent(url),\n        force: false\n    };\n\n     /**\n     * Defines the default options when calling the `LazyLoaderService.loadStyle()` method.\n     */\n    private defaultStyleOptions: LoadOptions = {\n        alreadyLoaded: (url) => this.isCached(url) || this.isStylePresent(url),\n        force: false\n    };\n\n    /**\n     * Keeps track of loaded lazy files status and references\n     */\n    private cache: { [url: string]: { lazyFile: LazyLoadedFile, observable: Observable<LazyLoadedFile> } };\n\n    constructor(private head: HeadService, private universal: UniversalService)\n    {\n        this.cache = {};\n    }\n\n    /**\n     * Checks whether the file from the specified url has already been cached.\n     * @param url The url for the file to check.\n     * @returns A value indicating whether the file from the specified url has already been cached.\n     */\n    public isCached(url: string): boolean\n    {\n        return !!this.cache[url];\n    }\n\n    /**\n     * Checks whether a script element is already present in `<head>` for the given url.\n     * This doesn't guarantee that the script has been loaded.\n     * \n     * @param {string} url The url of the loaded script.\n     * @returns {boolean} `true` if an element matching the url is present in `<head>`; otherwise `false.\n     */\n    public isScriptPresent(url: string): boolean\n    {\n        return this.head.contains('script', { src: url });\n    }\n\n    /**\n     * Checks whether a link element is already present in `<head>` for the given style url.\n     * This doesn't guarantee that the style has been loaded.\n     * \n     * @param {string} url The url of the loaded link.\n     * @returns {boolean} `true` if an element matching the url is present in `<head>`; otherwise `false.\n     */\n    public isStylePresent(url: string): boolean\n    {\n        return this.head.contains('link', { rel: 'stylesheet', href: url });\n    }\n\n    /**\n     * Loads a script programatically.\n     *\n     * @param url The full url of the script to load.\n     * @param options (Optional) Specifies custom options to override default behaviour.\n     * @returns An observable object which allows subscribers to know when the script has been loaded and access its associated `<script>` element.\n     *          The observable will complete immediately in case the script was already previously loaded.\n     *          If the script was already loaded outside of the service, the observable will stream `undefined`.\n     */\n    public loadScript(url: string, options: ScriptLoadOptions = this.defaultScriptOptions): Observable<LazyLoadedFile | null>\n    {\n        // Set default options if not specified by caller\n        options.async         = options.async         === undefined ? this.defaultScriptOptions.async : options.async;\n        options.defer         = options.defer         === undefined ? this.defaultScriptOptions.defer : options.defer;\n        options.alreadyLoaded = options.alreadyLoaded === undefined ? this.defaultScriptOptions.alreadyLoaded : options.alreadyLoaded;\n        options.force         = options.force         === undefined ? this.defaultScriptOptions.force : options.force;          \n\n        return this.loadFile(url, 'script', options as Required<ScriptLoadOptions>, this.createScriptElement.bind(this));\n    }\n\n    /**\n     * Loads a style programatically.\n     *\n     * @param url The full url of the style to load.\n     * @param options (Optional) Specifies custom options to override default behaviour.\n     * @returns An observable object which allows subscribers to know when the style has been loaded and access its associated `<link>` element.\n     *          The observable will complete immediately in case the style was already previously loaded.\n     *          If the style was already loaded outside of the service, the observable will stream `undefined`.\n     */\n    public loadStyle(url: string, options: LoadOptions = this.defaultStyleOptions): Observable<LazyLoadedFile | null>\n    {\n        // Set default options if not specified by caller\n        options.alreadyLoaded = options.alreadyLoaded === undefined ? this.defaultStyleOptions.alreadyLoaded : options.alreadyLoaded;\n        options.force         = options.force         === undefined ? this.defaultStyleOptions.force : options.force;\n\n        return this.loadFile(url, 'style', options as Required<LoadOptions>, this.createLinkElement.bind(this));\n    }\n\n    private loadFile(url: string, type: 'script' | 'style', options: Required<LoadOptions>, createElement: ElementCreator): Observable<LazyLoadedFile | null>\n    {\n        if (!this.universal.isPlatformBrowser) return of(null);\n\n        // If the script should be loaded, load it\n        if (!options.alreadyLoaded(url) || options.force)\n        {\n            // Initialize a base object to store the data later\n            const lazyFile: LazyLoadedFile = { url, type, completed: false, element: null };\n            // Create an observable that waits until the script has been loaded and executed\n            const observable = new Observable<LazyLoadedFile>(observer =>\n            {\n                // Create the callback that will mark the script as completed and notify the subscriber\n                const onLoad = () =>\n                {\n                    lazyFile.completed = true;\n\n                    observer.next(lazyFile);\n                    observer.complete();\n                };\n\n                // Create the actual file tag, start downloading and store the element reference\n                lazyFile.element = createElement(url, onLoad, observer.error.bind(observer), options);\n            });\n\n            // Cache the file and the observable for later use\n            this.cache[url] = { lazyFile: lazyFile, observable };\n\n            return observable;\n        }\n\n        // If the file was already loaded and it shouldn't be downloaded again, complete immediately with the previous link data.\n        // If the file was already loaded outside of the service, the observable will stream `undefined` as there is nothing cached.\n        return of(this.cache[url]?.lazyFile);\n    }\n\n    /**\n     * Creates a `<script>` tag for the given url and adds it to the `<head>` tag to start downloading the script.\n     *\n     * @param url       The url for the script to download.\n     * @param onLoad    The callback to execute when the script has been downloaded and executed.\n     * @param onError   The callback to execute when script download or execution has failed.\n     * @param options   The options to add to the script.\n     * @returns A reference to the `<script>` element that was added to the DOM.\n     */\n    private createScriptElement(url: string, onLoad: () => void, onError: (error: any) => void, options: ScriptLoadOptions): ElementRef<HTMLScriptElement>\n    {\n        return this.head.addScriptElement('text/javascript', url,\n            {\n                async: options.async,\n                defer: options.defer,\n                onload: onLoad,\n                onerror: onError\n            });\n    }\n\n    /**\n     * Creates a `<link>` tag for the given url and adds it to the `<head>` tag to start downloading the link.\n     *\n     * @param url       The url for the link to download.\n     * @param onLoad    The callback to execute when the script has been downloaded and executed.\n     * @param onError   The callback to execute when script download or execution has failed.\n     * @returns A reference to the `<link>` element that was added to the DOM.\n     */\n    private createLinkElement(url: string, onLoad: () => void, onError: (error: any) => void): ElementRef<HTMLLinkElement>\n    {\n        return this.head.addLinkElement('stylesheet',\n            {\n                type: 'text/css',\n                href: url,\n                onload: onLoad,\n                onerror: onError\n            });\n    }\n}\n","type LatePromise<T> = {\n    promise: Promise<T>;\n    resolve: (value: T | PromiseLike<T>) => void;\n    reject : (reason?: any) => void;\n};\n\n/**\n * Creates a promise without which doesn't have the actual async code to resolve, and extracts its `resolve()` and `reject()` methods for later use.\n * Use this when you have to create a promise for an async code that runs in a place different to the one where you create the promise, and it will\n * allow you full control of the promise from other parts of your code.\n *\n * @example\n * import { promiseLater } from '@bespunky/angular-zen/core';\n * // Other imports...\n *\n * export class SomeDirective implements OnInit, OnChanges\n * {\n *     private const waitForInit: Promise<SomeType>;\n *\n *     constructor()\n *     {\n *         this.waitForInit = promiseLater();\n *     }\n *\n *     ngOnInit()\n *     {\n *         this.waitForInit.resolve();\n *     }\n *\n *     ngOnChanges(changes: SimpleChanges)\n *     {\n *         this.waitForInit.promise.then(() => {\n *             // ... Some code\n *         });\n *     }\n * }\n *\n * @export\n * @template T The type of the value promised after resolving the async operation.\n * @returns An object containing the promise, anlong with its `resolve()` and `reject()` methods.\n */\nexport function promiseLater<T>(): LatePromise<T>\n{\n    const latePromise: Partial<LatePromise<T>> = { };\n\n    const promise = new Promise<T>((resolve, reject) =>\n    {\n        latePromise.resolve = resolve;\n        latePromise.reject  = reject;\n    });\n\n    latePromise.promise = promise;\n\n    return latePromise as LatePromise<T>;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}