UNPKG

claire-framework

Version:

- được viết bằng TypeScript - hỗ trợ websocket và HTTP request - hỗ trợ CLI để generate base project (claire-cli)

218 lines 15.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ModelMetadata_1 = require("./ModelMetadata"); const DataType_1 = require("../enum/DataType"); const FieldValidationMetadata_1 = require("../validator/FieldValidationMetadata"); const core_1 = require("../decorator/core"); /** * Init the model prototype of the class if not exist. * @param prototype class object prototype. */ const init_class_sql_prototype = (prototype) => { if (!prototype[core_1.METADATA]) { prototype[core_1.METADATA] = new ModelMetadata_1.ModelMetadata(); } return prototype[core_1.METADATA]; }; const getReflectDataType = (prototype, propertyKey) => { let t = Reflect.getMetadata("design:type", prototype, propertyKey); if (t) { switch (t.name) { case "Boolean": return DataType_1.DataType.BOOL; case "Number": return DataType_1.DataType.INTEGER; case "String": return DataType_1.DataType.STRING; case "Array": return DataType_1.DataType.ARRAY; default: return DataType_1.DataType.TEXT; } } return undefined; }; /** * Init the logic field of the class if not exist or append properties to the existed field. * @param prototype class object prototype. * @param propertyKey logic name of the field. * @param addedProperties the overriding properties. */ exports.check_for_field = (prototype, propertyKey, addedProperties) => { let meta = init_class_sql_prototype(prototype); let field = meta.getFieldByLogicName(propertyKey); if (!field) { field = new FieldValidationMetadata_1.FieldValidationMetadata(); field.fieldLogicName = propertyKey; let dataType = getReflectDataType(prototype, propertyKey); if (dataType) { field.dataType = dataType; } meta.addField(field); } else { Object.assign(field, addedProperties); } Object.assign(field, addedProperties); return field; }; /** * Mark a field of the model having a corresponding logic 'getter/setter' name. * @param fieldLogicName the logic name of the field */ exports.GetSet = (fieldLogicName) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { getSetField: fieldLogicName }); }; }; /** * Mark a field of the model as the data field, which will be used to store the data. * @param fieldDataName name of the field in the database table. * @param innerDataType explicit data type to support the database engine. */ exports.DataField = (fieldDataName, innerDataType) => { return (prototype, propertyKey) => { let addedProperties = {}; if (fieldDataName) { addedProperties.fieldDataName = fieldDataName; } if (innerDataType) { addedProperties.innerDataType = innerDataType; } let field = exports.check_for_field(prototype, propertyKey, addedProperties); //-- data field should be not nullable, but can be overwritten by other decorators if (field.nullable === undefined) { field.nullable = false; } }; }; /** * Mark a field of the model as primary key. If autoInc is true, the field is auto incremental. * @param autoInc whether the key is auto-incremented. */ exports.PrimaryKey = (autoInc) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isPrimaryKey: true, isAutoIncrement: autoInc, nullable: false }); }; }; /** * Mark a field of the model as foreign key. The referred model must be supplied. * @param model the model to refer of which this field is primary key. */ exports.ForeignKey = (model) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isForeignKey: true, referModel: model && model.name }); }; }; /** * Mark the field with unique constraint. */ exports.Unique = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isUnique: true }); }; }; /** * Mark the field with can-be-null constraint. */ exports.Optional = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { nullable: true }); }; }; /** * Mark the field with can-not-be-null constraint. */ exports.Required = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { nullable: false }); }; }; /** * Default value of the field. * @param value the default value. */ exports.DefaultValue = (value) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { defaultValue: value }); }; }; /** * Mark the field as auto-generated. This field can be populate from the business logic but from the user. */ exports.AutoGen = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isAutoGen: true }); }; }; exports.IsFile = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isFile: true }); }; }; /** * Add description meta info for this field. * @param comment the field description info. */ exports.Comment = (comment) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { description: comment }); }; }; /** * Mark the model that validation should be checked. * @constructor */ exports.Validate = () => { return (constructor) => { let modelMetaData = init_class_sql_prototype(constructor.prototype); modelMetaData.needValidate = true; return constructor; }; }; exports.Range = (from, to) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { inRange: { from, to } }); }; }; exports.InSet = (set) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { inSet: set }); }; }; exports.SubSet = (set, allowEmpty = true) => { return (prototype, propertyKey) => { exports.IsArray(allowEmpty)(prototype, propertyKey); exports.check_for_field(prototype, propertyKey, { subSet: set }); }; }; exports.Match = (regex) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { match: regex }); }; }; exports.IsInteger = () => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { isInteger: true }); }; }; exports.IsArray = (allowEmpty = true) => { return (prototype, propertyKey) => { let field = exports.check_for_field(prototype, propertyKey, { allowEmptyArray: allowEmpty }); if (field.dataType && !field.innerDataType) { field.innerDataType = field.dataType; } field.dataType = DataType_1.DataType.ARRAY; }; }; exports.GreaterThan = (value) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { greaterThan: value }); }; }; exports.LessThan = (value) => { return (prototype, propertyKey) => { exports.check_for_field(prototype, propertyKey, { lessThan: value }); }; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGFibGVNYXBwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvbW9kZWwvVGFibGVNYXBwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSxtREFBOEM7QUFDOUMsK0NBQTBDO0FBQzFDLGtGQUE2RTtBQUM3RSw0Q0FBMkM7QUFFM0M7OztHQUdHO0FBQ0gsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLFNBQWMsRUFBaUIsRUFBRTtJQUMvRCxJQUFJLENBQUMsU0FBUyxDQUFDLGVBQVEsQ0FBQyxFQUFFO1FBQ3RCLFNBQVMsQ0FBQyxlQUFRLENBQUMsR0FBRyxJQUFJLDZCQUFhLEVBQUUsQ0FBQztLQUM3QztJQUNELE9BQU8sU0FBUyxDQUFDLGVBQVEsQ0FBQyxDQUFDO0FBQy9CLENBQUMsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxTQUFjLEVBQUUsV0FBbUIsRUFBd0IsRUFBRTtJQUNyRixJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxTQUFTLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDbkUsSUFBSSxDQUFDLEVBQUU7UUFDSCxRQUFRLENBQUMsQ0FBQyxJQUFJLEVBQUU7WUFDWixLQUFLLFNBQVM7Z0JBQ1YsT0FBTyxtQkFBUSxDQUFDLElBQUksQ0FBQztZQUN6QixLQUFLLFFBQVE7Z0JBQ1QsT0FBTyxtQkFBUSxDQUFDLE9BQU8sQ0FBQztZQUM1QixLQUFLLFFBQVE7Z0JBQ1QsT0FBTyxtQkFBUSxDQUFDLE1BQU0sQ0FBQztZQUMzQixLQUFLLE9BQU87Z0JBQ1IsT0FBTyxtQkFBUSxDQUFDLEtBQUssQ0FBQztZQUMxQjtnQkFDSSxPQUFPLG1CQUFRLENBQUMsSUFBSSxDQUFDO1NBQzVCO0tBQ0o7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNyQixDQUFDLENBQUM7QUFFRjs7Ozs7R0FLRztBQUNVLFFBQUEsZUFBZSxHQUFHLENBQUMsU0FBYyxFQUFFLFdBQW1CLEVBQUUsZUFB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