UNPKG

@datorama/akita-ng-entity-service

Version:
271 lines 34.9 kB
import { HttpClient } from '@angular/common/http'; import { inject } from '@angular/core'; import { EntityService, isDefined } from '@datorama/akita'; import { catchError, finalize, isObservable, of, switchMap, tap, throwError } from 'rxjs'; import { errorAction, successAction } from './action-factory'; import { isID } from './helpers'; import { HttpMethod, NgEntityServiceNotifier } from './ng-entity-service-notifier'; import { defaultConfig, mergeDeep, NG_ENTITY_SERVICE_CONFIG } from './ng-entity-service.config'; import { NgEntityServiceLoader } from './ng-entity-service.loader'; export const mapResponse = (config) => switchMap((res) => { const mappedResponse = config?.mapResponseFn ? config.mapResponseFn(res) : res; return isObservable(mappedResponse) ? mappedResponse : of(mappedResponse); }); export class NgEntityService extends EntityService { constructor(store, config = {}) { super(); this.store = store; this.config = config; this.http = inject(HttpClient); this.loader = inject(NgEntityServiceLoader); this.notifier = inject(NgEntityServiceNotifier); const globalConfig = inject(NG_ENTITY_SERVICE_CONFIG); this.mergedConfig = mergeDeep({}, defaultConfig, globalConfig, this.getDecoratorConfig(), config); this.baseUrl = this.mergedConfig.baseUrl; this.httpMethodMap = this.mergedConfig.httpMethods; this.dispatchSuccess = successAction(this.store.storeName, this.notifier); this.dispatchError = errorAction(this.store.storeName, this.notifier); } get api() { if (!this.baseUrl) { throw new Error(`baseUrl of ${this.constructor.name} is not defined.`); } return `${this.baseUrl}/${this.resourceName}`; } get resourceName() { return this.mergedConfig.resourceName || this.store.storeName; } setBaseUrl(baseUrl) { this.baseUrl = baseUrl; } getHttp() { return this.http; } getConfig() { return this.mergedConfig; } get(idOrConfig, config) { const method = this.getHttpMethod(HttpMethod.GET); const isSingle = isID(idOrConfig); const entityId = isSingle ? idOrConfig : undefined; const conf = (!isSingle ? idOrConfig : config) || {}; const url = this.resolveUrl(conf, entityId); this.loader.dispatch({ method, loading: true, entityId, storeName: this.store.storeName, }); return this.http.request(method, url, conf).pipe(mapResponse(conf), tap((data) => { if (!conf.skipWrite) { if (isSingle) { this.store.upsert(entityId, data, (id, newState) => ({ id, ...newState })); } else { if (conf.append) { this.store.add(data); } else if (conf.upsert) { this.store.upsertMany(data); } else { this.store.set(data); } } } this.dispatchSuccess({ method, payload: data, successMsg: conf.successMsg, }); }), catchError((error) => this.handleError(method, error, conf.errorMsg)), finalize(() => { this.loader.dispatch({ method, loading: false, entityId, storeName: this.store.storeName, }); })); } /** * Add a new entity - Creates a POST request * * @example * service.add(entity).subscribe() * service.add(entity, config).subscribe() */ add(entity, config) { const url = this.resolveUrl(config); const method = this.getHttpMethod(HttpMethod.POST); this.loader.dispatch({ method, loading: true, storeName: this.store.storeName, }); const configWithBody = { ...config, ...{ body: entity } }; return this.http.request(method, url, configWithBody).pipe(mapResponse(config), tap((responseEntity) => { if (!config || (config && !config.skipWrite)) { this.store.add(responseEntity, config); } this.dispatchSuccess({ method, payload: responseEntity, successMsg: config && config.successMsg, }); }), catchError((error) => this.handleError(method, error, config && config.errorMsg)), finalize(() => { this.loader.dispatch({ method, loading: false, storeName: this.store.storeName, }); })); } /** * Update an entity - Creates a PUT/PATCH request * * @example * service.update(id, entity).subscribe() * service.update(id, entity, config).subscribe() */ update(id, entity, config) { const url = this.resolveUrl(config, id); const method = (config && config.method) || this.getHttpMethod(HttpMethod.PUT); this.loader.dispatch({ method, loading: true, entityId: id, storeName: this.store.storeName, }); const configWithBody = { ...config, ...{ body: entity } }; return this.http.request(method, url, configWithBody).pipe(mapResponse(config), tap((responseEntity) => { if (!config || (config && !config.skipWrite)) { this.store.update(id, responseEntity); } this.dispatchSuccess({ method, payload: responseEntity, successMsg: config && config.successMsg, }); }), catchError((error) => this.handleError(method, error, config && config.errorMsg)), finalize(() => { this.loader.dispatch({ method, loading: false, entityId: id, storeName: this.store.storeName, }); })); } /** * Delete an entity - Creates a DELETE request * * @example * service.delete(id).subscribe() * service.delete(id, config).subscribe() */ delete(id, config) { const url = this.resolveUrl(config, id); const method = this.getHttpMethod(HttpMethod.DELETE); this.loader.dispatch({ method, loading: true, entityId: id, storeName: this.store.storeName, }); return this.http.request(method, url, config).pipe(mapResponse(config), tap((res) => { if (!config || (config && !config.skipWrite)) { this.store.remove(id); } this.dispatchSuccess({ method, payload: res, successMsg: config && config.successMsg, }); }), catchError((error) => this.handleError(method, error, config && config.errorMsg)), finalize(() => { this.loader.dispatch({ method, loading: false, entityId: id, storeName: this.store.storeName, }); })); } /** * Gets the mapped HttpMethod. * * The default HttpMethod can be changed like so: * ```ts * { * provide: NG_ENTITY_SERVICE_CONFIG, * useValue: { * httpMethods: { * PUT: HttpMethod.PATCH, * }, * } as NgEntityServiceGlobalConfig, * } * ``` * * @param type HttpMethod to get the user configured HttpMethod for * @returns User configured HttpMethod for the method, else the default HttpMethod */ getHttpMethod(type) { let httpMethod; if (this.httpMethodMap) { httpMethod = this.httpMethodMap[type]; } if (!httpMethod) { throw new Error('Unknown HttpMethod'); } return httpMethod; } /** * Gets the value given via the NgEntityServiceConfig decorator * * ```ts * @NgEntityServiceConfig({ * baseUrl: 'foo', * resourceName: 'bar', * }) * ``` * * @param key The property key * @returns The value of the given decorator key */ getDecoratorValue(key) { return this.constructor[key]; } getDecoratorConfig() { const config = {}; const baseUrl = this.getDecoratorValue('baseUrl'); if (baseUrl) { config.baseUrl = baseUrl; } const resourceName = this.getDecoratorValue('resourceName'); if (resourceName) { config.resourceName = resourceName; } return config; } resolveUrl(config, id) { const { url, urlPostfix } = Object(config); let final = this.api; if (url) { return url; } if (isDefined(id)) { final += `/${id}`; } if (urlPostfix) { final += `/${urlPostfix}`; } return final; } handleError(method, error, errorMsg) { this.dispatchError({ method, errorMsg, payload: error, }); return throwError(error); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctZW50aXR5LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9uZy1lbnRpdHktc2VydmljZS9zcmMvbGliL25nLWVudGl0eS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxhQUFhLEVBQXNELFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9HLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBYyxFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEcsT0FBTyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFBdUIsVUFBVSxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDeEcsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQStCLHdCQUF3QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0gsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFHbkUsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUksTUFBc0IsRUFBRSxFQUFFLENBQ3ZELFNBQVMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO0lBQ2hCLE1BQU0sY0FBYyxHQUFHLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUUvRSxPQUFPLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFD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QVcsQ0FBQyxNQUFrQixFQUFFLEtBQVUsRUFBRSxRQUFpQjtRQUNyRSxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQ2pCLE1BQU07WUFDTixRQUFRO1lBQ1IsT0FBTyxFQUFFLEtBQUs7U0FDZixDQUFDLENBQUM7UUFFSCxPQUFPLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBFbnRpdHlTZXJ2aWNlLCBFbnRpdHlTdGF0ZSwgRW50aXR5U3RvcmUsIGdldEVudGl0eVR5cGUsIGdldElEVHlwZSwgaXNEZWZpbmVkIH0gZnJvbSAnQGRhdG9yYW1hL2FraXRhJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIGZpbmFsaXplLCBpc09ic2VydmFibGUsIE9ic2VydmFibGUsIG9mLCBzd2l0Y2hNYXAsIHRhcCwgdGhyb3dFcnJvciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZXJyb3JBY3Rpb24sIHN1Y2Nlc3NBY3Rpb24gfSBmcm9tICcuL2FjdGlvbi1mYWN0b3J5JztcbmltcG9ydCB7IGlzSUQgfSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IHsgRW50aXR5U2VydmljZUFjdGlvbiwgSHR0cE1ldGhvZCwgTmdFbnRpdHlTZXJ2aWNlTm90aWZpZXIgfSBmcm9tICcuL25nLWVudGl0eS1zZXJ2aWNlLW5vdGlmaWVyJztcbmltcG9ydCB7IGRlZmF1bHRDb25maWcsIG1lcmdlRGVlcCwgTmdFbnRpdHlTZXJ2aWNlR2xvYmFsQ29uZmlnLCBOR19FTlRJVFlfU0VSVklDRV9DT05GSUcgfSBmcm9tICcuL25nLWVudGl0eS1zZXJ2aWNlLmNvbmZpZyc7XG5pbXBvcnQgeyBOZ0VudGl0eVNlcnZpY2VMb2FkZXIgfSBmcm9tICcuL25nLWVudGl0eS1zZXJ2aWNlLmxvYWRlcic7XG5pbXBvcnQgeyBIdHRwQWRkQ29uZmlnLCBIdHRwQ29uZmlnLCBIdHRwRGVsZXRlQ29uZmlnLCBIdHRwR2V0Q29uZmlnLCBIdHRwVXBkYXRlQ29uZmlnLCBOZ0VudGl0eVNlcnZpY2VQYXJhbXMgfSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IGNvbnN0IG1hcFJlc3BvbnNlID0gPFQ+KGNvbmZpZz86IEh0dHBDb25maWc8VD4pID0+XG4gIHN3aXRjaE1hcCgocmVzKSA9PiB7XG4gICAgY29uc3QgbWFwcGVkUmVzcG9uc2UgPSBjb25maWc/Lm1hcFJlc3BvbnNlRm4gPyBjb25maWcubWFwUmVzcG9uc2VGbihyZXMpIDogcmVzO1xuXG4gICAgcmV0dXJuIGlzT2JzZXJ2YWJsZShtYXBwZWRSZXNwb25zZSkgPyBtYXBwZWRSZXNwb25zZSA6IG9mKG1hcHBlZFJlc3BvbnNlKTtcbiAgfSk7XG5cbmV4cG9ydCBjbGFzcyBOZ0VudGl0eVNlcnZpY2U8UyBleHRlbmRzIEVudGl0eVN0YXRlID0gYW55PiBleHRlbmRzIEVudGl0eVNlcnZpY2U8Uz4ge1xuICBiYXNlVXJsOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxvYWRlcjogTmdFbnRpdHlTZXJ2aWNlTG9hZGVyO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaHR0cDogSHR0cENsaWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSBub3RpZmllcjogTmdFbnRpdHlTZXJ2aWNlTm90aWZpZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWVyZ2VkQ29uZmlnOiBOZ0VudGl0eVNlcnZpY2VQYXJhbXMgJiBOZ0VudGl0eVNlcnZpY2VHbG9iYWxDb25maWc7XG4gIHByaXZhdGUgcmVhZG9ubHkgaHR0cE1ldGhvZE1hcDpcbiAgICB8IFBhcnRpYWw8e1xuICAgICAgICBHRVQ6IEh0dHBNZXRob2Q7XG4gICAgICAgIFBPU1Q6IEh0dHBNZXRob2Q7XG4gICAgICAgIFBBVENIOiBIdHRwTWV0aG9kO1xuICAgICAgICBQVVQ6IEh0dHBNZXRob2Q7XG4gICAgICAgIERFTEVURTogSHR0cE1ldGhvZDtcbiAgICAgIH0+XG4gICAgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkaXNwYXRjaFN1Y2Nlc3M6IChhY3Rpb246IFBhcnRpYWw8RW50aXR5U2VydmljZUFjdGlvbj4pID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGlzcGF0Y2hFcnJvcjogKGFjdGlvbjogUGFydGlhbDxFbnRpdHlTZXJ2aWNlQWN0aW9uPikgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgc3RvcmU6IEVudGl0eVN0b3JlPFM+LCByZWFkb25seSBjb25maWc6IE5nRW50aXR5U2VydmljZVBhcmFtcyA9IHt9KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLmh0dHAgPSBpbmplY3QoSHR0cENsaWVudCk7XG4gICAgdGhpcy5sb2FkZXIgPSBpbmplY3QoTmdFbnRpdHlTZXJ2aWNlTG9hZGVyKTtcbiAgICB0aGlzLm5vdGlmaWVyID0gaW5qZWN0KE5nRW50aXR5U2VydmljZU5vdGlmaWVyKTtcbiAgICBjb25zdCBnbG9iYWxDb25maWcgPSBpbmplY3QoTkdfRU5USVRZX1NFUlZJQ0VfQ09ORklHKTtcbiAgICB0aGlzLm1lcmdlZENvbmZpZyA9IG1lcmdlRGVlcCh7fSwgZGVmYXVsdENvbmZpZywgZ2xvYmFsQ29uZmlnLCB0aGlzLmdldERlY29yYXRvckNvbmZpZygpLCBjb25maWcpO1xuICAgIHRoaXMuYmFzZVVybCA9IHRoaXMubWVyZ2VkQ29uZmlnLmJhc2VVcmw7XG4gICAgdGhpcy5odHRwTWV0aG9kTWFwID0gdGhpcy5tZXJnZWRDb25maWcuaHR0cE1ldGhvZHM7XG5cbiAgICB0aGlzLmRpc3BhdGNoU3VjY2VzcyA9IHN1Y2Nlc3NBY3Rpb24odGhpcy5zdG9yZS5zdG9yZU5hbWUsIHRoaXMubm90aWZpZXIpO1xuICAgIHRoaXMuZGlzcGF0Y2hFcnJvciA9IGVycm9yQWN0aW9uKHRoaXMuc3RvcmUuc3RvcmVOYW1lLCB0aGlzLm5vdGlmaWVyKTtcbiAgfVxuXG4gIGdldCBhcGkoKSB7XG4gICAgaWYgKCF0aGlzLmJhc2VVcmwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgYmFzZVVybCBvZiAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gaXMgbm90IGRlZmluZWQuYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGAke3RoaXMuYmFzZVVybH0vJHt0aGlzLnJlc291cmNlTmFtZX1gO1xuICB9XG5cbiAgZ2V0IHJlc291cmNlTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXJnZWRDb25maWcucmVzb3VyY2VOYW1lIHx8IHRoaXMuc3RvcmUuc3RvcmVOYW1lO1xuICB9XG5cbiAgc2V0QmFzZVVybChiYXNlVXJsOiBzdHJpbmcpIHtcbiAgICB0aGlzLmJhc2VVcmwgPSBiYXNlVXJsO1xuICB9XG5cbiAgZ2V0SHR0cCgpIHtcbiAgICByZXR1cm4gdGhpcy5odHRwO1xuICB9XG5cbiAgZ2V0Q29uZmlnKCkge1xuICAgIHJldHVybiB0aGlzLm1lcmdlZENvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgb25lIGVudGl0eSAtIENyZWF0ZXMgYSBHRVQgcmVxdWVzdFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBzZXJ2aWNlLmdldChpZCkuc3Vic2NyaWJlKClcbiAgICogc2VydmljZS5nZXQoaWQsIHsgaGVhZGVycywgcGFyYW1zLCB1cmwgfSkuc3Vic2NyaWJlKClcbiAgICovXG4gIGdldDxUPihpZD86IGdldElEVHlwZTxTPiwgY29uZmlnPzogSHR0cEdldENvbmZpZzxUPik6IE9ic2VydmFibGU8VD47XG4gIC8qKlxuICAgKiBHZXQgYWxsIGVudGl0aWVzIC0gQ3JlYXRlcyBhIEdFVCByZXF1ZXN0XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIHNlcnZpY2UuZ2V0KCkuc3Vic2NyaWJlKClcbiAgICogc2VydmljZS5nZXQoeyBoZWFkZXJzLCBwYXJhbXMsIHVybCB9KS5zdWJzY3JpYmUoKVxuICAgKi9cbiAgZ2V0PFQ+KGNvbmZpZz86IEh0dHBHZXRDb25maWc8VD4pOiBPYnNlcnZhYmxlPFQ+O1xuICBnZXQ8VD4oaWRPckNvbmZpZz86IGdldElEVHlwZTxTPiB8IEh0dHBHZXRDb25maWc8VD4sIGNvbmZpZz86IEh0dHBHZXRDb25maWc8VD4pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCBtZXRob2QgPSB0aGlzLmdldEh0dHBNZXRob2QoSHR0cE1ldGhvZC5HRVQpO1xuICAgIGNvbnN0IGlzU2luZ2xlID0gaXNJRChpZE9yQ29uZmlnKTtcbiAgICBjb25zdCBlbnRpdHlJZCA9IGlzU2luZ2xlID8gKGlkT3JDb25maWcgYXMgZ2V0SURUeXBlPFM+KSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBjb25mID0gKCFpc1NpbmdsZSA/IChpZE9yQ29uZmlnIGFzIEh0dHBHZXRDb25maWc8VD4pIDogY29uZmlnKSB8fCB7fTtcbiAgICBjb25zdCB1cmwgPSB0aGlzLnJlc29sdmVVcmwoY29uZiwgZW50aXR5SWQpO1xuXG4gICAgdGhpcy5sb2FkZXIuZGlzcGF0Y2goe1xuICAgICAgbWV0aG9kLFxuICAgICAgbG9hZGluZzogdHJ1ZSxcbiAgICAgIGVudGl0eUlkLFxuICAgICAgc3RvcmVOYW1lOiB0aGlzLnN0b3JlLnN0b3JlTmFtZSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLmh0dHAucmVxdWVzdChtZXRob2QsIHVybCwgY29uZikucGlwZShcbiAgICAgIG1hcFJlc3BvbnNlKGNvbmYpLFxuICAgICAgdGFwKChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKCFjb25mLnNraXBXcml0ZSkge1xuICAgICAgICAgIGlmIChpc1NpbmdsZSkge1xuICAgICAgICAgICAgdGhpcy5zdG9yZS51cHNlcnQoZW50aXR5SWQgYXMgYW55LCBkYXRhLCAoaWQsIG5ld1N0YXRlKSA9PiAoeyBpZCwgLi4ubmV3U3RhdGUgfSkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZi5hcHBlbmQpIHtcbiAgICAgICAgICAgICAgdGhpcy5zdG9yZS5hZGQoZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbmYudXBzZXJ0KSB7XG4gICAgICAgICAgICAgIHRoaXMuc3RvcmUudXBzZXJ0TWFueShkYXRhKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHRoaXMuc3RvcmUuc2V0KGRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGlzcGF0Y2hTdWNjZXNzKHtcbiAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgcGF5bG9hZDogZGF0YSxcbiAgICAgICAgICBzdWNjZXNzTXNnOiBjb25mLnN1Y2Nlc3NNc2csXG4gICAgICAgIH0pO1xuICAgICAgfSksXG4gICAgICBjYXRjaEVycm9yKChlcnJvcikgPT4gdGhpcy5oYW5kbGVFcnJvcihtZXRob2QsIGVycm9yLCBjb25mLmVycm9yTXNnKSksXG4gICAgICBmaW5hbGl6ZSgoKSA9PiB7XG4gICAgICAgIHRoaXMubG9hZGVyLmRpc3BhdGNoKHtcbiAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgbG9hZGluZzogZmFsc2UsXG4gICAgICAgICAgZW50aXR5SWQsXG4gICAgICAgICAgc3RvcmVOYW1lOiB0aGlzLnN0b3JlLnN0b3JlTmFtZSxcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbmV3IGVudGl0eSAtIENyZWF0ZXMgYSBQT1NUIHJlcXVlc3RcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogc2VydmljZS5hZGQoZW50aXR5KS5zdWJzY3JpYmUoKVxuICAgKiBzZXJ2aWNlLmFkZChlbnRpdHksIGNvbmZpZykuc3Vic2NyaWJlKClcbiAgICovXG4gIGFkZDxUPihlbnRpdHk6IGdldEVudGl0eVR5cGU8Uz4sIGNvbmZpZz86IEh0dHBBZGRDb25maWc8VD4pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCB1cmwgPSB0aGlzLnJlc29sdmVVcmwoY29uZmlnKTtcbiAgICBjb25zdCBtZXRob2QgPSB0aGlzLmdldEh0dHBNZXRob2QoSHR0cE1ldGhvZC5QT1NUKTtcblxuICAgIHRoaXMubG9hZGVyLmRpc3BhdGNoKHtcbiAgICAgIG1ldGhvZCxcbiAgICAgIGxvYWRpbmc6IHRydWUsXG4gICAgICBzdG9yZU5hbWU6IHRoaXMuc3RvcmUuc3RvcmVOYW1lLFxuICAgIH0pO1xuXG4gICAgY29uc3QgY29uZmlnV2l0aEJvZHkgPSB7IC4uLmNvbmZpZywgLi4ueyBib2R5OiBlbnRpdHkgfSB9O1xuXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5yZXF1ZXN0KG1ldGhvZCwgdXJsLCBjb25maWdXaXRoQm9keSkucGlwZShcbiAgICAgIG1hcFJlc3BvbnNlKGNvbmZpZyksXG4gICAgICB0YXAoKHJlc3BvbnNlRW50aXR5OiBhbnkpID0+IHtcbiAgICAgICAgaWYgKCFjb25maWcgfHwgKGNvbmZpZyAmJiAhY29uZmlnLnNraXBXcml0ZSkpIHtcbiAgICAgICAgICB0aGlzLnN0b3JlLmFkZChyZXNwb25zZUVudGl0eSwgY29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpc3BhdGNoU3VjY2Vzcyh7XG4gICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgIHBheWxvYWQ6IHJlc3BvbnNlRW50aXR5LFxuICAgICAgICAgIHN1Y2Nlc3NNc2c6IGNvbmZpZyAmJiBjb25maWcuc3VjY2Vzc01zZyxcbiAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB0aGlzLmhhbmRsZUVycm9yKG1ldGhvZCwgZXJyb3IsIGNvbmZpZyAmJiBjb25maWcuZXJyb3JNc2cpKSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgdGhpcy5sb2FkZXIuZGlzcGF0Y2goe1xuICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICBzdG9yZU5hbWU6IHRoaXMuc3RvcmUuc3RvcmVOYW1lLFxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYW4gZW50aXR5IC0gQ3JlYXRlcyBhIFBVVC9QQVRDSCByZXF1ZXN0XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIHNlcnZpY2UudXBkYXRlKGlkLCBlbnRpdHkpLnN1YnNjcmliZSgpXG4gICAqIHNlcnZpY2UudXBkYXRlKGlkLCBlbnRpdHksIGNvbmZpZykuc3Vic2NyaWJlKClcbiAgICovXG4gIHVwZGF0ZTxUPihpZDogZ2V0SURUeXBlPFM+LCBlbnRpdHk6IFBhcnRpYWw8Z2V0RW50aXR5VHlwZTxTPj4sIGNvbmZpZz86IEh0dHBVcGRhdGVDb25maWc8VD4pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCB1cmwgPSB0aGlzLnJlc29sdmVVcmwoY29uZmlnLCBpZCk7XG4gICAgY29uc3QgbWV0aG9kID0gKGNvbmZpZyAmJiBjb25maWcubWV0aG9kKSB8fCB0aGlzLmdldEh0dHBNZXRob2QoSHR0cE1ldGhvZC5QVVQpO1xuXG4gICAgdGhpcy5sb2FkZXIuZGlzcGF0Y2goe1xuICAgICAgbWV0aG9kLFxuICAgICAgbG9hZGluZzogdHJ1ZSxcbiAgICAgIGVudGl0eUlkOiBpZCxcbiAgICAgIHN0b3JlTmFtZTogdGhpcy5zdG9yZS5zdG9yZU5hbWUsXG4gICAgfSk7XG5cbiAgICBjb25zdCBjb25maWdXaXRoQm9keSA9IHsgLi4uY29uZmlnLCAuLi57IGJvZHk6IGVudGl0eSB9IH07XG5cbiAgICByZXR1cm4gdGhpcy5odHRwLnJlcXVlc3QobWV0aG9kLCB1cmwsIGNvbmZpZ1dpdGhCb2R5KS5waXBlKFxuICAgICAgbWFwUmVzcG9uc2UoY29uZmlnKSxcbiAgICAgIHRhcCgocmVzcG9uc2VFbnRpdHk6IGFueSkgPT4ge1xuICAgICAgICBpZiAoIWNvbmZpZyB8fCAoY29uZmlnICYmICFjb25maWcuc2tpcFdyaXRlKSkge1xuICAgICAgICAgIHRoaXMuc3RvcmUudXBkYXRlKGlkLCByZXNwb25zZUVudGl0eSBhcyBhbnkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hTdWNjZXNzKHtcbiAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgcGF5bG9hZDogcmVzcG9uc2VFbnRpdHksXG4gICAgICAgICAgc3VjY2Vzc01zZzogY29uZmlnICYmIGNvbmZpZy5zdWNjZXNzTXNnLFxuICAgICAgICB9KTtcbiAgICAgIH0pLFxuICAgICAgY2F0Y2hFcnJvcigoZXJyb3IpID0+IHRoaXMuaGFuZGxlRXJyb3IobWV0aG9kLCBlcnJvciwgY29uZmlnICYmIGNvbmZpZy5lcnJvck1zZykpLFxuICAgICAgZmluYWxpemUoKCkgPT4ge1xuICAgICAgICB0aGlzLmxvYWRlci5kaXNwYXRjaCh7XG4gICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgIGxvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgIGVudGl0eUlkOiBpZCxcbiAgICAgICAgICBzdG9yZU5hbWU6IHRoaXMuc3RvcmUuc3RvcmVOYW1lLFxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKSBhcyBPYnNlcnZhYmxlPFQ+O1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSBhbiBlbnRpdHkgLSBDcmVhdGVzIGEgREVMRVRFIHJlcXVlc3RcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogc2VydmljZS5kZWxldGUoaWQpLnN1YnNjcmliZSgpXG4gICAqIHNlcnZpY2UuZGVsZXRlKGlkLCBjb25maWcpLnN1YnNjcmliZSgpXG4gICAqL1xuICBkZWxldGU8VD4oaWQ6IGdldElEVHlwZTxTPiwgY29uZmlnPzogSHR0cERlbGV0ZUNvbmZpZzxUPik6IE9ic2VydmFibGU8VD4ge1xuICAgIGNvbnN0IHVybCA9IHRoaXMucmVzb2x2ZVVybChjb25maWcsIGlkKTtcbiAgICBjb25zdCBtZXRob2QgPSB0aGlzLmdldEh0dHBNZXRob2QoSHR0cE1ldGhvZC5ERUxFVEUpO1xuXG4gICAgdGhpcy5sb2FkZXIuZGlzcGF0Y2goe1xuICAgICAgbWV0aG9kLFxuICAgICAgbG9hZGluZzogdHJ1ZSxcbiAgICAgIGVudGl0eUlkOiBpZCxcbiAgICAgIHN0b3JlTmFtZTogdGhpcy5zdG9yZS5zdG9yZU5hbWUsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwLnJlcXVlc3QobWV0aG9kLCB1cmwsIGNvbmZpZykucGlwZShcbiAgICAgIG1hcFJlc3BvbnNlKGNvbmZpZyksXG4gICAgICB0YXAoKHJlczogYW55KSA9PiB7XG4gICAgICAgIGlmICghY29uZmlnIHx8IChjb25maWcgJiYgIWNvbmZpZy5za2lwV3JpdGUpKSB7XG4gICAgICAgICAgdGhpcy5zdG9yZS5yZW1vdmUoaWQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hTdWNjZXNzKHtcbiAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgcGF5bG9hZDogcmVzLFxuICAgICAgICAgIHN1Y2Nlc3NNc2c6IGNvbmZpZyAmJiBjb25maWcuc3VjY2Vzc01zZyxcbiAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB0aGlzLmhhbmRsZUVycm9yKG1ldGhvZCwgZXJyb3IsIGNvbmZpZyAmJiBjb25maWcuZXJyb3JNc2cpKSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgdGhpcy5sb2FkZXIuZGlzcGF0Y2goe1xuICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICBlbnRpdHlJZDogaWQsXG4gICAgICAgICAgc3RvcmVOYW1lOiB0aGlzLnN0b3JlLnN0b3JlTmFtZSEsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApIGFzIE9ic2VydmFibGU8VD47XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbWFwcGVkIEh0dHBNZXRob2QuXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IEh0dHBNZXRob2QgY2FuIGJlIGNoYW5nZWQgbGlrZSBzbzpcbiAgICogYGBgdHNcbiAgICoge1xuICAgKiAgIHByb3ZpZGU6IE5HX0VOVElUWV9TRVJWSUNFX0NPTkZJRyxcbiAgICogICB1c2VWYWx1ZToge1xuICAgKiAgICAgaHR0cE1ldGhvZHM6IHtcbiAgICogICAgICAgUFVUOiBIdHRwTWV0aG9kLlBBVENILFxuICAgKiAgICAgfSxcbiAgICogICB9IGFzIE5nRW50aXR5U2VydmljZUdsb2JhbENvbmZpZyxcbiAgICogfVxuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIHR5cGUgSHR0cE1ldGhvZCB0byBnZXQgdGhlIHVzZXIgY29uZmlndXJlZCBIdHRwTWV0aG9kIGZvclxuICAgKiBAcmV0dXJucyBVc2VyIGNvbmZpZ3VyZWQgSHR0cE1ldGhvZCBmb3IgdGhlIG1ldGhvZCwgZWxzZSB0aGUgZGVmYXVsdCBIdHRwTWV0aG9kXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0SHR0cE1ldGhvZCh0eXBlOiBIdHRwTWV0aG9kKSB7XG4gICAgbGV0IGh0dHBNZXRob2QhOiBIdHRwTWV0aG9kIHwgdW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLmh0dHBNZXRob2RNYXApIHtcbiAgICAgIGh0dHBNZXRob2QgPSB0aGlzLmh0dHBNZXRob2RNYXBbdHlwZV07XG4gICAgfVxuICAgIGlmICghaHR0cE1ldGhvZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIEh0dHBNZXRob2QnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaHR0cE1ldGhvZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB2YWx1ZSBnaXZlbiB2aWEgdGhlIE5nRW50aXR5U2VydmljZUNvbmZpZyBkZWNvcmF0b3JcbiAgICpcbiAgICogYGBgdHNcbiAgICogQE5nRW50aXR5U2VydmljZUNvbmZpZyh7XG4gICAqICAgYmFzZVVybDogJ2ZvbycsXG4gICAqICAgcmVzb3VyY2VOYW1lOiAnYmFyJyxcbiAgICogfSlcbiAgICogYGBgXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgVGhlIHByb3BlcnR5IGtleVxuICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgb2YgdGhlIGdpdmVuIGRlY29yYXRvciBrZXlcbiAgICovXG4gIHByaXZhdGUgZ2V0RGVjb3JhdG9yVmFsdWUoa2V5OiBrZXlvZiBOZ0VudGl0eVNlcnZpY2VQYXJhbXMpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiAodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpW2tleV07XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0RGVjb3JhdG9yQ29uZmlnKCkge1xuICAgIGNvbnN0IGNvbmZpZzogTmdFbnRpdHlTZXJ2aWNlUGFyYW1zID0ge307XG5cbiAgICBjb25zdCBiYXNlVXJsID0gdGhpcy5nZXREZWNvcmF0b3JWYWx1ZSgnYmFzZVVybCcpO1xuICAgIGlmIChiYXNlVXJsKSB7XG4gICAgICBjb25maWcuYmFzZVVybCA9IGJhc2VVcmw7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb3VyY2VOYW1lID0gdGhpcy5nZXREZWNvcmF0b3JWYWx1ZSgncmVzb3VyY2VOYW1lJyk7XG4gICAgaWYgKHJlc291cmNlTmFtZSkge1xuICAgICAgY29uZmlnLnJlc291cmNlTmFtZSA9IHJlc291cmNlTmFtZTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJlc29sdmVVcmwoY29uZmlnPzogSHR0cENvbmZpZywgaWQ/OiBhbnkpIHtcbiAgICBjb25zdCB7IHVybCwgdXJsUG9zdGZpeCB9ID0gT2JqZWN0KGNvbmZpZykgYXMgSHR0cENvbmZpZztcbiAgICBsZXQgZmluYWwgPSB0aGlzLmFwaTtcblxuICAgIGlmICh1cmwpIHtcbiAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuXG4gICAgaWYgKGlzRGVmaW5lZChpZCkpIHtcbiAgICAgIGZpbmFsICs9IGAvJHtpZH1gO1xuICAgIH1cblxuICAgIGlmICh1cmxQb3N0Zml4KSB7XG4gICAgICBmaW5hbCArPSBgLyR7dXJsUG9zdGZpeH1gO1xuICAgIH1cblxuICAgIHJldHVybiBmaW5hbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVFcnJvcihtZXRob2Q6IEh0dHBNZXRob2QsIGVycm9yOiBhbnksIGVycm9yTXNnPzogc3RyaW5nKTogYW55IHtcbiAgICB0aGlzLmRpc3BhdGNoRXJyb3Ioe1xuICAgICAgbWV0aG9kLFxuICAgICAgZXJyb3JNc2csXG4gICAgICBwYXlsb2FkOiBlcnJvcixcbiAgICB9KTtcblxuICAgIHJldHVybiB0aHJvd0Vycm9yKGVycm9yKTtcbiAgfVxufVxuIl19