import electron from 'electron'; import NeDB from 'nedb'; import fsPath from 'path'; import crypto from 'crypto'; import * as util from '../common/misc'; const TYPE_RESOURCE = 'Resource'; const TYPE_CONFIG = 'Config'; export const SYNC_MODE_OFF = 'paused'; export const SYNC_MODE_ON = 'active'; export function allActiveResources (resourceGroupId = null) { if (resourceGroupId) { return findActiveResources({resourceGroupId}); } else { return findActiveResources({}); } } export function activeResourcesForResourceGroup (resourceGroupId) { return findActiveResources({resourceGroupId}); } export function allResources () { return findResources({}); } export async function findResources (query) { return _execDB(TYPE_RESOURCE, 'find', query); } export async function findActiveResources (query) { const configs = await findActiveConfigs(); const resourceGroupIds = configs.map(c => c.resourceGroupId); return findResources(Object.assign({resourceGroupId: {$in: resourceGroupIds}}, query)); } export async function findActiveDirtyResources () { return findActiveResources({dirty: true}); } export async function findActiveDirtyResourcesForResourceGroup (resourceGroupId) { return findActiveResources({dirty: true, resourceGroupId}); } export async function findDirtyResourcesForResourceGroup (resourceGroupId) { return findResources({dirty: true, resourceGroupId}); } export async function findResourcesForResourceGroup (resourceGroupId) { return findResources({resourceGroupId}); } export async function getResourceByDocId (id, resourceGroupId = null) { let query; if (resourceGroupId) { query = {id, resourceGroupId}; } else { query = {id}; } const rawDocs = await _execDB(TYPE_RESOURCE, 'find', query); return rawDocs.length >= 1 ? rawDocs[0] : null; } export async function insertResource (resource) { const h = crypto.createHash('md5'); h.update(resource.resourceGroupId); h.update(resource.id); const newResource = Object.assign({}, resource, {_id: `rs_${h.digest('hex')}`}); await _execDB(TYPE_RESOURCE, 'insert', newResource); return newResource; } export async function updateResource (resource, ...patches) { const newDoc = Object.assign(resource, ...patches); await _execDB(TYPE_RESOURCE, 'update', {_id: resource._id}, newDoc); return newDoc } export function removeResource (resource) { return _execDB(TYPE_RESOURCE, 'remove', {_id: resource._id}); } // ~~~~~~ // // Config // // ~~~~~~ // export function findConfigs (query) { return _execDB(TYPE_CONFIG, 'find', query) } export function allConfigs () { return findConfigs({}) } export function findInactiveConfigs (excludedResourceGroupId = null) { if (excludedResourceGroupId) { return findConfigs({ syncMode: SYNC_MODE_OFF, $not: {excludedResourceGroupId} }) } else { return findConfigs({syncMode: SYNC_MODE_OFF}) } } export function findActiveConfigs (resourceGroupId = null) { if (resourceGroupId) { return findConfigs({syncMode: SYNC_MODE_ON, resourceGroupId}) } else { return findConfigs({syncMode: SYNC_MODE_ON}) } } export async function getConfig (resourceGroupId) { const rawDocs = await _execDB(TYPE_CONFIG, 'find', {resourceGroupId}); return rawDocs.length >= 1 ? _initConfig(rawDocs[0]) : null; } export async function updateConfig (config, ...patches) { const doc = _initConfig(Object.assign(config, ...patches)); await _execDB(TYPE_CONFIG, 'update', {_id: doc._id}, doc); return doc; } export function removeConfig (config) { return _execDB(TYPE_CONFIG, 'remove', {_id: config._id}); } export async function insertConfig (config) { const doc = _initConfig(config); await _execDB(TYPE_CONFIG, 'insert', doc); return doc; } function _initConfig (data) { return Object.assign({ _id: util.generateId('scf'), syncMode: SYNC_MODE_ON, resourceGroupId: null }, data); } // ~~~~~~~ // // Helpers // // ~~~~~~~ // let _database = null; function _getDB (type) { if (!_database) { const basePath = electron.remote.app.getPath('userData'); _database = {}; // NOTE: Do not EVER change this. EVER! const resourcePath = fsPath.join(basePath, 'sync/Resource.db'); const configPath = fsPath.join(basePath, 'sync/Config.db'); // Fill in the defaults _database['Resource'] = new NeDB({filename: resourcePath, autoload: true}); _database['Config'] = new NeDB({ filename: configPath, autoload: true }); // Done console.log(`-- Initialize Sync DB at ${basePath} --`); } return _database[type]; } function _execDB (type, fnName, ...args) { return new Promise((resolve, reject) => { _getDB(type)[fnName](...args, (err, data) => { err ? reject(err) : resolve(data); }); }); }