# PouchORM An ORM for PouchDB inspired by [Hood.ie](https://hood.ie/) and [Django](https://djangoproject.com) ## Usage ### Type Definition In a type definition class, specify a static `getUniqueID` method and optionally a static `validate` method. ```js import { PouchDB } from 'pouchdb'; import { TypeSpec } from 'PouchORM'; class FileSpec extends TypeSpec { static getUniqueID(doc) { return doc.digest.substr(0, 16); } static validate(doc) { const REQUIRED_PROPS = ['filename', 'size', 'digest']; const missing_props = REQUIRED_PROPS.filter(prop => !doc.hasOwnProperty(prop)); if (missing_props) { throw new ValidationError('FileType missing required props: ', missing_props); } } } export const FileType = PouchDB.registerType('File', FileSpec); ``` Document properties of a type are not directly defined but the type definition. Specific properties can be enforced by the `validate` method. The following properties are illegal: * starting with an underscore (\_) - these are used by PouchDB internally * starting with a double dollar-sign ($$) - these are reserved for future use by PouchORM. (Single dollar-sign properties may be used for your implementation’s meta-data.) ### Type Functions * `FileType.getOrCreate(obj)` - Try to save the passed object as a document. If it fails with a /409 Conflict/, look up the existing one and return it (ignoring differences between passed object and the found object) * /obj/ - an object containing a partial document including an `id` property * _Returns_ a FileType instance * `FileType.find(idOrSelector, options)` - Find one or many records. Optionally return a subscribeable that will fire events when the selection changes. * /idOrSelector/ * if a string or number is passed, `find` will attempt to lookup the document with this as the id. * if an object is passed, it will be treated as a selector for a find query * /options/ can have the following optional properties * /index/ - specify a specific index to use with the passed selector * /live/ - boolean (default /false/) return a subscribeable that will fire when the results of the selector are updated. * /…/ - other options will be passed to `db.changes()` when `live: true` * _Returns_ * if `options.live` is /false/, an array of FileType instances will be returned * if `options.live` is /true/, a subscribeable will be returned. Subscription callbacks will be called when the results of /idOrSelector/ changes * `FileType.index(index, fields)` - Create a PouchDB [Index](https://pouchdb.com/api.html#create_index) that can be used by `FileType.find` to sort on non-ID fields * /index/ - a string value that can optionally be provided to the options object of `FileType.find` * /fields/ - an array of field names for PouchDB to index on. * _Returns_ void * `FileType.delete(id)` - Remove a document from the db * /id/ - the id string of the document to be removed * _Returns_ void * `FileType.subscribe(callback)` - subscribe to all FileType changes * _Returns_ - a function that unsubscribes the passed callback when called. ### Type Properties * `FileType.db` - the PouchDB database used by `FileType` * `FileType.name` - the type name passed to the `registerType` function * `FileType.prefix` - the prefix used on all document ids stored in PouchDB * `FileType.selector` - the PouchDB selector definition used by ‘subscribe’ and ‘find’ ### Instance Methods Creating a new instance is standard Javascript for any new instance: ```js let note = new FileType({ filename: 'note.txt', type: 'text/plain' }); ``` * _static_ `note.getUniqueID(doc)` - You _must override_ this function in your type definition to provide the id to be used for this document. * /doc/ - an object representing the document. This could be an instance of the type or a bare object with properties for this type. * _Returns_ - a unique string value to be used as a document id * _static_ `note.validate()` - By default this does nothing. Optionally override it with a method that throws exceptions when a document is invalid to block writing invalid data to the database. * `note.save()` - Calls `validate()` and then writes the document to the database. * _Returns_ - a self-reference to the instance * `note.update(props, save=true)` - Update this instance * /props/ - a deeply nested object that will be applied to this instance * /save/ - a boolean to save this document after updating. * _Returns_ - a self-reference to the instance * `note.addAttachment(name, blob)` - Add a named attachment to this instance. * /name/ - the name used to reference the attachment * /blob/ - a blob instance of the actual data * _Returns_ - a self-reference to the instance * `note.getAttachment(name)` - Retrieve a named attachment from this instance. * /name/ - the name of the attachment specified in `addAttachment` * _Returns_ - a Blob instance of the attachment data * `note.removeAttachment(name)` - Remove a named attachment from this instance. * /name/ - the name of the attachment specified in `addAttachment` * _Returns_ - * `note.delete()` - Flag this document as `_deleted` == `true`. This will cause it to not show up in `find` results. (_Note_: documents are left in the database in this state to allow for deletion to be synced to other nodes. To truly remove documents, [compact your database](https://pouchdb.com/api.html#compaction).)