@angular/fire
Version:
The official library for Firebase and Angular
182 lines • 17.7 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { from } from 'rxjs';
import { fromCollectionRef } from '../observable/fromRef';
import { filter, map, observeOn, scan } from 'rxjs/operators';
import { docChanges, sortedChanges } from './changes';
import { AngularFirestoreDocument } from '../document/document';
/**
* @param {?=} events
* @return {?}
*/
export function validateEventsArray(events) {
if (!events || events.length === 0) {
events = ['added', 'removed', 'modified'];
}
return events;
}
/**
* AngularFirestoreCollection service
*
* This class creates a reference to a Firestore Collection. A reference and a query are provided in
* in the constructor. The query can be the unqueried reference if no query is desired.The class
* is generic which gives you type safety for data update methods and data streaming.
*
* This class uses Symbol.observable to transform into Observable using Observable.from().
*
* This class is rarely used directly and should be created from the AngularFirestore service.
*
* Example:
*
* const collectionRef = firebase.firestore.collection('stocks');
* const query = collectionRef.where('price', '>', '0.01');
* const fakeStock = new AngularFirestoreCollection<Stock>(collectionRef, query);
*
* // NOTE!: the updates are performed on the reference not the query
* await fakeStock.add({ name: 'FAKE', price: 0.01 });
*
* // Subscribe to changes as snapshots. This provides you data updates as well as delta updates.
* fakeStock.valueChanges().subscribe(value => console.log(value));
* @template T
*/
export class AngularFirestoreCollection {
/**
* The constructor takes in a CollectionReference and Query to provide wrapper methods
* for data operations and data streaming.
*
* Note: Data operation methods are done on the reference not the query. This means
* when you update data it is not updating data to the window of your query unless
* the data fits the criteria of the query. See the AssociatedRefence type for details
* on this implication.
* @param {?} ref
* @param {?} query
* @param {?} afs
*/
constructor(ref, query, afs) {
this.ref = ref;
this.query = query;
this.afs = afs;
}
/**
* Listen to the latest change in the stream. This method returns changes
* as they occur and they are not sorted by query order. This allows you to construct
* your own data structure.
* @param {?=} events
* @return {?}
*/
stateChanges(events) {
if (!events || events.length === 0) {
return docChanges(this.query, this.afs.schedulers.outsideAngular).pipe(this.afs.keepUnstableUntilFirst);
}
return docChanges(this.query, this.afs.schedulers.outsideAngular).pipe(map((/**
* @param {?} actions
* @return {?}
*/
actions => actions.filter((/**
* @param {?} change
* @return {?}
*/
change => events.indexOf(change.type) > -1)))), filter((/**
* @param {?} changes
* @return {?}
*/
changes => changes.length > 0)), this.afs.keepUnstableUntilFirst);
}
/**
* Create a stream of changes as they occur it time. This method is similar to stateChanges()
* but it collects each event in an array over time.
* @param {?=} events
* @return {?}
*/
auditTrail(events) {
return this.stateChanges(events).pipe(scan((/**
* @param {?} current
* @param {?} action
* @return {?}
*/
(current, action) => [...current, ...action]), []));
}
/**
* Create a stream of synchronized changes. This method keeps the local array in sorted
* query order.
* @param {?=} events
* @return {?}
*/
snapshotChanges(events) {
/** @type {?} */
const validatedEvents = validateEventsArray(events);
/** @type {?} */
const scheduledSortedChanges$ = sortedChanges(this.query, validatedEvents, this.afs.schedulers.outsideAngular);
return scheduledSortedChanges$.pipe(this.afs.keepUnstableUntilFirst);
}
/**
* @template K
* @param {?=} options
* @return {?}
*/
valueChanges(options = {}) {
return fromCollectionRef(this.query, this.afs.schedulers.outsideAngular)
.pipe(map((/**
* @param {?} actions
* @return {?}
*/
actions => actions.payload.docs.map((/**
* @param {?} a
* @return {?}
*/
a => {
if (options.idField) {
return (/** @type {?} */ (Object.assign(Object.assign({}, (/** @type {?} */ (a.data()))), { [options.idField]: a.id })));
}
else {
return a.data();
}
})))), this.afs.keepUnstableUntilFirst);
}
/**
* Retrieve the results of the query once.
* @param {?=} options
* @return {?}
*/
get(options) {
return from(this.query.get(options)).pipe(observeOn(this.afs.schedulers.insideAngular));
}
/**
* Add data to a collection reference.
*
* Note: Data operation methods are done on the reference not the query. This means
* when you update data it is not updating data to the window of your query unless
* the data fits the criteria of the query.
* @param {?} data
* @return {?}
*/
add(data) {
return this.ref.add(data);
}
/**
* Create a reference to a single document in a collection.
* @template T
* @param {?=} path
* @return {?}
*/
doc(path) {
return new AngularFirestoreDocument(this.ref.doc(path), this.afs);
}
}
if (false) {
/** @type {?} */
AngularFirestoreCollection.prototype.ref;
/**
* @type {?}
* @private
*/
AngularFirestoreCollection.prototype.query;
/**
* @type {?}
* @private
*/
AngularFirestoreCollection.prototype.afs;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9maXJlc3RvcmUvY29sbGVjdGlvbi9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUk5RCxPQUFPLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN0RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7Ozs7QUFHaEUsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQTZCO0lBQy9ELElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDbEMsTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztLQUMzQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF5QkQsTUFBTSxPQUFPLDBCQUEwQjs7Ozs7Ozs7Ozs7OztJQVVyQyxZQUNrQixHQUF3QixFQUN2QixLQUFZLEVBQ1osR0FBcUI7UUFGdEIsUUFBRyxHQUFILEdBQUcsQ0FBcUI7UUFDdkIsVUFBSyxHQUFMLEtBQUssQ0FBTztRQUNaLFFBQUcsR0FBSCxHQUFHLENBQWtCO0lBQUksQ0FBQzs7Ozs7Ozs7SUFPN0MsWUFBWSxDQUFDLE1BQTZCO1FBQ3hDLElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDbEMsT0FBTyxVQUFVLENBQUksSUFBSSxDQUFDLEtBQUssRUFB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QUMsQ0FBQztJQUN2RSxDQUFDO0NBQ0Y7OztJQS9GRyx5Q0FBd0M7Ozs7O0lBQ3hDLDJDQUE2Qjs7Ozs7SUFDN0IseUNBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnJvbSwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZnJvbUNvbGxlY3Rpb25SZWYgfSBmcm9tICcuLi9vYnNlcnZhYmxlL2Zyb21SZWYnO1xuaW1wb3J0IHsgZmlsdGVyLCBtYXAsIG9ic2VydmVPbiwgc2NhbiB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGZpcmVzdG9yZSB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cbmltcG9ydCB7IENvbGxlY3Rpb25SZWZlcmVuY2UsIERvY3VtZW50Q2hhbmdlQWN0aW9uLCBEb2N1bWVudENoYW5nZVR5cGUsIERvY3VtZW50RGF0YSwgRG9jdW1lbnRSZWZlcmVuY2UsIFF1ZXJ5IH0gZnJvbSAnLi4vaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBkb2NDaGFuZ2VzLCBzb3J0ZWRDaGFuZ2VzIH0gZnJvbSAnLi9jaGFuZ2VzJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlc3RvcmVEb2N1bWVudCB9IGZyb20gJy4uL2RvY3VtZW50L2RvY3VtZW50JztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlc3RvcmUgfSBmcm9tICcuLi9maXJlc3RvcmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVFdmVudHNBcnJheShldmVudHM/OiBEb2N1bWVudENoYW5nZVR5cGVbXSkge1xuICBpZiAoIWV2ZW50cyB8fCBldmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZXZlbnRzID0gWydhZGRlZCcsICdyZW1vdmVkJywgJ21vZGlmaWVkJ107XG4gIH1cbiAgcmV0dXJuIGV2ZW50cztcbn1cblxuLyoqXG4gKiBBbmd1bGFyRmlyZXN0b3JlQ29sbGVjdGlvbiBzZXJ2aWNlXG4gKlxuICogVGhpcyBjbGFzcyBjcmVhdGVzIGEgcmVmZXJlbmNlIHRvIGEgRmlyZXN0b3JlIENvbGxlY3Rpb24uIEEgcmVmZXJlbmNlIGFuZCBhIHF1ZXJ5IGFyZSBwcm92aWRlZCBpblxuICogaW4gdGhlIGNvbnN0cnVjdG9yLiBUaGUgcXVlcnkgY2FuIGJlIHRoZSB1bnF1ZXJpZWQgcmVmZXJlbmNlIGlmIG5vIHF1ZXJ5IGlzIGRlc2lyZWQuVGhlIGNsYXNzXG4gKiBpcyBnZW5lcmljIHdoaWNoIGdpdmVzIHlvdSB0eXBlIHNhZmV0eSBmb3IgZGF0YSB1cGRhdGUgbWV0aG9kcyBhbmQgZGF0YSBzdHJlYW1pbmcuXG4gKlxuICogVGhpcyBjbGFzcyB1c2VzIFN5bWJvbC5vYnNlcnZhYmxlIHRvIHRyYW5zZm9ybSBpbnRvIE9ic2VydmFibGUgdXNpbmcgT2JzZXJ2YWJsZS5mcm9tKCkuXG4gKlxuICogVGhpcyBjbGFzcyBpcyByYXJlbHkgdXNlZCBkaXJlY3RseSBhbmQgc2hvdWxkIGJlIGNyZWF0ZWQgZnJvbSB0aGUgQW5ndWxhckZpcmVzdG9yZSBzZXJ2aWNlLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogY29uc3QgY29sbGVjdGlvblJlZiA9IGZpcmViYXNlLmZpcmVzdG9yZS5jb2xsZWN0aW9uKCdzdG9ja3MnKTtcbiAqIGNvbnN0IHF1ZXJ5ID0gY29sbGVjdGlvblJlZi53aGVyZSgncHJpY2UnLCAnPicsICcwLjAxJyk7XG4gKiBjb25zdCBmYWtlU3RvY2sgPSBuZXcgQW5ndWxhckZpcmVzdG9yZUNvbGxlY3Rpb248U3RvY2s+KGNvbGxlY3Rpb25SZWYsIHF1ZXJ5KTtcbiAqXG4gKiAvLyBOT1RFITogdGhlIHVwZGF0ZXMgYXJlIHBlcmZvcm1lZCBvbiB0aGUgcmVmZXJlbmNlIG5vdCB0aGUgcXVlcnlcbiAqIGF3YWl0IGZha2VTdG9jay5hZGQoeyBuYW1lOiAnRkFLRScsIHByaWNlOiAwLjAxIH0pO1xuICpcbiAqIC8vIFN1YnNjcmliZSB0byBjaGFuZ2VzIGFzIHNuYXBzaG90cy4gVGhpcyBwcm92aWRlcyB5b3UgZGF0YSB1cGRhdGVzIGFzIHdlbGwgYXMgZGVsdGEgdXBkYXRlcy5cbiAqIGZha2VTdG9jay52YWx1ZUNoYW5nZXMoKS5zdWJzY3JpYmUodmFsdWUgPT4gY29uc29sZS5sb2codmFsdWUpKTtcbiAqL1xuZXhwb3J0IGNsYXNzIEFuZ3VsYXJGaXJlc3RvcmVDb2xsZWN0aW9uPFQ9IERvY3VtZW50RGF0YT4ge1xuICAvKipcbiAgICogVGhlIGNvbnN0cnVjdG9yIHRha2VzIGluIGEgQ29sbGVjdGlvblJlZmVyZW5jZSBhbmQgUXVlcnkgdG8gcHJvdmlkZSB3cmFwcGVyIG1ldGhvZHNcbiAgICogZm9yIGRhdGEgb3BlcmF0aW9ucyBhbmQgZGF0YSBzdHJlYW1pbmcuXG4gICAqXG4gICAqIE5vdGU6IERhdGEgb3BlcmF0aW9uIG1ldGhvZHMgYXJlIGRvbmUgb24gdGhlIHJlZmVyZW5jZSBub3QgdGhlIHF1ZXJ5LiBUaGlzIG1lYW5zXG4gICAqIHdoZW4geW91IHVwZGF0ZSBkYXRhIGl0IGlzIG5vdCB1cGRhdGluZyBkYXRhIHRvIHRoZSB3aW5kb3cgb2YgeW91ciBxdWVyeSB1bmxlc3NcbiAgICogdGhlIGRhdGEgZml0cyB0aGUgY3JpdGVyaWEgb2YgdGhlIHF1ZXJ5LiBTZWUgdGhlIEFzc29jaWF0ZWRSZWZlbmNlIHR5cGUgZm9yIGRldGFpbHNcbiAgICogb24gdGhpcyBpbXBsaWNhdGlvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSByZWY6IENvbGxlY3Rpb25SZWZlcmVuY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBxdWVyeTogUXVlcnksXG4gICAgcHJpdmF0ZSByZWFkb25seSBhZnM6IEFuZ3VsYXJGaXJlc3RvcmUpIHsgfVxuXG4gIC8qKlxuICAgKiBMaXN0ZW4gdG8gdGhlIGxhdGVzdCBjaGFuZ2UgaW4gdGhlIHN0cmVhbS4gVGhpcyBtZXRob2QgcmV0dXJucyBjaGFuZ2VzXG4gICAqIGFzIHRoZXkgb2NjdXIgYW5kIHRoZXkgYXJlIG5vdCBzb3J0ZWQgYnkgcXVlcnkgb3JkZXIuIFRoaXMgYWxsb3dzIHlvdSB0byBjb25zdHJ1Y3RcbiAgICogeW91ciBvd24gZGF0YSBzdHJ1Y3R1cmUuXG4gICAqL1xuICBzdGF0ZUNoYW5nZXMoZXZlbnRzPzogRG9jdW1lbnRDaGFuZ2VUeXBlW10pOiBPYnNlcnZhYmxlPERvY3VtZW50Q2hhbmdlQWN0aW9uPFQ+W10+IHtcbiAgICBpZiAoIWV2ZW50cyB8fCBldmVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gZG9jQ2hhbmdlczxUPih0aGlzLnF1ZXJ5LCB0aGlzLmFmcy5zY2hlZHVsZXJzLm91dHNpZGVBbmd1bGFyKS5waXBlKFxuICAgICAgICB0aGlzLmFmcy5rZWVwVW5zdGFibGVVbnRpbEZpcnN0XG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZG9jQ2hhbmdlczxUPih0aGlzLnF1ZXJ5LCB0aGlzLmFmcy5zY2hlZHVsZXJzLm91dHNpZGVBbmd1bGFyKS5waXBlKFxuICAgICAgbWFwKGFjdGlvbnMgPT4gYWN0aW9ucy5maWx0ZXIoY2hhbmdlID0+IGV2ZW50cy5pbmRleE9mKGNoYW5nZS50eXBlKSA+IC0xKSksXG4gICAgICBmaWx0ZXIoY2hhbmdlcyA9PiAgY2hhbmdlcy5sZW5ndGggPiAwKSxcbiAgICAgIHRoaXMuYWZzLmtlZXBVbnN0YWJsZVVudGlsRmlyc3RcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHN0cmVhbSBvZiBjaGFuZ2VzIGFzIHRoZXkgb2NjdXIgaXQgdGltZS4gVGhpcyBtZXRob2QgaXMgc2ltaWxhciB0byBzdGF0ZUNoYW5nZXMoKVxuICAgKiBidXQgaXQgY29sbGVjdHMgZWFjaCBldmVudCBpbiBhbiBhcnJheSBvdmVyIHRpbWUuXG4gICAqL1xuICBhdWRpdFRyYWlsKGV2ZW50cz86IERvY3VtZW50Q2hhbmdlVHlwZVtdKTogT2JzZXJ2YWJsZTxEb2N1bWVudENoYW5nZUFjdGlvbjxUPltdPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVDaGFuZ2VzKGV2ZW50cykucGlwZShzY2FuKChjdXJyZW50LCBhY3Rpb24pID0+IFsuLi5jdXJyZW50LCAuLi5hY3Rpb25dLCBbXSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHN0cmVhbSBvZiBzeW5jaHJvbml6ZWQgY2hhbmdlcy4gVGhpcyBtZXRob2Qga2VlcHMgdGhlIGxvY2FsIGFycmF5IGluIHNvcnRlZFxuICAgKiBxdWVyeSBvcmRlci5cbiAgICovXG4gIHNuYXBzaG90Q2hhbmdlcyhldmVudHM/OiBEb2N1bWVudENoYW5nZVR5cGVbXSk6IE9ic2VydmFibGU8RG9jdW1lbnRDaGFuZ2VBY3Rpb248VD5bXT4ge1xuICAgIGNvbnN0IHZhbGlkYXRlZEV2ZW50cyA9IHZhbGlkYXRlRXZlbnRzQXJyYXkoZXZlbnRzKTtcbiAgICBjb25zdCBzY2hlZHVsZWRTb3J0ZWRDaGFuZ2VzJCA9IHNvcnRlZENoYW5nZXM8VD4odGhpcy5xdWVyeSwgdmFsaWRhdGVkRXZlbnRzLCB0aGlzLmFmcy5zY2hlZHVsZXJzLm91dHNpZGVBbmd1bGFyKTtcbiAgICByZXR1cm4gc2NoZWR1bGVkU29ydGVkQ2hhbmdlcyQucGlwZShcbiAgICAgIHRoaXMuYWZzLmtlZXBVbnN0YWJsZVVudGlsRmlyc3RcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbiB0byBhbGwgZG9jdW1lbnRzIGluIHRoZSBjb2xsZWN0aW9uIGFuZCBpdHMgcG9zc2libGUgcXVlcnkgYXMgYW4gT2JzZXJ2YWJsZS5cbiAgICpcbiAgICogSWYgdGhlIGBpZEZpZWxkYCBvcHRpb24gaXMgcHJvdmlkZWQsIGRvY3VtZW50IElEcyBhcmUgaW5jbHVkZWQgYW5kIG1hcHBlZCB0byB0aGVcbiAgICogcHJvdmlkZWQgYGlkRmllbGRgIHByb3BlcnR5IG5hbWUuXG4gICAqL1xuICB2YWx1ZUNoYW5nZXMoKTogT2JzZXJ2YWJsZTxUW10+O1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gIHZhbHVlQ2hhbmdlcyh7fSk6IE9ic2VydmFibGU8VFtdPjtcbiAgdmFsdWVDaGFuZ2VzPEsgZXh0ZW5kcyBzdHJpbmc+KG9wdGlvbnM6IHtpZEZpZWxkOiBLfSk6IE9ic2VydmFibGU8KFQgJiB7IFtUIGluIEtdOiBzdHJpbmcgfSlbXT47XG4gIHZhbHVlQ2hhbmdlczxLIGV4dGVuZHMgc3RyaW5nPihvcHRpb25zOiB7aWRGaWVsZD86IEt9ID0ge30pOiBPYnNlcnZhYmxlPFRbXT4ge1xuICAgIHJldHVybiBmcm9tQ29sbGVjdGlvblJlZjxUPih0aGlzLnF1ZXJ5LCB0aGlzLmFmcy5zY2hlZHVsZXJzLm91dHNpZGVBbmd1bGFyKVxuICAgICAgLnBpcGUoXG4gICAgICAgIG1hcChhY3Rpb25zID0+IGFjdGlvbnMucGF5bG9hZC5kb2NzLm1hcChhID0+IHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5pZEZpZWxkKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5hLmRhdGEoKSBhcyB7fSxcbiAgICAgICAgICAgICAgLi4ueyBbb3B0aW9ucy5pZEZpZWxkXTogYS5pZCB9XG4gICAgICAgICAgICB9IGFzIFQgJiB7IFtUIGluIEtdOiBzdHJpbmcgfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGEuZGF0YSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkpLFxuICAgICAgICB0aGlzLmFmcy5rZWVwVW5zdGFibGVVbnRpbEZpcnN0XG4gICAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIHRoZSByZXN1bHRzIG9mIHRoZSBxdWVyeSBvbmNlLlxuICAgKi9cbiAgZ2V0KG9wdGlvbnM/OiBmaXJlc3RvcmUuR2V0T3B0aW9ucykge1xuICAgIHJldHVybiBmcm9tKHRoaXMucXVlcnkuZ2V0KG9wdGlvbnMpKS5waXBlKFxuICAgICAgb2JzZXJ2ZU9uKHRoaXMuYWZzLnNjaGVkdWxlcnMuaW5zaWRlQW5ndWxhciksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgZGF0YSB0byBhIGNvbGxlY3Rpb24gcmVmZXJlbmNlLlxuICAgKlxuICAgKiBOb3RlOiBEYXRhIG9wZXJhdGlvbiBtZXRob2RzIGFyZSBkb25lIG9uIHRoZSByZWZlcmVuY2Ugbm90IHRoZSBxdWVyeS4gVGhpcyBtZWFuc1xuICAgKiB3aGVuIHlvdSB1cGRhdGUgZGF0YSBpdCBpcyBub3QgdXBkYXRpbmcgZGF0YSB0byB0aGUgd2luZG93IG9mIHlvdXIgcXVlcnkgdW5sZXNzXG4gICAqIHRoZSBkYXRhIGZpdHMgdGhlIGNyaXRlcmlhIG9mIHRoZSBxdWVyeS5cbiAgICovXG4gIGFkZChkYXRhOiBUKTogUHJvbWlzZTxEb2N1bWVudFJlZmVyZW5jZT4ge1xuICAgIHJldHVybiB0aGlzLnJlZi5hZGQoZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgcmVmZXJlbmNlIHRvIGEgc2luZ2xlIGRvY3VtZW50IGluIGEgY29sbGVjdGlvbi5cbiAgICovXG4gIGRvYzxUPihwYXRoPzogc3RyaW5nKTogQW5ndWxhckZpcmVzdG9yZURvY3VtZW50PFQ+IHtcbiAgICByZXR1cm4gbmV3IEFuZ3VsYXJGaXJlc3RvcmVEb2N1bWVudDxUPih0aGlzLnJlZi5kb2MocGF0aCksIHRoaXMuYWZzKTtcbiAgfVxufVxuIl19