Class-based types for the ORM feel a little more natural.
This commit is contained in:
parent
278fc68831
commit
d2c1d3b63c
@ -1,52 +1,75 @@
|
|||||||
import { PouchDB, TYPES as t } from '../services/db.js';
|
import { PouchDB, TypeSpec } from '../services/db.js';
|
||||||
import { log } from '../services/console.js';
|
import { log } from '../services/console.js';
|
||||||
import { sha256 } from '../utils/crypto.js';
|
import { sha256 } from '../utils/crypto.js';
|
||||||
import { blobToArrayBuffer } from '../utils/conversion.js';
|
import { blobToArrayBuffer } from '../utils/conversion.js';
|
||||||
|
|
||||||
export const FileType = PouchDB.registerType({
|
class FileSpec extends TypeSpec {
|
||||||
name: 'File',
|
static getUniqueID(doc) {
|
||||||
getUniqueID: doc => doc.digest.substr(0, 16),
|
return doc.digest.substr(0, 16);
|
||||||
// schema: {
|
|
||||||
// name: t.REQUIRED_STRING,
|
|
||||||
// mimetype: t.REQUIRED_STRING,
|
|
||||||
// digest: t.REQUIRED_STRING,
|
|
||||||
// size: t.INTEGER,
|
|
||||||
// modifiedDate: t.DATE,
|
|
||||||
// addDate: t.DATE,
|
|
||||||
// hasData: t.REQUIRED_BOOLEAN,
|
|
||||||
// tags: {
|
|
||||||
// type: "object",
|
|
||||||
// additionalProperties: t.BOOLEAN
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
methods: {
|
|
||||||
getURL: doc => `/${FileType.prefix}/${doc._id}/data`,
|
|
||||||
getFromURL: async path => {
|
|
||||||
if (path.endsWith('/')) {
|
|
||||||
path = path.substr(0, path.length - 1);
|
|
||||||
}
|
|
||||||
const [_, db, id, attname] = path.split('/');
|
|
||||||
const doc = await FileType.find(id);
|
|
||||||
return await doc.getAttachment(attname);
|
|
||||||
},
|
|
||||||
upload: async function(blob) {
|
|
||||||
const digest = await sha256(await blobToArrayBuffer(blob));
|
|
||||||
const lastModified = blob.lastModified ? new Date(blob.lastModified) : new Date();
|
|
||||||
return await FileType.getOrCreate({
|
|
||||||
name: blob.name,
|
|
||||||
mimetype: blob.type,
|
|
||||||
size: blob.size,
|
|
||||||
lastModified: lastModified.toISOString(),
|
|
||||||
addDate: new Date().toISOString(),
|
|
||||||
digest,
|
|
||||||
tags: {},
|
|
||||||
_attachments: {
|
|
||||||
data: {
|
|
||||||
content_type: blob.type,
|
|
||||||
data: blob
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
static getURL(doc, attachmentName = 'data') {
|
||||||
|
const end = attachmentName ? '/' + attachmentName : '';
|
||||||
|
return `/${doc._prefix}/${doc._id}` + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getDocFromURL(path) {
|
||||||
|
if (path.endsWith('/')) {
|
||||||
|
path = path.substr(0, path.length - 1);
|
||||||
|
}
|
||||||
|
const [_, db, id, attname] = path.split('/');
|
||||||
|
return await FileType.find(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getFromURL(path) {
|
||||||
|
if (path.endsWith('/')) {
|
||||||
|
path = path.substr(0, path.length - 1);
|
||||||
|
}
|
||||||
|
const [_, db, id, attname] = path.split('/');
|
||||||
|
const doc = await FileType.find(id);
|
||||||
|
if (attname) {
|
||||||
|
return await doc.getAttachment(attname);
|
||||||
|
}
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async upload(blob) {
|
||||||
|
const digest = await sha256(await blobToArrayBuffer(blob));
|
||||||
|
const lastModified = blob.lastModified ? new Date(blob.lastModified) : new Date();
|
||||||
|
return await FileType.getOrCreate({
|
||||||
|
name: blob.name,
|
||||||
|
mimetype: blob.type,
|
||||||
|
size: blob.size,
|
||||||
|
lastModified: lastModified.toISOString(),
|
||||||
|
addDate: new Date().toISOString(),
|
||||||
|
digest,
|
||||||
|
tags: {},
|
||||||
|
_attachments: {
|
||||||
|
data: {
|
||||||
|
content_type: blob.type,
|
||||||
|
data: blob
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static validate(doc) {
|
||||||
|
// // TODO actually validate perhaps against a JSON schema
|
||||||
|
//
|
||||||
|
// const schema = {
|
||||||
|
// name: t.REQUIRED_STRING,
|
||||||
|
// mimetype: t.REQUIRED_STRING,
|
||||||
|
// digest: t.REQUIRED_STRING,
|
||||||
|
// size: t.INTEGER,
|
||||||
|
// modifiedDate: t.DATE,
|
||||||
|
// addDate: t.DATE,
|
||||||
|
// hasData: t.REQUIRED_BOOLEAN,
|
||||||
|
// tags: {
|
||||||
|
// type: "object",
|
||||||
|
// additionalProperties: t.BOOLEAN
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileType = PouchDB.registerType('File', FileSpec);
|
||||||
|
|||||||
@ -1,104 +1,113 @@
|
|||||||
import { PouchDB, TYPES as t } from '../services/db.js';
|
import { PouchDB, TypeSpec } from '../services/db.js';
|
||||||
import { blobToArrayBuffer } from '../utils/conversion.js';
|
import { blobToArrayBuffer } from '../utils/conversion.js';
|
||||||
import { backgroundTask } from '../utils/event.js';
|
import { backgroundTask } from '../utils/event.js';
|
||||||
import { FileType } from './file.js';
|
import { FileType } from './file.js';
|
||||||
|
|
||||||
export const ImageType = PouchDB.registerType({
|
class ImageSpec extends TypeSpec {
|
||||||
name: 'Image',
|
static async upload(blob) {
|
||||||
getUniqueID: doc => doc.digest.substr(0, 16),
|
const f = await FileType.upload(blob, false);
|
||||||
getSequence: doc => new Date(doc.originalDate).getTime(),
|
return await ImageType.getOrCreate({
|
||||||
// schema: {
|
digest: f.digest,
|
||||||
// originalDate: t.REQUIRED_DATE,
|
originalDate: f.lastModified,
|
||||||
// digest: t.REQUIRED_STRING,
|
importing: true,
|
||||||
// width: t.INTEGER,
|
width: 0,
|
||||||
// height: t.INTEGER,
|
height: 0,
|
||||||
// sizes: {
|
sizes: {
|
||||||
// type: 'object',
|
full: FileType.getURL(f)
|
||||||
// properties: {
|
|
||||||
// full: t.REQUIRED_STRING,
|
|
||||||
// thumbnail: t.STRING,
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// orientation: t.INTEGER,
|
|
||||||
// make: t.STRING,
|
|
||||||
// model: t.STRING,
|
|
||||||
// flash: t.BOOLEAN,
|
|
||||||
// iso: t.INTEGER,
|
|
||||||
// gps: {
|
|
||||||
// type: 'object',
|
|
||||||
// properties: {
|
|
||||||
// latitude: t.NUMBER,
|
|
||||||
// longitude: t.NUMBER,
|
|
||||||
// altitude: t.NUMBER,
|
|
||||||
// heading: t.NUMBER,
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// tags: {
|
|
||||||
// type: "object",
|
|
||||||
// additionalProperties: t.BOOLEAN
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
methods: {
|
|
||||||
upload: async function(blob) {
|
|
||||||
const f = await FileType.upload(blob, false);
|
|
||||||
return await ImageType.getOrCreate({
|
|
||||||
digest: f.digest,
|
|
||||||
originalDate: f.lastModified,
|
|
||||||
importing: true,
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
sizes: {
|
|
||||||
full: FileType.getURL(f)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
processImportables: backgroundTask(async function _processImportables(importables) {
|
|
||||||
if (!importables.length) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
const image = importables[0];
|
|
||||||
const { _id, _rev } = image;
|
|
||||||
const imageData = await FileType.getFromURL(image.sizes.full);
|
|
||||||
|
|
||||||
const ExifParser = await import('exif-parser');
|
|
||||||
|
|
||||||
const buffer = await blobToArrayBuffer(imageData);
|
|
||||||
|
|
||||||
const exifData = ExifParser.create(buffer).parse();
|
|
||||||
const { tags, imageSize } = exifData;
|
|
||||||
const { width, height } = imageSize;
|
|
||||||
const originalDate = new Date(
|
|
||||||
tags.DateTimeOriginal
|
|
||||||
? new Date(tags.DateTimeOriginal * 1000).toISOString()
|
|
||||||
: image.originalDate
|
|
||||||
).toISOString();
|
|
||||||
|
|
||||||
const img = await ImageType.getOrCreate({
|
|
||||||
originalDate,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
orientation: tags.Orientation,
|
|
||||||
digest: image.digest,
|
|
||||||
make: tags.Make,
|
|
||||||
model: tags.Model,
|
|
||||||
flash: !!tags.Flash,
|
|
||||||
iso: tags.ISO,
|
|
||||||
sizes: image.sizes,
|
|
||||||
gps: {
|
|
||||||
latitude: tags.GPSLatitude,
|
|
||||||
longitude: tags.GPSLongitude,
|
|
||||||
altitude: tags.GPSAltitude,
|
|
||||||
heading: tags.GPSImgDirection
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
image.delete();
|
|
||||||
|
|
||||||
const module = await import('../context/generateThumbnails');
|
|
||||||
await module.generateThumbnailForImage(img);
|
|
||||||
}, false)
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
ImageType.find({ importing: true }, true).then(fw => fw.subscribe(ImageType.processImportables));
|
static getUniqueID(doc) {
|
||||||
|
return doc.digest.substr(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSequence(doc) {
|
||||||
|
return new Date(doc.originalDate).getTime();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// static validate(doc) {
|
||||||
|
// // TODO actually validate perhaps against a JSON schema
|
||||||
|
//
|
||||||
|
// const schema = {
|
||||||
|
// originalDate: t.REQUIRED_DATE,
|
||||||
|
// digest: t.REQUIRED_STRING,
|
||||||
|
// width: t.INTEGER,
|
||||||
|
// height: t.INTEGER,
|
||||||
|
// sizes: {
|
||||||
|
// type: 'object',
|
||||||
|
// properties: {
|
||||||
|
// full: t.REQUIRED_STRING,
|
||||||
|
// thumbnail: t.STRING,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// orientation: t.INTEGER,
|
||||||
|
// make: t.STRING,
|
||||||
|
// model: t.STRING,
|
||||||
|
// flash: t.BOOLEAN,
|
||||||
|
// iso: t.INTEGER,
|
||||||
|
// gps: {
|
||||||
|
// type: 'object',
|
||||||
|
// properties: {
|
||||||
|
// latitude: t.NUMBER,
|
||||||
|
// longitude: t.NUMBER,
|
||||||
|
// altitude: t.NUMBER,
|
||||||
|
// heading: t.NUMBER,
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// tags: {
|
||||||
|
// type: "object",
|
||||||
|
// additionalProperties: t.BOOLEAN
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
const processImportables = backgroundTask(async function _processImportables(importables) {
|
||||||
|
if (!importables.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = importables[0];
|
||||||
|
const { _id, _rev } = image;
|
||||||
|
const imageData = await FileType.getFromURL(image.sizes.full);
|
||||||
|
|
||||||
|
const ExifParser = await import('exif-parser');
|
||||||
|
|
||||||
|
const buffer = await blobToArrayBuffer(imageData);
|
||||||
|
|
||||||
|
const exifData = ExifParser.create(buffer).parse();
|
||||||
|
const { tags, imageSize } = exifData;
|
||||||
|
const { width, height } = imageSize;
|
||||||
|
const originalDate = new Date(
|
||||||
|
tags.DateTimeOriginal ? new Date(tags.DateTimeOriginal * 1000).toISOString() : image.originalDate
|
||||||
|
).toISOString();
|
||||||
|
|
||||||
|
const img = await ImageType.getOrCreate({
|
||||||
|
originalDate,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
orientation: tags.Orientation,
|
||||||
|
digest: image.digest,
|
||||||
|
make: tags.Make,
|
||||||
|
model: tags.Model,
|
||||||
|
flash: !!tags.Flash,
|
||||||
|
iso: tags.ISO,
|
||||||
|
sizes: image.sizes,
|
||||||
|
gps: {
|
||||||
|
latitude: tags.GPSLatitude,
|
||||||
|
longitude: tags.GPSLongitude,
|
||||||
|
altitude: tags.GPSAltitude,
|
||||||
|
heading: tags.GPSImgDirection
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
image.delete();
|
||||||
|
|
||||||
|
const module = await import('../context/generateThumbnails');
|
||||||
|
await module.generateThumbnailForImage(img);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
export const ImageType = PouchDB.registerType('Image', ImageSpec);
|
||||||
|
|
||||||
|
ImageType.find({ importing: true }, true).then(fw => fw.subscribe(processImportables));
|
||||||
|
|||||||
@ -10,6 +10,12 @@ export function error(...args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function warn(...args) {
|
||||||
|
if (__DEV__) {
|
||||||
|
console.warn(...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function group(...args) {
|
export function group(...args) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.group(...args);
|
console.group(...args);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import http from 'pouchdb-adapter-http';
|
|||||||
import replication from 'pouchdb-replication';
|
import replication from 'pouchdb-replication';
|
||||||
import find from 'pouchdb-find';
|
import find from 'pouchdb-find';
|
||||||
|
|
||||||
import { log } from './console.js';
|
import { log, warn } from './console.js';
|
||||||
import { isObject } from '../utils/comparators.js';
|
import { isObject } from '../utils/comparators.js';
|
||||||
import { LiveArray } from '../utils/livearray.js';
|
import { LiveArray } from '../utils/livearray.js';
|
||||||
import { deepAssign } from '../utils/conversion.js';
|
import { deepAssign } from '../utils/conversion.js';
|
||||||
@ -16,128 +16,102 @@ export const PouchDB = core
|
|||||||
.plugin(find)
|
.plugin(find)
|
||||||
.plugin(PouchORM);
|
.plugin(PouchORM);
|
||||||
|
|
||||||
export function generateAttachmentUrl(dbName, docId, attachmentKey) {
|
export class TypeSpec {
|
||||||
return `/_doc_attachments/${dbName}/${docId}/${attachmentKey}`;
|
constructor(props) {
|
||||||
}
|
this._populateId(props);
|
||||||
|
Object.assign(this, props);
|
||||||
const dbs = new Map();
|
|
||||||
export function getDatabase(name = 'gallery') {
|
|
||||||
if (!dbs.has(name)) {
|
|
||||||
dbs.set(name, new PouchDB(name));
|
|
||||||
}
|
}
|
||||||
return dbs.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getOrCreate(doc) {
|
static getSequence(doc) {
|
||||||
const db = getDatabase();
|
return '';
|
||||||
try {
|
}
|
||||||
const results = await db.get(doc._id);
|
|
||||||
return [results, false];
|
static getUniqueID(doc) {
|
||||||
} catch (e) {
|
throw 'NotImplemented';
|
||||||
if (e.status === 404) {
|
}
|
||||||
const results = db.put(doc);
|
|
||||||
return [results, true];
|
static validate(doc) {}
|
||||||
|
|
||||||
|
instantiate(doc) {
|
||||||
|
return new this._cls(docs);
|
||||||
|
}
|
||||||
|
|
||||||
|
_populateId(doc) {
|
||||||
|
if (!doc._id) {
|
||||||
|
doc._id = `${this._prefix}_${this._cls.getSequence(doc)}_${this._cls.getUniqueID(doc)}`;
|
||||||
}
|
}
|
||||||
throw e;
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
export function PouchORM(PouchDB) {
|
||||||
async function update(props, save = true) {
|
PouchDB.registerType = (name, cls, db) => {
|
||||||
deepAssign(this, props);
|
|
||||||
if (save) {
|
|
||||||
await this.save();
|
|
||||||
} else {
|
|
||||||
this.validate();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PouchDB.registerType = opts => {
|
|
||||||
const { getUniqueID, getSequence, schema, name } = opts;
|
|
||||||
const prefix = name.toLowerCase();
|
const prefix = name.toLowerCase();
|
||||||
const db = opts.db || new PouchDB(prefix);
|
const _db = db || PouchDB(prefix);
|
||||||
|
|
||||||
function populateId(doc) {
|
if (!cls.hasOwnProperty('validate')) {
|
||||||
if (!doc._id) {
|
warn(`${cls.name} has no validation.`);
|
||||||
const sequence = getSequence ? getSequence(doc).toString(36) : '';
|
|
||||||
doc._id = `${prefix}_${sequence}_${getUniqueID(doc)}`;
|
|
||||||
}
|
|
||||||
return doc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate() {
|
const instantiate = doc => new cls(doc);
|
||||||
// FIXME
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function save() {
|
|
||||||
const { rev } = await db.put(this.validate());
|
|
||||||
this._rev = rev;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addAttachment(attName, dataBlob) {
|
|
||||||
const { rev } = await db.putAttachment(this._id, attName, this._rev, dataBlob, dataBlob.type);
|
|
||||||
|
|
||||||
this._rev = rev;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getAttachment(attName) {
|
|
||||||
return await db.getAttachment(this._id, attName);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeAttachment(attName) {
|
|
||||||
return await db.removeAttachment(this._id, attName, this._rev);
|
|
||||||
}
|
|
||||||
|
|
||||||
function instantiate(docOrResultSet) {
|
|
||||||
Object.defineProperties(docOrResultSet, {
|
|
||||||
update: { value: update.bind(docOrResultSet) },
|
|
||||||
save: { value: save.bind(docOrResultSet) },
|
|
||||||
delete: { value: _delete.bind(docOrResultSet) },
|
|
||||||
addAttachment: { value: addAttachment.bind(docOrResultSet) },
|
|
||||||
getAttachment: { value: getAttachment.bind(docOrResultSet) },
|
|
||||||
removeAttachment: { value: removeAttachment.bind(docOrResultSet) },
|
|
||||||
validate: { value: validate.bind(docOrResultSet) }
|
|
||||||
});
|
|
||||||
return docOrResultSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function find(idOrQuery, live = false) {
|
async function find(idOrQuery, live = false) {
|
||||||
let results = [];
|
|
||||||
|
|
||||||
if (typeof idOrQuery === 'string') {
|
if (typeof idOrQuery === 'string') {
|
||||||
results = await db.get(idOrQuery);
|
return instantiate(await _db.get(idOrQuery));
|
||||||
} else {
|
|
||||||
const selector = Object.assign(
|
|
||||||
{ _deleted: { exists: false } },
|
|
||||||
isObject(idOrQuery) ? idOrQuery : { _id: { $gt: `${prefix}_0`, $lt: `${prefix}_\ufff0` } }
|
|
||||||
);
|
|
||||||
if (live) {
|
|
||||||
return LiveArray(db, idOrQuery, instantiate);
|
|
||||||
}
|
|
||||||
results = await db.find({ selector: idOrQuery });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return instantiate(results);
|
const selector = Object.assign(
|
||||||
}
|
{ _deleted: { exists: false } },
|
||||||
|
isObject(idOrQuery) ? idOrQuery : { _id: { $gt: `${prefix}_0`, $lt: `${prefix}_\ufff0` } }
|
||||||
async function _delete() {
|
);
|
||||||
return await this.update({ _deleted: true });
|
if (live) {
|
||||||
}
|
return LiveArray(_db, idOrQuery, instantiate);
|
||||||
|
|
||||||
async function _new(props, save = true) {
|
|
||||||
const doc = instantiate(populateId(props));
|
|
||||||
if (save) {
|
|
||||||
await doc.save();
|
|
||||||
}
|
}
|
||||||
return doc;
|
return (await _db.find({ selector: idOrQuery })).docs.map(instantiate);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getOrCreate(props) {
|
async function getOrCreate(props) {
|
||||||
let doc = await _new(props, false);
|
let doc = await new cls(props);
|
||||||
try {
|
try {
|
||||||
await doc.save();
|
await doc.save();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -149,28 +123,18 @@ export function PouchORM(PouchDB) {
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.assign(
|
Object.defineProperties(cls.prototype, {
|
||||||
{
|
_name: { value: name },
|
||||||
new: _new,
|
_prefix: { value: prefix },
|
||||||
getOrCreate,
|
_db: { value: _db },
|
||||||
find,
|
_cls: { value: cls }
|
||||||
prefix,
|
});
|
||||||
db
|
|
||||||
// delete: // FIXME
|
Object.defineProperties(cls, {
|
||||||
},
|
getOrCreate: { value: getOrCreate },
|
||||||
opts.methods || {}
|
find: { value: find }
|
||||||
);
|
});
|
||||||
|
|
||||||
|
return cls;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TYPES = {
|
|
||||||
STRING: { type: 'string' },
|
|
||||||
INTEGER: { type: 'integer' },
|
|
||||||
BOOLEAN: { type: 'boolean' },
|
|
||||||
DATE: { type: 'date' }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add required types
|
|
||||||
Object.keys(TYPES).forEach(k => {
|
|
||||||
TYPES['REQUIRED_' + k] = Object.assign({ required: true }, TYPES[k]);
|
|
||||||
});
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user