@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
126 lines (125 loc) • 5.53 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.hashOnCreateUpdate = hashOnCreateUpdate;
exports.hash = hash;
exports.composedFromCreateUpdate = composedFromCreateUpdate;
exports.composedFromKeys = composedFromKeys;
exports.composed = composed;
exports.versionCreateUpdate = versionCreateUpdate;
exports.version = version;
const constants_1 = require("./constants.cjs");
const reflection_1 = require("@decaf-ts/reflection");
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
const decorators_1 = require("../operations/decorators.cjs");
const errors_1 = require("../repository/errors.cjs");
const Repository_1 = require("../repository/Repository.cjs");
const operations_1 = require("../operations/index.cjs");
/**
*
* @param {str} str
* @memberOf db-decorators.model
*/
function hashOnCreateUpdate(data, key, model, oldModel) {
if (!model[key])
return;
const hash = decorator_validation_1.Hashing.hash(model[key]);
if (oldModel && model[key] === hash)
return;
model[key] = hash;
}
function hash() {
return (0, reflection_1.apply)((0, decorators_1.onCreateUpdate)(hashOnCreateUpdate), (0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.HASH), {}));
}
function composedFromCreateUpdate(context, data, key, model) {
try {
const { args, type, prefix, suffix, separator } = data;
const composed = args.map((arg) => {
if (!(arg in model))
throw new errors_1.InternalError((0, decorator_validation_1.sf)("Property {0} not found to compose from", arg));
if (type === "keys")
return arg;
if (typeof model[arg] === "undefined")
throw new errors_1.InternalError((0, decorator_validation_1.sf)("Property {0} does not contain a value to compose from", arg));
return model[arg].toString();
});
if (prefix)
composed.unshift(prefix);
if (suffix)
composed.push(suffix);
model[key] = composed.join(separator);
}
catch (e) {
throw new errors_1.InternalError(`Failed to compose value: ${e}`);
}
}
function composedFrom(args, hashResult = false, separator = constants_1.DefaultSeparator, type = "values", prefix = "", suffix = "") {
const data = {
args: args,
hashResult: hashResult,
separator: separator,
type: type,
prefix: prefix,
suffix: suffix,
};
const decorators = [
(0, decorators_1.onCreateUpdate)(composedFromCreateUpdate, data),
(0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.COMPOSED), data),
];
if (hashResult)
decorators.push(hash());
return (0, reflection_1.apply)(...decorators);
}
function composedFromKeys(args, separator = constants_1.DefaultSeparator, hash = false, prefix = "", suffix = "") {
return composedFrom(args, hash, separator, "keys", prefix, suffix);
}
function composed(args, separator = constants_1.DefaultSeparator, hash = false, prefix = "", suffix = "") {
return composedFrom(args, hash, separator, "values", prefix, suffix);
}
/**
* Creates a decorator function that updates the version of a model during create or update operations.
*
* @param {CrudOperations} operation - The type of operation being performed (CREATE or UPDATE).
* @returns {function} A function that updates the version of the model based on the operation type.
*
* @template M - Type extending Model
* @template V - Type extending IRepository<M>
*
* @this {V} - The repository instance
* @param {Context<M>} context - The context of the operation
* @param {unknown} data - Additional data for the operation (not used in this function)
* @param {string} key - The key of the version property in the model
* @param {M} model - The model being updated
* @throws {InternalError} If an invalid operation is provided or if version update fails
*/
function versionCreateUpdate(operation) {
return function versionCreateUpdate(context, data, key, model) {
try {
switch (operation) {
case operations_1.OperationKeys.CREATE:
model[key] = 1;
break;
case operations_1.OperationKeys.UPDATE:
model[key]++;
break;
default:
throw new errors_1.InternalError(`Invalid operation: ${operation}`);
}
}
catch (e) {
throw new errors_1.InternalError(`Failed to update version: ${e}`);
}
};
}
/**
* @description Creates a decorator for versioning a property in a model.
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations.
*
* @returns {Function} A composite decorator that:
* - Sets the type of the property to Number
* - Applies a version update on create operations
* - Applies a version update on update operations
* - Adds metadata indicating this property is used for versioning
*/
function version() {
return (0, reflection_1.apply)((0, decorator_validation_1.type)(Number.name), (0, decorators_1.onCreate)(versionCreateUpdate(operations_1.OperationKeys.CREATE)), (0, decorators_1.onUpdate)(versionCreateUpdate(operations_1.OperationKeys.UPDATE)), (0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.VERSION), true));
}