UNPKG

rxdb

Version:

A local-first realtime NoSQL Database for JavaScript applications - https://rxdb.info/

125 lines (115 loc) 3.78 kB
/** * For the ORM capabilities, * we have to merge the document prototype * with the ORM functions and the data * We do this iterating over the properties and * adding them to a new object. * In the future we should do this by chaining the __proto__ objects */ import type { RxCollection, RxDocument, RxDocumentData } from './types/index.d.ts'; import { createRxDocumentConstructor, basePrototype, createWithConstructor as createRxDocumentWithConstructor } from './rx-document.ts'; import { runPluginHooks } from './hooks.ts'; import { overwritable } from './overwritable.ts'; import { getFromMapOrCreate } from './plugins/utils/index.ts'; const constructorForCollection = new WeakMap(); export function getDocumentPrototype( rxCollection: RxCollection ): any { const schemaProto = rxCollection.schema.getDocumentPrototype(); const ormProto = getDocumentOrmPrototype(rxCollection); const baseProto = basePrototype; const proto = {}; [ schemaProto, ormProto, baseProto ].forEach(obj => { const props = Object.getOwnPropertyNames(obj); props.forEach(key => { const desc: any = Object.getOwnPropertyDescriptor(obj, key); /** * When enumerable is true, it will show on console dir(instance) * To not pollute the output, only getters and methods are enumerable */ let enumerable = true; if ( key.startsWith('_') || key.endsWith('_') || key.startsWith('$') || key.endsWith('$') ) enumerable = false; if (typeof desc.value === 'function') { // when getting a function, we automatically do a .bind(this) Object.defineProperty(proto, key, { get() { return desc.value.bind(this); }, enumerable, configurable: false }); } else { desc.enumerable = enumerable; desc.configurable = false; if (desc.writable) desc.writable = false; Object.defineProperty(proto, key, desc); } }); }); return proto; } export function getRxDocumentConstructor<RxDocType, ORM>( rxCollection: RxCollection<RxDocType, ORM> ) { return getFromMapOrCreate( constructorForCollection, rxCollection, () => createRxDocumentConstructor( getDocumentPrototype(rxCollection as any) ) ); } /** * Create a RxDocument-instance from the jsonData * and the prototype merge. * You should never call this method directly, * instead you should get the document from collection._docCache.getCachedRxDocument(). */ export function createNewRxDocument<RxDocType, ORM, Reactivity>( rxCollection: RxCollection<RxDocType, ORM, {}, {}, Reactivity>, documentConstructor: any, docData: RxDocumentData<RxDocType> ): RxDocument<RxDocType, ORM, Reactivity> { const doc = createRxDocumentWithConstructor( documentConstructor, rxCollection as any, overwritable.deepFreezeWhenDevMode(docData as any) ); rxCollection._runHooksSync('post', 'create', docData, doc); runPluginHooks('postCreateRxDocument', doc); return doc as any; } /** * returns the prototype-object * that contains the orm-methods, * used in the proto-merge */ export function getDocumentOrmPrototype(rxCollection: RxCollection): any { const proto: any = {}; Object .entries(rxCollection.methods) .forEach(([k, v]) => { proto[k] = v; }); return proto; }