UNPKG

rxdb

Version:

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

93 lines (89 loc) 3.52 kB
import { BehaviorSubject } from 'rxjs'; import { INTERNAL_CONTEXT_COLLECTION, getPrimaryKeyOfInternalDocument } from "../../rx-database-internal-store.js"; import { getPreviousVersions } from "../../rx-schema.js"; import { PROMISE_RESOLVE_FALSE, PROMISE_RESOLVE_NULL, clone, flatClone, getFromMapOrCreate, toPromise } from "../utils/index.js"; export async function getOldCollectionMeta(migrationState) { var collectionDocKeys = getPreviousVersions(migrationState.collection.schema.jsonSchema).map(version => migrationState.collection.name + '-' + version); var found = await migrationState.database.internalStore.findDocumentsById(collectionDocKeys.map(key => getPrimaryKeyOfInternalDocument(key, INTERNAL_CONTEXT_COLLECTION)), false); if (found.length > 1) { throw new Error('more than one old collection meta found'); } return found[0]; } /** * runs the doc-data through all following migrationStrategies * so it will match the newest schema. * @throws Error if final doc does not match final schema or migrationStrategy crashes * @return final object or null if migrationStrategy deleted it */ export function migrateDocumentData(collection, docSchemaVersion, docData) { /** * We cannot deep-clone Blob or Buffer * so we just flat clone it here * and attach it to the deep cloned document data. */ var attachmentsBefore = flatClone(docData._attachments); var mutateableDocData = clone(docData); var meta = mutateableDocData._meta; delete mutateableDocData._meta; mutateableDocData._attachments = attachmentsBefore; var nextVersion = docSchemaVersion + 1; // run the document through migrationStrategies var currentPromise = Promise.resolve(mutateableDocData); var _loop = function () { var version = nextVersion; currentPromise = currentPromise.then(docOrNull => runStrategyIfNotNull(collection, version, docOrNull)); nextVersion++; }; while (nextVersion <= collection.schema.version) { _loop(); } return currentPromise.then(doc => { if (doc === null) { return PROMISE_RESOLVE_NULL; } doc._meta = meta; return doc; }); } export function runStrategyIfNotNull(collection, version, docOrNull) { if (docOrNull === null) { return PROMISE_RESOLVE_NULL; } else { var ret = collection.migrationStrategies[version](docOrNull, collection); var retPromise = toPromise(ret); return retPromise; } } /** * returns true if a migration is needed */ export async function mustMigrate(migrationState) { if (migrationState.collection.schema.version === 0) { return PROMISE_RESOLVE_FALSE; } var oldColDoc = await getOldCollectionMeta(migrationState); return !!oldColDoc; } export var MIGRATION_DEFAULT_BATCH_SIZE = 200; export var DATA_MIGRATION_STATE_SUBJECT_BY_DATABASE = new WeakMap(); export function addMigrationStateToDatabase(migrationState) { var allSubject = getMigrationStateByDatabase(migrationState.database); var allList = allSubject.getValue().slice(0); allList.push(migrationState); allSubject.next(allList); } export function getMigrationStateByDatabase(database) { return getFromMapOrCreate(DATA_MIGRATION_STATE_SUBJECT_BY_DATABASE, database, () => new BehaviorSubject([])); } /** * Complete on database destroy * so people do not have to unsubscribe */ export function onDatabaseDestroy(database) { var subject = DATA_MIGRATION_STATE_SUBJECT_BY_DATABASE.get(database); if (subject) { subject.complete(); } } //# sourceMappingURL=migration-helpers.js.map