@tangential/firebase-util
Version:
Utility classes and shared functionality for Tangential services that use Firebase.
134 lines • 15.5 kB
JavaScript
import { set, push, remove, update, onValue } from 'firebase/database';
import { BehaviorSubject } from 'rxjs';
import { filter, first } from 'rxjs/operators';
import { Placeholder } from './placeholder';
export const OnRefKeys = {
value: 'value',
child_added: 'child_added',
child_removed: 'child_removed',
child_changed: 'child_changed',
child_moved: 'child_moved',
};
/**
* Copy-paste for local use, rather than create a dependency on core.
*/
const isObject = function (value) {
return (typeof value === 'object' || value['constructor'] === Object);
};
/**
* Prevent typescript casting issues while maintaining/enhancing type safety.
*/
export class FireBlanket {
/**
* Read the value once and return.
* @param query
*/
static value(query) {
return new Promise((resolve, reject) => {
onValue(query, (snap) => {
resolve(snap);
}, {
onlyOnce: true
});
});
}
static value$(query) {
const subject = new BehaviorSubject(Placeholder); // this semicolon is required.
/** @todo: ggranum: The unsubscribe is hacky, and won't actually remove the firebase
* listener unless there is a 'next' element called
* @maybeBug: Possible memory leak for long-running sessions with many value listeners
* */
subject['_firebaseUnsubscribe'] = onValue(query, (snap) => {
if (subject.closed) {
subject['_firebaseUnsubscribe']();
delete subject['_firebaseUnsubscribe'];
}
subject.next(snap);
}, (error) => {
subject.error(error);
});
return subject;
}
static awaitValue$(query) {
return this.value$(query).pipe(filter(v => v !== Placeholder));
}
static valueOnce$(query) {
return this.value$(query).pipe(first(v => v !== Placeholder));
}
static set(ref, value) {
return new Promise((resolve, reject) => {
try {
set(ref, value).then(() => { }).catch((e) => {
if (e) {
reject(e);
}
else {
resolve();
}
});
}
catch (e) {
reject(e);
}
});
}
static push(ref, value) {
return new Promise((resolve, reject) => {
try {
push(ref, value).catch((e) => {
if (e) {
reject(e);
}
else {
resolve();
}
});
}
catch (e) {
reject(e);
}
});
}
static update(ref, value) {
return update(ref, value);
}
static remove(ref) {
return remove(ref);
}
}
FireBlanket.util = {
clean(obj, deep = true) {
const cleanObj = {};
Object.keys(obj).forEach((key) => {
let value = obj[key];
if (FireBlanket.util.isLegalFirebaseKey(key) && FireBlanket.util.isLegalFirebaseValue(value)) {
cleanObj[key] = (deep && isObject(value)) ? FireBlanket.util.clean(value) : value;
}
});
return cleanObj;
},
removeIllegalKeys(obj) {
const cleanObj = {};
Object.keys(obj).forEach((key) => {
if (FireBlanket.util.isLegalFirebaseKey(key)) {
cleanObj[key] = obj[key];
}
});
return cleanObj;
},
isLegalFirebaseKey(key) {
return key !== null && key !== undefined && !key.startsWith('$');
},
isLegalFirebaseValue(value) {
return value !== null && value !== undefined;
},
isFirebaseGeneratedId(key) {
let isKey = false;
// starts with "-" will be true for over a decade.
if (key && key.length === 20 && key.startsWith('-')) {
isKey = true;
}
return isKey;
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZS1ibGFua2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ2VudGlhbC9maXJlYmFzZS11dGlsL3NyYy9saWIvZmlyZS1ibGFua2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDdEUsT0FBTyxFQUFDLGVBQWUsRUFBYSxNQUFNLE1BQU0sQ0FBQTtBQUNoRCxPQUFPLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQyxNQUFNLGdCQUFnQixDQUFBO0FBRTVDLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxlQUFlLENBQUE7QUFHekMsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHO0lBQ3ZCLEtBQUssRUFBb0IsT0FBTztJQUNoQyxXQUFXLEVBQWMsYUFBYTtJQUN0QyxhQUFhLEVBQVksZUFBZTtJQUN4QyxhQUFhLEVBQVksZUFBZTtJQUN4QyxXQUFXLEVBQWMsYUFBYTtDQUN2QyxDQUFBO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBRyxVQUFVLEtBQVU7SUFDbkMsT0FBTyxDQUFDLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssTUFBTSxDQUFDLENBQUE7QUFDdkUsQ0FBQyxDQUFBO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sV0FBVztJQTRDdEI7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFZO1FBQ3ZCLE9BQU8sSUFBSSxPQUFPLENBQWUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbkQsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLElBQWtCLEVBQUUsRUFBRTtnQkFDcEMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hCLENBQUMsRUFBRTtnQkFDRCxR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UyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNsRSxDQUFDO0lBRUQsb0JBQW9CLENBQUMsS0FBVTtRQUM3QixPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksS0FBSyxLQUFLLFNBQVMsQ0FBQTtJQUM5QyxDQUFDO0lBRUQscUJBQXFCLENBQUMsR0FBVztRQUMvQixJQUFJLEtBQUssR0FBRyxLQUFLLENBQUE7UUFDakIsa0RBQWtEO1FBQ2xELElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssRUFBRSxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDbkQsS0FBSyxHQUFHLElBQUksQ0FBQTtTQUNiO1FBQ0QsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0NBRUYsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7RGF0YWJhc2VSZWZlcmVuY2UsIFF1ZXJ5LCBEYXRhU25hcHNob3R9IGZyb20gJ0BmaXJlYmFzZS9kYXRhYmFzZSdcbmltcG9ydCB7IHNldCwgcHVzaCwgcmVtb3ZlLCB1cGRhdGUsIG9uVmFsdWUgfSBmcm9tICdmaXJlYmFzZS9kYXRhYmFzZSdcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlfSBmcm9tICdyeGpzJ1xuaW1wb3J0IHtmaWx0ZXIsIGZpcnN0fSBmcm9tICdyeGpzL29wZXJhdG9ycydcblxuaW1wb3J0IHtQbGFjZWhvbGRlcn0gZnJvbSAnLi9wbGFjZWhvbGRlcidcblxuZXhwb3J0IHR5cGUgT25SZWZLZXkgPSAndmFsdWUnIHwgJ2NoaWxkX2FkZGVkJyB8ICdjaGlsZF9yZW1vdmVkJyB8ICdjaGlsZF9jaGFuZ2VkJyB8ICdjaGlsZF9tb3ZlZCdcbmV4cG9ydCBjb25zdCBPblJlZktleXMgPSB7XG4gIHZhbHVlOiAgICAgICAgIDxPblJlZktleT4ndmFsdWUnLFxuICBjaGlsZF9hZGRlZDogICA8T25SZWZLZXk+J2NoaWxkX2FkZGVkJyxcbiAgY2hpbGRfcmVtb3ZlZDogPE9uUmVmS2V5PidjaGlsZF9yZW1vdmVkJyxcbiAgY2hpbGRfY2hhbmdlZDogPE9uUmVmS2V5PidjaGlsZF9jaGFuZ2VkJyxcbiAgY2hpbGRfbW92ZWQ6ICAgPE9uUmVmS2V5PidjaGlsZF9tb3ZlZCcsXG59XG5cbi8qKlxuICogQ29weS1wYXN0ZSBmb3IgbG9jYWwgdXNlLCByYXRoZXIgdGhhbiBjcmVhdGUgYSBkZXBlbmRlbmN5IG9uIGNvcmUuXG4gKi9cbmNvbnN0IGlzT2JqZWN0ID0gZnVuY3Rpb24gKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnIHx8IHZhbHVlWydjb25zdHJ1Y3RvciddID09PSBPYmplY3QpXG59XG5cbi8qKlxuICogUHJldmVudCB0eXBlc2NyaXB0IGNhc3RpbmcgaXNzdWVzIHdoaWxlIG1haW50YWluaW5nL2VuaGFuY2luZyB0eXBlIHNhZmV0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEZpcmVCbGFua2V0IHtcblxuICBzdGF0aWMgdXRpbCA9IHtcblxuICAgIGNsZWFuPFQgZXh0ZW5kcyBvYmplY3Q+KG9iajogVCwgZGVlcDogYm9vbGVhbiA9IHRydWUpOiBUIHtcbiAgICAgIGNvbnN0IGNsZWFuT2JqOiBUID0gPFQ+e31cbiAgICAgIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgIGxldCB2YWx1ZSA9IChvYmogYXMgYW55KVtrZXldXG4gICAgICAgIGlmIChGaXJlQmxhbmtldC51dGlsLmlzTGVnYWxGaXJlYmFzZUtleShrZXkpICYmIEZpcmVCbGFua2V0LnV0aWwuaXNMZWdhbEZpcmViYXNlVmFsdWUodmFsdWUpKSB7XG4gICAgICAgICAgKGNsZWFuT2JqIGFzIGFueSlba2V5XSA9IChkZWVwICYmIGlzT2JqZWN0KHZhbHVlKSkgPyBGaXJlQmxhbmtldC51dGlsLmNsZWFuKHZhbHVlKSA6IHZhbHVlXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgICByZXR1cm4gY2xlYW5PYmpcbiAgICB9LFxuXG4gICAgcmVtb3ZlSWxsZWdhbEtleXM8VCBleHRlbmRzIG9iamVjdD4ob2JqOiBUKTogVCB7XG4gICAgICBjb25zdCBjbGVhbk9iajogVCA9IDxUPnt9XG4gICAgICBPYmplY3Qua2V5cyhvYmogYXMgYW55KS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgaWYgKEZpcmVCbGFua2V0LnV0aWwuaXNMZWdhbEZpcmViYXNlS2V5KGtleSkpIHtcbiAgICAgICAgICAoY2xlYW5PYmogYXMgYW55KVtrZXldID0gKG9iaiBhcyBhbnkpW2tleV1cbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIHJldHVybiBjbGVhbk9ialxuICAgIH0sXG5cbiAgICBpc0xlZ2FsRmlyZWJhc2VLZXkoa2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiBrZXkgIT09IG51bGwgJiYga2V5ICE9PSB1bmRlZmluZWQgJiYgIWtleS5zdGFydHNXaXRoKCckJylcbiAgICB9LFxuXG4gICAgaXNMZWdhbEZpcmViYXNlVmFsdWUodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWRcbiAgICB9LFxuXG4gICAgaXNGaXJlYmFzZUdlbmVyYXRlZElkKGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICBsZXQgaXNLZXkgPSBmYWxzZVxuICAgICAgLy8gc3RhcnRzIHdpdGggXCItXCIgd2lsbCBiZSB0cnVlIGZvciBvdmVyIGEgZGVjYWRlLlxuICAgICAgaWYgKGtleSAmJiBrZXkubGVuZ3RoID09PSAyMCAmJiBrZXkuc3RhcnRzV2l0aCgnLScpKSB7XG4gICAgICAgIGlzS2V5ID0gdHJ1ZVxuICAgICAgfVxuICAgICAgcmV0dXJuIGlzS2V5XG4gICAgfVxuXG4gIH1cblxuICAvKipcbiAgICogUmVhZCB0aGUgdmFsdWUgb25jZSBhbmQgcmV0dXJuLlxuICAgKiBAcGFyYW0gcXVlcnlcbiAgICovXG4gIHN0YXRpYyB2YWx1ZShxdWVyeTogUXVlcnkpOiBQcm9taXNlPERhdGFTbmFwc2hvdD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxEYXRhU25hcHNob3Q+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIG9uVmFsdWUocXVlcnksIChzbmFwOiBEYXRhU25hcHNob3QpID0+IHtcbiAgICAgICAgcmVzb2x2ZShzbmFwKTtcbiAgICAgIH0sIHtcbiAgICAgICAgb25seU9uY2U6IHRydWVcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIHZhbHVlJChxdWVyeTogUXVlcnkpOiBPYnNlcnZhYmxlPERhdGFTbmFwc2hvdD4ge1xuICAgIGNvbnN0IHN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KFBsYWNlaG9sZGVyKTsgLy8gdGhpcyBzZW1pY29sb24gaXMgcmVxdWlyZWQuXG5cbiAgICAvKiogQHRvZG86IGdncmFudW06IFRoZSB1bnN1YnNjcmliZSBpcyBoYWNreSwgYW5kIHdvbid0IGFjdHVhbGx5IHJlbW92ZSB0aGUgZmlyZWJhc2VcbiAgICAgKiBsaXN0ZW5lciB1bmxlc3MgdGhlcmUgaXMgYSAnbmV4dCcgZWxlbWVudCBjYWxsZWRcbiAgICAgKiBAbWF5YmVCdWc6IFBvc3NpYmxlIG1lbW9yeSBsZWFrIGZvciBsb25nLXJ1bm5pbmcgc2Vzc2lvbnMgd2l0aCBtYW55IHZhbHVlIGxpc3RlbmVyc1xuICAgICAqICovXG4gICAgICAoc3ViamVjdCBhcyBhbnkpWydfZmlyZWJhc2VVbnN1YnNjcmliZSddID0gb25WYWx1ZShxdWVyeSwgKHNuYXA6IERhdGFTbmFwc2hvdCkgPT4ge1xuICAgICAgaWYoc3ViamVjdC5jbG9zZWQpe1xuICAgICAgICAoc3ViamVjdCBhcyBhbnkpWydfZmlyZWJhc2VVbnN1YnNjcmliZSddKClcbiAgICAgICAgZGVsZXRlIChzdWJqZWN0IGFzIGFueSlbJ19maXJlYmFzZVVuc3Vic2NyaWJlJ11cbiAgICAgIH1cbiAgICAgIHN1YmplY3QubmV4dChzbmFwKVxuICAgIH0sIChlcnJvcjogYW55KSA9PiB7XG4gICAgICBzdWJqZWN0LmVycm9yKGVycm9yKVxuICAgIH0pXG4gICAgcmV0dXJuIHN1YmplY3RcbiAgfVxuXG4gIHN0YXRpYyBhd2FpdFZhbHVlJChxdWVyeTogUXVlcnkpOiBPYnNlcnZhYmxlPERhdGFTbmFwc2hvdD4ge1xuICAgIHJldHVybiB0aGlzLnZhbHVlJChxdWVyeSkucGlwZShmaWx0ZXIodiA9PiB2ICE9PSBQbGFjZWhvbGRlcikpXG4gIH1cblxuICBzdGF0aWMgdmFsdWVPbmNlJChxdWVyeTogUXVlcnkpOiBPYnNlcnZhYmxlPERhdGFTbmFwc2hvdD4ge1xuICAgIHJldHVybiB0aGlzLnZhbHVlJChxdWVyeSkucGlwZShmaXJzdCh2ID0+IHYgIT09IFBsYWNlaG9sZGVyKSlcbiAgfVxuXG4gIHN0YXRpYyBzZXQ8VD4ocmVmOiBEYXRhYmFzZVJlZmVyZW5jZSwgdmFsdWU6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgc2V0KHJlZiwgdmFsdWUpLnRoZW4oKCkgPT4ge30pLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgIGlmIChlKSB7XG4gICAgICAgICAgICByZWplY3QoZSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSlcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgc3RhdGljIHB1c2g8VD4ocmVmOiBEYXRhYmFzZVJlZmVyZW5jZSwgdmFsdWU6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcHVzaChyZWYsIHZhbHVlKS5jYXRjaCgoZTogRXJyb3IpID0+IHtcbiAgICAgICAgICBpZiAoZSkge1xuICAgICAgICAgICAgcmVqZWN0KGUpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIHN0YXRpYyB1cGRhdGU8VCBleHRlbmRzIG9iamVjdD4ocmVmOiBEYXRhYmFzZVJlZmVyZW5jZSwgdmFsdWU6IFQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICByZXR1cm4gdXBkYXRlKHJlZiwgdmFsdWUgKVxuICB9XG5cbiAgc3RhdGljIHJlbW92ZTxUPihyZWY6IERhdGFiYXNlUmVmZXJlbmNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHJlbW92ZShyZWYpXG4gIH1cbn1cbiJdfQ==