import _ from 'lodash'; import PouchDB from 'pouchdb'; import PouchDBFind from 'pouchdb-find'; import uri from '../lib/ids'; import changeHandler from './change-handler'; PouchDB.plugin(PouchDBFind); const dbDefinitionId = uri('dbdef', {}); const currentDbDefinition = { _id: dbDefinitionId, type: dbDefinitionId, def: { version: '0.000001' }, }; declare global { var db: any; var dbReady: boolean; } export const initDb = async (params: any) => { console.log({ caller: 'initDb' }); if (globalThis.db === undefined) { globalThis.db = new PouchDB('dyomedea', { auto_compaction: false, revs_limit: 10, }); } const db = globalThis.db; var previousDbDefinition = { _id: dbDefinitionId, type: dbDefinitionId, def: { version: '0' }, }; try { previousDbDefinition = await db.get(dbDefinitionId); } catch (error: any) { if (error.status !== 404) { console.log( `Unexpected error fetching db definition: ${JSON.stringify(error)}` ); return; } } if (previousDbDefinition.def.version < currentDbDefinition.def.version) { previousDbDefinition.def = currentDbDefinition.def; db.put(previousDbDefinition); // TODO: support migrations } //await await db.compact(); await db.viewCleanup(); // WARNING: defs must use the canonical form and be identical to what will be returned by db.getIndexes const requiredIndexes: any = [ { name: 'type', def: { fields: [{ type: 'desc' }, { id: 'desc' }], }, }, ]; const existingIndexes = (await db.getIndexes()).indexes; const pruneIndex = ({ name, def }: any) => ({ name, def }); const isSameIndex = (idx1: any, idx2: any) => { return _.isEqual(pruneIndex(idx1), pruneIndex(idx2)); }; const findIndex = (targetIndexes: any, index: any) => targetIndexes.find((targetIndex: any) => { return isSameIndex(targetIndex, index); }); for (var index of existingIndexes) { if (index.type === 'json') { // Non system indexes // console.log(`Checking existing index :${JSON.stringify(index)}`); if (!findIndex(requiredIndexes, index)) { // console.log(`db.deleteIndex(${JSON.stringify(index)})`); await db.deleteIndex(index); } } } for (index of requiredIndexes) { if (!findIndex(existingIndexes, index)) { // console.log(`db.createIndex(${JSON.stringify(index)})`); await db.createIndex({ name: index.name, ...index.def }); } } globalThis.dbReady = true; console.log({ caller: 'initDb / before db.changes' }); const changes = db .changes({ since: 'now', live: true, include_docs: false }) .on('change', changeHandler) .on('complete', (info: any) => { console.log({ caller: 'changes / complete', info }); }) .on('error', (error: any) => { console.log({ caller: 'changes / complete', error }); }); // console.log({ caller: 'initDb / back from db.changes', changes }); // changes.cancel(); /* const indexes = await db.getIndexes(); console.log(`indexes: ${JSON.stringify(indexes)}`); const explain1 = await db.explain({ selector: { type: 'trkpt', gpx: 'xxxx', }, // sort: ['trkpt.time'], // use_index: 'type-trkpt-gpx-time', }); console.log(`explain1: ${JSON.stringify(explain1)}`); const explain2 = await db.explain({ selector: { type: 'gpx', }, // sort: ['trkpt.time'], // use_index: 'type-trkpt-gpx-time', }); console.log(`explain2: ${JSON.stringify(explain2)}`); */ };