UNPKG

@iotize/ionic

Version:

Iotize specific building blocks on top of @ionic/angular.

240 lines 34.5 kB
import { Injectable } from '@angular/core'; import { Tap } from '@iotize/tap'; import { ConnectionState } from '@iotize/tap/protocol/api'; import { defer, Observable } from 'rxjs'; import { catchError, map, shareReplay, switchMap, tap } from 'rxjs/operators'; import { CurrentDeviceService, LONG_RANGE_PROTOCOL_FILTER, } from './current-device.service'; import { debug } from './logger'; import { ProtocolFactoryService } from './protocol-factory.service'; import * as i0 from "@angular/core"; import * as i1 from "./current-device.service"; import * as i2 from "./protocol-factory.service"; const TAG = 'TapConnectionService'; export const TAP_CONNECTION_OPTIONS_PROVIDER = 'TapConnectionOptions'; export var TapRegisterProtocolsMethod; (function (TapRegisterProtocolsMethod) { /** * Only register altertive protocol when connecting with nfc using ndef */ TapRegisterProtocolsMethod["NDEF_ONLY"] = "NDEF_ONLY"; /** * Register alternative protocols using NDEF if present or service if not */ TapRegisterProtocolsMethod["NDEF_OR_SERVICE"] = "NDEF_OR_SERVICE"; /** * Register alternative protocols using service (even if ndef is available) */ TapRegisterProtocolsMethod["SERVICE_ONLY"] = "SERVICE_ONLY"; })(TapRegisterProtocolsMethod || (TapRegisterProtocolsMethod = {})); /** * User can the replace with its own service */ export class TapConnectionService { constructor(tapService, protocolFactory) { this.tapService = tapService; this.protocolFactory = protocolFactory; this.tapFactory = (protocol) => { return Tap.fromProtocol(protocol); }; } /** * Create a Tap connection Observable shared stream */ connect(meta, config) { return new Observable((emitter) => { const subscription = this.createConnectionObservable(meta, config, emitter).subscribe({ error: async (err) => { console.warn(`Tap connection failed with error`, err); await this.tapService .remove(false) .catch((err) => console.warn('ignored error', err)); emitter.error(err); }, complete: () => emitter.complete(), }); return () => { subscription.unsubscribe(); }; }).pipe(shareReplay(1)); } createConnectionObservable(protocolMeta, config, emitter) { let connectObservable = defer(async () => { const protocol = await this.protocolFactory.create(protocolMeta); const tap = this.tapFactory(protocol); emitter.next({ message: `Initialize Tap from ${protocolMeta.type}...`, tap, }); return tap; }); if (config.encryption) { const encryptionOptions = config.encryption; connectObservable = connectObservable.pipe(switchMap(async (tap) => { emitter.next({ message: `Enable encryption...`, tap, }); if (encryptionOptions.keys) { debug(TAG, 'Set encryption keys: ', encryptionOptions.keys); tap.encryption.setEncryptionKeys(encryptionOptions.keys); } if (encryptionOptions.encryption) { if (!tap.encryption.sessionKey && !tap.isConnected()) { await tap.connect(); } tap.encryption.resume(); debug(TAG, 'Enable encryption: ', encryptionOptions.encryption); } if (encryptionOptions.frameCounter != undefined) { tap.encryption.setEncryptedFrameCounter(encryptionOptions.frameCounter); } return tap; })); } connectObservable = connectObservable.pipe(switchMap(async (tap) => { if (this.tapService.hasTap) { await this.tapService.remove(); } this.tapService.setTapFromEvent({ protocolMeta: protocolMeta, tap: tap, }, { emit: false, // We emit only at the end of initialisation }); tap.keepAlive.stop(); return tap; })); if (protocolMeta.type === 'nfc') { if (config.nfcPairing) { connectObservable = connectObservable.pipe(switchMap(async (tap) => { emitter.next({ message: `NFC pairing...`, tap, }); debug(TAG, 'nfcPairing'); await tap.connect(); await tap.nfcPairing(); return tap; })); } } if (config.registerProtocolsMethod !== false) { connectObservable = connectObservable.pipe(switchMap(async (tap) => { if (!tap.isConnected()) { emitter.next({ message: `Connecting with ${protocolMeta.type}...`, tap, }); await tap.connect(); } emitter.next({ message: `Initializing protocols...`, tap, }); await this.registerAlternativeProtocols(config.registerProtocolsMethod, protocolMeta); return tap; })); } const switchProtocol = config.switchProtocol; if (protocolMeta.type === 'nfc') { connectObservable = connectObservable.pipe(switchMap(async (tap) => { if (switchProtocol) { const protocolMeta = this.tapService.availableProtocols.find(LONG_RANGE_PROTOCOL_FILTER); if (protocolMeta) { debug(TAG, 'Using long range protocol: ', protocolMeta); emitter.next({ message: `Switch to ${protocolMeta.type}`, tap, }); await this.tapService.useProtocolFromMeta(protocolMeta); } } else { debug(TAG, 'keep NFC protocol'); const nfcProtocol = tap.protocol; // for NFC connection await nfcProtocol._connect().toPromise(); nfcProtocol.setConnectionState(ConnectionState.CONNECTED); } return tap; })); } if (config.refreshSessionState) { connectObservable = connectObservable.pipe(switchMap(async (tap) => { debug(TAG, 'refreshSessionState'); emitter.next({ message: 'Refreshing user session...', tap, }); await tap.auth.refreshSessionState(); return tap; })); } if (config.keepAlive !== false) { connectObservable = connectObservable.pipe(tap((tap) => { tap.keepAlive.start(); })); } return connectObservable.pipe(map((tap) => { this.tapService.notifyNewTap(); return tap; }), catchError((originalError) => { console.warn(`Tap connection failed with error`, originalError); return defer(async () => { await this.tapService .remove(false) .catch((err) => console.warn('ignored error', err)); throw originalError; }); })); } async registerAlternativeProtocols(registerAlternativeProtocolMethod, initialProtocolMeta) { if (registerAlternativeProtocolMethod === false) { return; } registerAlternativeProtocolMethod = registerAlternativeProtocolMethod || TapRegisterProtocolsMethod.NDEF_OR_SERVICE; debug(TAG, `Register alternative protocols with method: ${registerAlternativeProtocolMethod}`); const tap = this.tapService.tap; switch (registerAlternativeProtocolMethod) { case TapRegisterProtocolsMethod.NDEF_OR_SERVICE: let registeredProtocolMeta; if (!tap.isConnected()) { await tap.connect(); } if (initialProtocolMeta.type === 'nfc') { registeredProtocolMeta = await this.tapService.registerProtocolsFromTag(initialProtocolMeta.info.tag); } else { await this.tapService.registerProtocolsFromTap().catch((err) => { console.warn('Failed to register protocols from tap', err); }); } break; case TapRegisterProtocolsMethod.SERVICE_ONLY: if (!tap.isConnected()) { await tap.connect(); } await this.tapService.registerProtocolsFromTap().catch((err) => { console.warn('Failed to register protocols from tap', err); }); break; case TapRegisterProtocolsMethod.NDEF_ONLY: if (initialProtocolMeta.type === 'nfc') { await this.tapService.registerProtocolsFromTag(initialProtocolMeta.info.tag); } break; } } } /** @nocollapse */ TapConnectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TapConnectionService, deps: [{ token: i1.CurrentDeviceService }, { token: i2.ProtocolFactoryService }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ TapConnectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TapConnectionService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TapConnectionService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.CurrentDeviceService }, { type: i2.ProtocolFactoryService }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFwLWNvbm5lY3Rpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9zcmMvbGliL3RhcC1jb25uZWN0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWxDLE9BQU8sRUFBZSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlFLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsMEJBQTBCLEdBQzNCLE1BQU0sMEJBQTBCLENBQUM7QUFFbEMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNqQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7OztBQUVwRSxNQUFNLEdBQUcsR0FBRyxzQkFBc0IsQ0FBQztBQUVuQyxNQUFNLENBQUMsTUFBTSwrQkFBK0IsR0FBRyxzQkFBc0IsQ0FBQztBQUV0RSxNQUFNLENBQU4sSUFBWSwwQkFlWDtBQWZELFdBQVksMEJBQTBCO0lBQ3BDOztPQUVHO0lBQ0gscURBQXVCLENBQUE7SUFFdkI7O09BRUc7SUFDSCxpRUFBbUMsQ0FBQTtJQUVuQzs7T0FFRztJQUNILDJEQUE2QixDQUFBO0FBQy9CLENBQUMsRUFmVywwQkFBMEIsS0FBMUIsMEJBQTBCLFFBZXJDO0FBOENEOztHQUVHO0FBSUgsTUFBTSxPQUFPLG9CQUFvQjtJQUsvQixZQUNVLFVBQWdDLEVBQ2hDLGVBQXVDO1FBRHZDLGVB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SUFuUVUsb0JBQW9CO3lJQUFwQixvQkFBb0IsY0FGbkIsTUFBTTs0RkFFUCxvQkFBb0I7a0JBSGhDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTkZDQ29tUHJvdG9jb2wgfSBmcm9tICdAaW90aXplL2RldmljZS1jb20tbmZjLmNvcmRvdmEnO1xuaW1wb3J0IHsgVGFwIH0gZnJvbSAnQGlvdGl6ZS90YXAnO1xuaW1wb3J0IHsgRW5jcnlwdGlvbk9wdGlvbnMgfSBmcm9tICdAaW90aXplL3RhcC9hdXRoJztcbmltcG9ydCB7IENvbVByb3RvY29sLCBDb25uZWN0aW9uU3RhdGUgfSBmcm9tICdAaW90aXplL3RhcC9wcm90b2NvbC9hcGknO1xuaW1wb3J0IHsgZGVmZXIsIE9ic2VydmFibGUsIFN1YnNjcmliZXIgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgc2hhcmVSZXBsYXksIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge1xuICBDdXJyZW50RGV2aWNlU2VydmljZSxcbiAgTE9OR19SQU5HRV9QUk9UT0NPTF9GSUxURVIsXG59IGZyb20gJy4vY3VycmVudC1kZXZpY2Uuc2VydmljZSc7XG5pbXBvcnQgeyBQcm90b2NvbE1ldGEgfSBmcm9tICcuL2V4dGVuc2lvbnMvcHJvdG9jb2wtaW5mbyc7XG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCB7IFByb3RvY29sRmFjdG9yeVNlcnZpY2UgfSBmcm9tICcuL3Byb3RvY29sLWZhY3Rvcnkuc2VydmljZSc7XG5cbmNvbnN0IFRBRyA9ICdUYXBDb25uZWN0aW9uU2VydmljZSc7XG5cbmV4cG9ydCBjb25zdCBUQVBfQ09OTkVDVElPTl9PUFRJT05TX1BST1ZJREVSID0gJ1RhcENvbm5lY3Rpb25PcHRpb25zJztcblxuZXhwb3J0IGVudW0gVGFwUmVnaXN0ZXJQcm90b2NvbHNNZXRob2Qge1xuICAvKipcbiAgICogT25seSByZWdpc3RlciBhbHRlcnRpdmUgcHJvdG9jb2wgd2hlbiBjb25uZWN0aW5nIHdpdGggbmZjIHVzaW5nIG5kZWZcbiAgICovXG4gIE5ERUZfT05MWSA9ICdOREVGX09OTFknLFxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhbHRlcm5hdGl2ZSBwcm90b2NvbHMgdXNpbmcgTkRFRiBpZiBwcmVzZW50IG9yIHNlcnZpY2UgaWYgbm90XG4gICAqL1xuICBOREVGX09SX1NFUlZJQ0UgPSAnTkRFRl9PUl9TRVJWSUNFJyxcblxuICAvKipcbiAgICogUmVnaXN0ZXIgYWx0ZXJuYXRpdmUgcHJvdG9jb2xzIHVzaW5nIHNlcnZpY2UgKGV2ZW4gaWYgbmRlZiBpcyBhdmFpbGFibGUpXG4gICAqL1xuICBTRVJWSUNFX09OTFkgPSAnU0VSVklDRV9PTkxZJyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUYXBDb25uZWN0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTZXQgdG8gdHJ1ZSBpZiB5b3Ugd2FudCB0byBhdXRvbWF0aWNhbGx5IGNvbm5lY3Qgd2l0aCBhIGxvbmcgcmFuZ2UgcHJvdG9jb2wgd2hlbiBjb25uZWN0aW5nIHdpdGggTkZDXG4gICAqL1xuICBzd2l0Y2hQcm90b2NvbD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSByZWdpc3RlciBhbHRlcm5hdGl2ZSBwcm90b2NvbCBtZXRob2Qgd2hlbiB3ZSBhcmUgY29ubmVjdGlvbiB0byB0aGUgdGFwXG4gICAqIFRoaXMgd2lsbCBwZXJmb3JtcyBhZGRpdGlvbmFsIHJlcXVlc3RzIGxlYWRpbmcgdG8gYSBzbG93ZXIgY29ubmVjdGlvblxuICAgKi9cbiAgcmVnaXN0ZXJQcm90b2NvbHNNZXRob2Q/OiBUYXBSZWdpc3RlclByb3RvY29sc01ldGhvZCB8IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBTZXQgdG8gdHJ1ZSB0byByZWZyZXNoIHNlc3Npb24gc3RhdGUgYWZ0ZXIgY29ubmVjdGlvblxuICAgKi9cbiAgcmVmcmVzaFNlc3Npb25TdGF0ZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRydWUgdG8gcGVyZm9ybSBORkMgcGFpcmluZyBvbiBjb25uZWN0aW9uXG4gICAqL1xuICBuZmNQYWlyaW5nPzogYm9vbGVhbjtcblxuICAvLyAvKipcbiAgLy8gICogVHJ1ZSB0byBlbmFibGUgZW5jcnlwdGlvbiB3aGlsZSB1c2luZyBORkMgcHJvdG9jb2xcbiAgLy8gICovXG4gIC8vIG5mY0VuYWJsZUVuY3J5cHRpb24/OiBib29sZWFuXG5cbiAgLyoqXG4gICAqIEVuY3J5cHRpb24ga2V5cyBmb3IgdGFwIGluaXRpYWxpemF0aW9uXG4gICAqL1xuICBlbmNyeXB0aW9uPzogRW5jcnlwdGlvbk9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFN0YXJ0IGtlZXAgYWxpdmUgKGlmIHRydWUgb3IgdW5kZWZpbmVkKVxuICAgKiBJZiBmYWxzZSwga2VlcCBhbGl2ZSBpcyBub3Qgc3RhcnRlZFxuICAgKi9cbiAga2VlcEFsaXZlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb25uZWN0aW9uRXZlbnQge1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIHRhcDogVGFwO1xufVxuXG4vKipcbiAqIFVzZXIgY2FuIHRoZSByZXBsYWNlIHdpdGggaXRzIG93biBzZXJ2aWNlXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBUYXBDb25uZWN0aW9uU2VydmljZSB7XG4gIHByaXZhdGUgdGFwRmFjdG9yeTogKHByb3RvY29sOiBDb21Qcm90b2NvbCkgPT4gVGFwID0gKHByb3RvY29sKSA9PiB7XG4gICAgcmV0dXJuIFRhcC5mcm9tUHJvdG9jb2wocHJvdG9jb2wpO1xuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdGFwU2VydmljZTogQ3VycmVudERldmljZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwcm90b2NvbEZhY3Rvcnk6IFByb3RvY29sRmFjdG9yeVNlcnZpY2VcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBUYXAgY29ubmVjdGlvbiBPYnNlcnZhYmxlIHNoYXJlZCBzdHJlYW1cbiAgICovXG4gIGNvbm5lY3QoXG4gICAgbWV0YTogUHJvdG9jb2xNZXRhLFxuICAgIGNvbmZpZzogVGFwQ29ubmVjdGlvbk9wdGlvbnNcbiAgKTogT2JzZXJ2YWJsZTxDb25uZWN0aW9uRXZlbnQ+IHtcbiAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKGVtaXR0ZXI6IFN1YnNjcmliZXI8Q29ubmVjdGlvbkV2ZW50PikgPT4ge1xuICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5jcmVhdGVDb25uZWN0aW9uT2JzZXJ2YWJsZShcbiAgICAgICAgbWV0YSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBlbWl0dGVyXG4gICAgICApLnN1YnNjcmliZSh7XG4gICAgICAgIGVycm9yOiBhc3luYyAoZXJyKSA9PiB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGBUYXAgY29ubmVjdGlvbiBmYWlsZWQgd2l0aCBlcnJvcmAsIGVycik7XG4gICAgICAgICAgYXdhaXQgdGhpcy50YXBTZXJ2aWNlXG4gICAgICAgICAgICAucmVtb3ZlKGZhbHNlKVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IGNvbnNvbGUud2FybignaWdub3JlZCBlcnJvcicsIGVycikpO1xuICAgICAgICAgIGVtaXR0ZXIuZXJyb3IoZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgY29tcGxldGU6ICgpID0+IGVtaXR0ZXIuY29tcGxldGUoKSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB9O1xuICAgIH0pLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICB9XG5cbiAgY3JlYXRlQ29ubmVjdGlvbk9ic2VydmFibGUoXG4gICAgcHJvdG9jb2xNZXRhOiBQcm90b2NvbE1ldGEsXG4gICAgY29uZmlnOiBUYXBDb25uZWN0aW9uT3B0aW9ucyxcbiAgICBlbWl0dGVyOiBTdWJzY3JpYmVyPENvbm5lY3Rpb25FdmVudD5cbiAgKSB7XG4gICAgbGV0IGNvbm5lY3RPYnNlcnZhYmxlID0gZGVmZXIoYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvdG9jb2wgPSBhd2FpdCB0aGlzLnByb3RvY29sRmFjdG9yeS5jcmVhdGUocHJvdG9jb2xNZXRhKTtcbiAgICAgIGNvbnN0IHRhcCA9IHRoaXMudGFwRmFjdG9yeShwcm90b2NvbCk7XG4gICAgICBlbWl0dGVyLm5leHQoe1xuICAgICAgICBtZXNzYWdlOiBgSW5pdGlhbGl6ZSBUYXAgZnJvbSAke3Byb3RvY29sTWV0YS50eXBlfS4uLmAsXG4gICAgICAgIHRhcCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRhcDtcbiAgICB9KTtcblxuICAgIGlmIChjb25maWcuZW5jcnlwdGlvbikge1xuICAgICAgY29uc3QgZW5jcnlwdGlvbk9wdGlvbnMgPSBjb25maWcuZW5jcnlwdGlvbjtcbiAgICAgIGNvbm5lY3RPYnNlcnZhYmxlID0gY29ubmVjdE9ic2VydmFibGUucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKGFzeW5jICh0YXApID0+IHtcbiAgICAgICAgICBlbWl0dGVyLm5leHQoe1xuICAgICAgICAgICAgbWVzc2FnZTogYEVuYWJsZSBlbmNyeXB0aW9uLi4uYCxcbiAgICAgICAgICAgIHRhcCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpZiAoZW5jcnlwdGlvbk9wdGlvbnMua2V5cykge1xuICAgICAgICAgICAgZGVidWcoVEFHLCAnU2V0IGVuY3J5cHRpb24ga2V5czogJywgZW5jcnlwdGlvbk9wdGlvbnMua2V5cyk7XG4gICAgICAgICAgICB0YXAuZW5jcnlwdGlvbi5zZXRFbmNyeXB0aW9uS2V5cyhlbmNyeXB0aW9uT3B0aW9ucy5rZXlzKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGVuY3J5cHRpb25PcHRpb25zLmVuY3J5cHRpb24pIHtcbiAgICAgICAgICAgIGlmICghdGFwLmVuY3J5cHRpb24uc2Vzc2lvbktleSAmJiAhdGFwLmlzQ29ubmVjdGVkKCkpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGFwLmNvbm5lY3QoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRhcC5lbmNyeXB0aW9uLnJlc3VtZSgpO1xuICAgICAgICAgICAgZGVidWcoVEFHLCAnRW5hYmxlIGVuY3J5cHRpb246ICcsIGVuY3J5cHRpb25PcHRpb25zLmVuY3J5cHRpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoZW5jcnlwdGlvbk9wdGlvbnMuZnJhbWVDb3VudGVyICE9IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGFwLmVuY3J5cHRpb24uc2V0RW5jcnlwdGVkRnJhbWVDb3VudGVyKFxuICAgICAgICAgICAgICBlbmNyeXB0aW9uT3B0aW9ucy5mcmFtZUNvdW50ZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0YXA7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbm5lY3RPYnNlcnZhYmxlID0gY29ubmVjdE9ic2VydmFibGUucGlwZShcbiAgICAgIHN3aXRjaE1hcChhc3luYyAodGFwKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLnRhcFNlcnZpY2UuaGFzVGFwKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy50YXBTZXJ2aWNlLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudGFwU2VydmljZS5zZXRUYXBGcm9tRXZlbnQoXG4gICAgICAgICAge1xuICAgICAgICAgICAgcHJvdG9jb2xNZXRhOiBwcm90b2NvbE1ldGEsXG4gICAgICAgICAgICB0YXA6IHRhcCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGVtaXQ6IGZhbHNlLCAvLyBXZSBlbWl0IG9ubHkgYXQgdGhlIGVuZCBvZiBpbml0aWFsaXNhdGlvblxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdGFwLmtlZXBBbGl2ZS5zdG9wKCk7XG4gICAgICAgIHJldHVybiB0YXA7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICBpZiAocHJvdG9jb2xNZXRhLnR5cGUgPT09ICduZmMnKSB7XG4gICAgICBpZiAoY29uZmlnLm5mY1BhaXJpbmcpIHtcbiAgICAgICAgY29ubmVjdE9ic2VydmFibGUgPSBjb25uZWN0T2JzZXJ2YWJsZS5waXBlKFxuICAgICAgICAgIHN3aXRjaE1hcChhc3luYyAodGFwKSA9PiB7XG4gICAgICAgICAgICBlbWl0dGVyLm5leHQoe1xuICAgICAgICAgICAgICBtZXNzYWdlOiBgTkZDIHBhaXJpbmcuLi5gLFxuICAgICAgICAgICAgICB0YXAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRlYnVnKFRBRywgJ25mY1BhaXJpbmcnKTtcbiAgICAgICAgICAgIGF3YWl0IHRhcC5jb25uZWN0KCk7XG4gICAgICAgICAgICBhd2FpdCB0YXAubmZjUGFpcmluZygpO1xuICAgICAgICAgICAgcmV0dXJuIHRhcDtcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb25maWcucmVnaXN0ZXJQcm90b2NvbHNNZXRob2QgIT09IGZhbHNlKSB7XG4gICAgICBjb25uZWN0T2JzZXJ2YWJsZSA9IGNvbm5lY3RPYnNlcnZhYmxlLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcChhc3luYyAodGFwKSA9PiB7XG4gICAgICAgICAgaWYgKCF0YXAuaXNDb25uZWN0ZWQoKSkge1xuICAgICAgICAgICAgZW1pdHRlci5uZXh0KHtcbiAgICAgICAgICAgICAgbWVzc2FnZTogYENvbm5lY3Rpbmcgd2l0aCAke3Byb3RvY29sTWV0YS50eXBlfS4uLmAsXG4gICAgICAgICAgICAgIHRhcCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYXdhaXQgdGFwLmNvbm5lY3QoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZW1pdHRlci5uZXh0KHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IGBJbml0aWFsaXppbmcgcHJvdG9jb2xzLi4uYCxcbiAgICAgICAgICAgIHRhcCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyQWx0ZXJuYXRpdmVQcm90b2NvbHMoXG4gICAgICAgICAgICBjb25maWcucmVnaXN0ZXJQcm90b2NvbHNNZXRob2QsXG4gICAgICAgICAgICBwcm90b2NvbE1ldGFcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiB0YXA7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHN3aXRjaFByb3RvY29sID0gY29uZmlnLnN3aXRjaFByb3RvY29sO1xuICAgIGlmIChwcm90b2NvbE1ldGEudHlwZSA9PT0gJ25mYycpIHtcbiAgICAgIGNvbm5lY3RPYnNlcnZhYmxlID0gY29ubmVjdE9ic2VydmFibGUucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKGFzeW5jICh0YXApID0+IHtcbiAgICAgICAgICBpZiAoc3dpdGNoUHJvdG9jb2wpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3RvY29sTWV0YSA9IHRoaXMudGFwU2VydmljZS5hdmFpbGFibGVQcm90b2NvbHMuZmluZChcbiAgICAgICAgICAgICAgTE9OR19SQU5HRV9QUk9UT0NPTF9GSUxURVJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAocHJvdG9jb2xNZXRhKSB7XG4gICAgICAgICAgICAgIGRlYnVnKFRBRywgJ1VzaW5nIGxvbmcgcmFuZ2UgcHJvdG9jb2w6ICcsIHByb3RvY29sTWV0YSk7XG4gICAgICAgICAgICAgIGVtaXR0ZXIubmV4dCh7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYFN3aXRjaCB0byAke3Byb3RvY29sTWV0YS50eXBlfWAsXG4gICAgICAgICAgICAgICAgdGFwLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy50YXBTZXJ2aWNlLnVzZVByb3RvY29sRnJvbU1ldGEocHJvdG9jb2xNZXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVidWcoVEFHLCAna2VlcCBORkMgcHJvdG9jb2wnKTtcbiAgICAgICAgICAgIGNvbnN0IG5mY1Byb3RvY29sID0gdGFwLnByb3RvY29sIGFzIE5GQ0NvbVByb3RvY29sO1xuICAgICAgICAgICAgLy8gZm9yIE5GQyBjb25uZWN0aW9uXG4gICAgICAgICAgICBhd2FpdCBuZmNQcm90b2NvbC5fY29ubmVjdCgpLnRvUHJvbWlzZSgpO1xuICAgICAgICAgICAgbmZjUHJvdG9jb2wuc2V0Q29ubmVjdGlvblN0YXRlKENvbm5lY3Rpb25TdGF0ZS5DT05ORUNURUQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGFwO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLnJlZnJlc2hTZXNzaW9uU3RhdGUpIHtcbiAgICAgIGNvbm5lY3RPYnNlcnZhYmxlID0gY29ubmVjdE9ic2VydmFibGUucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKGFzeW5jICh0YXApID0+IHtcbiAgICAgICAgICBkZWJ1ZyhUQUcsICdyZWZyZXNoU2Vzc2lvblN0YXRlJyk7XG4gICAgICAgICAgZW1pdHRlci5uZXh0KHtcbiAgICAgICAgICAgIG1lc3NhZ2U6ICdSZWZyZXNoaW5nIHVzZXIgc2Vzc2lvbi4uLicsXG4gICAgICAgICAgICB0YXAsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYXdhaXQgdGFwLmF1dGgucmVmcmVzaFNlc3Npb25TdGF0ZSgpO1xuICAgICAgICAgIHJldHVybiB0YXA7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChjb25maWcua2VlcEFsaXZlICE9PSBmYWxzZSkge1xuICAgICAgY29ubmVjdE9ic2VydmFibGUgPSBjb25uZWN0T2JzZXJ2YWJsZS5waXBlKFxuICAgICAgICB0YXAoKHRhcCkgPT4ge1xuICAgICAgICAgIHRhcC5rZWVwQWxpdmUuc3RhcnQoKTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbm5lY3RPYnNlcnZhYmxlLnBpcGUoXG4gICAgICBtYXAoKHRhcCkgPT4ge1xuICAgICAgICB0aGlzLnRhcFNlcnZpY2Uubm90aWZ5TmV3VGFwKCk7XG4gICAgICAgIHJldHVybiB0YXA7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKG9yaWdpbmFsRXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS53YXJuKGBUYXAgY29ubmVjdGlvbiBmYWlsZWQgd2l0aCBlcnJvcmAsIG9yaWdpbmFsRXJyb3IpO1xuICAgICAgICByZXR1cm4gZGVmZXIoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHRoaXMudGFwU2VydmljZVxuICAgICAgICAgICAgLnJlbW92ZShmYWxzZSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiBjb25zb2xlLndhcm4oJ2lnbm9yZWQgZXJyb3InLCBlcnIpKTtcbiAgICAgICAgICB0aHJvdyBvcmlnaW5hbEVycm9yO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHJlZ2lzdGVyQWx0ZXJuYXRpdmVQcm90b2NvbHMoXG4gICAgcmVnaXN0ZXJBbHRlcm5hdGl2ZVByb3RvY29sTWV0aG9kOlxuICAgICAgfCBUYXBSZWdpc3RlclByb3RvY29sc01ldGhvZFxuICAgICAgfCBmYWxzZVxuICAgICAgfCB1bmRlZmluZWQsXG4gICAgaW5pdGlhbFByb3RvY29sTWV0YTogUHJvdG9jb2xNZXRhXG4gICkge1xuICAgIGlmIChyZWdpc3RlckFsdGVybmF0aXZlUHJvdG9jb2xNZXRob2QgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlZ2lzdGVyQWx0ZXJuYXRpdmVQcm90b2NvbE1ldGhvZCA9XG4gICAgICByZWdpc3RlckFsdGVybmF0aXZlUHJvdG9jb2xNZXRob2QgfHxcbiAgICAgIFRhcFJlZ2lzdGVyUHJvdG9jb2xzTWV0aG9kLk5ERUZfT1JfU0VSVklDRTtcbiAgICBkZWJ1ZyhcbiAgICAgIFRBRyxcbiAgICAgIGBSZWdpc3RlciBhbHRlcm5hdGl2ZSBwcm90b2NvbHMgd2l0aCBtZXRob2Q6ICR7cmVnaXN0ZXJBbHRlcm5hdGl2ZVByb3RvY29sTWV0aG9kfWBcbiAgICApO1xuICAgIGNvbnN0IHRhcCA9IHRoaXMudGFwU2VydmljZS50YXA7XG4gICAgc3dpdGNoIChyZWdpc3RlckFsdGVybmF0aXZlUHJvdG9jb2xNZXRob2QpIHtcbiAgICAgIGNhc2UgVGFwUmVnaXN0ZXJQcm90b2NvbHNNZXRob2QuTkRFRl9PUl9TRVJWSUNFOlxuICAgICAgICBsZXQgcmVnaXN0ZXJlZFByb3RvY29sTWV0YTogUHJvdG9jb2xNZXRhIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIXRhcC5pc0Nvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgYXdhaXQgdGFwLmNvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5pdGlhbFByb3RvY29sTWV0YS50eXBlID09PSAnbmZjJykge1xuICAgICAgICAgIHJlZ2lzdGVyZWRQcm90b2NvbE1ldGEgPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy50YXBTZXJ2aWNlLnJlZ2lzdGVyUHJvdG9jb2xzRnJvbVRhZyhcbiAgICAgICAgICAgICAgaW5pdGlhbFByb3RvY29sTWV0YS5pbmZvLnRhZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnRhcFNlcnZpY2UucmVnaXN0ZXJQcm90b2NvbHNGcm9tVGFwKCkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdGYWlsZWQgdG8gcmVnaXN0ZXIgcHJvdG9jb2xzIGZyb20gdGFwJywgZXJyKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVGFwUmVnaXN0ZXJQcm90b2NvbHNNZXRob2QuU0VSVklDRV9PTkxZOlxuICAgICAgICBpZiAoIXRhcC5pc0Nvbm5lY3RlZCgpKSB7XG4gICAgICAgICAgYXdhaXQgdGFwLmNvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLnRhcFNlcnZpY2UucmVnaXN0ZXJQcm90b2NvbHNGcm9tVGFwKCkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUud2FybignRmFpbGVkIHRvIHJlZ2lzdGVyIHByb3RvY29scyBmcm9tIHRhcCcsIGVycik7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVGFwUmVnaXN0ZXJQcm90b2NvbHNNZXRob2QuTkRFRl9PTkxZOlxuICAgICAgICBpZiAoaW5pdGlhbFByb3RvY29sTWV0YS50eXBlID09PSAnbmZjJykge1xuICAgICAgICAgIGF3YWl0IHRoaXMudGFwU2VydmljZS5yZWdpc3RlclByb3RvY29sc0Zyb21UYWcoXG4gICAgICAgICAgICBpbml0aWFsUHJvdG9jb2xNZXRhLmluZm8udGFnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn1cbiJdfQ==