@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
227 lines (226 loc) • 8.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.readonly = readonly;
exports.timestampHandler = timestampHandler;
exports.timestamp = timestamp;
exports.serializeOnCreateUpdate = serializeOnCreateUpdate;
exports.serializeAfterAll = serializeAfterAll;
exports.serialize = serialize;
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
const constants_1 = require("../model/constants.cjs");
const constants_2 = require("./constants.cjs");
const constants_3 = require("../operations/constants.cjs");
const decorators_1 = require("../operations/decorators.cjs");
const errors_1 = require("../repository/errors.cjs");
const reflection_1 = require("@decaf-ts/reflection");
const repository_1 = require("../repository/index.cjs");
/**
* Marks the property as readonly.
*
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES.READONLY.INVALID}
*
* @decorator readonly
*
* @category Decorators
*/
function readonly(message = constants_2.DEFAULT_ERROR_MESSAGES.READONLY.INVALID) {
return (0, decorator_validation_1.propMetadata)(decorator_validation_1.Validation.updateKey(constants_1.DBKeys.READONLY), {
message: message,
});
}
async function timestampHandler(context, data, key, model) {
model[key] = context.timestamp;
}
/**
* Marks the property as timestamp.
* Makes it {@link required}
* Makes it a {@link date}
*
* Date Format:
*
* <pre>
* Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java),
* I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify.
* You can display date, time, AM/PM, etc.
*
* Date and Time Patterns
* yy = 2-digit year; yyyy = full year
* M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
* EEEE = full weekday name; EEE = short weekday name
* d = digit day; dd = 2-digit day
* h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
* m = minutes; mm = 2-digit minutes; aaa = AM/PM
* s = seconds; ss = 2-digit seconds
* S = miliseconds
* </pre>
*
* @param {string[]} operation The {@link DBOperations} to act on. Defaults to {@link DBOperations.CREATE_UPDATE}
* @param {string} [format] The TimeStamp format. defaults to {@link DEFAULT_TIMESTAMP_FORMAT}
* @param {{new: UpdateValidator}} [validator] defaults to {@link TimestampValidator}
*
* @decorator timestamp
*
* @category Decorators
*/
function timestamp(operation = constants_3.DBOperations.CREATE_UPDATE, format = constants_1.DEFAULT_TIMESTAMP_FORMAT) {
const decorators = [
(0, decorator_validation_1.date)(format, constants_2.DEFAULT_ERROR_MESSAGES.TIMESTAMP.DATE),
(0, decorator_validation_1.required)(constants_2.DEFAULT_ERROR_MESSAGES.TIMESTAMP.REQUIRED),
(0, decorators_1.on)(operation, timestampHandler),
];
if (operation.indexOf(constants_3.OperationKeys.UPDATE) !== -1)
decorators.push((0, decorator_validation_1.propMetadata)(decorator_validation_1.Validation.updateKey(constants_1.DBKeys.TIMESTAMP), {
message: constants_2.DEFAULT_ERROR_MESSAGES.TIMESTAMP.INVALID,
}));
return (0, reflection_1.apply)(...decorators);
}
async function serializeOnCreateUpdate(data, key, model, oldModel) {
if (!model[key])
return;
try {
model[key] = JSON.stringify(model[key]);
}
catch (e) {
throw new errors_1.SerializationError((0, decorator_validation_1.sf)("Failed to serialize {0} property on {1} model: {2}", key, model.constructor.name, e.message));
}
}
async function serializeAfterAll(data, key, model) {
if (!model[key])
return;
if (typeof model[key] !== "string")
return;
try {
model[key] = JSON.parse(model[key]);
}
catch (e) {
throw new errors_1.SerializationError((0, decorator_validation_1.sf)("Failed to deserialize {0} property on {1} model: {2}", key, model.constructor.name, e.message));
}
}
/**
* @summary Serialize Decorator
* @description properties decorated will the serialized before stored in the db
*
* @function serialize
*
* @memberOf module:wallet-db.Decorators
*/
function serialize() {
return (0, reflection_1.apply)((0, decorators_1.onCreateUpdate)(serializeOnCreateUpdate), (0, decorators_1.after)(constants_3.DBOperations.ALL, serializeAfterAll), (0, decorator_validation_1.type)([String.name, Object.name]), (0, reflection_1.metadata)(repository_1.Repository.key(constants_1.DBKeys.SERIALIZE), {}));
}
//
// /**
// * @summary One To One relation Decorators
// *
// * @param {Constructor<any>} clazz the {@link Sequence} to use. Defaults to {@link NoneSequence}
// * @param {CascadeMetadata} [cascadeOptions]
// * @param {boolean} _populate If true, replaces the specified key in the document with the corresponding record from the database
// *
// * @function onToOne
// *
// * @memberOf module:wallet-db.Decorators
// *
// * @see oneToMany
// * @see manyToOne
// */
// export function oneToOne(
// clazz: Constructor<any>,
// cascadeOptions: CascadeMetadata = DefaultCascade,
// _populate: boolean = true,
// ) {
// Model.register(clazz);
// return (target: any, propertyKey: string) => {
// type([clazz.name, String.name])(target, propertyKey);
// onCreate(oneToOneOnCreate)(target, propertyKey);
// onUpdate(oneToOneOnUpdate, cascadeOptions as any)(target, propertyKey);
// onDelete(oneToOneOnDelete, cascadeOptions)(target, propertyKey);
//
// afterCreate(populate, _populate)(target, propertyKey);
// afterUpdate(populate, _populate)(target, propertyKey);
// afterRead(populate, _populate)(target, propertyKey);
// afterDelete(populate, _populate)(target, propertyKey);
//
// Reflect.defineMetadata(
// getDBKey(WalletDbKeys.ONE_TO_ONE),
// {
// constructor: clazz.name,
// cascade: cascadeOptions,
// populate: _populate,
// },
// target,
// propertyKey,
// );
// };
// }
//
// /**
// * @summary One To Many relation Decorators
// *
// * @param {Constructor<any>} clazz the {@link Sequence} to use. Defaults to {@link NoneSequence}
// * @param {CascadeMetadata} [cascadeOptions]
// *
// * @function onToMany
// *
// * @memberOf module:wallet-db.Decorators
// *
// * @see oneToOne
// * @see manyToOne
// */
// export function oneToMany(
// clazz: Constructor<any>,
// cascadeOptions: CascadeMetadata = DefaultCascade,
// _populate: boolean = true,
// ) {
// Model.register(clazz);
// return (target: any, propertyKey: string) => {
// list([clazz, String])(target, propertyKey);
// onCreate(oneToManyOnCreate)(target, propertyKey);
// onUpdate(oneToManyOnUpdate, cascadeOptions)(target, propertyKey);
// onDelete(oneToManyOnDelete, cascadeOptions)(target, propertyKey);
//
// afterCreate(populate, _populate)(target, propertyKey);
// afterUpdate(populate, _populate)(target, propertyKey);
// afterRead(populate, _populate)(target, propertyKey);
// afterDelete(populate, _populate)(target, propertyKey);
//
// Reflect.defineMetadata(
// getDBKey(WalletDbKeys.ONE_TO_MANY),
// {
// constructor: clazz.name,
// cascade: cascadeOptions,
// },
// target,
// propertyKey,
// );
// };
// }
//
// /**
// * @summary Many To One relation Decorators
// *
// * @param {Constructor<any>} clazz the {@link Sequence} to use. Defaults to {@link NoneSequence}
// * @param {CascadeMetadata} [cascadeOptions]
// *
// * @function manyToOne
// *
// * @memberOf module:wallet-db.Decorators
// *
// * @see oneToMany
// * @see oneToOne
// */
// export function manyToOne(
// clazz: Constructor<any>,
// cascadeOptions: CascadeMetadata = DefaultCascade,
// ) {
// Model.register(clazz);
// return (target: any, propertyKey: string) => {
// Reflect.defineMetadata(
// getDBKey(WalletDbKeys.MANY_TO_ONE),
// {
// constructor: clazz.name,
// cascade: cascadeOptions,
// },
// target,
// propertyKey,
// );
// };
// }