| 
									
										
										
										
											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, | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |     defaultTo: null, | 
					
						
							|  |  |  |     notNullable: false, | 
					
						
							|  |  |  |     unsigned: false, | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     ...opts, | 
					
						
							|  |  |  |     ...(attribute.column || {}), | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const createTable = (meta) => { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |   const table = { | 
					
						
							|  |  |  |     name: meta.tableName, | 
					
						
							|  |  |  |     indexes: meta.indexes || [], | 
					
						
							|  |  |  |     foreignKeys: meta.foreignKeys || [], | 
					
						
							|  |  |  |     columns: [], | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-05 19:44:58 +02:00
										 |  |  |   for (const key of Object.keys(meta.attributes)) { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     const attribute = meta.attributes[key]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (types.isRelation(attribute.type)) { | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |       if (attribute.morphColumn && attribute.owner) { | 
					
						
							|  |  |  |         const { idColumn, typeColumn } = attribute.morphColumn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         table.columns.push( | 
					
						
							|  |  |  |           createColumn(idColumn.name, { | 
					
						
							|  |  |  |             type: 'integer', | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |             column: { | 
					
						
							|  |  |  |               unsigned: true, | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |           }) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |         table.columns.push(createColumn(typeColumn.name, { type: 'string' })); | 
					
						
							| 
									
										
										
										
											2021-07-26 17:52:59 +02:00
										 |  |  |       } else if (attribute.joinColumn && attribute.owner) { | 
					
						
							|  |  |  |         // NOTE: we could pass uniquness for oneToOne to avoid creating more than one to one
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |         const { name: columnName, referencedColumn, referencedTable } = attribute.joinColumn; | 
					
						
							| 
									
										
										
										
											2021-07-30 20:45:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |         const column = createColumn(columnName, { | 
					
						
							|  |  |  |           type: 'integer', | 
					
						
							|  |  |  |           column: { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |             unsigned: true, | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |           }, | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         table.columns.push(column); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         table.foreignKeys.push({ | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |           name: `${table.name}_${columnName}_fk`, | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |           columns: [columnName], | 
					
						
							|  |  |  |           referencedTable, | 
					
						
							|  |  |  |           referencedColumns: [referencedColumn], | 
					
						
							| 
									
										
										
										
											2021-08-10 09:36:02 +02:00
										 |  |  |           // NOTE: could allow configuration
 | 
					
						
							|  |  |  |           onDelete: 'SET NULL', | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-09-16 11:37:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         table.indexes.push({ | 
					
						
							|  |  |  |           name: `${table.name}_${columnName}_fk`, | 
					
						
							|  |  |  |           columns: [columnName], | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-09-22 10:49:43 +02:00
										 |  |  |     } else if (types.isScalar(attribute.type)) { | 
					
						
							|  |  |  |       const column = createColumn(attribute.columnName || key, attribute); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       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
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  | const getColumnType = (attribute) => { | 
					
						
							| 
									
										
										
										
											2021-06-02 15:53:22 +02:00
										 |  |  |   if (attribute.columnType) { | 
					
						
							|  |  |  |     return attribute.columnType; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (attribute.type) { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     case 'increments': { | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |       return { | 
					
						
							|  |  |  |         type: 'increments', | 
					
						
							| 
									
										
										
										
											2022-03-22 19:41:16 +01:00
										 |  |  |         args: [{ primary: true, primaryKey: true }], | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |         notNullable: true, | 
					
						
							|  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     // 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-12-09 12:31:52 -07:00
										 |  |  |     case 'string': | 
					
						
							|  |  |  |     case 'enumeration': { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |       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 'integer': { | 
					
						
							|  |  |  |       return { type: 'integer' }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'biginteger': { | 
					
						
							|  |  |  |       return { type: 'bigInteger' }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'float': { | 
					
						
							| 
									
										
										
										
											2021-09-16 14:04:10 +02:00
										 |  |  |       return { type: 'double' }; | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     case 'decimal': { | 
					
						
							|  |  |  |       return { type: 'decimal', args: [10, 2] }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'date': { | 
					
						
							|  |  |  |       return { type: 'date' }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'time': { | 
					
						
							|  |  |  |       return { type: 'time', args: [{ precision: 3 }] }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'datetime': { | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         type: 'datetime', | 
					
						
							|  |  |  |         args: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             useTz: false, | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |             precision: 6, | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'timestamp': { | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         type: 'timestamp', | 
					
						
							|  |  |  |         args: [ | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |             useTz: false, | 
					
						
							| 
									
										
										
										
											2021-09-15 12:25:09 +02:00
										 |  |  |             precision: 6, | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |           }, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case 'boolean': { | 
					
						
							|  |  |  |       return { type: 'boolean' }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: { | 
					
						
							| 
									
										
										
										
											2021-12-22 19:59:03 +05:30
										 |  |  |       throw new Error(`Unknown type ${attribute.type}`); | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-02 15:53:22 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-08 23:33:39 +02:00
										 |  |  |   metadata.forEach((metadata) => { | 
					
						
							| 
									
										
										
										
											2021-06-17 16:17:15 +02:00
										 |  |  |     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 }; |