UNPKG

node-red-contrib-smartnora

Version:

Google Smart Home integration via Smart Nora https://smart-nora.eu/

139 lines (138 loc) 5.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const app_1 = require("firebase/app"); const auth_1 = require("firebase/auth"); const database_1 = require("firebase/database"); const rxjs_1 = require("rxjs"); const config_1 = require("./config"); const ENCODE_MAP = new Map([ ['.', '%2E'], ['#', '%23'], ['$', '%24'], ['[', '%5B'], [']', '%5D'], ['/', '%2F'], ]); const DECODE_MAP = new Map([ ['%2E', '.'], ['%23', '#'], ['%24', '$'], ['%5B', '['], ['%5D', ']'], ['%2F', '/'], ]); class FirebaseContextStorage { constructor(config) { this.config = config; this.context = {}; } async open() { this.close(); const get$ = new rxjs_1.Observable(observer => { const app = (0, app_1.initializeApp)(config_1.FIREBASE_CONFIG, 'app-context'); observer.next(app); return () => (0, app_1.deleteApp)(app); }).pipe((0, rxjs_1.switchMap)(async (app) => { var _a; const auth = (0, auth_1.getAuth)(app); const { user } = await (0, auth_1.signInWithEmailAndPassword)(auth, this.config.email, this.config.password); this.db = (0, database_1.getDatabase)(app); this.contextReferece = (0, database_1.ref)(this.db, `context_store/${user.uid}/${this.encode((_a = this.config.group) !== null && _a !== void 0 ? _a : 'default')}`); return this.contextReferece; }), (0, rxjs_1.switchMap)(ctxRef => new rxjs_1.Observable(observer => (0, database_1.onValue)(ctxRef, data => { var _a; this.context = (_a = data.val()) !== null && _a !== void 0 ? _a : {}; observer.next(this.context); }))), (0, rxjs_1.retry)({ delay: _err => (0, rxjs_1.timer)(5000), }), (0, rxjs_1.share)()); const subscription = get$.subscribe(); await (0, rxjs_1.firstValueFrom)(get$); this.cleanup = () => subscription.unsubscribe(); } close() { var _a; (_a = this === null || this === void 0 ? void 0 : this.cleanup) === null || _a === void 0 ? void 0 : _a.call(this); delete this.cleanup; } get(scope, key, callback) { const getValue = (singleKey) => { var _a; return this.parse((_a = this.context[this.encode(scope)]) === null || _a === void 0 ? void 0 : _a[this.encode(singleKey)]); }; if (Array.isArray(key)) { const values = key.map(k => getValue(k)); callback === null || callback === void 0 ? void 0 : callback(null, ...values); return values; } else { const value = getValue(key); callback === null || callback === void 0 ? void 0 : callback(null, value); return value; } } set(scope, key, value, callback) { const encodedScope = this.encode(scope); const scopeUpdate = {}; const updateValue = (singleKey, singleValue) => { var _a, _b; var _c; const encodedKey = this.encode(singleKey); if (singleValue === null || singleValue === undefined) { scopeUpdate[encodedKey] = null; (_a = this.context[encodedScope]) === null || _a === void 0 ? true : delete _a[encodedKey]; } else { singleValue = JSON.stringify(singleValue); (_b = (_c = this.context)[encodedScope]) !== null && _b !== void 0 ? _b : (_c[encodedScope] = {}); this.context[encodedScope][encodedKey] = singleValue; scopeUpdate[encodedKey] = singleValue; } }; if (Array.isArray(key)) { for (const [index, k] of key.entries()) { updateValue(k, value[index]); } } else { updateValue(key, value); } const reference = (0, database_1.child)(this.contextReferece, encodedScope); (0, database_1.update)(reference, scopeUpdate) .then(() => callback === null || callback === void 0 ? void 0 : callback(null)) .catch(err => callback === null || callback === void 0 ? void 0 : callback(err)); } keys(scope, callback) { var _a; const encodedScope = this.encode(scope); const keys = Object.keys((_a = this.context[encodedScope]) !== null && _a !== void 0 ? _a : {}).map(k => this.decode(k)); callback === null || callback === void 0 ? void 0 : callback(null, keys); return keys; } async delete(scope) { const encodedScope = this.encode(scope); const reference = (0, database_1.child)(this.contextReferece, encodedScope); delete this.context[encodedScope]; await (0, database_1.remove)(reference); } async clean(activeNodes) { const keepScopes = ['global', ...activeNodes].map(n => this.encode(n)); const scopes = Object.keys(this.context) .filter(key => !keepScopes.some(e => key.startsWith(e))); await Promise.all(scopes.map(scope => this.delete(scope))); } encode(value) { return value.replace(/[/.#$[\]]/g, m => { var _a; return (_a = ENCODE_MAP.get(m)) !== null && _a !== void 0 ? _a : m; }); } decode(value) { return value.replace(/%[\dA-F]{2}/g, m => { var _a; return (_a = DECODE_MAP.get(m)) !== null && _a !== void 0 ? _a : m; }); } parse(value) { try { return value && JSON.parse(value); } catch (_a) { return null; } } } module.exports = function (config) { return new FirebaseContextStorage(config); };