UNPKG

simplyfire

Version:

A lightweight firestore api for firebase cloud functions & Angular.

273 lines 42.9 kB
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