UNPKG

simplyfire

Version:

A lightweight firestore api for firebase cloud functions & Angular.

150 lines 22.6 kB
import { AbstractFirestoreApi, QueryBuilder } from '../../ngx/db'; import { arrayToChunks } from '../utils'; export class FirestoreCloudService extends AbstractFirestoreApi { static getInstance(admin, settings = {}) { this.instance ?? (this.instance = new this()); this.instance.initialize(admin, settings); return this.instance; } initialize(admin, settings) { admin.initializeApp(); this.db = admin.firestore(); this.db.settings(settings); this.admin = admin; } // ----------------------------------------------------------------------------------------------------- // @ Abstract members // ----------------------------------------------------------------------------------------------------- async collection(collection, qb) { return (await this.collectionSnapshot(collection, qb)).docs.map((doc) => ({ id: doc.id, ...doc.data() })); } async collectionGroup(collectionId, qb) { return (await this.collectionGroupSnapshot(collectionId, qb)).docs.map((doc) => ({ id: doc.id, ...doc.data() })); } async doc(path) { const snapshot = await this.docRef(path).get(); return (snapshot.exists && { id: snapshot.id, ...snapshot.data() }) || null; } async upsert(collection, data, opts = { merge: true }) { const timestamp = this.serverTimestamp; // eslint-disable-next-line prefer-const let { id, ...updata } = data; updata.createdTs ?? (updata.createdTs = timestamp); if (!id) { id = this.db.collection(collection).doc().id; } updata.updatedTs = timestamp; await this.docRef(`${collection}/${id}`).set(Object.assign({}, updata), opts); return id; } async update(path, data) { await this.docRef(path).update(data); } async delete(path) { await this.docRef(path).delete(); } /** * Bulk update data */ async bulkUpsert(path, data, opts = { merge: true }) { const bulkIds = []; const promises = []; const timestamp = this.serverTimestamp; 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; chunks.forEach((d) => { let { id, ...updata } = d; id ?? (id = this.db.collection(path).doc().id); updata.createdTs ?? (updata.createdTs = timestamp); updata.updatedTs = timestamp; batch.set(this.docRef(`${path}/${id}`), updata, opts); bulkIds.push(id); }); 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; 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; } /** * Bulk delete data */ async bulkDelete(collection, qb, maxSize = 1000) { if (!qb) { qb = new QueryBuilder(); qb.limit(maxSize); } const bulkIds = []; const promises = []; const snapshot = await this.collectionSnapshot(collection, 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((doc) => batch.delete(doc.ref) && bulkIds.push(doc.id)); const p = batch.commit(); promises.push(p); } await Promise.all(promises); return bulkIds; } get batch() { return this.db.batch(); } get serverTimestamp() { return this.admin.firestore.FieldValue.serverTimestamp(); } increment(n = 1) { return this.admin.firestore.FieldValue.increment(n); } /** * Returns a generated Firestore Document Id. */ createId(colPath) { return this.db.collection(colPath ?? '_').doc().id; } runTransaction(updateFunction) { return this.db.runTransaction(updateFunction); } // Recursively delete a reference and log the references of failures. // https://github.com/googleapis/nodejs-firestore/pull/1494 recursiveDelete(ref, bulkWriter) { return this.db.recursiveDelete(ref, bulkWriter); } // ----------------------------------------------------------------------------------------------------- // @ Custom methods // ----------------------------------------------------------------------------------------------------- /** * Create a Firestore Timestamp * * @param date */ createTimestamp(date = new Date()) { return this.admin.firestore.Timestamp.fromDate(date); } collectionSnapshot(path, qb) { const collectionRef = this.db.collection(path); return (qb ? qb.exec(collectionRef) : collectionRef).get(); } collectionGroupSnapshot(collectionId, qb) { const groupRef = this.db.collectionGroup(collectionId); return (qb ? qb.exec(groupRef) : groupRef).get(); } docRef(path) { return this.db.doc(path); } } FirestoreCloudService.instance = null; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZXN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvbGliL2Z1bmN0aW9ucy9maXJlc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBSXpDLE1BQU0sT0FBTyxxQkFBc0IsU0FBUSxvQkFBb0I7SUFNN0QsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFVLEVBQUUsV0FBOEIsRUFBRTtRQUM3RCxJQUFJLENBQUMsUUFBUSxLQUFiLElBQUksQ0FBQyxRQUFRLEdBQUssSUFBSSxJQUFJLEVBQUUsRUFBQztRQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFMUMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxVQUFVLENBQUMsS0FBVSxFQUFFLFFBQTJCO1FBQ2hELEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUV0QixJQUFJLENBQUMsRUFBRSxHQUFHLEtBQUssQ0FBQyxTQUFTLEVBQWUsQ0FBQztRQUN6QyxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNyQixDQUFDO0lBRUQsd0dBQXdHO0lBQ3hHLHFCQUFxQjtJQUNyQix3R0FBd0c7SUFDeEcsS0FBSyxDQUFDLFVBQVUsQ0FBVSxVQUFrQixFQUFFLEVBQWlCO1FBQzdELE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUs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a0JBQWtCLENBQUMsSUFBWSxFQUFFLEVBQWlCO1FBQ2hELE1BQU0sYUFBYSxHQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXBELE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzdELENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxZQUFvQixFQUFFLEVBQWlCO1FBQzdELE1BQU0sUUFBUSxHQUFRLElBQUksQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRTVELE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ25ELENBQUM7SUFFRCxNQUFNLENBQUMsSUFBWTtRQUNqQixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLENBQUM7O0FBaE1jLDhCQUFRLEdBQTBCLElBQUksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtcbiAgUXVlcnlTbmFwc2hvdCxcbiAgV3JpdGVCYXRjaCxcbiAgRG9jdW1lbnREYXRhLFxuICBTZXRPcHRpb25zLFxuICBEb2N1bWVudFJlZmVyZW5jZSxcbiAgRmlyZWJhc2VGaXJlc3RvcmUsXG4gIFRyYW5zYWN0aW9uLFxuICBDb2xsZWN0aW9uUmVmZXJlbmNlLFxuICBTZXR0aW5ncyBhcyBGaXJlc3RvcmVTZXR0aW5nc1xufSBmcm9tICdAZmlyZWJhc2UvZmlyZXN0b3JlLXR5cGVzJztcblxuaW1wb3J0IHsgQWJzdHJhY3RGaXJlc3RvcmVBcGksIFF1ZXJ5QnVpbGRlciB9IGZyb20gJy4uLy4uL25neC9kYic7XG5pbXBvcnQgeyBhcnJheVRvQ2h1bmtzIH0gZnJvbSAnLi4vdXRpbHMnO1xuXG50eXBlIEZpcmVzdG9yZSA9IEZpcmViYXNlRmlyZXN0b3JlO1xuXG5leHBvcnQgY2xhc3MgRmlyZXN0b3JlQ2xvdWRTZXJ2aWNlIGV4dGVuZHMgQWJzdHJhY3RGaXJlc3RvcmVBcGkge1xuICBwcml2YXRlIGRiOiBGaXJlc3RvcmU7XG4gIHByaXZhdGUgYWRtaW46IGFueTtcblxuICBwcml2YXRlIHN0YXRpYyBpbnN0YW5jZTogRmlyZXN0b3JlQ2xvdWRTZXJ2aWNlID0gbnVsbDtcblxuICBzdGF0aWMgZ2V0SW5zdGFuY2UoYWRtaW46IGFueSwgc2V0dGluZ3M6IEZpcmVzdG9yZVNldHRpbmdzID0ge30pIHtcbiAgICB0aGlzLmluc3RhbmNlID8/PSBuZXcgdGhpcygpO1xuICAgIHRoaXMuaW5zdGFuY2UuaW5pdGlhbGl6ZShhZG1pbiwgc2V0dGluZ3MpO1xuXG4gICAgcmV0dXJuIHRoaXMuaW5zdGFuY2U7XG4gIH1cblxuICBpbml0aWFsaXplKGFkbWluOiBhbnksIHNldHRpbmdzOiBGaXJlc3RvcmVTZXR0aW5ncykge1xuICAgIGFkbWluLmluaXRpYWxpemVBcHAoKTtcblxuICAgIHRoaXMuZGIgPSBhZG1pbi5maXJlc3RvcmUoKSBhcyBGaXJlc3RvcmU7XG4gICAgdGhpcy5kYi5zZXR0aW5ncyhzZXR0aW5ncyk7XG4gICAgdGhpcy5hZG1pbiA9IGFkbWluO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gQCBBYnN0cmFjdCBtZW1iZXJzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGFzeW5jIGNvbGxlY3Rpb248VCA9IGFueT4oY29sbGVjdGlvbjogc3RyaW5nLCBxYj86IFF1ZXJ5QnVpbGRlcik6IFByb21pc2U8VFtdPiB7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLmNvbGxlY3Rpb25TbmFwc2hvdChjb2xsZWN0aW9uLCBxYikpLmRvY3MubWFwKChkb2MpID0+ICh7IGlkOiBkb2MuaWQsIC4uLmRvYy5kYXRhKCkgfSBhcyBhbnkpKTtcbiAgfVxuXG4gIGFzeW5jIGNvbGxlY3Rpb25Hcm91cDxUID0gYW55Pihjb2xsZWN0aW9uSWQ6IHN0cmluZywgcWI/OiBRdWVyeUJ1aWxkZXIpOiBQcm9taXNlPFRbXT4ge1xuICAgIHJldHVybiAoYXdhaXQgdGhpcy5jb2xsZWN0aW9uR3JvdXBTbmFwc2hvdChjb2xsZWN0aW9uSWQsIHFiKSkuZG9jcy5tYXAoXG4gICAgICAoZG9jKSA9PiAoeyBpZDogZG9jLmlkLCAuLi5kb2MuZGF0YSgpIH0gYXMgYW55KVxuICAgICk7XG4gIH1cblxuICBhc3luYyBkb2M8VCA9IGFueT4ocGF0aDogc3RyaW5nKTogUHJvbWlzZTxUPiB7XG4gICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCB0aGlzLmRvY1JlZihwYXRoKS5nZXQoKTtcbiAgICByZXR1cm4gKHNuYXBzaG90LmV4aXN0cyAmJiAoeyBpZDogc25hcHNob3QuaWQsIC4uLnNuYXBzaG90LmRhdGEoKSB9IGFzIGFueSkpIHx8IG51bGw7XG4gIH1cblxuICBhc3luYyB1cHNlcnQoY29sbGVjdGlvbjogc3RyaW5nLCBkYXRhOiB7IFtrZXk6IHN0cmluZ106IGFueSB9LCBvcHRzOiBTZXRPcHRpb25zID0geyBtZXJnZTogdHJ1ZSB9KSB7XG4gICAgY29uc3QgdGltZXN0YW1wID0gdGhpcy5zZXJ2ZXJUaW1lc3RhbXA7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHsgaWQsIC4uLnVwZGF0YSB9ID0gZGF0YTtcbiAgICB1cGRhdGEuY3JlYXRlZFRzID8/PSB0aW1lc3RhbXA7XG5cbiAgICBpZiAoIWlkKSB7XG4gICAgICBpZCA9IHRoaXMuZGIuY29sbGVjdGlvbihjb2xsZWN0aW9uKS5kb2MoKS5pZDtcbiAgICB9XG5cbiAgICB1cGRhdGEudXBkYXRlZFRzID0gdGltZXN0YW1wO1xuICAgIGF3YWl0IHRoaXMuZG9jUmVmKGAke2NvbGxlY3Rpb259LyR7aWR9YCkuc2V0KE9iamVjdC5hc3NpZ24oe30sIHVwZGF0YSksIG9wdHMpO1xuXG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgYXN5bmMgdXBkYXRlKHBhdGg6IHN0cmluZywgZGF0YTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSkge1xuICAgIGF3YWl0IHRoaXMuZG9jUmVmKHBhdGgpLnVwZGF0ZShkYXRhKTtcbiAgfVxuXG4gIGFzeW5jIGRlbGV0ZShwYXRoOiBzdHJpbmcpIHtcbiAgICBhd2FpdCB0aGlzLmRvY1JlZihwYXRoKS5kZWxldGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWxrIHVwZGF0ZSBkYXRhXG4gICAqL1xuICBhc3luYyBidWxrVXBzZXJ0KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBkYXRhOiBEb2N1bWVudERhdGFbXSB8IHsgZGF0YTogRG9jdW1lbnREYXRhOyBxYj86IFF1ZXJ5QnVpbGRlciB9LFxuICAgIG9wdHM6IFNldE9wdGlvbnMgPSB7IG1lcmdlOiB0cnVlIH1cbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IGJ1bGtJZHMgPSBbXTtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXG4gICAgY29uc3QgdGltZXN0YW1wID0gdGhpcy5zZXJ2ZXJUaW1lc3RhbXA7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgLy8gRHVlIHRvIGEgYmF0Y2ggbGltaXRhdGlvbiwgbmVlZCB0byBzcGxpdCBkb2NzIGFycmF5IGludG8gY2h1bmtzXG4gICAgICBmb3IgKGNvbnN0IGNodW5rcyBvZiBhcnJheVRvQ2h1bmtzKGRhdGEsIHRoaXMuQkFUQ0hfTUFYX1dSSVRFUykpIHtcbiAgICAgICAgY29uc3QgYmF0Y2ggPSB0aGlzLmJhdGNoO1xuXG4gICAgICAgIGNodW5rcy5mb3JFYWNoKChkKSA9PiB7XG4gICAgICAgICAgbGV0IHsgaWQsIC4uLnVwZGF0YSB9ID0gZDtcbiAgICAgICAgICBpZCA/Pz0gdGhpcy5kYi5jb2xsZWN0aW9uKHBhdGgpLmRvYygpLmlkO1xuICAgICAgICAgIHVwZGF0YS5jcmVhdGVkVHMgPz89IHRpbWVzdGFtcDtcbiAgICAgICAgICB1cGRhdGEudXBkYXRlZFRzID0gdGltZXN0YW1wO1xuXG4gICAgICAgICAgYmF0Y2guc2V0KHRoaXMuZG9jUmVmKGAke3BhdGh9LyR7aWR9YCksIHVwZGF0YSwgb3B0cyk7XG4gICAgICAgICAgYnVsa0lkcy5wdXNoKGlkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHAgPSBiYXRjaC5jb21taXQoKTtcbiAgICAgICAgcHJvbWlzZXMucHVzaChwKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCB0aGlzLmNvbGxlY3Rpb25TbmFwc2hvdChwYXRoLCBkYXRhLnFiKTtcbiAgICAgIC8vIER1ZSB0byBhIGJhdGNoIGxpbWl0YXRpb24sIG5lZWQgdG8gc3BsaXQgZG9jcyBhcnJheSBpbnRvIGNodW5rc1xuICAgICAgZm9yIChjb25zdCBjaHVua3Mgb2YgYXJyYXlUb0NodW5rcyhzbmFwc2hvdC5kb2NzLCB0aGlzLkJBVENIX01BWF9XUklURVMpKSB7XG4gICAgICAgIGNvbnN0IGJhdGNoID0gdGhpcy5iYXRjaDtcblxuICAgICAgICBjaHVua3MuZm9yRWFjaCgoZCkgPT4gYmF0Y2guc2V0KGQucmVmLCB7IHVwZGF0ZWRUczogdGltZXN0YW1wLCAuLi5kYXRhLmRhdGEgfSwgb3B0cykgJiYgYnVsa0lkcy5wdXNoKGQuaWQpKTtcblxuICAgICAgICBjb25zdCBwID0gYmF0Y2guY29tbWl0KCk7XG4gICAgICAgIHByb21pc2VzLnB1c2gocCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgcmV0dXJuIGJ1bGtJZHM7XG4gIH1cblxuICAvKipcbiAgICogQnVsayBkZWxldGUgZGF0YVxuICAgKi9cbiAgYXN5bmMgYnVsa0RlbGV0ZShjb2xsZWN0aW9uOiBzdHJpbmcsIHFiPzogUXVlcnlCdWlsZGVyLCBtYXhTaXplID0gMTAwMCkge1xuICAgIGlmICghcWIpIHtcbiAgICAgIHFiID0gbmV3IFF1ZXJ5QnVpbGRlcigpO1xuICAgICAgcWIubGltaXQobWF4U2l6ZSk7XG4gICAgfVxuXG4gICAgY29uc3QgYnVsa0lkcyA9IFtdO1xuICAgIGNvbnN0IHByb21pc2VzID0gW107XG4gICAgY29uc3Qgc25hcHNob3Q6IFF1ZXJ5U25hcHNob3QgPSBhd2FpdCB0aGlzLmNvbGxlY3Rpb25TbmFwc2hvdChjb2xsZWN0aW9uLCBxYik7XG5cbiAgICAvLyBEdWUgdG8gYSBiYXRjaCBsaW1pdGF0aW9uLCBuZWVkIHRvIHNwbGl0IGRvY3MgYXJyYXkgaW50byBjaHVua3NcbiAgICBmb3IgKGNvbnN0IGNodW5rcyBvZiBhcnJheVRvQ2h1bmtzKHNuYXBzaG90LmRvY3MsIHRoaXMuQkFUQ0hfTUFYX1dSSVRFUykpIHtcbiAgICAgIGNvbnN0IGJhdGNoID0gdGhpcy5iYXRjaDtcblxuICAgICAgY2h1bmtzLmZvckVhY2goKGRvYykgPT4gYmF0Y2guZGVsZXRlKGRvYy5yZWYpICYmIGJ1bGtJZHMucHVzaChkb2MuaWQpKTtcbiAgICAgIGNvbnN0IHAgPSBiYXRjaC5jb21taXQoKTtcbiAgICAgIHByb21pc2VzLnB1c2gocCk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgcmV0dXJuIGJ1bGtJZHM7XG4gIH1cblxuICBnZXQgYmF0Y2goKTogV3JpdGVCYXRjaCB7XG4gICAgcmV0dXJuIHRoaXMuZGIuYmF0Y2goKTtcbiAgfVxuXG4gIGdldCBzZXJ2ZXJUaW1lc3RhbXAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRtaW4uZmlyZXN0b3JlLkZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCk7XG4gIH1cblxuICBpbmNyZW1lbnQobiA9IDEpIHtcbiAgICByZXR1cm4gdGhpcy5hZG1pbi5maXJlc3RvcmUuRmllbGRWYWx1ZS5pbmNyZW1lbnQobik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGdlbmVyYXRlZCBGaXJlc3RvcmUgRG9jdW1lbnQgSWQuXG4gICAqL1xuICBjcmVhdGVJZChjb2xQYXRoPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZGIuY29sbGVjdGlvbihjb2xQYXRoID8/ICdfJykuZG9jKCkuaWQ7XG4gIH1cblxuICBydW5UcmFuc2FjdGlvbih1cGRhdGVGdW5jdGlvbjogKHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbikgPT4gUHJvbWlzZTx1bmtub3duPik6IFByb21pc2U8dW5rbm93bj4ge1xuICAgIHJldHVybiB0aGlzLmRiLnJ1blRyYW5zYWN0aW9uKHVwZGF0ZUZ1bmN0aW9uKTtcbiAgfVxuXG4gIC8vIFJlY3Vyc2l2ZWx5IGRlbGV0ZSBhIHJlZmVyZW5jZSBhbmQgbG9nIHRoZSByZWZlcmVuY2VzIG9mIGZhaWx1cmVzLlxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ29vZ2xlYXBpcy9ub2RlanMtZmlyZXN0b3JlL3B1bGwvMTQ5NFxuICByZWN1cnNpdmVEZWxldGUocmVmOiBDb2xsZWN0aW9uUmVmZXJlbmNlPHVua25vd24+IHwgRG9jdW1lbnRSZWZlcmVuY2U8dW5rbm93bj4sIGJ1bGtXcml0ZXI/OiBhbnkpIHtcbiAgICByZXR1cm4gKHRoaXMuZGIgYXMgYW55KS5yZWN1cnNpdmVEZWxldGUocmVmLCBidWxrV3JpdGVyKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEAgQ3VzdG9tIG1ldGhvZHNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRmlyZXN0b3JlIFRpbWVzdGFtcFxuICAgKlxuICAgKiBAcGFyYW0gZGF0ZVxuICAgKi9cblxuICBjcmVhdGVUaW1lc3RhbXAoZGF0ZTogRGF0ZSA9IG5ldyBEYXRlKCkpIHtcbiAgICByZXR1cm4gdGhpcy5hZG1pbi5maXJlc3RvcmUuVGltZXN0YW1wLmZyb21EYXRlKGRhdGUpO1xuICB9XG5cbiAgY29sbGVjdGlvblNuYXBzaG90KHBhdGg6IHN0cmluZywgcWI/OiBRdWVyeUJ1aWxkZXIpOiBQcm9taXNlPFF1ZXJ5U25hcHNob3Q+IHtcbiAgICBjb25zdCBjb2xsZWN0aW9uUmVmOiBhbnkgPSB0aGlzLmRiLmNvbGxlY3Rpb24ocGF0aCk7XG5cbiAgICByZXR1cm4gKHFiID8gcWIuZXhlYyhjb2xsZWN0aW9uUmVmKSA6IGNvbGxlY3Rpb25SZWYpLmdldCgpO1xuICB9XG5cbiAgY29sbGVjdGlvbkdyb3VwU25hcHNob3QoY29sbGVjdGlvbklkOiBzdHJpbmcsIHFiPzogUXVlcnlCdWlsZGVyKTogUHJvbWlzZTxRdWVyeVNuYXBzaG90PiB7XG4gICAgY29uc3QgZ3JvdXBSZWY6IGFueSA9IHRoaXMuZGIuY29sbGVjdGlvbkdyb3VwKGNvbGxlY3Rpb25JZCk7XG5cbiAgICByZXR1cm4gKHFiID8gcWIuZXhlYyhncm91cFJlZikgOiBncm91cFJlZikuZ2V0KCk7XG4gIH1cblxuICBkb2NSZWYocGF0aDogc3RyaW5nKTogRG9jdW1lbnRSZWZlcmVuY2U8RG9jdW1lbnREYXRhPiB7XG4gICAgcmV0dXJuIHRoaXMuZGIuZG9jKHBhdGgpO1xuICB9XG59XG4iXX0=