UNPKG

@sqb/connect

Version:

Multi-dialect database connection framework written with TypeScript

89 lines (88 loc) 3.6 kB
import { Insert, Param } from '@sqb/builder'; import { ColumnFieldMetadata } from '../model/column-field-metadata.js'; import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js'; import { EntityMetadata } from '../model/entity-metadata.js'; import { isColumnField, isEmbeddedField } from '../util/orm.helper.js'; export class CreateCommand { // istanbul ignore next constructor() { throw new Error('This class is abstract'); } static async execute(args) { const { entity } = args; const tableName = entity.tableName; if (!tableName) throw new Error(`${entity.ctor.name} is not decorated with @Entity decorator`); // Create a context const ctx = { entity, queryParams: {}, queryValues: {}, colCount: 0, }; // Prepare await this._prepareParams(ctx, entity, args.values); if (!ctx.colCount) throw new Error('No field given to create new entity instance'); const query = Insert(tableName, ctx.queryValues); if (args.returning) { const primaryIndexColumns = EntityMetadata.getPrimaryIndexColumns(entity); if (primaryIndexColumns.length) query.returning(...primaryIndexColumns.map(col => col.fieldName)); } const qr = await args.connection.execute(query, { params: ctx.queryParams, objectRows: false, cursor: false, }); if (args.returning && qr.fields && qr.rows?.length) { const keyValues = {}; for (const f of qr.fields.values()) { const el = EntityMetadata.getColumnFieldByFieldName(entity, f.fieldName); if (el) keyValues[el.name] = qr.rows[0][f.index]; } return keyValues; } } static async _prepareParams(ctx, entity, values, prefix, suffix) { let v; prefix = prefix || ''; suffix = suffix || ''; for (const col of Object.values(entity.fields)) { v = values[col.name]; if (isColumnField(col)) { if (col.noInsert) continue; if (v == null && col.default !== undefined) { v = typeof col.default === 'function' ? col.default(values) : col.default; } if (typeof col.serialize === 'function') v = col.serialize(v, col.name); if (v == null) { if (col.notNull && !col.autoGenerated) { throw new Error(`${entity.name}.${col.name} is required and can't be null`); } continue; } ColumnFieldMetadata.checkEnumValue(col, v); const fieldName = prefix + col.fieldName + suffix; const k = ('I$_' + fieldName).substring(0, 30); ctx.queryValues[fieldName] = Param({ name: k, dataType: col.dataType, isArray: col.isArray, }); ctx.queryParams[k] = v; ctx.colCount++; } else if (v != null && isEmbeddedField(col)) { const type = await EmbeddedFieldMetadata.resolveType(col); await this._prepareParams(ctx, type, v, col.fieldNamePrefix, col.fieldNameSuffix); } } } }