simplyfire
Version:
A lightweight firestore api for firebase cloud functions & Angular.
273 lines • 42.9 kB
JavaScript
import { Injectable } from '@angular/core';
import { getFirestore, doc, docData, addDoc, setDoc, updateDoc, deleteDoc, collection, collectionData, collectionGroup, collectionChanges, getDocs, increment, writeBatch, serverTimestamp, query, where, orderBy, limit, limitToLast, startAt, startAfter, endAt, endBefore, runTransaction, documentId } from '@angular/fire/firestore';
import { combineLatest, defer, lastValueFrom, of } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
import { QueryBuilder, AbstractFirestoreApi } from '../db';
import { arrayToChunks } from '../utils';
import * as i0 from "@angular/core";
const queryOps = {
query,
where,
orderBy,
limit,
limitToLast,
startAt,
startAfter,
endAt,
endBefore
};
const CACHE_MAX_AGE = 5 * 60 * 1000;
export class FirestoreService extends AbstractFirestoreApi {
constructor() {
super(...arguments);
this.cache = new Map();
}
get firestore() {
return getFirestore();
}
// -----------------------------------------------------------------------------------------------------
// @ Abstract members
// -----------------------------------------------------------------------------------------------------
collection(path, qb, maxAge = CACHE_MAX_AGE) {
return lastValueFrom(this.collectionWithCache(path, qb, maxAge).pipe(take(1)));
}
collectionGroup(collectionId, qb, maxAge = CACHE_MAX_AGE) {
return lastValueFrom(this.collectionGroupWithCache(collectionId, qb, maxAge).pipe(take(1)));
}
doc(path, maxAge = CACHE_MAX_AGE) {
return lastValueFrom(this.docWithCache(path, maxAge).pipe(take(1)));
}
docRef(path) {
return doc(this.firestore, path);
}
async upsert(collectionPath, data, opts = { merge: true }) {
const timestamp = this.serverTimestamp;
let { id, ...updata } = data;
updata.createdTs ?? (updata.createdTs = timestamp);
updata.updatedTs = timestamp;
if (id) {
await setDoc(this.docRef(`${collectionPath}/${id}`), Object.assign({}, updata), opts);
}
else {
id = (await addDoc(collection(this.firestore, collectionPath), updata)).id;
}
return id;
}
update(docPath, data) {
const updatedTs = this.serverTimestamp;
// ignore id
delete data['id'];
return updateDoc(this.docRef(docPath), Object.assign({}, data, { updatedTs }));
}
delete(docPath) {
return deleteDoc(this.docRef(docPath));
}
async bulkUpsert(path, data, opts = { merge: true }) {
const bulkIds = [];
const promises = [];
if (Array.isArray(data)) {
// Due to a batch limitation, need to split docs array into chunks
for (const chunks of arrayToChunks(data, this.BATCH_MAX_WRITES)) {
const batch = this.batch;
const timestamp = this.serverTimestamp;
chunks.forEach(async ({ id, ...updata }) => {
updata.createdTs ?? (updata.createdTs = timestamp);
updata.updatedTs = timestamp;
let docRef;
if (id) {
docRef = this.docRef(`${path}/${id}`);
}
else {
docRef = doc(collection(this.firestore, path));
}
bulkIds.push(docRef.id);
batch.set(docRef, updata, opts);
});
const p = batch.commit();
promises.push(p);
}
}
else {
const snapshot = await this.collectionSnapshot(path, data.qb);
// Due to a batch limitation, need to split docs array into chunks
for (const chunks of arrayToChunks(snapshot.docs, this.BATCH_MAX_WRITES)) {
const batch = this.batch;
const timestamp = this.serverTimestamp;
chunks.forEach((d) => batch.set(d.ref, { updatedTs: timestamp, ...data.data }, opts) && bulkIds.push(d.id));
const p = batch.commit();
promises.push(p);
}
}
await Promise.all(promises);
return bulkIds;
}
async bulkDelete(path, qb, maxSize = 1000) {
qb ?? (qb = new QueryBuilder());
qb.limit(maxSize);
const bulkIds = [];
const promises = [];
const snapshot = await this.collectionSnapshot(path, qb);
// Due to a batch limitation, need to split docs array into chunks
for (const chunks of arrayToChunks(snapshot.docs, this.BATCH_MAX_WRITES)) {
const batch = this.batch;
chunks.forEach((d) => batch.delete(d.ref) && bulkIds.push(d.id));
const p = batch.commit();
promises.push(p);
}
await Promise.all(promises);
return bulkIds;
}
/**
* write batch
*/
get batch() {
return writeBatch(this.firestore);
}
/**
* firestore timestamp
*/
get serverTimestamp() {
return serverTimestamp();
}
/**
* FieldValue increment
*/
increment(n = 1) {
return increment(n);
}
/**
* Returns a generated Firestore Document Id.
*/
createId(colPath) {
return doc(collection(this.firestore, colPath ?? '_')).id;
}
runTransaction(updateFunction) {
return runTransaction(this.firestore, updateFunction);
}
// -----------------------------------------------------------------------------------------------------
// @ Custom methods
// -----------------------------------------------------------------------------------------------------
collectionValueChanges(path, qb) {
const collectionRef = collection(this.firestore, path);
qb ?? (qb = new QueryBuilder());
return collectionData(qb.exec(collectionRef, queryOps), { idField: 'id' }).pipe((s) => (qb?.joins ?? []).map((j) => leftJoin(this, ...j)).reduce((ss, o) => o(ss), s));
}
collectionGroupValueChanges(collectionId, qb) {
const collectionRef = collectionGroup(this.firestore, collectionId);
qb ?? (qb = new QueryBuilder());
return collectionData(qb.exec(collectionRef, queryOps), { idField: 'id' }).pipe((s) => (qb?.joins ?? []).map((j) => leftJoin(this, ...j)).reduce((ss, o) => o(ss), s));
}
collectionSnapshot(path, qb) {
qb ?? (qb = new QueryBuilder());
const collectionRef = collection(this.firestore, path);
return getDocs(qb.exec(collectionRef, queryOps));
}
collectionSnapshotChanges(path, qb, events) {
const collectionRef = collection(this.firestore, path);
qb ?? (qb = new QueryBuilder());
return collectionChanges(qb.exec(collectionRef, queryOps), { events }).pipe(map((changes) => changes.map((c) => Object.assign({}, c.doc.data(), { id: c.doc.id }))), (s) => (qb?.joins ?? []).map((j) => leftJoin(this, ...j)).reduce((ss, o) => o(ss), s));
}
collectionGroupSnapshotChanges(collectionId, qb, events) {
const collectionRef = collectionGroup(this.firestore, collectionId);
qb ?? (qb = new QueryBuilder());
return collectionChanges(qb.exec(collectionRef, queryOps), { events }).pipe(map((changes) => changes.map((c) => Object.assign({}, c.doc.data(), { id: c.doc.id }))), (s) => (qb?.joins ?? []).map((j) => leftJoin(this, ...j)).reduce((ss, o) => o(ss), s));
}
docValueChanges(path) {
const docRef = doc(this.firestore, path);
return docData(docRef, { idField: 'id' });
}
/**
* @experimental
*
* Cache collection data in memory
*/
collectionWithCache(path, qb, maxAge) {
return this.fetchFromCache(path + (qb ? JSON.stringify(qb) : ''), this.collectionValueChanges(path, qb), maxAge);
}
/**
* @experimental
*
* Cache collectionGroup data in memory
*/
collectionGroupWithCache(collectionId, qb, maxAge) {
return this.fetchFromCache(collectionId + (qb ? JSON.stringify(qb) : ''), this.collectionGroupValueChanges(collectionId, qb), maxAge);
}
/**
* @experimental
*
* Cache document data in memory
*/
docWithCache(path, maxAge) {
return this.fetchFromCache(path, this.docValueChanges(path), maxAge);
}
/**
* @experimental
*
* Delete cached data from the memory
*/
deleteCache(path, qb) {
const key = path + (qb ? JSON.stringify(qb) : '');
return this.cache.delete(key);
}
fetchFromCache(key, source, maxAge) {
const cached = this.cache.get(key);
if (maxAge === 0 || !cached || (maxAge && Date.now() - cached.lastRead > maxAge)) {
return source.pipe(map((data) => this.cache.set(key, { lastRead: Date.now(), data }) && data));
}
return of(cached.data);
}
}
FirestoreService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: FirestoreService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
FirestoreService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: FirestoreService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: FirestoreService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
const leftJoin = (fs, key, collection, alias, maxAge) => {
if (key === alias) {
throw Error('Due to use of Cache, you must use different alias for a key.');
}
return (source) => defer(() => {
let ret;
return source.pipe(switchMap((data) => {
ret = data;
const fetchJoinData = (id) => {
if (Array.isArray(id)) {
const qb = new QueryBuilder();
qb.where(documentId(), 'in', id);
return fs.collectionWithCache(collection, qb, maxAge);
}
return fs.docWithCache(`${collection}/${id}`, maxAge);
};
if (Array.isArray(data)) {
const docs$ = ret.filter((i) => i[key]).map((i) => fetchJoinData(i[key]));
return docs$.length ? combineLatest(docs$) : of([]);
}
return data && data[key] ? fetchJoinData(data[key]) : of(null);
}), map((joins) => {
if (Array.isArray(ret)) {
return ret.map((r) => {
const id = r[key];
if (id) {
if (Array.isArray(id)) {
r[alias] = joins
.filter((j) => Array.isArray(j) && JSON.stringify(j.map((jj) => jj.id).sort()) === JSON.stringify(id.sort()))
.pop();
}
else {
r[alias] = joins.filter((j) => j?.id === id).pop();
}
}
return r;
});
}
if (ret) {
ret[alias] = joins;
}
return ret;
}));
});
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZXN0b3JlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy9uZ3gvc2VydmljZXMvZmlyZXN0b3JlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQ0wsWUFBWSxFQUNaLEdBQUcsRUFDSCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNULFVBQVUsRUFDVixjQUFjLEVBQ2QsZUFBZSxFQUNmLGlCQUFpQixFQUNqQixPQUFPLEVBQ1AsU0FBUyxFQUNULFVBQVUsRUFDVixlQUFlLEVBQ2YsS0FBSyxFQUNMLEtBQUssRUFDTCxPQUFPLEVBQ1AsS0FBSyxFQUNMLFdBQVcsRUFDWCxPQUFPLEVBQ1AsVUFBVSxFQUNWLEtBQUssRUFDTCxTQUFTLEVBQ1QsY0FBYyxFQUNkLFVBQVUsRUFDWCxNQUFNLHlCQUF5QixDQUFDO0FBVWpDLE9BQU8sRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0UsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFDOztBQUV6QyxNQUFNLFFBQVEsR0FBRztJQUNmLEtBQUs7SUFDTCxLQUFLO0lBQ0wsT0FBTztJQUNQLEtBQUs7SUFDTCxXQUFXO0lBQ1gsT0FBTztJQUNQLFVBQVU7SUFDVixLQUFLO0lBQ0wsU0FBUztDQUNWLENBQUM7QUFFRixNQUFNLGFBQWEsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUtwQyxNQUFNLE9B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Q0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7YUFDcEI7WUFFRCxPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIGdldEZpcmVzdG9yZSxcbiAgZG9jLFxuICBkb2NEYXRhLFxuICBhZGREb2MsXG4gIHNldERvYyxcbiAgdXBkYXRlRG9jLFxuICBkZWxldGVEb2MsXG4gIGNvbGxlY3Rpb24sXG4gIGNvbGxlY3Rpb25EYXRhLFxuICBjb2xsZWN0aW9uR3JvdXAsXG4gIGNvbGxlY3Rpb25DaGFuZ2VzLFxuICBnZXREb2NzLFxuICBpbmNyZW1lbnQsXG4gIHdyaXRlQmF0Y2gsXG4gIHNlcnZlclRpbWVzdGFtcCxcbiAgcXVlcnksXG4gIHdoZXJlLFxuICBvcmRlckJ5LFxuICBsaW1pdCxcbiAgbGltaXRUb0xhc3QsXG4gIHN0YXJ0QXQsXG4gIHN0YXJ0QWZ0ZXIsXG4gIGVuZEF0LFxuICBlbmRCZWZvcmUsXG4gIHJ1blRyYW5zYWN0aW9uLFxuICBkb2N1bWVudElkXG59IGZyb20gJ0Bhbmd1bGFyL2ZpcmUvZmlyZXN0b3JlJztcbmltcG9ydCB0eXBlIHtcbiAgRmlyZXN0b3JlLFxuICBEb2N1bWVudENoYW5nZVR5cGUsXG4gIERvY3VtZW50RGF0YSxcbiAgUXVlcnlTbmFwc2hvdCxcbiAgU2V0T3B0aW9ucyxcbiAgVHJhbnNhY3Rpb25cbn0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9maXJlc3RvcmUnO1xuXG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBkZWZlciwgbGFzdFZhbHVlRnJvbSwgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgc3dpdGNoTWFwLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBRdWVyeUJ1aWxkZXIsIEFic3RyYWN0RmlyZXN0b3JlQXBpIH0gZnJvbSAnLi4vZGInO1xuaW1wb3J0IHsgYXJyYXlUb0NodW5rcyB9IGZyb20gJy4uL3V0aWxzJztcblxuY29uc3QgcXVlcnlPcHMgPSB7XG4gIHF1ZXJ5LFxuICB3aGVyZSxcbiAgb3JkZXJCeSxcbiAgbGltaXQsXG4gIGxpbWl0VG9MYXN0LFxuICBzdGFydEF0LFxuICBzdGFydEFmdGVyLFxuICBlbmRBdCxcbiAgZW5kQmVmb3JlXG59O1xuXG5jb25zdCBDQUNIRV9NQVhfQUdFID0gNSAqIDYwICogMTAwMDtcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgRmlyZXN0b3JlU2VydmljZSBleHRlbmRzIEFic3RyYWN0RmlyZXN0b3JlQXBpIHtcbiAgZ2V0IGZpcmVzdG9yZSgpOiBGaXJlc3RvcmUge1xuICAgIHJldHVybiBnZXRGaXJlc3RvcmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEAgQWJzdHJhY3QgbWVtYmVyc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIGNvbGxlY3Rpb248VCA9IGFueT4ocGF0aDogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlciwgbWF4QWdlID0gQ0FDSEVfTUFYX0FHRSk6IFByb21pc2U8VFtdPiB7XG4gICAgcmV0dXJuIGxhc3RWYWx1ZUZyb20odGhpcy5jb2xsZWN0aW9uV2l0aENhY2hlKHBhdGgsIHFiLCBtYXhBZ2UpLnBpcGUodGFrZSgxKSkpO1xuICB9XG5cbiAgY29sbGVjdGlvbkdyb3VwPFQgPSBhbnk+KGNvbGxlY3Rpb25JZDogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlciwgbWF4QWdlID0gQ0FDSEVfTUFYX0FHRSk6IFByb21pc2U8VFtdPiB7XG4gICAgcmV0dXJuIGxhc3RWYWx1ZUZyb20odGhpcy5jb2xsZWN0aW9uR3JvdXBXaXRoQ2FjaGUoY29sbGVjdGlvbklkLCBxYiwgbWF4QWdlKS5waXBlKHRha2UoMSkpKTtcbiAgfVxuXG4gIGRvYzxUID0gYW55PihwYXRoOiBzdHJpbmcsIG1heEFnZSA9IENBQ0hFX01BWF9BR0UpOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gbGFzdFZhbHVlRnJvbSh0aGlzLmRvY1dpdGhDYWNoZShwYXRoLCBtYXhBZ2UpLnBpcGUodGFrZSgxKSkpO1xuICB9XG5cbiAgZG9jUmVmKHBhdGg6IHN0cmluZykge1xuICAgIHJldHVybiBkb2ModGhpcy5maXJlc3RvcmUsIHBhdGgpIGFzIGFueTtcbiAgfVxuXG4gIGFzeW5jIHVwc2VydChcbiAgICBjb2xsZWN0aW9uUGF0aDogc3RyaW5nLFxuICAgIGRhdGE6IHsgW2tleTogc3RyaW5nXTogYW55IH0sXG4gICAgb3B0czogU2V0T3B0aW9ucyA9IHsgbWVyZ2U6IHRydWUgfVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHRpbWVzdGFtcCA9IHRoaXMuc2VydmVyVGltZXN0YW1wO1xuXG4gICAgbGV0IHsgaWQsIC4uLnVwZGF0YSB9ID0gZGF0YTtcbiAgICB1cGRhdGEuY3JlYXRlZFRzID8/PSB0aW1lc3RhbXA7XG4gICAgdXBkYXRhLnVwZGF0ZWRUcyA9IHRpbWVzdGFtcDtcblxuICAgIGlmIChpZCkge1xuICAgICAgYXdhaXQgc2V0RG9jKHRoaXMuZG9jUmVmKGAke2NvbGxlY3Rpb25QYXRofS8ke2lkfWApLCBPYmplY3QuYXNzaWduKHt9LCB1cGRhdGEpLCBvcHRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWQgPSAoYXdhaXQgYWRkRG9jKGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoKSwgdXBkYXRhKSkuaWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgdXBkYXRlKGRvY1BhdGg6IHN0cmluZywgZGF0YTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSkge1xuICAgIGNvbnN0IHVwZGF0ZWRUcyA9IHRoaXMuc2VydmVyVGltZXN0YW1wO1xuXG4gICAgLy8gaWdub3JlIGlkXG4gICAgZGVsZXRlIGRhdGFbJ2lkJ107XG5cbiAgICByZXR1cm4gdXBkYXRlRG9jKHRoaXMuZG9jUmVmKGRvY1BhdGgpLCBPYmplY3QuYXNzaWduKHt9LCBkYXRhLCB7IHVwZGF0ZWRUcyB9KSk7XG4gIH1cblxuICBkZWxldGUoZG9jUGF0aDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGRlbGV0ZURvYyh0aGlzLmRvY1JlZihkb2NQYXRoKSk7XG4gIH1cblxuICBhc3luYyBidWxrVXBzZXJ0KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBkYXRhOiBEb2N1bWVudERhdGFbXSB8IHsgZGF0YTogRG9jdW1lbnREYXRhOyBxYj86IFF1ZXJ5QnVpbGRlciB9LFxuICAgIG9wdHM6IFNldE9wdGlvbnMgPSB7IG1lcmdlOiB0cnVlIH1cbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IGJ1bGtJZHMgPSBbXTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIC8vIER1ZSB0byBhIGJhdGNoIGxpbWl0YXRpb24sIG5lZWQgdG8gc3BsaXQgZG9jcyBhcnJheSBpbnRvIGNodW5rc1xuICAgICAgZm9yIChjb25zdCBjaHVua3Mgb2YgYXJyYXlUb0NodW5rcyhkYXRhLCB0aGlzLkJBVENIX01BWF9XUklURVMpKSB7XG4gICAgICAgIGNvbnN0IGJhdGNoID0gdGhpcy5iYXRjaDtcbiAgICAgICAgY29uc3QgdGltZXN0YW1wID0gdGhpcy5zZXJ2ZXJUaW1lc3RhbXA7XG5cbiAgICAgICAgY2h1bmtzLmZvckVhY2goYXN5bmMgKHsgaWQsIC4uLnVwZGF0YSB9KSA9PiB7XG4gICAgICAgICAgdXBkYXRhLmNyZWF0ZWRUcyA/Pz0gdGltZXN0YW1wO1xuICAgICAgICAgIHVwZGF0YS51cGRhdGVkVHMgPSB0aW1lc3RhbXA7XG5cbiAgICAgICAgICBsZXQgZG9jUmVmOiBhbnk7XG5cbiAgICAgICAgICBpZiAoaWQpIHtcbiAgICAgICAgICAgIGRvY1JlZiA9IHRoaXMuZG9jUmVmKGAke3BhdGh9LyR7aWR9YCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRvY1JlZiA9IGRvYyhjb2xsZWN0aW9uKHRoaXMuZmlyZXN0b3JlLCBwYXRoKSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnVsa0lkcy5wdXNoKGRvY1JlZi5pZCk7XG4gICAgICAgICAgYmF0Y2guc2V0KGRvY1JlZiwgdXBkYXRhLCBvcHRzKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgcCA9IGJhdGNoLmNvbW1pdCgpO1xuICAgICAgICBwcm9taXNlcy5wdXNoKHApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHRoaXMuY29sbGVjdGlvblNuYXBzaG90KHBhdGgsIGRhdGEucWIpO1xuXG4gICAgICAvLyBEdWUgdG8gYSBiYXRjaCBsaW1pdGF0aW9uLCBuZWVkIHRvIHNwbGl0IGRvY3MgYXJyYXkgaW50byBjaHVua3NcbiAgICAgIGZvciAoY29uc3QgY2h1bmtzIG9mIGFycmF5VG9DaHVua3Moc25hcHNob3QuZG9jcywgdGhpcy5CQVRDSF9NQVhfV1JJVEVTKSkge1xuICAgICAgICBjb25zdCBiYXRjaCA9IHRoaXMuYmF0Y2g7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IHRoaXMuc2VydmVyVGltZXN0YW1wO1xuXG4gICAgICAgIGNodW5rcy5mb3JFYWNoKChkKSA9PiBiYXRjaC5zZXQoZC5yZWYsIHsgdXBkYXRlZFRzOiB0aW1lc3RhbXAsIC4uLmRhdGEuZGF0YSB9LCBvcHRzKSAmJiBidWxrSWRzLnB1c2goZC5pZCkpO1xuXG4gICAgICAgIGNvbnN0IHAgPSBiYXRjaC5jb21taXQoKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG5cbiAgICByZXR1cm4gYnVsa0lkcztcbiAgfVxuXG4gIGFzeW5jIGJ1bGtEZWxldGUocGF0aDogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlciwgbWF4U2l6ZSA9IDEwMDApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgcWIgPz89IG5ldyBRdWVyeUJ1aWxkZXIoKTtcbiAgICBxYi5saW1pdChtYXhTaXplKTtcblxuICAgIGNvbnN0IGJ1bGtJZHMgPSBbXTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgY29uc3Qgc25hcHNob3Q6IFF1ZXJ5U25hcHNob3Q8RG9jdW1lbnREYXRhPiA9IGF3YWl0IHRoaXMuY29sbGVjdGlvblNuYXBzaG90KHBhdGgsIHFiKTtcblxuICAgIC8vIER1ZSB0byBhIGJhdGNoIGxpbWl0YXRpb24sIG5lZWQgdG8gc3BsaXQgZG9jcyBhcnJheSBpbnRvIGNodW5rc1xuICAgIGZvciAoY29uc3QgY2h1bmtzIG9mIGFycmF5VG9DaHVua3Moc25hcHNob3QuZG9jcywgdGhpcy5CQVRDSF9NQVhfV1JJVEVTKSkge1xuICAgICAgY29uc3QgYmF0Y2ggPSB0aGlzLmJhdGNoO1xuXG4gICAgICBjaHVua3MuZm9yRWFjaCgoZCkgPT4gYmF0Y2guZGVsZXRlKGQucmVmKSAmJiBidWxrSWRzLnB1c2goZC5pZCkpO1xuICAgICAgY29uc3QgcCA9IGJhdGNoLmNvbW1pdCgpO1xuICAgICAgcHJvbWlzZXMucHVzaChwKTtcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG5cbiAgICByZXR1cm4gYnVsa0lkcztcbiAgfVxuXG4gIC8qKlxuICAgKiB3cml0ZSBiYXRjaFxuICAgKi9cbiAgZ2V0IGJhdGNoKCkge1xuICAgIHJldHVybiB3cml0ZUJhdGNoKHRoaXMuZmlyZXN0b3JlKSBhcyBhbnk7XG4gIH1cblxuICAvKipcbiAgICogZmlyZXN0b3JlIHRpbWVzdGFtcFxuICAgKi9cbiAgZ2V0IHNlcnZlclRpbWVzdGFtcCgpIHtcbiAgICByZXR1cm4gc2VydmVyVGltZXN0YW1wKCk7XG4gIH1cblxuICAvKipcbiAgICogRmllbGRWYWx1ZSBpbmNyZW1lbnRcbiAgICovXG4gIGluY3JlbWVudChuID0gMSkge1xuICAgIHJldHVybiBpbmNyZW1lbnQobik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGdlbmVyYXRlZCBGaXJlc3RvcmUgRG9jdW1lbnQgSWQuXG4gICAqL1xuICBjcmVhdGVJZChjb2xQYXRoPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGRvYyhjb2xsZWN0aW9uKHRoaXMuZmlyZXN0b3JlLCBjb2xQYXRoID8/ICdfJykpLmlkO1xuICB9XG5cbiAgcnVuVHJhbnNhY3Rpb24odXBkYXRlRnVuY3Rpb246ICh0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24gfCBhbnkpID0+IFByb21pc2U8dW5rbm93bj4pOiBQcm9taXNlPHVua25vd24+IHtcbiAgICByZXR1cm4gcnVuVHJhbnNhY3Rpb24odGhpcy5maXJlc3RvcmUsIHVwZGF0ZUZ1bmN0aW9uKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEAgQ3VzdG9tIG1ldGhvZHNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBjb2xsZWN0aW9uVmFsdWVDaGFuZ2VzPFQgPSBhbnk+KHBhdGg6IHN0cmluZywgcWI/OiBRdWVyeUJ1aWxkZXIpOiBPYnNlcnZhYmxlPFRbXT4ge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25SZWYgPSBjb2xsZWN0aW9uKHRoaXMuZmlyZXN0b3JlLCBwYXRoKTtcbiAgICBxYiA/Pz0gbmV3IFF1ZXJ5QnVpbGRlcigpO1xuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25EYXRhKHFiLmV4ZWMoY29sbGVjdGlvblJlZiwgcXVlcnlPcHMpLCB7IGlkRmllbGQ6ICdpZCcgfSkucGlwZSgocykgPT5cbiAgICAgIChxYj8uam9pbnMgPz8gW10pLm1hcCgoaikgPT4gbGVmdEpvaW4odGhpcywgLi4uaikpLnJlZHVjZSgoc3MsIG8pID0+IG8oc3MpLCBzKVxuICAgICk7XG4gIH1cblxuICBjb2xsZWN0aW9uR3JvdXBWYWx1ZUNoYW5nZXM8VCA9IGFueT4oY29sbGVjdGlvbklkOiBzdHJpbmcsIHFiPzogUXVlcnlCdWlsZGVyKTogT2JzZXJ2YWJsZTxUW10+IHtcbiAgICBjb25zdCBjb2xsZWN0aW9uUmVmID0gY29sbGVjdGlvbkdyb3VwKHRoaXMuZmlyZXN0b3JlLCBjb2xsZWN0aW9uSWQpO1xuICAgIHFiID8/PSBuZXcgUXVlcnlCdWlsZGVyKCk7XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbkRhdGEocWIuZXhlYyhjb2xsZWN0aW9uUmVmLCBxdWVyeU9wcyksIHsgaWRGaWVsZDogJ2lkJyB9KS5waXBlKChzKSA9PlxuICAgICAgKHFiPy5qb2lucyA/PyBbXSkubWFwKChqKSA9PiBsZWZ0Sm9pbih0aGlzLCAuLi5qKSkucmVkdWNlKChzcywgbykgPT4gbyhzcyksIHMpXG4gICAgKTtcbiAgfVxuXG4gIGNvbGxlY3Rpb25TbmFwc2hvdChwYXRoOiBzdHJpbmcsIHFiPzogUXVlcnlCdWlsZGVyKTogUHJvbWlzZTxRdWVyeVNuYXBzaG90PGFueT4gfCBhbnk+IHtcbiAgICBxYiA/Pz0gbmV3IFF1ZXJ5QnVpbGRlcigpO1xuXG4gICAgY29uc3QgY29sbGVjdGlvblJlZiA9IGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIHBhdGgpO1xuICAgIHJldHVybiBnZXREb2NzKHFiLmV4ZWMoY29sbGVjdGlvblJlZiwgcXVlcnlPcHMpKTtcbiAgfVxuXG4gIGNvbGxlY3Rpb25TbmFwc2hvdENoYW5nZXM8VCA9IGFueT4ocGF0aDogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlciwgZXZlbnRzPzogRG9jdW1lbnRDaGFuZ2VUeXBlW10pOiBPYnNlcnZhYmxlPFRbXT4ge1xuICAgIGNvbnN0IGNvbGxlY3Rpb25SZWY6IGFueSA9IGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIHBhdGgpO1xuICAgIHFiID8/PSBuZXcgUXVlcnlCdWlsZGVyKCk7XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbkNoYW5nZXMocWIuZXhlYyhjb2xsZWN0aW9uUmVmLCBxdWVyeU9wcyksIHsgZXZlbnRzIH0pLnBpcGUoXG4gICAgICBtYXAoKGNoYW5nZXMpID0+IGNoYW5nZXMubWFwKChjKSA9PiBPYmplY3QuYXNzaWduKHt9LCBjLmRvYy5kYXRhKCksIHsgaWQ6IGMuZG9jLmlkIH0gYXMgYW55KSkpLFxuICAgICAgKHMpID0+IChxYj8uam9pbnMgPz8gW10pLm1hcCgoaikgPT4gbGVmdEpvaW4odGhpcywgLi4uaikpLnJlZHVjZSgoc3MsIG8pID0+IG8oc3MpLCBzKVxuICAgICk7XG4gIH1cblxuICBjb2xsZWN0aW9uR3JvdXBTbmFwc2hvdENoYW5nZXM8VCA9IGFueT4oXG4gICAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gICAgcWI/OiBRdWVyeUJ1aWxkZXIsXG4gICAgZXZlbnRzPzogRG9jdW1lbnRDaGFuZ2VUeXBlW11cbiAgKTogT2JzZXJ2YWJsZTxUW10+IHtcbiAgICBjb25zdCBjb2xsZWN0aW9uUmVmOiBhbnkgPSBjb2xsZWN0aW9uR3JvdXAodGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25JZCk7XG4gICAgcWIgPz89IG5ldyBRdWVyeUJ1aWxkZXIoKTtcblxuICAgIHJldHVybiBjb2xsZWN0aW9uQ2hhbmdlcyhxYi5leGVjKGNvbGxlY3Rpb25SZWYsIHF1ZXJ5T3BzKSwgeyBldmVudHMgfSkucGlwZShcbiAgICAgIG1hcCgoY2hhbmdlcykgPT4gY2hhbmdlcy5tYXAoKGMpID0+IE9iamVjdC5hc3NpZ24oe30sIGMuZG9jLmRhdGEoKSwgeyBpZDogYy5kb2MuaWQgfSBhcyBhbnkpKSksXG4gICAgICAocykgPT4gKHFiPy5qb2lucyA/PyBbXSkubWFwKChqKSA9PiBsZWZ0Sm9pbih0aGlzLCAuLi5qKSkucmVkdWNlKChzcywgbykgPT4gbyhzcyksIHMpXG4gICAgKTtcbiAgfVxuXG4gIGRvY1ZhbHVlQ2hhbmdlczxUID0gYW55PihwYXRoOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCBkb2NSZWY6IGFueSA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgcGF0aCk7XG4gICAgcmV0dXJuIGRvY0RhdGE8VD4oZG9jUmVmLCB7IGlkRmllbGQ6ICdpZCcgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGV4cGVyaW1lbnRhbFxuICAgKlxuICAgKiBDYWNoZSBjb2xsZWN0aW9uIGRhdGEgaW4gbWVtb3J5XG4gICAqL1xuICBjb2xsZWN0aW9uV2l0aENhY2hlPFQgPSBhbnk+KHBhdGg6IHN0cmluZywgcWI/OiBRdWVyeUJ1aWxkZXIsIG1heEFnZT86IG51bWJlcik6IE9ic2VydmFibGU8VFtdPiB7XG4gICAgcmV0dXJuIHRoaXMuZmV0Y2hGcm9tQ2FjaGUocGF0aCArIChxYiA/IEpTT04uc3RyaW5naWZ5KHFiKSA6ICcnKSwgdGhpcy5jb2xsZWN0aW9uVmFsdWVDaGFuZ2VzPFQ+KHBhdGgsIHFiKSwgbWF4QWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZXhwZXJpbWVudGFsXG4gICAqXG4gICAqIENhY2hlIGNvbGxlY3Rpb25Hcm91cCBkYXRhIGluIG1lbW9yeVxuICAgKi9cbiAgY29sbGVjdGlvbkdyb3VwV2l0aENhY2hlPFQgPSBhbnk+KGNvbGxlY3Rpb25JZDogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlciwgbWF4QWdlPzogbnVtYmVyKTogT2JzZXJ2YWJsZTxUW10+IHtcbiAgICByZXR1cm4gdGhpcy5mZXRjaEZyb21DYWNoZShcbiAgICAgIGNvbGxlY3Rpb25JZCArIChxYiA/IEpTT04uc3RyaW5naWZ5KHFiKSA6ICcnKSxcbiAgICAgIHRoaXMuY29sbGVjdGlvbkdyb3VwVmFsdWVDaGFuZ2VzPFQ+KGNvbGxlY3Rpb25JZCwgcWIpLFxuICAgICAgbWF4QWdlXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZXhwZXJpbWVudGFsXG4gICAqXG4gICAqIENhY2hlIGRvY3VtZW50IGRhdGEgaW4gbWVtb3J5XG4gICAqL1xuICBkb2NXaXRoQ2FjaGUocGF0aDogc3RyaW5nLCBtYXhBZ2U/OiBudW1iZXIpIHtcbiAgICByZXR1cm4gdGhpcy5mZXRjaEZyb21DYWNoZShwYXRoLCB0aGlzLmRvY1ZhbHVlQ2hhbmdlcyhwYXRoKSwgbWF4QWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZXhwZXJpbWVudGFsXG4gICAqXG4gICAqIERlbGV0ZSBjYWNoZWQgZGF0YSBmcm9tIHRoZSBtZW1vcnlcbiAgICovXG4gIGRlbGV0ZUNhY2hlKHBhdGg6IHN0cmluZywgcWI/OiBRdWVyeUJ1aWxkZXIpIHtcbiAgICBjb25zdCBrZXkgPSBwYXRoICsgKHFiID8gSlNPTi5zdHJpbmdpZnkocWIpIDogJycpO1xuICAgIHJldHVybiB0aGlzLmNhY2hlLmRlbGV0ZShrZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBmZXRjaEZyb21DYWNoZShrZXk6IHN0cmluZywgc291cmNlOiBPYnNlcnZhYmxlPGFueT4sIG1heEFnZTogbnVtYmVyKSB7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5jYWNoZS5nZXQoa2V5KTtcblxuICAgIGlmIChtYXhBZ2UgPT09IDAgfHwgIWNhY2hlZCB8fCAobWF4QWdlICYmIERhdGUubm93KCkgLSBjYWNoZWQubGFzdFJlYWQgPiBtYXhBZ2UpKSB7XG4gICAgICByZXR1cm4gc291cmNlLnBpcGUobWFwKChkYXRhKSA9PiB0aGlzLmNhY2hlLnNldChrZXksIHsgbGFzdFJlYWQ6IERhdGUubm93KCksIGRhdGEgfSkgJiYgZGF0YSkpO1xuICAgIH1cblxuICAgIHJldHVybiBvZihjYWNoZWQuZGF0YSk7XG4gIH1cbn1cblxuY29uc3QgbGVmdEpvaW4gPSAoZnM6IEZpcmVzdG9yZVNlcnZpY2UsIGtleTogc3RyaW5nLCBjb2xsZWN0aW9uOiBzdHJpbmcsIGFsaWFzOiBzdHJpbmcsIG1heEFnZT86IG51bWJlcikgPT4ge1xuICBpZiAoa2V5ID09PSBhbGlhcykge1xuICAgIHRocm93IEVycm9yKCdEdWUgdG8gdXNlIG9mIENhY2hlLCB5b3UgbXVzdCB1c2UgZGlmZmVyZW50IGFsaWFzIGZvciBhIGtleS4nKTtcbiAgfVxuXG4gIHJldHVybiAoc291cmNlOiBPYnNlcnZhYmxlPGFueSB8IGFueVtdPikgPT5cbiAgICBkZWZlcigoKSA9PiB7XG4gICAgICBsZXQgcmV0OiBhbnk7XG5cbiAgICAgIHJldHVybiBzb3VyY2UucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKChkYXRhKSA9PiB7XG4gICAgICAgICAgcmV0ID0gZGF0YTtcblxuICAgICAgICAgIGNvbnN0IGZldGNoSm9pbkRhdGEgPSAoaWQ6IHN0cmluZyB8IHN0cmluZ1tdKSA9PiB7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShpZCkpIHtcbiAgICAgICAgICAgICAgY29uc3QgcWIgPSBuZXcgUXVlcnlCdWlsZGVyKCk7XG4gICAgICAgICAgICAgIHFiLndoZXJlKGRvY3VtZW50SWQoKSwgJ2luJywgaWQpO1xuICAgICAgICAgICAgICByZXR1cm4gZnMuY29sbGVjdGlvbldpdGhDYWNoZShjb2xsZWN0aW9uLCBxYiwgbWF4QWdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZzLmRvY1dpdGhDYWNoZShgJHtjb2xsZWN0aW9ufS8ke2lkfWAsIG1heEFnZSk7XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgICAgICBjb25zdCBkb2NzJCA9IChyZXQgYXMgYW55W10pLmZpbHRlcigoaSkgPT4gaVtrZXldKS5tYXAoKGkpID0+IGZldGNoSm9pbkRhdGEoaVtrZXldKSk7XG4gICAgICAgICAgICByZXR1cm4gZG9jcyQubGVuZ3RoID8gY29tYmluZUxhdGVzdChkb2NzJCkgOiBvZihbXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGRhdGEgJiYgZGF0YVtrZXldID8gZmV0Y2hKb2luRGF0YShkYXRhW2tleV0pIDogb2YobnVsbCk7XG4gICAgICAgIH0pLFxuICAgICAgICBtYXAoKGpvaW5zKSA9PiB7XG4gICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmV0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHJldC5tYXAoKHIpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgaWQgPSByW2tleV07XG4gICAgICAgICAgICAgIGlmIChpZCkge1xuICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGlkKSkge1xuICAgICAgICAgICAgICAgICAgclthbGlhc10gPSBqb2luc1xuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKFxuICAgICAgICAgICAgICAgICAgICAgIChqOiBhbnkpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGopICYmIEpTT04uc3RyaW5naWZ5KGoubWFwKChqaikgPT4gamouaWQpLnNvcnQoKSkgPT09IEpTT04uc3RyaW5naWZ5KGlkLnNvcnQoKSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAucG9wKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJbYWxpYXNdID0gam9pbnMuZmlsdGVyKChqOiBhbnkpID0+IGo/LmlkID09PSBpZCkucG9wKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHI7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmV0KSB7XG4gICAgICAgICAgICByZXRbYWxpYXNdID0gam9pbnM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG59O1xuIl19