@nozbe/watermelondb
Version:
Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast
158 lines (148 loc) • 5.78 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.addColumns = addColumns;
exports.createTable = createTable;
exports.schemaMigrations = schemaMigrations;
exports.unsafeExecuteSql = unsafeExecuteSql;
var _sortBy = _interopRequireDefault(require("../../utils/fp/sortBy"));
var _invariant = _interopRequireDefault(require("../../utils/common/invariant"));
var _isObj = _interopRequireDefault(require("../../utils/fp/isObj"));
var _index = require("../index");
// NOTE: Only require files needed (critical path on web)
// Creates a specification of how to migrate between different versions of
// database schema. Every time you change the database schema, you must
// create a corresponding migration.
//
// See docs for more details
//
// Example:
//
// schemaMigrations({
// migrations: [
// {
// toVersion: 3,
// steps: [
// createTable({
// name: 'comments',
// columns: [
// { name: 'post_id', type: 'string', isIndexed: true },
// { name: 'body', type: 'string' },
// ],
// }),
// addColumns({
// table: 'posts',
// columns: [
// { name: 'subtitle', type: 'string', isOptional: true },
// { name: 'is_pinned', type: 'boolean' },
// ],
// }),
// ],
// },
// {
// toVersion: 2,
// steps: [
// // ...
// ],
// },
// ],
// })
function schemaMigrations(migrationSpec) {
var {
migrations: migrations
} = migrationSpec;
if ('production' !== process.env.NODE_ENV) {
// validate migrations spec object
(0, _invariant.default)(Array.isArray(migrations), 'Missing migrations array');
// validate migrations format
migrations.forEach(function (migration) {
(0, _invariant.default)((0, _isObj.default)(migration), "Invalid migration (not an object) in schema migrations");
var {
toVersion: toVersion,
steps: steps
} = migration;
(0, _invariant.default)('number' === typeof toVersion, 'Invalid migration - `toVersion` must be a number');
(0, _invariant.default)(2 <= toVersion, "Invalid migration to version ".concat(toVersion, ". Minimum possible migration version is 2"));
(0, _invariant.default)(Array.isArray(steps) && steps.every(function (step) {
return 'string' === typeof step.type;
}), "Invalid migration steps for migration to version ".concat(toVersion, ". 'steps' should be an array of migration step calls"));
});
}
// TODO: Force order of migrations?
var sortedMigrations = (0, _sortBy.default)(function (migration) {
return migration.toVersion;
}, migrations);
var oldestMigration = sortedMigrations[0];
var newestMigration = sortedMigrations[sortedMigrations.length - 1];
var minVersion = oldestMigration ? oldestMigration.toVersion - 1 : 1;
var maxVersion = (null === newestMigration || void 0 === newestMigration ? void 0 : newestMigration.toVersion) || 1;
if ('production' !== process.env.NODE_ENV) {
// validate that migration spec is without gaps and duplicates
sortedMigrations.reduce(function (maxCoveredVersion, migration) {
var {
toVersion: toVersion
} = migration;
if (maxCoveredVersion) {
(0, _invariant.default)(toVersion === maxCoveredVersion + 1, "Invalid migrations! Migrations listed cover range from version ".concat(minVersion, " to ").concat(maxCoveredVersion, ", but migration ").concat(JSON.stringify(migration), " is to version ").concat(toVersion, ". Migrations must be listed without gaps, or duplicates."));
}
return toVersion;
}, null);
}
return {
sortedMigrations: sortedMigrations,
minVersion: minVersion,
maxVersion: maxVersion,
validated: true
};
}
function createTable(tableSchemaSpec) {
var schema = (0, _index.tableSchema)(tableSchemaSpec);
return {
type: 'create_table',
schema: schema
};
}
function addColumns({
table: table,
columns: columns,
unsafeSql: unsafeSql
}) {
if ('production' !== process.env.NODE_ENV) {
(0, _invariant.default)(table, "Missing table name in addColumn()");
(0, _invariant.default)(columns && Array.isArray(columns), "Missing 'columns' or not an array in addColumn()");
columns.forEach(function (column) {
return (0, _index.validateColumnSchema)(column);
});
}
return {
type: 'add_columns',
table: table,
columns: columns,
unsafeSql: unsafeSql
};
}
function unsafeExecuteSql(sql) {
if ('production' !== process.env.NODE_ENV) {
(0, _invariant.default)('string' === typeof sql, "SQL passed to unsafeExecuteSql is not a string");
(0, _invariant.default)(sql.trimEnd().endsWith(';'), "SQL passed to unsafeExecuteSql must end with a semicolon (it would work when executed individually but break if multiple migration steps are executed)");
}
return {
type: 'sql',
sql: sql
};
}
/*
TODO: Those types of migrations are currently not implemented. If you need them, feel free to contribute!
// table operations
destroyTable('table_name')
renameTable({ from: 'old_table_name', to: 'new_table_name' })
// column operations
renameColumn({ table: 'table_name', from: 'old_column_name', to: 'new_column_name' })
destroyColumn({ table: 'table_name', column: 'column_name' })
// indexing
addColumnIndex({ table: 'table_name', column: 'column_name' })
removeColumnIndex({ table: 'table_name', column: 'column_name' })
// optionality
makeColumnOptional({ table: 'table_name', column: 'column_name' }) // allows nulls now
makeColumnRequired({ table: 'table_name', column: 'column_name' }) // nulls are changed to null value ('', 0, false)
*/