UNPKG

@iotize/ionic

Version:

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

161 lines 22.8 kB
import { Injectable } from '@angular/core'; import { Platform } from '@ionic/angular'; import { toError } from '@iotize/app-common'; import { bufferToHexString, hexStringToBuffer, } from '@iotize/common/byte-converter'; import { NEVER, ReplaySubject, Subject } from 'rxjs'; import { catchError, filter, share, switchMap } from 'rxjs/operators'; import { debug } from '../../logger'; import { NFC } from '../../nfc'; import * as i0 from "@angular/core"; import * as i1 from "../../nfc"; import * as i2 from "@ionic/angular"; const TAG = 'NfcService'; export class NfcService { constructor(nfc, platform) { this.nfc = nfc; this.platform = platform; this._tagDiscoveredListener = new Subject(); this.tagDiscoveredEvents = this._tagDiscoveredListener.pipe(switchMap((v) => v), share()); this._ndefDiscoveredListener = new ReplaySubject(); this.ndefDiscoveredEvents = this._ndefDiscoveredListener.pipe(switchMap((v) => v)); this._tapDeviceDiscoveredEvent = new ReplaySubject(); this.tapDeviceDiscoveredEvent = this._tapDeviceDiscoveredEvent.pipe(switchMap((v) => v)); } async write(data) { try { await this.nfc.write(data); } catch (err) { if (err === 'cordova_not_available') { err = new Error(`NFC is not available on this device`); } throw err; } } async transceive(data) { const rawResponse = await this.nfc.transceive(data); const response = parseNFCTransceiveResponse(data, rawResponse); console.debug(`NFC transceive ${bufferToHexString(data)} => 0x${bufferToHexString(response)}`); return response; } async isEnabled() { try { return await this.nfc.enabled(); } catch (err) { console.error('NFC enabled error', err); return false; } } async setupTagDiscoveredListenerOnce() { if (this._setupTagDiscoveredListenerPromise) { return await this._setupTagDiscoveredListenerPromise; } else { return await this.setupTagDiscoveredListener(); } } async setupTapDeviceDiscoveredListener() { this._setupTapDeviceDiscoveredListenerPromise = createCatchSafePromise((resolve, reject) => { const tapDeviceDiscoveredListener = this.nfc.addTapDeviceListener(() => { resolve(); }, (err) => { reject(err); }); this._tapDeviceDiscoveredEvent.next(tapDeviceDiscoveredListener); }, 5000); await this._setupTapDeviceDiscoveredListenerPromise; } async setupTagDiscoveredListener() { this._setupTagDiscoveredListenerPromise = createCatchSafePromise((resolve, reject) => { debug(TAG, 'Adding TAG discovered listener...'); this._tagDiscoveredListener.next(this.nfc .addTagDiscoveredListener(() => { debug(TAG, 'NFC Tag discovered listener OK!'); resolve(); }, (error) => { debug(TAG, `NFC Tag discovered listener didn't start`, error); reject(error); }) .pipe(catchError((err) => { const error = toError(err); console.warn(`NFC Tag listener failed to initialize: ${error.message}`, err); reject(error); return NEVER; }), filter((event) => !!event) // First event is undefined ... )); }, 5000); await this._setupTagDiscoveredListenerPromise; } async setupNdefListener() { return await createCatchSafePromise((resolve, _reject) => { this._ndefDiscoveredListener.next(this.nfc .addNdefListener() // @warning callbacks are never called... .pipe(catchError((err) => { const error = toError(err); console.warn(`NDEF listener failed to initialize: ${error.message}`, err); return NEVER; }))); resolve(); }, 5000); } async closeNFC() { await this.nfc.close(); } /** * iOS specific commands */ async beginSessionFromTech(tech, alertMessage) { if (!this.platform.is('ios')) { return; } return this.nfc.beginSessionFromTech(tech, alertMessage); } async closeSession() { return this.nfc.closeSession(); } } /** @nocollapse */ NfcService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NfcService, deps: [{ token: i1.NFC }, { token: i2.Platform }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ NfcService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NfcService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NfcService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.NFC }, { type: i2.Platform }]; } }); function createCatchSafePromise(callback, timeout) { return new Promise((resolve, reject) => { if (timeout) { setTimeout(() => { reject(new Error(`Native code did not respond before timeout of ${timeout}ms`)); }, timeout); } try { callback(resolve, reject); } catch (error) { reject(error); } }); } function parseNFCTransceiveResponse(frame, resultBufferOrString) { if (!resultBufferOrString) { return new Uint8Array(0); } if (typeof resultBufferOrString === 'object') { if ('error' in resultBufferOrString) { const errorString = resultBufferOrString.error === 'cordova_not_available' ? `NFC is not available` : resultBufferOrString.error; throw new Error(`Failed to NFC transceive frame 0x${bufferToHexString(frame)} (error: ${errorString})`); } } if (typeof resultBufferOrString === 'string') { return hexStringToBuffer(resultBufferOrString); } else { return Buffer.from(resultBufferOrString); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZjLXNlcnZpY2Uuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9zcmMvbGliL3RhcC1zY2FubmVyL3RhcC1zY2FubmVyLW5mYy9uZmMtc2VydmljZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLGlCQUFpQixHQUNsQixNQUFNLCtCQUErQixDQUFDO0FBRXZDLE9BQU8sRUFBRSxLQUFLLEVBQWMsYUFBYSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFPLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0UsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyQyxPQUFPLEVBQUUsR0FBRyxFQUFzQixNQUFNLFdBQVcsQ0FBQzs7OztBQUdwRCxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUM7QUFlekIsTUFBTSxPQUFPLFVBQVU7SUE4QnJCLFlBQW1CLEdBQVEsRUFBVSxRQUFrQjtRQUFwQyxRQUFHLEdBQUgsR0FBRyxDQUFLO1FBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQTdCL0MsMkJBQXNCLEdBQUcsSUFBSSxPQUFPLEVBRXpDLENBQUM7UUFFSyx3QkFBbUIsR0FDMUIsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FDOUIsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFDbkIsS0FBSyxFQUFFLENBQ1IsQ0FBQztR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LE9BQU8sS0FBSyxFQUFFO1lBQ2QsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ2Y7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLDBCQUEwQixDQUNqQyxLQUFpQixFQUNqQixvQkFLUTtJQUVSLElBQUksQ0FBQyxvQkFBb0IsRUFBRTtRQUN6QixPQUFPLElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzFCO0lBQ0QsSUFBSSxPQUFPLG9CQUFvQixLQUFLLFFBQVEsRUFBRTtRQUM1QyxJQUFJLE9BQU8sSUFBSSxvQkFBb0IsRUFBRTtZQUNuQyxNQUFNLFdBQVcsR0FDZixvQkFBb0IsQ0FBQyxLQUFLLEtBQUssdUJBQXVCO2dCQUNwRCxDQUFDLENBQUMsc0JBQXNCO2dCQUN4QixDQUFDLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDO1lBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQ2Isb0NBQW9DLGlCQUFpQixDQUNuRCxLQUFLLENBQ04sWUFBWSxXQUFXLEdBQUcsQ0FDNUIsQ0FBQztTQUNIO0tBQ0Y7SUFFRCxJQUFJLE9BQU8sb0JBQW9CLEtBQUssUUFBUSxFQUFFO1FBQzVDLE9BQU8saUJBQWlCLENBQUMsb0JBQW9CLENBQUMsQ0FBQztLQUNoRDtTQUFNO1FBQ0wsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUM7S0FDMUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUGxhdGZvcm0gfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyB0b0Vycm9yIH0gZnJvbSAnQGlvdGl6ZS9hcHAtY29tbW9uJztcbmltcG9ydCB7XG4gIGJ1ZmZlclRvSGV4U3RyaW5nLFxuICBoZXhTdHJpbmdUb0J1ZmZlcixcbn0gZnJvbSAnQGlvdGl6ZS9jb21tb24vYnl0ZS1jb252ZXJ0ZXInO1xuaW1wb3J0IHsgRW5jcnlwdGlvbk9wdGlvbnMgfSBmcm9tICdAaW90aXplL3RhcC9hdXRoJztcbmltcG9ydCB7IE5FVkVSLCBPYnNlcnZhYmxlLCBSZXBsYXlTdWJqZWN0LCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBmaWx0ZXIsIHNoYXJlLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi4vLi4vbG9nZ2VyJztcbmltcG9ydCB7IE5GQywgTmRlZkV2ZW50LCBOZGVmVGFnIH0gZnJvbSAnLi4vLi4vbmZjJztcbmltcG9ydCB7IFRhZ0Rpc2NvdmVyZWRFdmVudCB9IGZyb20gJy4vZGVmaW5pdGlvbnMnO1xuXG5jb25zdCBUQUcgPSAnTmZjU2VydmljZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3ZlcmFibGVUYXBTdGF0ZUV2ZW50IHtcbiAgdGFnOiBOZGVmVGFnO1xuICB0YXA6IFJlY292ZXJhYmxlVGFwU3RhdGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3ZlcmFibGVUYXBTdGF0ZSB7XG4gIG5mY1BhaXJpbmdEb25lPzogYm9vbGVhbjtcbiAgZW5jcnlwdGlvbj86IEVuY3J5cHRpb25PcHRpb25zO1xufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgTmZjU2VydmljZSB7XG4gIHByaXZhdGUgX3RhZ0Rpc2NvdmVyZWRMaXN0ZW5lciA9IG5ldyBTdWJqZWN0PFxuICAgIE9ic2VydmFibGU8VGFnRGlzY292ZXJlZEV2ZW50PlxuICA+KCk7XG5cbiAgcmVhZG9ubHkgdGFnRGlzY292ZXJlZEV2ZW50czogT2JzZXJ2YWJsZTxUYWdEaXNjb3ZlcmVkRXZlbnQ+ID1cbiAgICB0aGlzLl90YWdEaXNjb3ZlcmVkTGlzdGVuZXIucGlwZShcbiAgICAgIHN3aXRjaE1hcCgodikgPT4gdiksXG4gICAgICBzaGFyZSgpXG4gICAgKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9uZGVmRGlzY292ZXJlZExpc3RlbmVyID0gbmV3IFJlcGxheVN1YmplY3Q8XG4gICAgT2JzZXJ2YWJsZTxOZGVmRXZlbnQ+XG4gID4oKTtcblxuICByZWFkb25seSBuZGVmRGlzY292ZXJlZEV2ZW50cyA9IHRoaXMuX25kZWZEaXNjb3ZlcmVkTGlzdGVuZXIucGlwZShcbiAgICBzd2l0Y2hNYXAoKHYpID0+IHYpXG4gICk7XG5cbiAgcHJpdmF0ZSBfdGFwRGV2aWNlRGlzY292ZXJlZEV2ZW50ID0gbmV3IFJlcGxheVN1YmplY3Q8XG4gICAgT2JzZXJ2YWJsZTxSZWNvdmVyYWJsZVRhcFN0YXRlRXZlbnQ+XG4gID4oKTtcblxuICByZWFkb25seSB0YXBEZXZpY2VEaXNjb3ZlcmVkRXZlbnQgPSB0aGlzLl90YXBEZXZpY2VEaXNjb3ZlcmVkRXZlbnQucGlwZShcbiAgICBzd2l0Y2hNYXAoKHYpID0+IHYpXG4gICk7XG5cbiAgcHJpdmF0ZSBfc2V0dXBUYXBEZXZpY2VEaXNjb3ZlcmVkTGlzdGVuZXJQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcbiAgcHJpdmF0ZSBfc2V0dXBUYWdEaXNjb3ZlcmVkTGlzdGVuZXJQcm9taXNlPzogUHJvbWlzZTx2b2lkPjtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgbmZjOiBORkMsIHByaXZhdGUgcGxhdGZvcm06IFBsYXRmb3JtKSB7fVxuXG4gIGFzeW5jIHdyaXRlKGRhdGE6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubmZjLndyaXRlKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciA9PT0gJ2NvcmRvdmFfbm90X2F2YWlsYWJsZScpIHtcbiAgICAgICAgZXJyID0gbmV3IEVycm9yKGBORkMgaXMgbm90IGF2YWlsYWJsZSBvbiB0aGlzIGRldmljZWApO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHRyYW5zY2VpdmUoZGF0YTogVWludDhBcnJheSk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IHJhd1Jlc3BvbnNlID0gYXdhaXQgdGhpcy5uZmMudHJhbnNjZWl2ZShkYXRhKTtcbiAgICBjb25zdCByZXNwb25zZSA9IHBhcnNlTkZDVHJhbnNjZWl2ZVJlc3BvbnNlKGRhdGEsIHJhd1Jlc3BvbnNlKTtcbiAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgYE5GQyB0cmFuc2NlaXZlICR7YnVmZmVyVG9IZXhTdHJpbmcoZGF0YSl9ID0+IDB4JHtidWZmZXJUb0hleFN0cmluZyhcbiAgICAgICAgcmVzcG9uc2VcbiAgICAgICl9YFxuICAgICk7XG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgYXN5bmMgaXNFbmFibGVkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5uZmMuZW5hYmxlZCgpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcignTkZDIGVuYWJsZWQgZXJyb3InLCBlcnIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNldHVwVGFnRGlzY292ZXJlZExpc3RlbmVyT25jZSgpIHtcbiAgICBpZiAodGhpcy5fc2V0dXBUYWdEaXNjb3ZlcmVkTGlzdGVuZXJQcm9taXNlKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5fc2V0dXBUYWdEaXNjb3ZlcmVkTGlzdGVuZXJQcm9taXNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5zZXR1cFRhZ0Rpc2NvdmVyZWRMaXN0ZW5lcigpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNldHVwVGFwRGV2aWNlRGlzY292ZXJlZExpc3RlbmVyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuX3NldHVwVGFwRGV2aWNlRGlzY292ZXJlZExpc3RlbmVyUHJvbWlzZSA9XG4gICAgICBjcmVhdGVDYXRjaFNhZmVQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgdGFwRGV2aWNlRGlzY292ZXJlZExpc3RlbmVyID0gdGhpcy5uZmMuYWRkVGFwRGV2aWNlTGlzdGVuZXIoXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgKGVycj86IEVycm9yKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuX3RhcERldmljZURpc2NvdmVyZWRFdmVudC5uZXh0KHRhcERldmljZURpc2NvdmVyZWRMaXN0ZW5lcik7XG4gICAgICB9LCA1MDAwKTtcbiAgICBhd2FpdCB0aGlzLl9zZXR1cFRhcERldmljZURpc2NvdmVyZWRMaXN0ZW5lclByb21pc2U7XG4gIH1cblxuICBhc3luYyBzZXR1cFRhZ0Rpc2NvdmVyZWRMaXN0ZW5lcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLl9zZXR1cFRhZ0Rpc2NvdmVyZWRMaXN0ZW5lclByb21pc2UgPSBjcmVhdGVDYXRjaFNhZmVQcm9taXNlPHZvaWQ+KFxuICAgICAgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBkZWJ1ZyhUQUcsICdBZGRpbmcgVEFHIGRpc2NvdmVyZWQgbGlzdGVuZXIuLi4nKTtcbiAgICAgICAgdGhpcy5fdGFnRGlzY292ZXJlZExpc3RlbmVyLm5leHQoXG4gICAgICAgICAgdGhpcy5uZmNcbiAgICAgICAgICAgIC5hZGRUYWdEaXNjb3ZlcmVkTGlzdGVuZXIoXG4gICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBkZWJ1ZyhUQUcsICdORkMgVGFnIGRpc2NvdmVyZWQgbGlzdGVuZXIgT0shJyk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgZGVidWcoVEFHLCBgTkZDIFRhZyBkaXNjb3ZlcmVkIGxpc3RlbmVyIGRpZG4ndCBzdGFydGAsIGVycm9yKTtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB0b0Vycm9yKGVycik7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgYE5GQyBUYWcgbGlzdGVuZXIgZmFpbGVkIHRvIGluaXRpYWxpemU6ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgICAgICAgICAgICAgZXJyXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIGZpbHRlcigoZXZlbnQpID0+ICEhZXZlbnQpIC8vIEZpcnN0IGV2ZW50IGlzIHVuZGVmaW5lZCAuLi5cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgICA1MDAwXG4gICAgKTtcbiAgICBhd2FpdCB0aGlzLl9zZXR1cFRhZ0Rpc2NvdmVyZWRMaXN0ZW5lclByb21pc2U7XG4gIH1cblxuICBhc3luYyBzZXR1cE5kZWZMaXN0ZW5lcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gYXdhaXQgY3JlYXRlQ2F0Y2hTYWZlUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgX3JlamVjdCkgPT4ge1xuICAgICAgdGhpcy5fbmRlZkRpc2NvdmVyZWRMaXN0ZW5lci5uZXh0KFxuICAgICAgICB0aGlzLm5mY1xuICAgICAgICAgIC5hZGROZGVmTGlzdGVuZXIoKSAvLyBAd2FybmluZyBjYWxsYmFja3MgYXJlIG5ldmVyIGNhbGxlZC4uLlxuICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gdG9FcnJvcihlcnIpO1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgYE5ERUYgbGlzdGVuZXIgZmFpbGVkIHRvIGluaXRpYWxpemU6ICR7ZXJyb3IubWVzc2FnZX1gLFxuICAgICAgICAgICAgICAgIGVyclxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICByZXR1cm4gTkVWRVI7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgIClcbiAgICAgICk7XG4gICAgICByZXNvbHZlKCk7XG4gICAgfSwgNTAwMCk7XG4gIH1cblxuICBhc3luYyBjbG9zZU5GQygpIHtcbiAgICBhd2FpdCB0aGlzLm5mYy5jbG9zZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGlPUyBzcGVjaWZpYyBjb21tYW5kc1xuICAgKi9cbiAgYXN5bmMgYmVnaW5TZXNzaW9uRnJvbVRlY2goXG4gICAgdGVjaDogc3RyaW5nLFxuICAgIGFsZXJ0TWVzc2FnZT86IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMucGxhdGZvcm0uaXMoJ2lvcycpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm5mYy5iZWdpblNlc3Npb25Gcm9tVGVjaCh0ZWNoLCBhbGVydE1lc3NhZ2UpO1xuICB9XG5cbiAgYXN5bmMgY2xvc2VTZXNzaW9uKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLm5mYy5jbG9zZVNlc3Npb24oKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVDYXRjaFNhZmVQcm9taXNlPFQ+KFxuICBjYWxsYmFjazogKFxuICAgIHJlc29sdmU6ICh2YWx1ZTogVCB8IFByb21pc2VMaWtlPFQ+KSA9PiB2b2lkLFxuICAgIHJlamVjdDogKHJlYXNvbj86IGFueSkgPT4gdm9pZFxuICApID0+IHZvaWQsXG4gIHRpbWVvdXQ/OiBudW1iZXJcbik6IFByb21pc2U8VD4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8VD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgcmVqZWN0KFxuICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBOYXRpdmUgY29kZSBkaWQgbm90IHJlc3BvbmQgYmVmb3JlIHRpbWVvdXQgb2YgJHt0aW1lb3V0fW1zYFxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH0sIHRpbWVvdXQpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY2FsbGJhY2socmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJzZU5GQ1RyYW5zY2VpdmVSZXNwb25zZShcbiAgZnJhbWU6IFVpbnQ4QXJyYXksXG4gIHJlc3VsdEJ1ZmZlck9yU3RyaW5nOlxuICAgIHwgQXJyYXlCdWZmZXJcbiAgICB8IHN0cmluZ1xuICAgIHwgeyBlcnJvcj86IHN0cmluZyB9XG4gICAgfCB1bmRlZmluZWRcbiAgICB8IG51bGxcbikge1xuICBpZiAoIXJlc3VsdEJ1ZmZlck9yU3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO1xuICB9XG4gIGlmICh0eXBlb2YgcmVzdWx0QnVmZmVyT3JTdHJpbmcgPT09ICdvYmplY3QnKSB7XG4gICAgaWYgKCdlcnJvcicgaW4gcmVzdWx0QnVmZmVyT3JTdHJpbmcpIHtcbiAgICAgIGNvbnN0IGVycm9yU3RyaW5nID1cbiAgICAgICAgcmVzdWx0QnVmZmVyT3JTdHJpbmcuZXJyb3IgPT09ICdjb3Jkb3ZhX25vdF9hdmFpbGFibGUnXG4gICAgICAgICAgPyBgTkZDIGlzIG5vdCBhdmFpbGFibGVgXG4gICAgICAgICAgOiByZXN1bHRCdWZmZXJPclN0cmluZy5lcnJvcjtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZhaWxlZCB0byBORkMgdHJhbnNjZWl2ZSBmcmFtZSAweCR7YnVmZmVyVG9IZXhTdHJpbmcoXG4gICAgICAgICAgZnJhbWVcbiAgICAgICAgKX0gKGVycm9yOiAke2Vycm9yU3RyaW5nfSlgXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0eXBlb2YgcmVzdWx0QnVmZmVyT3JTdHJpbmcgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGhleFN0cmluZ1RvQnVmZmVyKHJlc3VsdEJ1ZmZlck9yU3RyaW5nKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20ocmVzdWx0QnVmZmVyT3JTdHJpbmcpO1xuICB9XG59XG4iXX0=