ngx-turnstile
Version:
Angular component for Cloudflare Turnstile
261 lines • 32.4 kB
JavaScript
import { Component, Input, Output, EventEmitter, Inject, PLATFORM_ID, afterNextRender, signal, computed, } from '@angular/core';
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
import * as i0 from "@angular/core";
const SCRIPT_ID = 'ngx-turnstile';
const CALLBACK_NAME = 'onloadTurnstileCallback';
// Every mounted component waiting for the Turnstile script to finish loading.
// A single global onload callback notifies all of them, so multiple widgets on
// the same page each get rendered (not just the last one that was created).
const scriptLoadListeners = new Set();
export class NgxTurnstileComponent {
elementRef;
zone;
document;
platformId;
siteKey;
action;
cData;
theme = 'auto';
language = 'auto';
version = '0';
tabIndex;
appearance = 'always';
execution;
retry = 'auto';
retryInterval;
refreshExpired;
refreshTimeout;
size = 'normal';
responseField;
responseFieldName;
feedbackEnabled;
offlabelShowPrivacy;
offlabelShowHelp;
resolved = new EventEmitter();
errored = new EventEmitter();
beforeInteractive = new EventEmitter();
afterInteractive = new EventEmitter();
unsupported = new EventEmitter();
timeout = new EventEmitter();
widgetId = signal(undefined);
/** Whether the Cloudflare Turnstile script has finished loading. */
scriptLoaded = signal(false);
/** Whether a widget is currently rendered. Clients can watch this signal. */
widgetLoaded = computed(() => !!this.widgetId());
// Notifies this instance when the shared script finishes loading. Kept as a
// stable reference so it can be removed from the listener set on destroy.
onScriptLoad = () => this.zone.run(() => this.scriptLoaded.set(true));
constructor(elementRef, zone, document, platformId) {
this.elementRef = elementRef;
this.zone = zone;
this.document = document;
this.platformId = platformId;
// Touching `window` is only safe in the browser (skip during SSR).
if (isPlatformBrowser(this.platformId)) {
this.loadScript();
}
// Render once the host element exists (if the script is already loaded).
afterNextRender(() => {
if (this.scriptLoaded() && !this.widgetLoaded()) {
this.createWidget();
}
});
// Render once the script finishes loading (if not already rendered).
toObservable(this.scriptLoaded)
.pipe(takeUntilDestroyed())
.subscribe((scriptLoaded) => {
if (scriptLoaded && !this.widgetLoaded()) {
this.createWidget();
}
});
}
_getCloudflareTurnstileUrl() {
if (this.version === '0') {
return 'https://challenges.cloudflare.com/turnstile/v0/api.js';
}
throw 'Version not defined in ngx-turnstile component.';
}
loadScript() {
// Script already present (e.g. loaded by another widget or a prior route).
if (window.turnstile) {
this.scriptLoaded.set(true);
return;
}
// Register to be notified when the shared script finishes loading.
scriptLoadListeners.add(this.onScriptLoad);
// A single global callback fans out to every waiting instance.
window[CALLBACK_NAME] = () => {
// Copy then clear so a listener re-registering mid-notification is safe.
const listeners = Array.from(scriptLoadListeners);
scriptLoadListeners.clear();
listeners.forEach((listener) => listener());
};
// Only inject the script once, even with several widgets on the page.
const scriptPending = !!this.document.getElementById(SCRIPT_ID);
if (!scriptPending) {
const script = this.document.createElement('script');
script.src = `${this._getCloudflareTurnstileUrl()}?render=explicit&onload=${CALLBACK_NAME}`;
script.id = SCRIPT_ID;
script.async = true;
script.defer = true;
this.document.head.appendChild(script);
}
}
createWidget() {
// Only render once the script is loaded and the host element exists.
if (!this.scriptLoaded() || !this.elementRef?.nativeElement) {
return;
}
const turnstileOptions = {
sitekey: this.siteKey,
theme: this.theme,
language: this.language,
tabindex: this.tabIndex,
action: this.action,
cData: this.cData,
appearance: this.appearance,
retry: this.retry,
size: this.size,
callback: (token) => {
this.zone.run(() => this.resolved.emit(token));
},
'error-callback': (errorCode) => {
this.zone.run(() => this.errored.emit(errorCode));
// Returning false causes Turnstile to log error code as a console warning.
return false;
},
'expired-callback': () => {
this.zone.run(() => this.reset());
},
'before-interactive-callback': () => {
this.zone.run(() => this.beforeInteractive.emit());
},
'after-interactive-callback': () => {
this.zone.run(() => this.afterInteractive.emit());
},
'unsupported-callback': () => {
this.zone.run(() => this.unsupported.emit());
},
'timeout-callback': () => {
this.zone.run(() => this.timeout.emit());
},
};
// Only forward optional parameters when set, so we never override
// Cloudflare's defaults with an explicit `undefined`.
if (this.execution !== undefined) {
turnstileOptions.execution = this.execution;
}
if (this.retryInterval !== undefined) {
turnstileOptions['retry-interval'] = this.retryInterval;
}
if (this.refreshExpired !== undefined) {
turnstileOptions['refresh-expired'] = this.refreshExpired;
}
if (this.refreshTimeout !== undefined) {
turnstileOptions['refresh-timeout'] = this.refreshTimeout;
}
if (this.responseField !== undefined) {
turnstileOptions['response-field'] = this.responseField;
}
if (this.responseFieldName !== undefined) {
turnstileOptions['response-field-name'] = this.responseFieldName;
}
if (this.feedbackEnabled !== undefined) {
turnstileOptions['feedback-enabled'] = this.feedbackEnabled;
}
if (this.offlabelShowPrivacy !== undefined) {
turnstileOptions['offlabel-show-privacy'] = this.offlabelShowPrivacy;
}
if (this.offlabelShowHelp !== undefined) {
turnstileOptions['offlabel-show-help'] = this.offlabelShowHelp;
}
// Remove any existing widget so re-rendering doesn't create duplicates.
this.remove();
this.widgetId.set(window.turnstile.render(this.elementRef.nativeElement, turnstileOptions));
}
reset() {
if (this.widgetLoaded()) {
this.resolved.emit(null);
window.turnstile.reset(this.widgetId());
}
}
remove() {
if (this.widgetLoaded()) {
window.turnstile.remove(this.widgetId());
this.widgetId.set(undefined);
}
}
ngOnDestroy() {
scriptLoadListeners.delete(this.onScriptLoad);
this.remove();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxTurnstileComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NgxTurnstileComponent, isStandalone: true, selector: "ngx-turnstile", inputs: { siteKey: "siteKey", action: "action", cData: "cData", theme: "theme", language: "language", version: "version", tabIndex: "tabIndex", appearance: "appearance", execution: "execution", retry: "retry", retryInterval: "retryInterval", refreshExpired: "refreshExpired", refreshTimeout: "refreshTimeout", size: "size", responseField: "responseField", responseFieldName: "responseFieldName", feedbackEnabled: "feedbackEnabled", offlabelShowPrivacy: "offlabelShowPrivacy", offlabelShowHelp: "offlabelShowHelp" }, outputs: { resolved: "resolved", errored: "errored", beforeInteractive: "beforeInteractive", afterInteractive: "afterInteractive", unsupported: "unsupported", timeout: "timeout" }, exportAs: ["ngx-turnstile"], ngImport: i0, template: ``, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgxTurnstileComponent, decorators: [{
type: Component,
args: [{
selector: 'ngx-turnstile',
template: ``,
exportAs: 'ngx-turnstile',
standalone: true,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: Document, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }, { type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }], propDecorators: { siteKey: [{
type: Input
}], action: [{
type: Input
}], cData: [{
type: Input
}], theme: [{
type: Input
}], language: [{
type: Input
}], version: [{
type: Input
}], tabIndex: [{
type: Input
}], appearance: [{
type: Input
}], execution: [{
type: Input
}], retry: [{
type: Input
}], retryInterval: [{
type: Input
}], refreshExpired: [{
type: Input
}], refreshTimeout: [{
type: Input
}], size: [{
type: Input
}], responseField: [{
type: Input
}], responseFieldName: [{
type: Input
}], feedbackEnabled: [{
type: Input
}], offlabelShowPrivacy: [{
type: Input
}], offlabelShowHelp: [{
type: Input
}], resolved: [{
type: Output
}], errored: [{
type: Output
}], beforeInteractive: [{
type: Output
}], afterInteractive: [{
type: Output
}], unsupported: [{
type: Output
}], timeout: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXR1cm5zdGlsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdHVybnN0aWxlL3NyYy9saWIvbmd4LXR1cm5zdGlsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxLQUFLLEVBRUwsTUFBTSxFQUNOLFlBQVksRUFFWixNQUFNLEVBQ04sV0FBVyxFQUNYLGVBQWUsRUFDZixNQUFNLEVBQ04sUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM5RSxPQUFPLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBb0I5RCxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUM7QUFDbEMsTUFBTSxhQUFhLEdBQUcseUJBQXlCLENBQUM7QUFHaEQsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBYyxDQUFDO0FBUWxELE1BQU0sT0FBTyxxQkFBcUI7SUEwQ3RCO0lBQ0E7SUFDa0I7SUFDRztJQTVDdEIsT0FBTyxDQUFVO0lBQ2pCLE1BQU0sQ0FBVTtJQUNoQixLQUFLLENBQVU7SUFDZixLQUFLLEdBQStCLE1BQU0sQ0FBQztJQUMzQyxRQUFRLEdBQVksTUFBTSxDQUFDO0lBQzNCLE9BQU8sR0FBcUIsR0FBRyxDQUFDO0lBQ2hDLFFBQVEsQ0FBVTtJQUNsQixVQUFVLEdBQStDLFFBQVEsQ0FBQztJQUNsRSxTQUFTLENBQXdCO0lBQ2pDLEtBQUssR0FBc0IsTUFBTSxDQUFDO0lBQ2xDLGFBQWEsQ0FBVTtJQUN2QixjQUFjLENBQStCO0lBQzdDLGNBQWMsQ0FBK0I7SUFDN0MsSUFBSSxHQUF1QyxRQUFRLENBQUM7SUFDcEQsYUFBYSxD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ZWYsXG4gIElucHV0LFxuICBOZ1pvbmUsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPbkRlc3Ryb3ksXG4gIEluamVjdCxcbiAgUExBVEZPUk1fSUQsXG4gIGFmdGVyTmV4dFJlbmRlcixcbiAgc2lnbmFsLFxuICBjb21wdXRlZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0b09ic2VydmFibGUsIHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IERPQ1VNRU5ULCBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBUdXJuc3RpbGVPcHRpb25zIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3R1cm5zdGlsZS1vcHRpb25zJztcblxuZGVjbGFyZSBnbG9iYWwge1xuICBpbnRlcmZhY2UgV2luZG93IHtcbiAgICBvbmxvYWRUdXJuc3RpbGVDYWxsYmFjazogKCkgPT4gdm9pZDtcbiAgICB0dXJuc3RpbGU6IHtcbiAgICAgIHJlbmRlcjogKFxuICAgICAgICBpZE9yQ29udGFpbmVyOiBzdHJpbmcgfCBIVE1MRWxlbWVudCxcbiAgICAgICAgb3B0aW9uczogVHVybnN0aWxlT3B0aW9ucyxcbiAgICAgICkgPT4gc3RyaW5nO1xuICAgICAgcmVzZXQ6ICh3aWRnZXRJZE9yQ29udGFpbmVyOiBzdHJpbmcgfCBIVE1MRWxlbWVudCkgPT4gdm9pZDtcbiAgICAgIGdldFJlc3BvbnNlOiAoXG4gICAgICAgIHdpZGdldElkT3JDb250YWluZXI6IHN0cmluZyB8IEhUTUxFbGVtZW50LFxuICAgICAgKSA9PiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICByZW1vdmU6ICh3aWRnZXRJZE9yQ29udGFpbmVyOiBzdHJpbmcgfCBIVE1MRWxlbWVudCkgPT4gdm9pZDtcbiAgICB9O1xuICB9XG59XG5cbmNvbnN0IFNDUklQVF9JRCA9ICduZ3gtdHVybnN0aWxlJztcbmNvbnN0IENBTExCQUNLX05BTUUgPSAnb25sb2FkVHVybnN0aWxlQ2FsbGJhY2snO1xudHlwZSBTdXBwb3J0ZWRWZXJzaW9uID0gJzAnO1xuXG4vLyBFdmVyeSBtb3VudGVkIGNvbXBvbmVudCB3YWl0aW5nIGZvciB0aGUgVHVybnN0aWxlIHNjcmlwdCB0byBmaW5pc2ggbG9hZGluZy5cbi8vIEEgc2luZ2xlIGdsb2JhbCBvbmxvYWQgY2FsbGJhY2sgbm90aWZpZXMgYWxsIG9mIHRoZW0sIHNvIG11bHRpcGxlIHdpZGdldHMgb25cbi8vIHRoZSBzYW1lIHBhZ2UgZWFjaCBnZXQgcmVuZGVyZWQgKG5vdCBqdXN0IHRoZSBsYXN0IG9uZSB0aGF0IHdhcyBjcmVhdGVkKS5cbmNvbnN0IHNjcmlwdExvYWRMaXN0ZW5lcnMgPSBuZXcgU2V0PCgpID0+IHZvaWQ+KCk7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC10dXJuc3RpbGUnLFxuICB0ZW1wbGF0ZTogYGAsXG4gIGV4cG9ydEFzOiAnbmd4LXR1cm5zdGlsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIE5neFR1cm5zdGlsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIHNpdGVLZXkhOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGFjdGlvbj86IHN0cmluZztcbiAgQElucHV0KCkgY0RhdGE/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHRoZW1lPzogJ2xpZ2h0JyB8ICdkYXJrJyB8ICdhdXRvJyA9ICdhdXRvJztcbiAgQElucHV0KCkgbGFuZ3VhZ2U/OiBzdHJpbmcgPSAnYXV0byc7XG4gIEBJbnB1dCgpIHZlcnNpb246IFN1cHBvcnRlZFZlcnNpb24gPSAnMCc7XG4gIEBJbnB1dCgpIHRhYkluZGV4PzogbnVtYmVyO1xuICBASW5wdXQoKSBhcHBlYXJhbmNlPzogJ2Fsd2F5cycgfCAnZXhlY3V0ZScgfCAnaW50ZXJhY3Rpb24tb25seScgPSAnYWx3YXlzJztcbiAgQElucHV0KCkgZXhlY3V0aW9uPzogJ3JlbmRlcicgfCAnZXhlY3V0ZSc7XG4gIEBJbnB1dCgpIHJldHJ5PzogJ25ldmVyJyB8ICdhdXRvJyA9ICdhdXRvJztcbiAgQElucHV0KCkgcmV0cnlJbnRlcnZhbD86IG51bWJlcjtcbiAgQElucHV0KCkgcmVmcmVzaEV4cGlyZWQ/OiAnYXV0bycgfCAnbWFudWFsJyB8ICduZXZlcic7XG4gIEBJbnB1dCgpIHJlZnJlc2hUaW1lb3V0PzogJ2F1dG8nIHwgJ21hbnVhbCcgfCAnbmV2ZXInO1xuICBASW5wdXQoKSBzaXplPzogJ25vcm1hbCcgfCAnZmxleGlibGUnIHwgJ2NvbXBhY3QnID0gJ25vcm1hbCc7XG4gIEBJbnB1dCgpIHJlc3BvbnNlRmllbGQ/OiBib29sZWFuO1xuICBASW5wdXQoKSByZXNwb25zZUZpZWxkTmFtZT86IHN0cmluZztcbiAgQElucHV0KCkgZmVlZGJhY2tFbmFibGVkPzogYm9vbGVhbjtcbiAgQElucHV0KCkgb2ZmbGFiZWxTaG93UHJpdmFjeT86IGJvb2xlYW47XG4gIEBJbnB1dCgpIG9mZmxhYmVsU2hvd0hlbHA/OiBib29sZWFuO1xuXG4gIEBPdXRwdXQoKSByZXNvbHZlZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nIHwgbnVsbD4oKTtcbiAgQE91dHB1dCgpIGVycm9yZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bGw+KCk7XG4gIEBPdXRwdXQoKSBiZWZvcmVJbnRlcmFjdGl2ZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgQE91dHB1dCgpIGFmdGVySW50ZXJhY3RpdmUgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIEBPdXRwdXQoKSB1bnN1cHBvcnRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgQE91dHB1dCgpIHRpbWVvdXQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgcHJpdmF0ZSB3aWRnZXRJZCA9IHNpZ25hbDxzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBDbG91ZGZsYXJlIFR1cm5zdGlsZSBzY3JpcHQgaGFzIGZpbmlzaGVkIGxvYWRpbmcuICovXG4gIHB1YmxpYyBzY3JpcHRMb2FkZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8qKiBXaGV0aGVyIGEgd2lkZ2V0IGlzIGN1cnJlbnRseSByZW5kZXJlZC4gQ2xpZW50cyBjYW4gd2F0Y2ggdGhpcyBzaWduYWwuICovXG4gIHB1YmxpYyB3aWRnZXRMb2FkZWQgPSBjb21wdXRlZCgoKSA9PiAhIXRoaXMud2lkZ2V0SWQoKSk7XG5cbiAgLy8gTm90aWZpZXMgdGhpcyBpbnN0YW5jZSB3aGVuIHRoZSBzaGFyZWQgc2NyaXB0IGZpbmlzaGVzIGxvYWRpbmcuIEtlcHQgYXMgYVxuICAvLyBzdGFibGUgcmVmZXJlbmNlIHNvIGl0IGNhbiBiZSByZW1vdmVkIGZyb20gdGhlIGxpc3RlbmVyIHNldCBvbiBkZXN0cm95LlxuICBwcml2YXRlIG9uU2NyaXB0TG9hZCA9ICgpOiB2b2lkID0+XG4gICAgdGhpcy56b25lLnJ1bigoKSA9PiB0aGlzLnNjcmlwdExvYWRlZC5zZXQodHJ1ZSkpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsXG4gICAgQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3QsXG4gICkge1xuICAgIC8vIFRvdWNoaW5nIGB3aW5kb3dgIGlzIG9ubHkgc2FmZSBpbiB0aGUgYnJvd3NlciAoc2tpcCBkdXJpbmcgU1NSKS5cbiAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xuICAgICAgdGhpcy5sb2FkU2NyaXB0KCk7XG4gICAgfVxuXG4gICAgLy8gUmVuZGVyIG9uY2UgdGhlIGhvc3QgZWxlbWVudCBleGlzdHMgKGlmIHRoZSBzY3JpcHQgaXMgYWxyZWFkeSBsb2FkZWQpLlxuICAgIGFmdGVyTmV4dFJlbmRlcigoKSA9PiB7XG4gICAgICBpZiAodGhpcy5zY3JpcHRMb2FkZWQoKSAmJiAhdGhpcy53aWRnZXRMb2FkZWQoKSkge1xuICAgICAgICB0aGlzLmNyZWF0ZVdpZGdldCgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gUmVuZGVyIG9uY2UgdGhlIHNjcmlwdCBmaW5pc2hlcyBsb2FkaW5nIChpZiBub3QgYWxyZWFkeSByZW5kZXJlZCkuXG4gICAgdG9PYnNlcnZhYmxlKHRoaXMuc2NyaXB0TG9hZGVkKVxuICAgICAgLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKCkpXG4gICAgICAuc3Vic2NyaWJlKChzY3JpcHRMb2FkZWQpID0+IHtcbiAgICAgICAgaWYgKHNjcmlwdExvYWRlZCAmJiAhdGhpcy53aWRnZXRMb2FkZWQoKSkge1xuICAgICAgICAgIHRoaXMuY3JlYXRlV2lkZ2V0KCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0Q2xvdWRmbGFyZVR1cm5zdGlsZVVybCgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnZlcnNpb24gPT09ICcwJykge1xuICAgICAgcmV0dXJuICdodHRwczovL2NoYWxsZW5nZXMuY2xvdWRmbGFyZS5jb20vdHVybnN0aWxlL3YwL2FwaS5qcyc7XG4gICAgfVxuXG4gICAgdGhyb3cgJ1ZlcnNpb24gbm90IGRlZmluZWQgaW4gbmd4LXR1cm5zdGlsZSBjb21wb25lbnQuJztcbiAgfVxuXG4gIHByaXZhdGUgbG9hZFNjcmlwdCgpOiB2b2lkIHtcbiAgICAvLyBTY3JpcHQgYWxyZWFkeSBwcmVzZW50IChlLmcuIGxvYWRlZCBieSBhbm90aGVyIHdpZGdldCBvciBhIHByaW9yIHJvdXRlKS5cbiAgICBpZiAod2luZG93LnR1cm5zdGlsZSkge1xuICAgICAgdGhpcy5zY3JpcHRMb2FkZWQuc2V0KHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFJlZ2lzdGVyIHRvIGJlIG5vdGlmaWVkIHdoZW4gdGhlIHNoYXJlZCBzY3JpcHQgZmluaXNoZXMgbG9hZGluZy5cbiAgICBzY3JpcHRMb2FkTGlzdGVuZXJzLmFkZCh0aGlzLm9uU2NyaXB0TG9hZCk7XG5cbiAgICAvLyBBIHNpbmdsZSBnbG9iYWwgY2FsbGJhY2sgZmFucyBvdXQgdG8gZXZlcnkgd2FpdGluZyBpbnN0YW5jZS5cbiAgICB3aW5kb3dbQ0FMTEJBQ0tfTkFNRV0gPSAoKSA9PiB7XG4gICAgICAvLyBDb3B5IHRoZW4gY2xlYXIgc28gYSBsaXN0ZW5lciByZS1yZWdpc3RlcmluZyBtaWQtbm90aWZpY2F0aW9uIGlzIHNhZmUuXG4gICAgICBjb25zdCBsaXN0ZW5lcnMgPSBBcnJheS5mcm9tKHNjcmlwdExvYWRMaXN0ZW5lcnMpO1xuICAgICAgc2NyaXB0TG9hZExpc3RlbmVycy5jbGVhcigpO1xuICAgICAgbGlzdGVuZXJzLmZvckVhY2goKGxpc3RlbmVyKSA9PiBsaXN0ZW5lcigpKTtcbiAgICB9O1xuXG4gICAgLy8gT25seSBpbmplY3QgdGhlIHNjcmlwdCBvbmNlLCBldmVuIHdpdGggc2V2ZXJhbCB3aWRnZXRzIG9uIHRoZSBwYWdlLlxuICAgIGNvbnN0IHNjcmlwdFBlbmRpbmcgPSAhIXRoaXMuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoU0NSSVBUX0lEKTtcbiAgICBpZiAoIXNjcmlwdFBlbmRpbmcpIHtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgICBzY3JpcHQuc3JjID0gYCR7dGhpcy5fZ2V0Q2xvdWRmbGFyZVR1cm5zdGlsZVVybCgpfT9yZW5kZXI9ZXhwbGljaXQmb25sb2FkPSR7Q0FMTEJBQ0tfTkFNRX1gO1xuICAgICAgc2NyaXB0LmlkID0gU0NSSVBUX0lEO1xuICAgICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcbiAgICAgIHNjcmlwdC5kZWZlciA9IHRydWU7XG4gICAgICB0aGlzLmRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgY3JlYXRlV2lkZ2V0KCk6IHZvaWQge1xuICAgIC8vIE9ubHkgcmVuZGVyIG9uY2UgdGhlIHNjcmlwdCBpcyBsb2FkZWQgYW5kIHRoZSBob3N0IGVsZW1lbnQgZXhpc3RzLlxuICAgIGlmICghdGhpcy5zY3JpcHRMb2FkZWQoKSB8fCAhdGhpcy5lbGVtZW50UmVmPy5uYXRpdmVFbGVtZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdHVybnN0aWxlT3B0aW9uczogVHVybnN0aWxlT3B0aW9ucyA9IHtcbiAgICAgIHNpdGVrZXk6IHRoaXMuc2l0ZUtleSxcbiAgICAgIHRoZW1lOiB0aGlzLnRoZW1lLFxuICAgICAgbGFuZ3VhZ2U6IHRoaXMubGFuZ3VhZ2UsXG4gICAgICB0YWJpbmRleDogdGhpcy50YWJJbmRleCxcbiAgICAgIGFjdGlvbjogdGhpcy5hY3Rpb24sXG4gICAgICBjRGF0YTogdGhpcy5jRGF0YSxcbiAgICAgIGFwcGVhcmFuY2U6IHRoaXMuYXBwZWFyYW5jZSxcbiAgICAgIHJldHJ5OiB0aGlzLnJldHJ5LFxuICAgICAgc2l6ZTogdGhpcy5zaXplLFxuICAgICAgY2FsbGJhY2s6ICh0b2tlbjogc3RyaW5nKSA9PiB7XG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5yZXNvbHZlZC5lbWl0KHRva2VuKSk7XG4gICAgICB9LFxuICAgICAgJ2Vycm9yLWNhbGxiYWNrJzogKGVycm9yQ29kZTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5lcnJvcmVkLmVtaXQoZXJyb3JDb2RlKSk7XG4gICAgICAgIC8vIFJldHVybmluZyBmYWxzZSBjYXVzZXMgVHVybnN0aWxlIHRvIGxvZyBlcnJvciBjb2RlIGFzIGEgY29uc29sZSB3YXJuaW5nLlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICAgJ2V4cGlyZWQtY2FsbGJhY2snOiAoKSA9PiB7XG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5yZXNldCgpKTtcbiAgICAgIH0sXG4gICAgICAnYmVmb3JlLWludGVyYWN0aXZlLWNhbGxiYWNrJzogKCkgPT4ge1xuICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMuYmVmb3JlSW50ZXJhY3RpdmUuZW1pdCgpKTtcbiAgICAgIH0sXG4gICAgICAnYWZ0ZXItaW50ZXJhY3RpdmUtY2FsbGJhY2snOiAoKSA9PiB7XG4gICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5hZnRlckludGVyYWN0aXZlLmVtaXQoKSk7XG4gICAgICB9LFxuICAgICAgJ3Vuc3VwcG9ydGVkLWNhbGxiYWNrJzogKCkgPT4ge1xuICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMudW5zdXBwb3J0ZWQuZW1pdCgpKTtcbiAgICAgIH0sXG4gICAgICAndGltZW91dC1jYWxsYmFjayc6ICgpID0+IHtcbiAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB0aGlzLnRpbWVvdXQuZW1pdCgpKTtcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIC8vIE9ubHkgZm9yd2FyZCBvcHRpb25hbCBwYXJhbWV0ZXJzIHdoZW4gc2V0LCBzbyB3ZSBuZXZlciBvdmVycmlkZVxuICAgIC8vIENsb3VkZmxhcmUncyBkZWZhdWx0cyB3aXRoIGFuIGV4cGxpY2l0IGB1bmRlZmluZWRgLlxuICAgIGlmICh0aGlzLmV4ZWN1dGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0dXJuc3RpbGVPcHRpb25zLmV4ZWN1dGlvbiA9IHRoaXMuZXhlY3V0aW9uO1xuICAgIH1cbiAgICBpZiAodGhpcy5yZXRyeUludGVydmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHR1cm5zdGlsZU9wdGlvbnNbJ3JldHJ5LWludGVydmFsJ10gPSB0aGlzLnJldHJ5SW50ZXJ2YWw7XG4gICAgfVxuICAgIGlmICh0aGlzLnJlZnJlc2hFeHBpcmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHR1cm5zdGlsZU9wdGlvbnNbJ3JlZnJlc2gtZXhwaXJlZCddID0gdGhpcy5yZWZyZXNoRXhwaXJlZDtcbiAgICB9XG4gICAgaWYgKHRoaXMucmVmcmVzaFRpbWVvdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdHVybnN0aWxlT3B0aW9uc1sncmVmcmVzaC10aW1lb3V0J10gPSB0aGlzLnJlZnJlc2hUaW1lb3V0O1xuICAgIH1cbiAgICBpZiAodGhpcy5yZXNwb25zZUZpZWxkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHR1cm5zdGlsZU9wdGlvbnNbJ3Jlc3BvbnNlLWZpZWxkJ10gPSB0aGlzLnJlc3BvbnNlRmllbGQ7XG4gICAgfVxuICAgIGlmICh0aGlzLnJlc3BvbnNlRmllbGROYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHR1cm5zdGlsZU9wdGlvbnNbJ3Jlc3BvbnNlLWZpZWxkLW5hbWUnXSA9IHRoaXMucmVzcG9uc2VGaWVsZE5hbWU7XG4gICAgfVxuICAgIGlmICh0aGlzLmZlZWRiYWNrRW5hYmxlZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0dXJuc3RpbGVPcHRpb25zWydmZWVkYmFjay1lbmFibGVkJ10gPSB0aGlzLmZlZWRiYWNrRW5hYmxlZDtcbiAgICB9XG4gICAgaWYgKHRoaXMub2ZmbGFiZWxTaG93UHJpdmFjeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0dXJuc3RpbGVPcHRpb25zWydvZmZsYWJlbC1zaG93LXByaXZhY3knXSA9IHRoaXMub2ZmbGFiZWxTaG93UHJpdmFjeTtcbiAgICB9XG4gICAgaWYgKHRoaXMub2ZmbGFiZWxTaG93SGVscCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0dXJuc3RpbGVPcHRpb25zWydvZmZsYWJlbC1zaG93LWhlbHAnXSA9IHRoaXMub2ZmbGFiZWxTaG93SGVscDtcbiAgICB9XG5cbiAgICAvLyBSZW1vdmUgYW55IGV4aXN0aW5nIHdpZGdldCBzbyByZS1yZW5kZXJpbmcgZG9lc24ndCBjcmVhdGUgZHVwbGljYXRlcy5cbiAgICB0aGlzLnJlbW92ZSgpO1xuXG4gICAgdGhpcy53aWRnZXRJZC5zZXQoXG4gICAgICB3aW5kb3cudHVybnN0aWxlLnJlbmRlcih0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgdHVybnN0aWxlT3B0aW9ucyksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyByZXNldCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy53aWRnZXRMb2FkZWQoKSkge1xuICAgICAgdGhpcy5yZXNvbHZlZC5lbWl0KG51bGwpO1xuICAgICAgd2luZG93LnR1cm5zdGlsZS5yZXNldCh0aGlzLndpZGdldElkKCkhKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLndpZGdldExvYWRlZCgpKSB7XG4gICAgICB3aW5kb3cudHVybnN0aWxlLnJlbW92ZSh0aGlzLndpZGdldElkKCkhKTtcbiAgICAgIHRoaXMud2lkZ2V0SWQuc2V0KHVuZGVmaW5lZCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHNjcmlwdExvYWRMaXN0ZW5lcnMuZGVsZXRlKHRoaXMub25TY3JpcHRMb2FkKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG59XG4iXX0=