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
JavaScript
;
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;