197 lines
4.5 KiB
JavaScript
Raw Normal View History

2021-06-02 15:53:22 +02:00
'use strict';
2021-06-17 16:17:15 +02:00
const types = require('../types');
const createColumn = (name, attribute) => {
const { type, args = [], ...opts } = getColumnType(attribute);
return {
name,
type,
args,
...opts,
...(attribute.column || {}),
// TODO: allow passing custom params to the DB from the model definition
};
};
const shouldCreateColumn = attribute => {
return types.isScalar(attribute.type);
};
const createTable = meta => {
const table = {
// TODO: allow passing custom params to the DB from the model definition
name: meta.tableName,
indexes: meta.indexes || [],
foreignKeys: meta.foreignKeys || [],
columns: [],
};
// TODO: handle indexes
// TODO: handle foreignKeys
for (const key in meta.attributes) {
const attribute = meta.attributes[key];
// TODO: if relation & has a joinColumn -> create it
if (types.isRelation(attribute.type)) {
2021-06-23 15:37:20 +02:00
if (attribute.joinColumn && attribute.owner) {
// TODO: pass uniquness for oneToOne to avoid create more than one to one
2021-06-17 16:17:15 +02:00
const { name: columnName, referencedColumn, referencedTable } = attribute.joinColumn;
table.columns.push(
createColumn(columnName, {
type: 'integer',
unsigned: true,
})
);
table.foreignKeys.push({
// TODO: generate a name
name: `${columnName}_fk`,
columns: [columnName],
referencedTable,
referencedColumns: [referencedColumn],
onDelete: 'SET NULL', // NOTE: could allow ocnifguration
});
}
} else if (shouldCreateColumn(attribute)) {
// TODO: if column is unique then add a unique index outside so we can easily do the diff
const column = createColumn(key, meta.attributes[key]);
if (column.unique) {
table.indexes.push({
2021-06-02 15:53:22 +02:00
type: 'unique',
2021-06-17 16:17:15 +02:00
name: `${table.name}_${column.name}_unique`,
columns: [column.name],
});
}
if (column.primary) {
table.indexes.push({
2021-06-02 15:53:22 +02:00
type: 'primary',
2021-06-17 16:17:15 +02:00
name: `${table.name}_${column.name}_primary`,
columns: [column.name],
});
}
table.columns.push(column);
}
}
return table;
2021-06-02 15:53:22 +02:00
};
const getColumnType = attribute => {
if (attribute.columnType) {
return attribute.columnType;
}
switch (attribute.type) {
2021-06-17 16:17:15 +02:00
case 'increments': {
return { type: 'increments', args: [{ primary: true }] };
}
// We might want to convert email/password to string types before going into the orm with specific validators & transformers
2021-06-02 15:53:22 +02:00
case 'password':
case 'email':
2021-06-17 16:17:15 +02:00
case 'string': {
return { type: 'string' };
}
case 'uid': {
return {
type: 'string',
unique: true,
};
}
case 'richtext':
case 'text': {
return {
type: 'text',
args: ['longtext'],
};
}
case 'json': {
2021-06-29 16:27:35 +02:00
return { type: 'jsonb' };
2021-06-17 16:17:15 +02:00
}
case 'enumeration': {
2021-06-17 19:51:35 +02:00
return {
type: 'enum',
args: [
attribute.enum /*,{ useNative: true, existingType: true, enumName: 'foo_type', schemaName: 'public' }*/,
],
};
2021-06-17 16:17:15 +02:00
}
case 'integer': {
return { type: 'integer' };
}
case 'biginteger': {
return { type: 'bigInteger' };
}
// TODO: verify usage of double vs float
case 'float': {
return { type: 'double', args: [] };
}
// TODO: define precision
case 'decimal': {
return { type: 'decimal', args: [10, 2] };
}
case 'date': {
return { type: 'date' };
}
// TODO: define precision
case 'time': {
return { type: 'time', args: [{ precision: 3 }] };
}
case 'datetime': {
return {
type: 'datetime',
args: [
{
useTz: false,
precision: 6, // TODO: to define
},
],
};
}
// TODO: handle defaults
case 'timestamp': {
return {
type: 'timestamp',
args: [
{
useTz: false,
precision: 6, // TODO: to define
},
],
};
}
case 'boolean': {
return { type: 'boolean' };
}
default: {
throw new Error(`Unknow type ${attribute.type}`);
}
2021-06-02 15:53:22 +02:00
}
};
const metadataToSchema = metadata => {
2021-06-17 16:17:15 +02:00
const schema = {
tables: [],
addTable(table) {
this.tables.push(table);
return this;
},
};
2021-06-02 15:53:22 +02:00
2021-06-17 16:17:15 +02:00
metadata.forEach(metadata => {
schema.addTable(createTable(metadata));
});
2021-06-02 15:53:22 +02:00
2021-06-17 16:17:15 +02:00
return schema;
2021-06-02 15:53:22 +02:00
};
2021-06-17 16:17:15 +02:00
module.exports = { metadataToSchema, createTable };