Integrate PouchORM package into Gallery project
This commit is contained in:
parent
ad779629a5
commit
8cfb7f575e
@ -14,7 +14,7 @@
|
||||
"domvm": "~3.2.1",
|
||||
"exif-parser": "~0.1.9",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"frptools": "3.1.0",
|
||||
"frptools": "3.1.1",
|
||||
"linear-partitioning": "0.3.2",
|
||||
"pica": "~2.0.8",
|
||||
"pouchdb-adapter-http": "~6.4.1",
|
||||
@ -24,6 +24,7 @@
|
||||
"pouchdb-core": "~6.4.1",
|
||||
"pouchdb-find": "~6.4.1",
|
||||
"pouchdb-replication": "~6.4.1",
|
||||
"pouchorm": "~1.0.0",
|
||||
"router": "2.1.0",
|
||||
"semantic-ui-reset": "^2.2.12",
|
||||
"semantic-ui-site": "^2.2.12",
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { PouchDB, TypeSpec } from '../services/db.js';
|
||||
import { TypeSpec } from 'pouchorm';
|
||||
|
||||
import { PouchDB } from '../services/db.js';
|
||||
import { ImageType } from '../data/image.js';
|
||||
import { extractID } from '../utils/conversion.js';
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { PouchDB, TypeSpec } from '../services/db.js';
|
||||
import { TypeSpec } from 'pouchorm';
|
||||
|
||||
import { PouchDB } from '../services/db.js';
|
||||
import { sha256 } from '../utils/crypto.js';
|
||||
import { blobToArrayBuffer } from '../utils/conversion.js';
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { PouchDB, TypeSpec } from '../services/db.js';
|
||||
import { TypeSpec } from 'pouchorm';
|
||||
|
||||
import { PouchDB } from '../services/db.js';
|
||||
import { blobToArrayBuffer, deepAssign } from '../utils/conversion.js';
|
||||
import { backgroundTask } from '../utils/event.js';
|
||||
import { FileType } from './file.js';
|
||||
|
||||
@ -4,11 +4,7 @@ import http from 'pouchdb-adapter-http';
|
||||
import replication from 'pouchdb-replication';
|
||||
import find from 'pouchdb-find';
|
||||
|
||||
import { log, warn } from './console.js';
|
||||
import { isObject } from '../utils/comparators.js';
|
||||
import { LiveArray } from '../utils/livearray.js';
|
||||
import { Watcher } from '../utils/watcher.js';
|
||||
import { deepAssign, pouchDocHash } from '../utils/conversion.js';
|
||||
import { PouchORM } from 'pouchorm';
|
||||
|
||||
export const PouchDB = core
|
||||
.plugin(idb)
|
||||
@ -16,168 +12,3 @@ export const PouchDB = core
|
||||
.plugin(replication)
|
||||
.plugin(find)
|
||||
.plugin(PouchORM);
|
||||
|
||||
export class TypeSpec {
|
||||
constructor(props) {
|
||||
this._populateId(props);
|
||||
Object.assign(this, { $links: {} }, props, { type: this._prefix });
|
||||
}
|
||||
|
||||
static getUniqueID(doc) {
|
||||
throw 'NotImplemented';
|
||||
}
|
||||
|
||||
static validate(doc) {}
|
||||
|
||||
instantiate(doc) {
|
||||
return new this._cls(docs);
|
||||
}
|
||||
|
||||
_populateId(doc) {
|
||||
if (!doc._id) {
|
||||
doc._id = `${this._prefix}_${this._cls.getUniqueID(doc)}`;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
_hash() {
|
||||
return pouchDocHash(this);
|
||||
}
|
||||
|
||||
async delete() {
|
||||
return await this.update({ _deleted: true });
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._cls.validate(this);
|
||||
const { rev } = await this._db.put(this);
|
||||
this._rev = rev;
|
||||
return this;
|
||||
}
|
||||
|
||||
async addAttachment(attName, dataBlob) {
|
||||
const { rev } = await this._db.putAttachment(
|
||||
this._id,
|
||||
attName,
|
||||
this._rev,
|
||||
dataBlob,
|
||||
dataBlob.type
|
||||
);
|
||||
|
||||
this._rev = rev;
|
||||
return this;
|
||||
}
|
||||
|
||||
async getAttachment(attName) {
|
||||
return await this._db.getAttachment(this._id, attName);
|
||||
}
|
||||
|
||||
async removeAttachment(attName) {
|
||||
return await this._db.removeAttachment(this._id, attName, this._rev);
|
||||
}
|
||||
|
||||
async update(props, save = true) {
|
||||
deepAssign(this, props);
|
||||
if (save) {
|
||||
await this.save();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export function PouchORM(PouchDB) {
|
||||
PouchDB.registerType = (name, cls, db) => {
|
||||
const prefix = name.toLowerCase();
|
||||
const _db = db || PouchDB(prefix);
|
||||
_db.setMaxListeners(1000);
|
||||
const _baseSelector = Object.freeze({
|
||||
_id: { $gt: `${prefix}_0`, $lt: `${prefix}_\ufff0` }
|
||||
});
|
||||
const watch = Watcher(_db, _baseSelector, { include_docs: true });
|
||||
|
||||
if (!cls.hasOwnProperty('validate')) {
|
||||
warn(`${cls.name} has no validation.`);
|
||||
}
|
||||
|
||||
const instantiate = doc => new cls(doc);
|
||||
|
||||
async function find(idOrSelector, opts = {}) {
|
||||
if (typeof idOrSelector === 'string') {
|
||||
return instantiate(await _db.get(idOrSelector));
|
||||
}
|
||||
|
||||
const isSelector = isObject(idOrSelector);
|
||||
|
||||
const selector = Object.assign(
|
||||
isSelector && idOrSelector._deleted ? { _deleted: true } : { _deleted: { exists: false } },
|
||||
isSelector ? idOrSelector : _baseSelector
|
||||
);
|
||||
if (opts.index) {
|
||||
opts.use_index = [prefix, opts.index];
|
||||
delete opts.index;
|
||||
}
|
||||
if (opts.live) {
|
||||
opts.mapper = instantiate;
|
||||
return LiveArray(_db, idOrSelector, opts);
|
||||
}
|
||||
return (await _db.find(Object.assign({ selector: idOrSelector }, opts))).docs.map(instantiate);
|
||||
}
|
||||
|
||||
async function getOrCreate(props) {
|
||||
let doc = await new cls(props);
|
||||
try {
|
||||
await doc.save();
|
||||
} catch (e) {
|
||||
if (e.status !== 409) {
|
||||
throw e;
|
||||
}
|
||||
doc = await find(doc._id);
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
async function _delete(id) {
|
||||
try {
|
||||
const doc = await find(id);
|
||||
doc._deleted = true;
|
||||
await _db.put(doc);
|
||||
} catch (e) {
|
||||
if (e.status !== 404) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function _index(name, fields) {
|
||||
return _db.createIndex({
|
||||
index: {
|
||||
ddoc: prefix,
|
||||
fields,
|
||||
name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Object.defineProperties(cls.prototype, {
|
||||
_name: { value: name },
|
||||
_prefix: { value: prefix },
|
||||
_db: { value: _db },
|
||||
_cls: { value: cls },
|
||||
_baseSelector: { value: _baseSelector }
|
||||
});
|
||||
|
||||
Object.defineProperties(cls, {
|
||||
getOrCreate: { value: getOrCreate },
|
||||
find: { value: find },
|
||||
index: { value: _index },
|
||||
delete: { value: _delete },
|
||||
subscribe: { value: watch },
|
||||
db: { value: _db },
|
||||
name: { value: name },
|
||||
prefix: { value: prefix },
|
||||
selector: { value: _baseSelector }
|
||||
});
|
||||
|
||||
return cls;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
import { prop, computed, id } from 'frptools';
|
||||
|
||||
import { Watcher } from './watcher.js';
|
||||
import { pouchDocArrayHash } from './conversion.js';
|
||||
|
||||
// LiveArray is a subscribable property function that always returns the db results that match the provided selector and calls subscribers when the results change.
|
||||
export function LiveArray(db, selector, opts = {}) {
|
||||
const mapper = opts.mapper || id;
|
||||
opts.mapper && delete opts.mapper;
|
||||
opts.include_docs = true;
|
||||
const _watcher = Watcher(db, selector, opts);
|
||||
let changeSub = null;
|
||||
|
||||
const ready = prop(false);
|
||||
const data = prop({ docs: [] });
|
||||
const docs = computed(r => r.docs.map(mapper), [data], pouchDocArrayHash);
|
||||
|
||||
const cleanup = () => {
|
||||
docs.unsubscribeAll();
|
||||
ready.unsubscribeAll();
|
||||
if (changeSub) {
|
||||
changeSub();
|
||||
changeSub = null;
|
||||
}
|
||||
data({ docs: [] });
|
||||
};
|
||||
|
||||
const refresh = async function refresh(...args) {
|
||||
data(await db.find({ selector }));
|
||||
};
|
||||
|
||||
docs.ready = ready;
|
||||
docs.cleanup = cleanup;
|
||||
docs.selector = selector;
|
||||
docs.db = db;
|
||||
|
||||
refresh().then(() => {
|
||||
changeSub = _watcher(refresh);
|
||||
ready(true);
|
||||
});
|
||||
return docs;
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
import { log, error } from '../services/console.js';
|
||||
|
||||
export function Watcher(db, selector, opts) {
|
||||
const subscribers = new Set();
|
||||
let changes = null;
|
||||
|
||||
return function subscribe(fn) {
|
||||
subscribers.add(fn);
|
||||
|
||||
if (subscribers.size === 1 && !changes) {
|
||||
log(`Watching "${db.name}" for ${JSON.stringify(selector)}`);
|
||||
changes = db
|
||||
.changes(
|
||||
Object.assign(
|
||||
{
|
||||
since: 'now',
|
||||
live: true,
|
||||
selector
|
||||
},
|
||||
opts
|
||||
)
|
||||
)
|
||||
.on('change', change => {
|
||||
const { id, deleted, doc } = change;
|
||||
log(
|
||||
`Change from "${db.name}" for ${JSON.stringify(selector)} ${id} ${deleted ? 'deleted' : ''}`
|
||||
);
|
||||
subscribers.forEach(s => s(id, !!deleted, doc));
|
||||
})
|
||||
.on('error', err => {
|
||||
error(err);
|
||||
subscribers.empty();
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
subscribers.delete(fn);
|
||||
if (subscribers.size === 0 && changes) {
|
||||
log('Unwatching:', db, selector);
|
||||
changes.cancel();
|
||||
changes = null;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -2,8 +2,7 @@
|
||||
"name": "pouchorm",
|
||||
"version": "1.0.0",
|
||||
"description": "Document Abstraction Layer for PouchDB",
|
||||
"main": "lib/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
"main": "src/index.js",
|
||||
"files": ["dist", "lib", "src"],
|
||||
"scripts": {
|
||||
"test": "node ../../bin/runTests.js ./"
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { LiveArray } from './livearray.js';
|
||||
import { Watcher } from './watcher.js';
|
||||
import { isObject } from './utils.js';
|
||||
|
||||
export function PouchORM(PouchDB) {
|
||||
@ -12,7 +13,7 @@ export function PouchORM(PouchDB) {
|
||||
const watch = Watcher(_db, _baseSelector, { include_docs: true });
|
||||
|
||||
if (!cls.hasOwnProperty('validate')) {
|
||||
warn(`${cls.name} has no validation.`);
|
||||
// warn(`${cls.name} has no validation.`);
|
||||
}
|
||||
|
||||
const instantiate = doc => new cls(doc);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { pouchDocHash } from './utils.js';
|
||||
import { pouchDocHash, deepAssign } from './utils.js';
|
||||
|
||||
export class TypeSpec {
|
||||
constructor(props) {
|
||||
|
||||
@ -11,11 +11,13 @@ const digestRoutes = (routes, baseUrl) =>
|
||||
return '(' + regExStr.substring(1, regExStr.lastIndexOf('/')) + ')';
|
||||
});
|
||||
|
||||
return {
|
||||
return Object.assign(
|
||||
{
|
||||
matcher: new RegExp(`^${baseUrl}${reg}$`),
|
||||
_i: i,
|
||||
...route
|
||||
};
|
||||
_i: i
|
||||
},
|
||||
route
|
||||
);
|
||||
});
|
||||
|
||||
export function Router(routes, baseUrl = '#') {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user