UNPKG

@berry-cloud/ngx-unsplash

Version:

Lightweight Angular wrapper for the Unsplash API.

616 lines 79.8 kB
import { HttpHeaders, HttpParams } from '@angular/common/http'; import { Inject, Injectable, InjectionToken } from '@angular/core'; import { Observable, of } from 'rxjs'; import { map, mergeMap, tap } from 'rxjs/operators'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common/http"; export const UNSPLASH_CONFIG = new InjectionToken('unsplash.config'); class UnsplashService { constructor(http, config) { this.http = http; this.searchUrl = 'search/photos'; this.photosUrl = 'photos'; this.randomUrl = 'photos/random'; this.collectionsUrl = 'collections'; this.topicsUrl = 'topics'; this.usersUrl = 'users'; const config$ = config instanceof Observable ? config : of(config); this.config$ = config$.pipe(tap((config) => { if (!config) { throw new Error('Unsplash configuration undefined'); } if (!config.url) { throw new Error('Unsplash configuration url undefined'); } if (!config.authorization) { throw new Error('Unsplash configuration authorization undefined'); } })); } /** * [List photos](https://unsplash.com/documentation#list-photos). * * Get a single page from the list of all photos. * * @param options to be used when getting list of photos * * @returns Observable containing a {@link Photo} array */ photos(options) { return this.config$.pipe(mergeMap((config) => { let params = new HttpParams(); if (options?.page) { params = params.set('page', options.page.toString()); } if (options?.perPage) { params = params.set('per_page', options.perPage.toString()); } if (options?.orderBy) { params = params.set('order_by', options.orderBy); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(this.photosUrl, config); return this.http.get(url, { params, headers }); })); } /** * [List photos](https://unsplash.com/documentation#list-photos). * * Get a single page from the list of all photos. * * @param options to be used when getting list of photos * * @returns Observable containing a {@link Photo} array * * @deprecated Use {@link photos} instead */ list(options) { return this.photos(options); } /** * [Get a photo](https://unsplash.com/documentation#get-a-photo). * * Retrieve a single photo. * * @param id of the photo * * @returns Observable containing the {@link Photo} */ photo(id) { return this.config$.pipe(mergeMap((config) => { const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.photosUrl}/${id}`, config); return this.http.get(url, { headers }); })); } /** * [Get a photo](https://unsplash.com/documentation#get-a-photo). * * Retrieve a single photo. * * @param id of the photo * * @returns Observable containing the {@link Photo} * * @deprecated Use {@link photo} instead */ get(id) { return this.photo(id); } /** * [Get random photos](https://unsplash.com/documentation#get-a-random-photo). * * Retrieve random photos. * * @param options to be used when getting random photos * * @returns Observable containing a {@link Photo} array */ randomPhoto(options) { return this.config$.pipe(mergeMap((config) => { let params = new HttpParams(); if (options?.collections) { params = params.set('collections', options?.collections); } if (options?.topics) { params = params.set('topics', options?.topics); } if (options?.username) { params = params.set('username', options?.username); } if (options?.query) { params = params.set('query', options?.query); } if (options?.orientation) { params = params.set('orientation', options?.orientation); } if (options?.contentFilter) { params = params.set('content_filter', options?.contentFilter); } if (options?.count) { params = params.set('count', options?.count); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(this.randomUrl, config); return this.http.get(url, { params, headers }); })); } /** * [Get random photos](https://unsplash.com/documentation#get-a-random-photo). * * Retrieve random photos. * * @param options to be used when getting random photos * * @returns Observable containing a {@link Photo} array * * @deprecated Use {@link randomPhoto} instead */ random(options) { return this.randomPhoto(options); } /** * [Search photos](https://unsplash.com/documentation#search-photos). * * Get a single page of photo results for a query. * * @param query to search for * @param options to be used when searching photos * * @returns Observable containing a {@link SearchResult} */ searchPhotos(query, options) { return this.config$.pipe(mergeMap((config) => { let params = new HttpParams().set('query', query); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } if (options?.collections) { params = params.set('collections', options?.collections); } if (options?.contentFilter) { params = params.set('content_filter', options?.contentFilter); } if (options?.color) { params = params.set('color', options?.color); } if (options?.orientation) { params = params.set('orientation', options?.orientation); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(this.searchUrl, config); return this.http.get(url, { headers, params }); })); } /** * [Search photos](https://unsplash.com/documentation#search-photos). * * Get a single page of photo results for a query. * * @param query to search for * @param options to be used when searching photos * * @returns Observable containing a {@link SearchResult} * * @deprecated Use {@link searchPhotos} instead */ search(query, options) { return this.searchPhotos(query, options); } /** * [Trigger a download](https://help.unsplash.com/en/articles/2511258-guideline-triggering-a-download) * of a photo. * * @param photo to download * * @returns Observable containing the {@link Download} */ downloadPhoto(photo) { return this.config$.pipe(mergeMap((config) => { const headers = this.unsplashHeaders(config); const photoUrl = new URL(photo.links.download_location); // Remove the leading slash from the pathname and add the search const url = this.unsplashUrl(photoUrl.pathname.substring(1) + photoUrl.search, config); return this.http.get(url, { headers }); })); } /** * [Trigger a download](https://help.unsplash.com/en/articles/2511258-guideline-triggering-a-download) * of a photo. * * @param photo to download * * @returns Observable containing the {@link Download} * * @deprecated Use {@link downloadPhoto} instead */ download(photo) { return this.downloadPhoto(photo); } /** * [List collections](https://unsplash.com/documentation#list-collections). * Retrieve a list of collections. * * @param options to be used when getting collections * * @returns Observable containing a {@link Collection} array * * @throws Error if the Unsplash configuration is not provided */ collections(options) { return this.config$.pipe(mergeMap((config) => { let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(this.collectionsUrl, config); return this.http.get(url, { headers, params }); })); } /** * [Get a collection](https://unsplash.com/documentation#get-a-collection). * Retrieve a single collection. * * @param id of the collection to retrieve * * @returns Observable containing a {@link Collection} * * @throws Error if the collection id is not provided * @throws Error if the Unsplash configuration is not provided */ collection(id) { return this.config$.pipe(mergeMap((config) => { if (!id) { throw new Error('Collection id undefined'); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.collectionsUrl}/${id}`, config); return this.http.get(url, { headers }); })); } /** * [Get a collection's photos](https://unsplash.com/documentation#get-a-collections-photos). * Retrieve a list of photos in a collection. * * @param id of the collection to retrieve photos from * @param options to be used when getting photos from a collection * * @returns Observable containing a {@link Photo} array * * @throws Error if the collection id is not provided * @throws Error if the Unsplash configuration is not provided */ collectionPhotos(id, options) { return this.config$.pipe(mergeMap((config) => { if (!id) { throw new Error('Collection id undefined'); } let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orientation) { params = params.set('orientation', options?.orientation); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.collectionsUrl}/${id}/photos`, config); return this.http.get(url, { headers, params }); })); } /** * [List related collections](https://unsplash.com/documentation#list-a-collections-related-collections). * Retrieve a list of collections related to a particular one. * * @param id of the collection to retrieve related collections from * * @returns Observable containing a {@link Collection} array * * @throws Error if the collection id is not provided * @throws Error if the Unsplash configuration is not provided */ relatedCollections(id) { return this.config$.pipe(mergeMap((config) => { if (!id) { throw new Error('Collection id undefined'); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.collectionsUrl}/${id}/related`, config); return this.http.get(url, { headers }); })); } /** * [List topics](https://unsplash.com/documentation#list-topics). * Retrieve a list of topics. * * @param options to be used when getting topics * * @returns Observable containing a {@link Topic} array */ topics(options) { return this.config$.pipe(mergeMap((config) => { let params = new HttpParams(); if (options?.ids) { params = params.set('ids', options?.ids.join(',')); } if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(this.topicsUrl, config); return this.http.get(url, { headers, params }); })); } /** * [Get a topic](https://unsplash.com/documentation#get-a-topic). * Retrieve a single topic. * * @param id of the topic to retrieve * * @returns Observable containing a {@link Topic} * * @throws Error if the topic id is not provided * @throws Error if the Unsplash configuration is not provided */ topic(id) { return this.config$.pipe(mergeMap((config) => { if (!id) { throw new Error('Topic id undefined'); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.topicsUrl}/${id}`, config); return this.http.get(url, { headers }); })); } /** * [Get a topic's photos](https://unsplash.com/documentation#get-a-topics-photos). * Retrieve a list of photos in a topic. * * @param id of the topic to retrieve photos from * @param options to be used when getting photos from a topic * * @returns Observable containing a {@link Photo} array * * @throws Error if the topic id is not provided * @throws Error if the Unsplash configuration is not provided */ topicPhotos(id, options) { return this.config$.pipe(mergeMap((config) => { if (!id) { throw new Error('Topic id undefined'); } let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orientation) { params = params.set('orientation', options?.orientation); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.topicsUrl}/${id}/photos`, config); return this.http.get(url, { headers, params }); })); } /** * [Get a user](https://unsplash.com/documentation#get-a-user). * Retrieve public details on a given user. * * @param username of the user to retrieve * * @returns Observable containing a {@link User} * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ user(username) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}`, config); return this.http.get(url, { headers }); })); } /** * [Get a user's portfolio link](https://unsplash.com/documentation#get-a-users-portfolio-link). * Retrieve a single user’s portfolio link. * * @param username of the user to retrieve portfolio link from * * @returns Observable containing a {@link User} * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ userPortfolio(username) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}/portfolio`, config); return this.http.get(url, { headers }); }), map((response) => response.url)); } /** * [List a user’s photos](https://unsplash.com/documentation#list-a-users-photos). * Retrieve a list of photos uploaded by a user. * * @param username of the user to retrieve photos from * @param options to be used when getting photos from a user * * @returns Observable containing a {@link Photo} array * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ userPhotos(username, options) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } if (options?.stats) { params = params.set('stats', options?.stats); } if (options?.resolution) { params = params.set('resolution', options?.resolution); } if (options?.quantity) { params = params.set('quantity', options?.quantity); } if (options?.orientation) { params = params.set('orientation', options?.orientation); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}/photos`, config); return this.http.get(url, { headers, params }); })); } /** * [List a user’s liked photos](https://unsplash.com/documentation#list-a-users-liked-photos). * Retrieve a list of photos liked by a user. * * @param username of the user to retrieve liked photos from * @param options to be used when getting liked photos from a user * * @returns Observable containing a {@link Photo} array * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ userLikes(username, options) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}/likes`, config); return this.http.get(url, { headers, params }); })); } /** * [List a user’s collections](https://unsplash.com/documentation#list-a-users-collections). * Retrieve a list of collections created by the user. * * @param username of the user to retrieve collections from * @param options to be used when getting collections from a user * * @returns Observable containing a {@link Collection} array * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ userCollections(username, options) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } let params = new HttpParams(); if (options?.page) { params = params.set('page', options?.page); } if (options?.perPage) { params = params.set('per_page', options?.perPage); } if (options?.orderBy) { params = params.set('order_by', options?.orderBy); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}/collections`, config); return this.http.get(url, { headers, params }); })); } /** * [Get a user’s statistics](https://unsplash.com/documentation#get-a-users-statistics). * Retrieve total number of downloads, views and likes of all user’s photos, as well as the historical breakdown and average of these stats in a specific time frame (default is 30 days). * * @param username of the user to retrieve statistics from * @param options to be used when getting statistics from a user * * @returns Observable containing a {@link UserStatistics} object * * @throws Error if the user username is not provided * @throws Error if the Unsplash configuration is not provided */ userStatistics(username, options) { return this.config$.pipe(mergeMap((config) => { if (!username) { throw new Error('User username undefined'); } let params = new HttpParams(); if (options?.resolution) { params = params.set('resolution', options?.resolution); } if (options?.quantity) { params = params.set('quantity', options?.quantity); } const headers = this.unsplashHeaders(config); const url = this.unsplashUrl(`${this.usersUrl}/${username}/statistics`, config); return this.http.get(url, { headers, params }); })); } unsplashUrl(url, config) { return new URL(url, config.url.endsWith('/') ? config.url : config.url + '/').toString(); } unsplashHeaders(config) { return new HttpHeaders().set('authorization', config.authorization); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.9", ngImport: i0, type: UnsplashService, deps: [{ token: i1.HttpClient }, { token: UNSPLASH_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.9", ngImport: i0, type: UnsplashService, providedIn: 'root' }); } } export { UnsplashService }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.9", ngImport: i0, type: UnsplashService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: undefined, decorators: [{ type: Inject, args: [UNSPLASH_CONFIG] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5zcGxhc2guc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC11bnNwbGFzaC9zcmMvbGliL3Vuc3BsYXNoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFjLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMzRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7OztBQXVCcEQsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLElBQUksY0FBYyxDQUUvQyxpQkFBaUIsQ0FBQyxDQUFDO0FBUXJCLE1BR2EsZUFBZTtJQVUxQixZQUNVLElBQWdCLEVBRXhCLE1BQW1EO1FBRjNDLFNBQUksR0FBSixJQUFJLENBQVk7UUFWVCxjQUFTLEdBQUcsZUFBZSxDQUFDO1FBQzVCLGNBQVMsR0FBRyxRQUFRLENBQUM7UUFDckIsY0FBUyxHQUFHLGVBQWUsQ0FBQztRQUM1QixtQkFBYyxHQUFHLGFBQWEsQ0FBQztRQUMvQixjQUFTLEdBQUcsUUFBUSxDQUFDO1FBQ3JCLGFBQVEsR0FBRyxPQUFPLENBQUM7UUFTbEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxZQUFZLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFbkUsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUN6QixHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNiLElBQUksQ0FBQyxNQUFNLEVBQUU7Z0JBQ1gsTUFBTSxJQUFJLEtBQUssQ0FB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QyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cEhlYWRlcnMsIEh0dHBQYXJhbXMgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBtZXJnZU1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQ29sbGVjdGlvbiB9IGZyb20gJy4vbW9kZWwvY29sbGVjdGlvbic7XG5pbXBvcnQgeyBEb3dubG9hZCB9IGZyb20gJy4vbW9kZWwvZG93bmxvYWQnO1xuaW1wb3J0IHsgUGhvdG8gfSBmcm9tICcuL21vZGVsL3Bob3RvJztcbmltcG9ydCB7IFNlYXJjaFJlc3VsdCB9IGZyb20gJy4vbW9kZWwvc2VhcmNoLXJlc3VsdCc7XG5pbXBvcnQgeyBVc2VyU3RhdGlzdGljcyB9IGZyb20gJy4vbW9kZWwvc3RhdGlzdGljcyc7XG5pbXBvcnQgeyBUb3BpYyB9IGZyb20gJy4vbW9kZWwvdG9waWMnO1xuaW1wb3J0IHtcbiAgVW5zcGxhc2hDb2xvcixcbiAgVW5zcGxhc2hDb250ZW50RmlsdGVyLFxuICBVbnNwbGFzaEZlYXR1cmVkT3JkZXJCeSxcbiAgVW5zcGxhc2hPcmRlckJ5LFxuICBVbnNwbGFzaE9yaWVudGF0aW9uLFxuICBVbnNwbGFzaFJlc29sdXRpb24sXG4gIFVuc3BsYXNoU2VhcmNoT3JkZXJCeSxcbn0gZnJvbSAnLi9tb2RlbC90eXBlcyc7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSAnLi9tb2RlbC91c2VyJztcblxuZXhwb3J0IGludGVyZmFjZSBVbnNwbGFzaENvbmZpZyB7XG4gIHVybDogc3RyaW5nO1xuICBhdXRob3JpemF0aW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBVTlNQTEFTSF9DT05GSUcgPSBuZXcgSW5qZWN0aW9uVG9rZW48XG4gIFVuc3BsYXNoQ29uZmlnIHwgT2JzZXJ2YWJsZTxVbnNwbGFzaENvbmZpZz5cbj4oJ3Vuc3BsYXNoLmNvbmZpZycpO1xuXG4vLyBwcmV0dGllci1pZ25vcmVcbmV4cG9ydCB0eXBlIENvdW50ID1cbiAgfCAgMSB8ICAyIHwgIDMgfCAgNCB8ICA1IHwgIDYgfCAgNyB8ICA4IHwgIDkgfCAxMFxuICB8IDExIHwgMTIgfCAxMyB8IDE0IHwgMTUgfCAxNiB8IDE3IHwgMTggfCAxOSB8IDIwXG4gIHwgMjEgfCAyMiB8IDIzIHwgMjQgfCAyNSB8IDI2IHwgMjcgfCAyOCB8IDI5IHwgMzA7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBVbnNwbGFzaFNlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IHNlYXJjaFVybCA9ICdzZWFyY2gvcGhvdG9zJztcbiAgcHJpdmF0ZSByZWFkb25seSBwaG90b3NVcmwgPSAncGhvdG9zJztcbiAgcHJpdmF0ZSByZWFkb25seSByYW5kb21VcmwgPSAncGhvdG9zL3JhbmRvbSc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29sbGVjdGlvbnNVcmwgPSAnY29sbGVjdGlvbnMnO1xuICBwcml2YXRlIHJlYWRvbmx5IHRvcGljc1VybCA9ICd0b3BpY3MnO1xuICBwcml2YXRlIHJlYWRvbmx5IHVzZXJzVXJsID0gJ3VzZXJzJztcblxuICBwcml2YXRlIGNvbmZpZyQ6IE9ic2VydmFibGU8VW5zcGxhc2hDb25maWc+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBASW5qZWN0KFVOU1BMQVNIX0NPTkZJRylcbiAgICBjb25maWc6IFVuc3BsYXNoQ29uZmlnIHwgT2JzZXJ2YWJsZTxVbnNwbGFzaENvbmZpZz5cbiAgKSB7XG4gICAgY29uc3QgY29uZmlnJCA9IGNvbmZpZyBpbnN0YW5jZW9mIE9ic2VydmFibGUgPyBjb25maWcgOiBvZihjb25maWcpO1xuXG4gICAgdGhpcy5jb25maWckID0gY29uZmlnJC5waXBlKFxuICAgICAgdGFwKChjb25maWcpID0+IHtcbiAgICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3BsYXNoIGNvbmZpZ3VyYXRpb24gdW5kZWZpbmVkJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNvbmZpZy51cmwpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3BsYXNoIGNvbmZpZ3VyYXRpb24gdXJsIHVuZGVmaW5lZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFjb25maWcuYXV0aG9yaXphdGlvbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zcGxhc2ggY29uZmlndXJhdGlvbiBhdXRob3JpemF0aW9uIHVuZGVmaW5lZCcpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogW0xpc3QgcGhvdG9zXShodHRwczovL3Vuc3BsYXNoLmNvbS9kb2N1bWVudGF0aW9uI2xpc3QtcGhvdG9zKS5cbiAgICpcbiAgICogR2V0IGEgc2luZ2xlIHBhZ2UgZnJvbSB0aGUgbGlzdCBvZiBhbGwgcGhvdG9zLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyB0byBiZSB1c2VkIHdoZW4gZ2V0dGluZyBsaXN0IG9mIHBob3Rvc1xuICAgKlxuICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIGNvbnRhaW5pbmcgYSB7QGxpbmsgUGhvdG99IGFycmF5XG4gICAqL1xuICBwaG90b3Mob3B0aW9ucz86IHtcbiAgICBwYWdlPzogbnVtYmVyO1xuICAgIHBlclBhZ2U/OiBudW1iZXI7XG4gICAgb3JkZXJCeT86IFVuc3BsYXNoT3JkZXJCeTtcbiAgfSk6IE9ic2VydmFibGU8UGhvdG9bXT4ge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZyQucGlwZShcbiAgICAgIG1lcmdlTWFwKChjb25maWcpID0+IHtcbiAgICAgICAgbGV0IHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKCk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnM/LnBhZ2UpIHtcbiAgICAgICAgICBwYXJhbXMgPSBwYXJhbXMuc2V0KCdwYWdlJywgb3B0aW9ucy5wYWdlLnRvU3RyaW5nKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnM/LnBlclBhZ2UpIHtcbiAgICAgICAgICBwYXJhbXMgPSBwYXJhbXMuc2V0KCdwZXJfcGFnZScsIG9wdGlvbnMucGVyUGFnZS50b1N0cmluZygpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zPy5vcmRlckJ5KSB7XG4gICAgICAgICAgcGFyYW1zID0gcGFyYW1zLnNldCgnb3JkZXJfYnknLCBvcHRpb25zLm9yZGVyQnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaGVhZGVycyA9IHRoaXMudW5zcGxhc2hIZWFkZXJzKGNvbmZpZyk7XG5cbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy51bnNwbGFzaFVybCh0aGlzLnBob3Rvc1VybCwgY29uZmlnKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldDxQaG90b1tdPih1cmwsIHsgcGFyYW1zLCBoZWFkZXJzIH0pO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFtMaXN0IHBob3Rvc10oaHR0cHM6Ly91bnNwbGFzaC5jb20vZG9jdW1lbnRhdGlvbiNsaXN0LXBob3RvcykuXG4gICAqXG4gICAqIEdldCBhIHNpbmdsZSBwYWdlIGZyb20gdGhlIGxpc3Qgb2YgYWxsIHBob3Rvcy5cbiAgICpcbiAgICogQHBhcmFtIG9wdGlvbnMgdG8gYmUgdXNlZCB3aGVuIGdldHRpbmcgbGlzdCBvZiBwaG90b3NcbiAgICpcbiAgICogQHJldHVybnMgT2JzZXJ2YWJsZSBjb250YWluaW5nIGEge0BsaW5rIFBob3RvfSBhcnJheVxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIHBob3Rvc30gaW5zdGVhZFxuICAgKi9cbiAgbGlzdChvcHRpb25zPzoge1xuICAgIHBhZ2U/OiBudW1iZXI7XG4gICAgcGVyUGFnZT86IG51bWJlcjtcbiAgICBvcmRlckJ5PzogVW5zcGxhc2hPcmRlckJ5O1xuICB9KTogT2JzZXJ2YWJsZTxQaG90b1tdPiB7XG4gICAgcmV0dXJuIHRoaXMucGhvdG9zKG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFtHZXQgYSBwaG90b10oaHR0cHM6Ly91bnNwbGFzaC5jb20vZG9jdW1lbnRhdGlvbiNnZXQtYS1waG90bykuXG4gICAqXG4gICAqIFJldHJpZXZlIGEgc2luZ2xlIHBob3RvLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgb2YgdGhlIHBob3RvXG4gICAqXG4gICAqIEByZXR1cm5zICBPYnNlcnZhYmxlIGNvbnRhaW5pbmcgdGhlIHtAbGluayBQaG90b31cbiAgICovXG4gIHBob3RvKGlkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFBob3RvPiB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnJC5waXBlKFxuICAgICAgbWVyZ2VNYXAoKGNvbmZpZykgPT4ge1xuICAgICAgICBjb25zdCBoZWFkZXJzID0gdGhpcy51bnNwbGFzaEhlYWRlcnMoY29uZmlnKTtcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy51bnNwbGFzaFVybChgJHt0aGlzLnBob3Rvc1VybH0vJHtpZH1gLCBjb25maWcpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PFBob3RvPih1cmwsIHsgaGVhZGVycyB9KTtcbiAgICAgIH0p