UNPKG

rxdb

Version:

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

120 lines (108 loc) 3.54 kB
import type { FilledMangoQuery, MangoQuerySelector, MangoQuerySortPart, RxDocumentData, RxJsonSchema } from '../../types/index.d.ts'; import { Sort as MongoSort } from 'mongodb'; import { RXDB_VERSION, flatClone } from '../utils/index.ts'; import { MongoDBPreparedQuery, MongoQuerySelector } from './mongodb-types.ts'; import { getPrimaryFieldOfPrimaryKey } from '../../rx-schema-helper.ts'; export const RX_STORAGE_NAME_MONGODB = 'mongodb'; export const MONGO_OPTIONS_DRIVER_INFO = { driverInfo: { name: 'RxDB', version: RXDB_VERSION } }; /** * MongoDB uses the _id field by itself (max 12 bytes) * so we have to substitute the _id field if * it is used in the RxDocType. */ export const MONGO_ID_SUBSTITUTE_FIELDNAME = '__id'; export function primarySwapMongoDBQuerySelector<RxDocType>( primaryKey: keyof RxDocType, selector: MangoQuerySelector<RxDocType> ): MongoQuerySelector<RxDocType> { selector = flatClone(selector); if (primaryKey !== '_id') { return selector as any; } if (Array.isArray(selector)) { return selector.map(item => primarySwapMongoDBQuerySelector(primaryKey, item)) as any; } else if (typeof selector === 'object') { const ret: any = {}; Object.entries(selector).forEach(([k, v]) => { if (k === primaryKey) { ret._id = v; } else { if (k.startsWith('$')) { ret[k] = primarySwapMongoDBQuerySelector(primaryKey, v as any); } else { ret[k] = v; } } }); return ret; } else { return selector; } } export function prepareMongoDBQuery<RxDocType>( schema: RxJsonSchema<RxDocumentData<RxDocType>>, mutateableQuery: FilledMangoQuery<RxDocType> ) { const primaryKey = getPrimaryFieldOfPrimaryKey(schema.primaryKey) as any; const preparedQuery: MongoDBPreparedQuery<RxDocType> = { query: mutateableQuery, mongoSelector: primarySwapMongoDBQuerySelector( primaryKey, mutateableQuery.selector ), mongoSort: swapToMongoSort(mutateableQuery.sort) }; return preparedQuery; }; export function swapMongoToRxDoc<RxDocType>( docData: any ): RxDocumentData<RxDocType> { docData = flatClone(docData); if ((docData as any)[MONGO_ID_SUBSTITUTE_FIELDNAME]) { const value = (docData as any)[MONGO_ID_SUBSTITUTE_FIELDNAME]; delete (docData as any)[MONGO_ID_SUBSTITUTE_FIELDNAME]; (docData as any)._id = value; } else { delete (docData as any)._id; } return docData; } export function swapRxDocToMongo<RxDocType>( docData: RxDocumentData<RxDocType> ): any { docData = flatClone(docData); if ((docData as any)._id) { const value = (docData as any)._id; delete (docData as any)._id; (docData as any)[MONGO_ID_SUBSTITUTE_FIELDNAME] = value; } return docData; } export function swapToMongoSort<RxDocType>( sort: MangoQuerySortPart<RxDocType>[] ): MongoSort { const ret: any = {}; sort.forEach(sortPart => { const [key, direction] = Object.entries(sortPart)[0]; const mongoKey = key === '_id' ? MONGO_ID_SUBSTITUTE_FIELDNAME : key; const mongoDirection = direction === 'asc' ? 1 : -1; ret[mongoKey] = mongoDirection; }); return ret; } export function getMongoDBIndexName(index: string[]): string { return index.join('|'); }