@ng-supabase/core
Version:
ng-supabase is a component library and helper utilities for integrating Supabase in your angular application.
216 lines • 28.6 kB
JavaScript
import { Input, signal, inject, Component, ChangeDetectionStrategy, } from '@angular/core';
import { FormGroup, Validators, FormControl, ReactiveFormsModule, } from '@angular/forms';
// 3rd party.
import { Subject } from 'rxjs';
import { RouteService } from '../route.service';
import { LogService } from '../logging/log.service';
import { SupabaseConfig } from '../supabase-config';
import { SupabaseService } from '../supabase.service';
import { PersistentStorageService } from '../storage/persistent-storage.service';
import * as i0 from "@angular/core";
export class SignInComponent {
constructor() {
this.title = '';
this.email = '';
this.password = '';
this.usePassword = false;
this.redirectTo = '';
/**
* The absolute route to redirect to from the email link. This should not
* be used in conjunction with "redirectToPath" (use one or the other).
*/
this.redirectToUrl = '';
/**
* A route path to redirect to from the email link (as apposed to an absolute path).
* This path will be appended to the app's root URL and will be the URL that is
* targeted from the email link. This should not be used in conjunction with
* "redirectTo" (use one or the other).
*/
this.redirectToPath = '';
this.forgotPassword = false;
this.signingIn = new Subject();
this.form = new FormGroup({
email: new FormControl('', [Validators.required]),
password: new FormControl(''),
usePassword: new FormControl(false),
rememberMe: new FormControl(true),
});
this.errorMessage = signal(null);
this.wait = signal(null);
this.verifyingOtp = signal(false);
this.log = inject(LogService);
this.config = inject(SupabaseConfig);
this.supabase = inject(SupabaseService);
this.routeService = inject(RouteService);
this.storage = inject(PersistentStorageService);
}
ngOnInit() {
this.title = this.title ?? this.config.signIn.title;
const rememberMe = this.rememberMe ?? this.config.signIn.rememberMe;
this.form.controls.email.setValue(this.email);
this.form.controls.usePassword.setValue(this.usePassword);
this.form.controls.password.setValue(this.password);
this.form.controls.rememberMe.setValue(rememberMe);
this.tryLoadRememberMe();
}
showSignInWithPassword(event) {
event?.preventDefault();
this.form.controls.usePassword.setValue(true);
this.form.controls.password.setValidators([Validators.required]);
this.revalidateAllControls();
}
showSignInWithEmail(event) {
event?.preventDefault();
this.form.controls.usePassword.setValue(false);
this.form.controls.password.setValidators([]);
this.revalidateAllControls();
}
showForgotPassword(event) {
event?.preventDefault();
this.forgotPassword = true;
}
signIn() {
if (this.form.disabled || this.form.invalid) {
return;
}
this.form.value.usePassword
? this.signInWithPassword()
: this.signInWithMagicLink();
}
async verifyOtp(token) {
this.verifyingOtp.set(true);
const email = this.form.value.email;
const { error } = await this.supabase.client.auth.verifyOtp({
email,
token,
type: 'email',
});
if (error) {
this.errorMessage.set(error.message);
return;
}
const redirectUrl = this.getRedirectTo();
this.routeService.goTo(redirectUrl);
}
revalidateAllControls() {
Object.values(this.form.controls).forEach((control) => control.updateValueAndValidity());
}
async signInWithPassword() {
try {
this.log.debug('Logging in with password');
this.signingIn.next(true);
const email = this.form.value.email;
const password = this.form.value.password;
const { error } = await this.supabase.client.auth.signInWithPassword({
email,
password,
});
if (error) {
this.log.debug(`Sign in failed. ${error.message}`);
this.errorMessage.set(error.message);
return;
}
const redirect = this.getRedirectUrl();
this.log.debug(`Signed in successfully. Redirecting to ${redirect}`);
this.trySaveRememberMe();
await this.supabase.waitForSignedIn();
this.routeService.goTo(redirect);
}
catch (error) {
this.log.error(`Failed to sign in`);
// TODO: Handle - @rusty.green.
}
finally {
this.signingIn.next(false);
}
}
getRedirectUrl() {
return (this.redirectTo ||
this.routeService.getRedirectParamValue() ||
this.config.signIn.redirectTo ||
this.config.mainRoute);
}
async signInWithMagicLink() {
try {
this.signingIn.next(true);
const email = this.form.value.email;
const emailRedirectTo = this.getRedirectUrl().toString();
const { error } = await this.supabase.client.auth.signInWithOtp({
email,
options: {
emailRedirectTo,
// TODO: Pass/configure other options (like "shouldCreateUser") - @rusty.green
},
});
if (error) {
this.errorMessage.set(error.message);
return;
}
this.wait.set({
icon: 'pi pi-envelope',
title: 'Check your email',
enableOtp: this.config.signIn.otpEnabled,
message: `An email has been sent to <strong>${email}</strong> with a magic link to sign in. Simply click the link from your email and you will automatically be signed into this app.`,
});
this.trySaveRememberMe();
}
catch (error) {
// TODO: Handle - @russell.green
}
finally {
this.signingIn.next(false);
}
}
tryLoadRememberMe() {
const info = this.storage.getJson(this.config.signIn.rememberMeStorageKey);
if (info) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.form.patchValue(info);
this.form.value.usePassword
? this.showSignInWithPassword()
: this.showSignInWithEmail();
}
}
clearRememberMe() {
this.storage.removeItem(this.config.signIn.rememberMeStorageKey);
}
trySaveRememberMe() {
if (this.form.value.rememberMe) {
const { email, usePassword } = this.form.value;
const value = { email, usePassword };
this.storage.setJson(this.config.signIn.rememberMeStorageKey, value);
}
else {
this.clearRememberMe();
}
}
getRedirectTo() {
const fallback = this.config.routes.userProfile || this.config.routes.main;
return this.redirectToPath
? this.routeService.appendRoute(this.redirectToPath)
: this.redirectToUrl || this.routeService.appendRoute(fallback);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: SignInComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.6", type: SignInComponent, isStandalone: true, selector: "supabase-sign-in", inputs: { title: "title", email: "email", password: "password", usePassword: "usePassword", redirectTo: "redirectTo", rememberMe: "rememberMe", redirectToUrl: "redirectToUrl", redirectToPath: "redirectToPath" }, ngImport: i0, template: "", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.6", ngImport: i0, type: SignInComponent, decorators: [{
type: Component,
args: [{ selector: 'supabase-sign-in', standalone: true, imports: [ReactiveFormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "" }]
}], propDecorators: { title: [{
type: Input
}], email: [{
type: Input
}], password: [{
type: Input
}], usePassword: [{
type: Input
}], redirectTo: [{
type: Input
}], rememberMe: [{
type: Input
}], redirectToUrl: [{
type: Input
}], redirectToPath: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi1pbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2NvcmUvc3JjL2xpYi9zaWduLWluL3NpZ24taW4uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9jb3JlL3NyYy9saWIvc2lnbi1pbi9zaWduLWluLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFDTCxLQUFLLEVBQ0wsTUFBTSxFQUVOLE1BQU0sRUFDTixTQUFTLEVBQ1QsdUJBQXVCLEdBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsRUFDWCxtQkFBbUIsR0FDcEIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixhQUFhO0FBQ2IsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUkvQixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7O0FBVWpGLE1BQU0sT0FBTyxlQUFlO0lBUjVCO1FBU1csVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUNYLFVBQUssR0FBRyxFQUFFLENBQUM7UUFDWCxhQUFRLEdBQUcsRUFBRSxDQUFDO1FBQ2QsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFDcEIsZUFBVSxHQUFHLEVBQUUsQ0FBQztRQUd6Qjs7O1dBR0c7UUFDTSxrQkFBYSxHQUFHLEVBQUUsQ0FBQztRQUU1Qjs7Ozs7V0FLRztRQUNNLG1CQUFjLEdBQUcsRUFBRSxDQUFDO1FBRTdCLG1C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QUFDO1FBQ3ZFLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3pCLENBQUM7SUFDSCxDQUFDO0lBRVMsYUFBYTtRQUNyQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQzNFLE9BQU8sSUFBSSxDQUFDLGNBQWM7WUFDeEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7WUFDcEQsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDcEUsQ0FBQzs4R0EvTVUsZUFBZTtrR0FBZixlQUFlLGdTQ3BDNUIsRUFBQSx5REQrQlksbUJBQW1COzsyRkFLbEIsZUFBZTtrQkFSM0IsU0FBUzsrQkFDRSxrQkFBa0IsY0FDaEIsSUFBSSxXQUNQLENBQUMsbUJBQW1CLENBQUMsbUJBR2IsdUJBQXVCLENBQUMsTUFBTTs4QkFHdEMsS0FBSztzQkFBYixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQU1HLGFBQWE7c0JBQXJCLEtBQUs7Z0JBUUcsY0FBYztzQkFBdEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuZ3VsYXIuXG5pbXBvcnQgeyBVcmxUcmVlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7XG4gIElucHV0LFxuICBzaWduYWwsXG4gIE9uSW5pdCxcbiAgaW5qZWN0LFxuICBDb21wb25lbnQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEZvcm1Hcm91cCxcbiAgVmFsaWRhdG9ycyxcbiAgRm9ybUNvbnRyb2wsXG4gIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuLy8gM3JkIHBhcnR5LlxuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG4vLyBMb2NhbC5cbmltcG9ydCB7IFdhaXRNZXNzYWdlIH0gZnJvbSAnLi4vd2FpdC1tZXNzYWdlJztcbmltcG9ydCB7IFJvdXRlU2VydmljZSB9IGZyb20gJy4uL3JvdXRlLnNlcnZpY2UnO1xuaW1wb3J0IHsgTG9nU2VydmljZSB9IGZyb20gJy4uL2xvZ2dpbmcvbG9nLnNlcnZpY2UnO1xuaW1wb3J0IHsgU3VwYWJhc2VDb25maWcgfSBmcm9tICcuLi9zdXBhYmFzZS1jb25maWcnO1xuaW1wb3J0IHsgU3VwYWJhc2VTZXJ2aWNlIH0gZnJvbSAnLi4vc3VwYWJhc2Uuc2VydmljZSc7XG5pbXBvcnQgeyBQZXJzaXN0ZW50U3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuLi9zdG9yYWdlL3BlcnNpc3RlbnQtc3RvcmFnZS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3VwYWJhc2Utc2lnbi1pbicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL3NpZ24taW4uY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vc2lnbi1pbi5jb21wb25lbnQuc2NzcycsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSB0aXRsZSA9ICcnO1xuICBASW5wdXQoKSBlbWFpbCA9ICcnO1xuICBASW5wdXQoKSBwYXNzd29yZCA9ICcnO1xuICBASW5wdXQoKSB1c2VQYXNzd29yZCA9IGZhbHNlO1xuICBASW5wdXQoKSByZWRpcmVjdFRvID0gJyc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyTWU6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSByb3V0ZSB0byByZWRpcmVjdCB0byBmcm9tIHRoZSBlbWFpbCBsaW5rLiBUaGlzIHNob3VsZCBub3RcbiAgICogYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIFwicmVkaXJlY3RUb1BhdGhcIiAodXNlIG9uZSBvciB0aGUgb3RoZXIpLlxuICAgKi9cbiAgQElucHV0KCkgcmVkaXJlY3RUb1VybCA9ICcnO1xuXG4gIC8qKlxuICAgKiBBIHJvdXRlIHBhdGggdG8gcmVkaXJlY3QgdG8gZnJvbSB0aGUgZW1haWwgbGluayAoYXMgYXBwb3NlZCB0byBhbiBhYnNvbHV0ZSBwYXRoKS5cbiAgICogVGhpcyBwYXRoIHdpbGwgYmUgYXBwZW5kZWQgdG8gdGhlIGFwcCdzIHJvb3QgVVJMIGFuZCB3aWxsIGJlIHRoZSBVUkwgdGhhdCBpc1xuICAgKiB0YXJnZXRlZCBmcm9tIHRoZSBlbWFpbCBsaW5rLiBUaGlzIHNob3VsZCBub3QgYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoXG4gICAqIFwicmVkaXJlY3RUb1wiICh1c2Ugb25lIG9yIHRoZSBvdGhlcikuXG4gICAqL1xuICBASW5wdXQoKSByZWRpcmVjdFRvUGF0aCA9ICcnO1xuXG4gIGZvcmdvdFBhc3N3b3JkID0gZmFsc2U7XG4gIHNpZ25pbmdJbiA9IG5ldyBTdWJqZWN0PGJvb2xlYW4+KCk7XG4gIGZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICBlbWFpbDogbmV3IEZvcm1Db250cm9sKCcnLCBbVmFsaWRhdG9ycy5yZXF1aXJlZF0pLFxuICAgIHBhc3N3b3JkOiBuZXcgRm9ybUNvbnRyb2woJycpLFxuICAgIHVzZVBhc3N3b3JkOiBuZXcgRm9ybUNvbnRyb2woZmFsc2UpLFxuICAgIHJlbWVtYmVyTWU6IG5ldyBGb3JtQ29udHJvbCh0cnVlKSxcbiAgfSk7XG5cbiAgcmVhZG9ubHkgZXJyb3JNZXNzYWdlID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICByZWFkb25seSB3YWl0ID0gc2lnbmFsPFdhaXRNZXNzYWdlIHwgbnVsbD4obnVsbCk7XG4gIHJlYWRvbmx5IHZlcmlmeWluZ090cCA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZyA9IGluamVjdChMb2dTZXJ2aWNlKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbmZpZyA9IGluamVjdChTdXBhYmFzZUNvbmZpZyk7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdXBhYmFzZSA9IGluamVjdChTdXBhYmFzZVNlcnZpY2UpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcm91dGVTZXJ2aWNlID0gaW5qZWN0KFJvdXRlU2VydmljZSk7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdG9yYWdlID0gaW5qZWN0KFBlcnNpc3RlbnRTdG9yYWdlU2VydmljZSk7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy50aXRsZSA9IHRoaXMudGl0bGUgPz8gdGhpcy5jb25maWcuc2lnbkluLnRpdGxlO1xuICAgIGNvbnN0IHJlbWVtYmVyTWUgPSB0aGlzLnJlbWVtYmVyTWUgPz8gdGhpcy5jb25maWcuc2lnbkluLnJlbWVtYmVyTWU7XG4gICAgdGhpcy5mb3JtLmNvbnRyb2xzLmVtYWlsLnNldFZhbHVlKHRoaXMuZW1haWwpO1xuICAgIHRoaXMuZm9ybS5jb250cm9scy51c2VQYXNzd29yZC5zZXRWYWx1ZSh0aGlzLnVzZVBhc3N3b3JkKTtcbiAgICB0aGlzLmZvcm0uY29udHJvbHMucGFzc3dvcmQuc2V0VmFsdWUodGhpcy5wYXNzd29yZCk7XG4gICAgdGhpcy5mb3JtLmNvbnRyb2xzLnJlbWVtYmVyTWUuc2V0VmFsdWUocmVtZW1iZXJNZSk7XG4gICAgdGhpcy50cnlMb2FkUmVtZW1iZXJNZSgpO1xuICB9XG5cbiAgc2hvd1NpZ25JbldpdGhQYXNzd29yZChldmVudD86IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmZvcm0uY29udHJvbHMudXNlUGFzc3dvcmQuc2V0VmFsdWUodHJ1ZSk7XG4gICAgdGhpcy5mb3JtLmNvbnRyb2xzLnBhc3N3b3JkLnNldFZhbGlkYXRvcnMoW1ZhbGlkYXRvcnMucmVxdWlyZWRdKTtcbiAgICB0aGlzLnJldmFsaWRhdGVBbGxDb250cm9scygpO1xuICB9XG5cbiAgc2hvd1NpZ25JbldpdGhFbWFpbChldmVudD86IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmZvcm0uY29udHJvbHMudXNlUGFzc3dvcmQuc2V0VmFsdWUoZmFsc2UpO1xuICAgIHRoaXMuZm9ybS5jb250cm9scy5wYXNzd29yZC5zZXRWYWxpZGF0b3JzKFtdKTtcbiAgICB0aGlzLnJldmFsaWRhdGVBbGxDb250cm9scygpO1xuICB9XG5cbiAgc2hvd0ZvcmdvdFBhc3N3b3JkKGV2ZW50PzogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuZm9yZ290UGFzc3dvcmQgPSB0cnVlO1xuICB9XG5cbiAgc2lnbkluKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZvcm0uZGlzYWJsZWQgfHwgdGhpcy5mb3JtLmludmFsaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmZvcm0udmFsdWUudXNlUGFzc3dvcmRcbiAgICAgID8gdGhpcy5zaWduSW5XaXRoUGFzc3dvcmQoKVxuICAgICAgOiB0aGlzLnNpZ25JbldpdGhNYWdpY0xpbmsoKTtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeU90cCh0b2tlbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy52ZXJpZnlpbmdPdHAuc2V0KHRydWUpO1xuICAgIGNvbnN0IGVtYWlsID0gdGhpcy5mb3JtLnZhbHVlLmVtYWlsIGFzIHN0cmluZztcbiAgICBjb25zdCB7IGVycm9yIH0gPSBhd2FpdCB0aGlzLnN1cGFiYXNlLmNsaWVudC5hdXRoLnZlcmlmeU90cCh7XG4gICAgICBlbWFpbCxcbiAgICAgIHRva2VuLFxuICAgICAgdHlwZTogJ2VtYWlsJyxcbiAgICB9KTtcblxuICAgIGlmIChlcnJvcikge1xuICAgICAgdGhpcy5lcnJvck1lc3NhZ2Uuc2V0KGVycm9yLm1lc3NhZ2UpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJlZGlyZWN0VXJsID0gdGhpcy5nZXRSZWRpcmVjdFRvKCk7XG4gICAgdGhpcy5yb3V0ZVNlcnZpY2UuZ29UbyhyZWRpcmVjdFVybCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmV2YWxpZGF0ZUFsbENvbnRyb2xzKCk6IHZvaWQge1xuICAgIE9iamVjdC52YWx1ZXModGhpcy5mb3JtLmNvbnRyb2xzKS5mb3JFYWNoKChjb250cm9sKSA9PlxuICAgICAgY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KClcbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHNpZ25JbldpdGhQYXNzd29yZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5sb2cuZGVidWcoJ0xvZ2dpbmcgaW4gd2l0aCBwYXNzd29yZCcpO1xuICAgICAgdGhpcy5zaWduaW5nSW4ubmV4dCh0cnVlKTtcbiAgICAgIGNvbnN0IGVtYWlsID0gdGhpcy5mb3JtLnZhbHVlLmVtYWlsIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IHBhc3N3b3JkID0gdGhpcy5mb3JtLnZhbHVlLnBhc3N3b3JkIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IHsgZXJyb3IgfSA9IGF3YWl0IHRoaXMuc3VwYWJhc2UuY2xpZW50LmF1dGguc2lnbkluV2l0aFBhc3N3b3JkKHtcbiAgICAgICAgZW1haWwsXG4gICAgICAgIHBhc3N3b3JkLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChlcnJvcikge1xuICAgICAgICB0aGlzLmxvZy5kZWJ1ZyhgU2lnbiBpbiBmYWlsZWQuICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgdGhpcy5lcnJvck1lc3NhZ2Uuc2V0KGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlZGlyZWN0ID0gdGhpcy5nZXRSZWRpcmVjdFVybCgpO1xuICAgICAgdGhpcy5sb2cuZGVidWcoYFNpZ25lZCBpbiBzdWNjZXNzZnVsbHkuIFJlZGlyZWN0aW5nIHRvICR7cmVkaXJlY3R9YCk7XG4gICAgICB0aGlzLnRyeVNhdmVSZW1lbWJlck1lKCk7XG5cbiAgICAgIGF3YWl0IHRoaXMuc3VwYWJhc2Uud2FpdEZvclNpZ25lZEluKCk7XG4gICAgICB0aGlzLnJvdXRlU2VydmljZS5nb1RvKHJlZGlyZWN0IGFzIHN0cmluZyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubG9nLmVycm9yKGBGYWlsZWQgdG8gc2lnbiBpbmApO1xuICAgICAgLy8gVE9ETzogSGFuZGxlIC0gQHJ1c3R5LmdyZWVuLlxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLnNpZ25pbmdJbi5uZXh0KGZhbHNlKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0UmVkaXJlY3RVcmwoKTogc3RyaW5nIHwgc3RyaW5nW10gfCBVcmxUcmVlIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5yZWRpcmVjdFRvIHx8XG4gICAgICB0aGlzLnJvdXRlU2VydmljZS5nZXRSZWRpcmVjdFBhcmFtVmFsdWUoKSB8fFxuICAgICAgdGhpcy5jb25maWcuc2lnbkluLnJlZGlyZWN0VG8gfHxcbiAgICAgIHRoaXMuY29uZmlnLm1haW5Sb3V0ZVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgc2lnbkluV2l0aE1hZ2ljTGluaygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zaWduaW5nSW4ubmV4dCh0cnVlKTtcbiAgICAgIGNvbnN0IGVtYWlsID0gdGhpcy5mb3JtLnZhbHVlLmVtYWlsIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IGVtYWlsUmVkaXJlY3RUbyA9IHRoaXMuZ2V0UmVkaXJlY3RVcmwoKS50b1N0cmluZygpO1xuICAgICAgY29uc3QgeyBlcnJvciB9ID0gYXdhaXQgdGhpcy5zdXBhYmFzZS5jbGllbnQuYXV0aC5zaWduSW5XaXRoT3RwKHtcbiAgICAgICAgZW1haWwsXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICBlbWFpbFJlZGlyZWN0VG8sXG4gICAgICAgICAgLy8gVE9ETzogUGFzcy9jb25maWd1cmUgb3RoZXIgb3B0aW9ucyAobGlrZSBcInNob3VsZENyZWF0ZVVzZXJcIikgLSBAcnVzdHkuZ3JlZW5cbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5lcnJvck1lc3NhZ2Uuc2V0KGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMud2FpdC5zZXQoe1xuICAgICAgICBpY29uOiAncGkgcGktZW52ZWxvcGUnLFxuICAgICAgICB0aXRsZTogJ0NoZWNrIHlvdXIgZW1haWwnLFxuICAgICAgICBlbmFibGVPdHA6IHRoaXMuY29uZmlnLnNpZ25Jbi5vdHBFbmFibGVkLFxuICAgICAgICBtZXNzYWdlOiBgQW4gZW1haWwgaGFzIGJlZW4gc2VudCB0byA8c3Ryb25nPiR7ZW1haWx9PC9zdHJvbmc+IHdpdGggYSBtYWdpYyBsaW5rIHRvIHNpZ24gaW4uIFNpbXBseSBjbGljayB0aGUgbGluayBmcm9tIHlvdXIgZW1haWwgYW5kIHlvdSB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgc2lnbmVkIGludG8gdGhpcyBhcHAuYCxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLnRyeVNhdmVSZW1lbWJlck1lKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIFRPRE86IEhhbmRsZSAtIEBydXNzZWxsLmdyZWVuXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuc2lnbmluZ0luLm5leHQoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCB0cnlMb2FkUmVtZW1iZXJNZSgpOiB2b2lkIHtcbiAgICBjb25zdCBpbmZvID0gdGhpcy5zdG9yYWdlLmdldEpzb24odGhpcy5jb25maWcuc2lnbkluLnJlbWVtYmVyTWVTdG9yYWdlS2V5KTtcbiAgICBpZiAoaW5mbykge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKGluZm8pO1xuICAgICAgdGhpcy5mb3JtLnZhbHVlLnVzZVBhc3N3b3JkXG4gICAgICAgID8gdGhpcy5zaG93U2lnbkluV2l0aFBhc3N3b3JkKClcbiAgICAgICAgOiB0aGlzLnNob3dTaWduSW5XaXRoRW1haWwoKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xlYXJSZW1lbWJlck1lKCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmFnZS5yZW1vdmVJdGVtKHRoaXMuY29uZmlnLnNpZ25Jbi5yZW1lbWJlck1lU3RvcmFnZUtleSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdHJ5U2F2ZVJlbWVtYmVyTWUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZm9ybS52YWx1ZS5yZW1lbWJlck1lKSB7XG4gICAgICBjb25zdCB7IGVtYWlsLCB1c2VQYXNzd29yZCB9ID0gdGhpcy5mb3JtLnZhbHVlO1xuICAgICAgY29uc3QgdmFsdWUgPSB7IGVtYWlsLCB1c2VQYXNzd29yZCB9O1xuICAgICAgdGhpcy5zdG9yYWdlLnNldEpzb24odGhpcy5jb25maWcuc2lnbkluLnJlbWVtYmVyTWVTdG9yYWdlS2V5LCB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2xlYXJSZW1lbWJlck1lKCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGdldFJlZGlyZWN0VG8oKTogc3RyaW5nIHtcbiAgICBjb25zdCBmYWxsYmFjayA9IHRoaXMuY29uZmlnLnJvdXRlcy51c2VyUHJvZmlsZSB8fCB0aGlzLmNvbmZpZy5yb3V0ZXMubWFpbjtcbiAgICByZXR1cm4gdGhpcy5yZWRpcmVjdFRvUGF0aFxuICAgICAgPyB0aGlzLnJvdXRlU2VydmljZS5hcHBlbmRSb3V0ZSh0aGlzLnJlZGlyZWN0VG9QYXRoKVxuICAgICAgOiB0aGlzLnJlZGlyZWN0VG9VcmwgfHwgdGhpcy5yb3V0ZVNlcnZpY2UuYXBwZW5kUm91dGUoZmFsbGJhY2spO1xuICB9XG59XG4iLCIiXX0=