126 lines
2.8 KiB
JavaScript
Raw Normal View History

2021-06-02 15:53:22 +02:00
'use strict';
const { metadataToSchema } = require('./schema');
module.exports = db => {
const getSchemaBuilder = table => {
return table.schema ? db.connection.schema.withSchema(table.schema) : db.connection.schema;
};
const createColumn = (tableBuilder, column) => {
const { type, name, args = [], defaultTo, primary, unsigned, unique, notNullable } = column;
const col = tableBuilder[type](name, ...args);
// primary key auto increment
// TODO:: set index name
if (primary) {
col.primary();
}
if (unsigned) {
col.unsigned();
}
if (defaultTo) {
// allow some raw default values
col.defaultTo(...[].concat(defaultTo));
}
if (unique) {
// TODO:: set index name
col.unique();
}
if (notNullable) {
col.notNullable();
} else {
col.nullable();
}
return col;
};
const createIndex = (tableBuilder, index) => {
const { type, columns, name } = index;
switch (type) {
case 'primary': {
return tableBuilder.primary(columns, name);
}
case 'unique': {
return tableBuilder.unique(columns, name);
}
default: {
return tableBuilder.index(columns, name, type);
}
}
};
const createForeignKey = (tableBuilder, foreignKey) => {
const { name, column, referencedColumn, referencedTable, onDelete, onUpdate } = foreignKey;
const constraint = tableBuilder
.foreign(column, name)
.references(referencedColumn)
.inTable(referencedTable);
if (onDelete) {
constraint.onDelete(onDelete);
}
if (onUpdate) {
constraint.onUpdate(onUpdate);
}
};
const createTable = table => {
const schemaBuilder = getSchemaBuilder(table);
return schemaBuilder.createTable(table.name, tableBuilder => {
// columns
(table.columns || []).forEach(column => createColumn(tableBuilder, column));
//indexes
(table.indexes || []).forEach(index => createIndex(tableBuilder, index));
// foreign keys
(table.foreignKeys || []).forEach(foreignKey => createForeignKey(tableBuilder, foreignKey));
});
};
const dropTable = table => {
return getSchemaBuilder(table).dropTableIfExists(table.name);
};
const createSchema = async metadata => {
// TODO: ensure database exists;
const schema = metadataToSchema(metadata);
for (const table of schema.tables) {
await createTable(table);
}
};
const dropSchema = async (metadata, { dropDatabase = false } = {}) => {
if (dropDatabase) {
// TODO: drop database & return as it will drop everything
}
const schema = metadataToSchema(metadata);
for (const table of schema.tables.reverse()) {
await dropTable(table);
}
};
return {
createSchema,
dropSchema,
updateSchema() {},
createTable,
dropTable,
};
};