const { isPlainObject } = require('@kitmi/utils');
const FEATURE_NAME = 'logicalDeletion';
/**
* A rule specifies the entity will not be deleted physically.
* @module EntityFeature_LogicalDeletion
*/
/**
* Initialize the feature
* @param {Entity} entity - Entity to apply this feature
* @param {object} options - Field options, can be a string as a new status field or an object reference to a certain status of an existing field
*/
function feature(entity, args = []) {
let newField = true,
fieldInfo = {
name: 'isDeleted',
type: 'boolean',
default: false,
readOnly: true,
autoByDb: true,
},
fieldName,
featureSetting;
let [options] = args;
if (options) {
if (isPlainObject(options)) {
newField = false;
let keys = Object.keys(options);
if (keys.length !== 1) {
throw new Error(`Invalid options for feature "${FEATURE_NAME}".`);
}
let fieldName = keys[0];
featureSetting = {
field: fieldName,
value: options[fieldName],
};
} else if (typeof options === 'string') {
Object.assign(fieldInfo, { name: options });
} else {
throw new Error(`Invalid options for feature "${FEATURE_NAME}".`);
}
}
if (newField) {
fieldName = fieldInfo.name;
let timestampFieldName = 'deletedAt';
let deletedTimestamp = {
type: 'datetime',
readOnly: true,
optional: true,
writeOnce: true,
auto: 'now',
};
entity.addFeature(FEATURE_NAME, {
field: fieldName,
value: true,
timestampField: timestampFieldName,
});
entity.once('afterAddingFields', () => {
entity.addField(fieldName, fieldInfo);
entity.addField(timestampFieldName, deletedTimestamp);
});
} else {
entity.addFeature(FEATURE_NAME, featureSetting);
entity.once('afterAddingFields', () => {
if (!entity.hasField(featureSetting.field)) {
throw new Error(
`Field "${featureSetting.field}" used by feature "${FEATURE_NAME}" is not found in entity "${entity.name}".`
);
}
});
}
}
module.exports = feature;