UNPKG

pure-orm

Version:

A SQL Toolkit based on pure business objects passed to and from stateful data access objects

195 lines (194 loc) 8.24 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.create = void 0; const core_1 = require("./core"); const pgp_1 = require("./driver-integrations/pgp"); const create = ({ entities: externalEntities, db, logError }) => { const core = (0, core_1.createCore)({ entities: externalEntities }); let orm; if (db.$config.pgp) { orm = (0, pgp_1.createForPGP)({ core, db, logError }); } else { throw new Error(`You're database driver is not yet supported. You can make a PR to add it, or use the \`createCore\` export which doesn't try to abstract over the database driver, and instead you pass the results of the database driver queries to it.`); } /* ------------------------------------------------------------------------*/ /* Helper Utilities for CRUD functions ------------------------------------*/ /* ------------------------------------------------------------------------*/ const getSqlInsertParts = (model) => { const columns = orm .getEntityByModel(model) .columnNames.filter((column, index) => model[orm.getEntityByModel(model).propertyNames[index]] !== void 0) .map((col) => `"${col}"`) .join(', '); const values = orm .getEntityByModel(model) .propertyNames.map((property) => model[property]) .filter((value) => value !== void 0); const valuesVar = values.map((value, index) => `$${index + 1}`); return { columns, values, valuesVar }; }; const getSqlUpdateParts = (model, on = 'id') => { const clauseArray = orm .getEntityByModel(model) .columnNames.filter((sqlColumn, index) => model[orm.getEntityByModel(model).propertyNames[index]] !== void 0) .map((sqlColumn, index) => `"${sqlColumn}" = $${index + 1}`); const clause = clauseArray.join(', '); const idVar = `$${clauseArray.length + 1}`; const _values = orm .getEntityByModel(model) .propertyNames.map((property) => model[property]) .filter((value) => value !== void 0); const values = [..._values, model[on]]; return { clause, idVar, values }; }; const getMatchingParts = (model) => { const whereClause = orm .getEntityByModel(model) .propertyNames.map((property, index) => model[property] != null ? `"${orm.getEntityByModel(model).tableName}"."${orm.getEntityByModel(model).columnNames[index]}"` : null) .filter((x) => x != null) .map((x, i) => `${x} = $${i + 1}`) .join(' AND '); const values = orm .getEntityByModel(model) .propertyNames.map((property) => model[property] != null ? model[property] : null) .filter((x) => x != null); return { whereClause, values }; }; // This one returns an object, which allows it to be more versatile. // To-do: make this one even better and use it instead of the one above. const getMatchingPartsObject = (model) => { const whereClause = orm .getEntityByModel(model) .propertyNames.map((property, index) => model[property] != null ? `"${orm.getEntityByModel(model).tableName}"."${orm.getEntityByModel(model).columnNames[index]}"` : null) .filter((x) => x != null) .map((x, i) => `${x} = $(${i + 1})`) .join(' AND '); const values = orm .getEntityByModel(model) .propertyNames.map((property) => model[property] != null ? model[property] : null) .filter((x) => x != null) .reduce((accum, val, index) => Object.assign({}, accum, { [index + 1]: val }), {}); return { whereClause, values }; }; const getNewWith = (model, sqlColumns, values) => { const Constructor = model.constructor; const modelKeys = sqlColumns.map((key) => orm.getEntityByModel(model).propertyNames[orm.getEntityByModel(model).columnNames.indexOf(key)]); const modelData = modelKeys.reduce((data, key, index) => { data[key] = values[index]; return data; }, {}); return new Constructor(modelData); }; const getValueBySqlColumn = (model, sqlColumn) => { return model[orm.getEntityByModel(model).propertyNames[orm.getEntityByModel(model).columnNames.indexOf(sqlColumn)]]; }; const getSqlColumnForPropertyName = (model, propertyName) => { return orm.getEntityByModel(model).columnNames[orm.getEntityByModel(model).propertyNames.indexOf(propertyName)]; }; /* ------------------------------------------------------------------------*/ /* Built-in basic CRUD functions ------------------------------------------*/ /* ------------------------------------------------------------------------*/ // Standard create const create = (model) => { const { columns, values, valuesVar } = getSqlInsertParts(model); const query = ` INSERT INTO "${orm.getEntityByModel(model).tableName}" ( ${columns} ) VALUES ( ${valuesVar} ) RETURNING ${orm.getEntityByModel(model).selectColumnsClause}; `; return orm.one(query, values); }; // Standard update const update = (model, { on = 'id' } = {}) => { const { clause, idVar, values } = getSqlUpdateParts(model, on); const query = ` UPDATE "${orm.getEntityByModel(model).tableName}" SET ${clause} WHERE "${orm.getEntityByModel(model).tableName}".${getSqlColumnForPropertyName(model, on)} = ${idVar} RETURNING ${orm.getEntityByModel(model).selectColumnsClause}; `; return orm.one(query, values); }; // Standard delete const _delete = (model) => { const id = model.id; const query = ` DELETE FROM "${orm.getEntityByModel(model).tableName}" WHERE "${orm.getEntityByModel(model).tableName}".id = $(id) `; return orm.none(query, { id }); }; const deleteMatching = (model) => { const { whereClause, values } = getMatchingParts(model); const query = ` DELETE FROM "${orm.getEntityByModel(model).tableName}" WHERE ${whereClause}; `; return orm.none(query, values); }; const getMatching = (model) => { const { whereClause, values } = getMatchingParts(model); const query = ` SELECT ${orm.getEntityByModel(model).selectColumnsClause} FROM "${orm.getEntityByModel(model).tableName}" WHERE ${whereClause}; `; return orm.one(query, values); }; const getOneOrNoneMatching = (model) => { const { whereClause, values } = getMatchingParts(model); const query = ` SELECT ${orm.getEntityByModel(model).selectColumnsClause} FROM "${orm.getEntityByModel(model).tableName}" WHERE ${whereClause}; `; return orm.oneOrNone(query, values); }; const getAnyMatching = (model) => { const { whereClause, values } = getMatchingParts(model); const query = ` SELECT ${orm.getEntityByModel(model).selectColumnsClause} FROM "${orm.getEntityByModel(model).tableName}" WHERE ${whereClause}; `; return orm.any(query, values); }; const getAllMatching = (model) => { const { whereClause, values } = getMatchingParts(model); const query = ` SELECT ${orm.getEntityByModel(model).selectColumnsClause} FROM "${orm.getEntityByModel(model).tableName}" WHERE ${whereClause}; `; return orm.many(query, values); }; return Object.assign({}, orm, { // Built-in basic CRUD functions create, update, delete: _delete, deleteMatching, getMatching, getOneOrNoneMatching, getAnyMatching, getAllMatching, // Helper Utility functions getSqlInsertParts, getSqlUpdateParts, getMatchingParts, getMatchingPartsObject, getNewWith, getValueBySqlColumn, getSqlColumnForPropertyName }); }; exports.create = create;