UNPKG

rxdb

Version:

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

144 lines (130 loc) 4.15 kB
import { newRxError } from '../../rx-error.ts'; import { fillPrimaryKey, getPrimaryFieldOfPrimaryKey } from '../../rx-schema-helper.ts'; import type { BulkWriteRow, RxDocumentData, RxStorageInstance } from '../../types/index.d.ts'; export function ensurePrimaryKeyValid( primaryKey: string, docData: RxDocumentData<any> ) { if (!primaryKey) { throw newRxError('DOC20', { primaryKey, document: docData }); } /** * This is required so that we can left-pad * the primaryKey and we are still able to de-left-pad * it to get again the original key. */ if ( primaryKey !== primaryKey.trim() ) { throw newRxError('DOC21', { primaryKey, document: docData }); } if ( primaryKey.includes('\r') || primaryKey.includes('\n') ) { throw newRxError('DOC22', { primaryKey, document: docData }); } if ( primaryKey.includes('"') ) { throw newRxError('DOC23', { primaryKey, document: docData }); } } /** * Deeply checks if the object contains an * instance of the JavaScript Date class. * @recursive */ export function containsDateInstance(obj: any): boolean { if (typeof obj !== 'object' || obj === null) { return false; } for (let key in obj) { if (obj.hasOwnProperty(key)) { if (obj[key] instanceof Date) { return true; } if (typeof obj[key] === 'object' && containsDateInstance(obj[key])) { return true; } } } return false; } export function checkWriteRows<RxDocType>( storageInstance: RxStorageInstance<RxDocType, any, any, any>, rows: BulkWriteRow<RxDocType>[] ) { const primaryPath = getPrimaryFieldOfPrimaryKey(storageInstance.schema.primaryKey); for (const writeRow of rows) { // ensure that the primary key has not been changed writeRow.document = fillPrimaryKey( primaryPath, storageInstance.schema, writeRow.document ); /** * Ensure that _meta fields have been merged * and not replaced. * This is important so that when one plugin A * sets a _meta field and another plugin B does a write * to the document, it must be ensured that the * field of plugin A was not removed. */ if (writeRow.previous) { Object.keys(writeRow.previous._meta) .forEach(metaFieldName => { if (!Object.prototype.hasOwnProperty.call(writeRow.document._meta, metaFieldName)) { throw newRxError('SNH', { dataBefore: writeRow.previous, dataAfter: writeRow.document, args: { metaFieldName } }); } }); } /** * Ensure it can be structured cloned */ try { /** * Notice that structuredClone() is not available * in ReactNative, so we test for JSON.stringify() instead * @link https://github.com/pubkey/rxdb/issues/5046#issuecomment-1827374498 */ if (typeof structuredClone === 'function') { structuredClone(writeRow); } else { JSON.parse(JSON.stringify(writeRow)); } } catch (err) { throw newRxError('DOC24', { collection: storageInstance.collectionName, document: writeRow.document }); } /** * Ensure it does not contain a Date() object */ if (containsDateInstance(writeRow.document)) { throw newRxError('DOC24', { collection: storageInstance.collectionName, document: writeRow.document }); } } }