@webdocgroup/realm-migrations
Version:
Realm DB migration service for React Native
128 lines (127 loc) • 4.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RealmMigrationService = void 0;
const realm_1 = __importDefault(require("realm"));
const shouldRunMigrationsHook_1 = require("../HookPipelines/shouldRunMigrationsHook");
const Enabled_1 = require("../Hooks/Enabled");
class RealmMigrationService {
constructor({ databaseName, migrations, hooks = {}, enabled = true, }) {
this.migrations = [];
this.databaseName = databaseName;
this.migrations = migrations;
this.hooks = hooks;
this.enabled = enabled;
}
currentSchemaVersion() {
const dbPath = `${this.databaseName}.realm`;
const currentSchemaVersion = realm_1.default.schemaVersion(dbPath);
return currentSchemaVersion;
}
latestMigrationVersion() {
return this.migrations.length;
}
nextSchemaVersion() {
const currentSchemaVersion = this.currentSchemaVersion();
const nextSchemaVersion = currentSchemaVersion + 1;
if (this.migrations[nextSchemaVersion]) {
return nextSchemaVersion;
}
return currentSchemaVersion;
}
shouldRun({ currentVersion, latestMigrationVersion, }) {
return (0, shouldRunMigrationsHook_1.shouldRunMigrationsHook)({
props: {
currentVersion,
latestMigrationVersion,
},
hooks: [
(0, Enabled_1.enabled)({ enabled: this.enabled }),
...(this.hooks.shouldRunMigrations
? this.hooks.shouldRunMigrations
: []),
],
callback: () => {
return currentVersion < latestMigrationVersion;
},
});
}
/**
* Derives the schemas for a given version by combining all migrations
* up to that version.
*
* @param version The version to derive schemas for.
*
* @returns An array of schemas that represent the state of the database
* at the specified version.
*/
derriveSchemas(version) {
const migrationsForVersion = this.migrations.slice(0, version);
const schemasByName = migrationsForVersion.reduce((schemasByName, migration) => {
const schemasByNameInMigration = migration.schemas.reduce((acc, schema) => {
return { ...acc, [schema.name]: schema };
}, {});
return { ...schemasByName, ...schemasByNameInMigration };
}, {});
return Object.values(schemasByName);
}
migrationsToRun() {
const currentSchemaVersion = Math.max(0, this.currentSchemaVersion() - 1);
return this.migrations
.map((migration, index) => ({
...migration,
version: index + 1,
}))
.slice(currentSchemaVersion, this.migrations.length);
}
run() {
const currentVersion = this.currentSchemaVersion();
const latestMigrationVersion = this.latestMigrationVersion();
if (!this.shouldRun({ currentVersion, latestMigrationVersion })) {
console.info('No migrations to run', {
currentVersion,
latestMigrationVersion,
});
return {
schema: this.derriveSchemas(currentVersion),
schemaVersion: currentVersion,
};
}
const migrations = this.migrationsToRun();
let latestMigratedSchemas = [];
let schemaVersion = -1;
console.info(`Running ${migrations.length} migrations`, {
currentVersion,
latestMigrationVersion,
});
migrations.forEach((migration) => {
console.info(`Running migration: ${migration.description}`, {
migrationVersion: migration.version,
schemaCount: migration.schemas.length,
});
const derivedSchema = this.derriveSchemas(migration.version);
console.info('Derived schemas for migration', {
count: derivedSchema.length,
});
const migrated = new realm_1.default({
path: `${this.databaseName}.realm`,
onMigration: migration.migrate,
schema: derivedSchema,
schemaVersion: migration.version,
});
migrated.close();
latestMigratedSchemas = derivedSchema;
schemaVersion = migration.version;
});
console.info('Migrations completed', {
currentSchemaVersion: this.currentSchemaVersion(),
});
return {
schema: latestMigratedSchemas,
schemaVersion,
};
}
}
exports.RealmMigrationService = RealmMigrationService;