@decaf-ts/decorator-validation 1.5.5 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/dist/decorator-validation.js +1 -1
  2. package/dist/esm/decorator-validation.js +1 -1
  3. package/lib/esm/index.d.ts +1 -1
  4. package/lib/esm/index.js +1 -3
  5. package/lib/esm/model/Model.js +0 -2
  6. package/lib/esm/model/ModelErrorDefinition.js +0 -2
  7. package/lib/esm/model/Registry.js +0 -2
  8. package/lib/esm/model/constants.js +0 -2
  9. package/lib/esm/model/construction.js +0 -2
  10. package/lib/esm/model/decorators.js +0 -2
  11. package/lib/esm/model/index.js +0 -2
  12. package/lib/esm/model/types.js +0 -2
  13. package/lib/esm/model/utils.js +0 -2
  14. package/lib/esm/model/validation.js +0 -2
  15. package/lib/esm/utils/constants.js +0 -2
  16. package/lib/esm/utils/dates.js +0 -2
  17. package/lib/esm/utils/decorators.js +0 -2
  18. package/lib/esm/utils/hashing.js +0 -2
  19. package/lib/esm/utils/index.js +0 -2
  20. package/lib/esm/utils/registry.js +0 -2
  21. package/lib/esm/utils/serialization.js +0 -2
  22. package/lib/esm/utils/strings.js +0 -2
  23. package/lib/esm/validation/Validation.js +0 -2
  24. package/lib/esm/validation/Validators/DateValidator.js +0 -2
  25. package/lib/esm/validation/Validators/EmailValidator.js +0 -2
  26. package/lib/esm/validation/Validators/ListValidator.js +0 -2
  27. package/lib/esm/validation/Validators/MaxLengthValidator.js +0 -2
  28. package/lib/esm/validation/Validators/MaxValidator.js +0 -2
  29. package/lib/esm/validation/Validators/MinLengthValidator.js +0 -2
  30. package/lib/esm/validation/Validators/MinValidator.js +0 -2
  31. package/lib/esm/validation/Validators/PasswordValidator.js +0 -2
  32. package/lib/esm/validation/Validators/PatternValidator.js +0 -2
  33. package/lib/esm/validation/Validators/RequiredValidator.js +0 -2
  34. package/lib/esm/validation/Validators/StepValidator.js +0 -2
  35. package/lib/esm/validation/Validators/TypeValidator.js +0 -2
  36. package/lib/esm/validation/Validators/URLValidator.js +0 -2
  37. package/lib/esm/validation/Validators/Validator.js +0 -2
  38. package/lib/esm/validation/Validators/ValidatorRegistry.js +0 -2
  39. package/lib/esm/validation/Validators/constants.js +0 -2
  40. package/lib/esm/validation/Validators/decorators.js +0 -2
  41. package/lib/esm/validation/Validators/index.js +0 -2
  42. package/lib/esm/validation/Validators/types.js +0 -2
  43. package/lib/esm/validation/decorators.js +0 -2
  44. package/lib/esm/validation/index.js +0 -2
  45. package/lib/esm/validation/types.js +0 -2
  46. package/lib/index.d.ts +1 -1
  47. package/lib/index.js +59 -0
  48. package/lib/model/Model.js +300 -0
  49. package/lib/model/ModelErrorDefinition.js +56 -0
  50. package/lib/model/Registry.js +78 -0
  51. package/lib/model/constants.js +72 -0
  52. package/lib/model/construction.js +68 -0
  53. package/lib/model/decorators.js +67 -0
  54. package/lib/{validation/index.cjs → model/index.js} +9 -6
  55. package/lib/model/types.js +2 -0
  56. package/lib/model/utils.js +29 -0
  57. package/lib/model/validation.js +138 -0
  58. package/lib/utils/constants.js +30 -0
  59. package/lib/utils/dates.js +251 -0
  60. package/lib/utils/decorators.js +22 -0
  61. package/lib/utils/hashing.js +106 -0
  62. package/lib/utils/index.js +23 -0
  63. package/lib/utils/registry.js +2 -0
  64. package/lib/utils/serialization.js +93 -0
  65. package/lib/utils/strings.js +35 -0
  66. package/lib/validation/Validation.js +75 -0
  67. package/lib/validation/Validators/DateValidator.js +57 -0
  68. package/lib/validation/Validators/EmailValidator.js +53 -0
  69. package/lib/validation/Validators/ListValidator.js +70 -0
  70. package/lib/validation/Validators/MaxLengthValidator.js +55 -0
  71. package/lib/validation/Validators/MaxValidator.js +60 -0
  72. package/lib/validation/Validators/MinLengthValidator.js +55 -0
  73. package/lib/validation/Validators/MinValidator.js +60 -0
  74. package/lib/validation/Validators/PasswordValidator.js +53 -0
  75. package/lib/validation/Validators/PatternValidator.js +73 -0
  76. package/lib/validation/Validators/RequiredValidator.js +60 -0
  77. package/lib/validation/Validators/StepValidator.js +55 -0
  78. package/lib/validation/Validators/TypeValidator.js +63 -0
  79. package/lib/validation/Validators/URLValidator.js +52 -0
  80. package/lib/validation/Validators/Validator.js +51 -0
  81. package/lib/validation/Validators/ValidatorRegistry.js +85 -0
  82. package/lib/validation/Validators/constants.js +137 -0
  83. package/lib/validation/Validators/decorators.js +28 -0
  84. package/lib/validation/Validators/index.js +69 -0
  85. package/lib/validation/Validators/types.js +2 -0
  86. package/lib/validation/decorators.js +304 -0
  87. package/lib/validation/index.js +20 -0
  88. package/lib/validation/types.js +2 -0
  89. package/package.json +1 -1
  90. package/lib/index.cjs +0 -61
  91. package/lib/model/Model.cjs +0 -302
  92. package/lib/model/ModelErrorDefinition.cjs +0 -58
  93. package/lib/model/Registry.cjs +0 -80
  94. package/lib/model/constants.cjs +0 -74
  95. package/lib/model/construction.cjs +0 -70
  96. package/lib/model/decorators.cjs +0 -69
  97. package/lib/model/index.cjs +0 -27
  98. package/lib/model/types.cjs +0 -4
  99. package/lib/model/utils.cjs +0 -31
  100. package/lib/model/validation.cjs +0 -140
  101. package/lib/utils/constants.cjs +0 -32
  102. package/lib/utils/dates.cjs +0 -253
  103. package/lib/utils/decorators.cjs +0 -24
  104. package/lib/utils/hashing.cjs +0 -108
  105. package/lib/utils/index.cjs +0 -25
  106. package/lib/utils/registry.cjs +0 -4
  107. package/lib/utils/serialization.cjs +0 -95
  108. package/lib/utils/strings.cjs +0 -37
  109. package/lib/validation/Validation.cjs +0 -77
  110. package/lib/validation/Validators/DateValidator.cjs +0 -59
  111. package/lib/validation/Validators/EmailValidator.cjs +0 -55
  112. package/lib/validation/Validators/ListValidator.cjs +0 -72
  113. package/lib/validation/Validators/MaxLengthValidator.cjs +0 -57
  114. package/lib/validation/Validators/MaxValidator.cjs +0 -62
  115. package/lib/validation/Validators/MinLengthValidator.cjs +0 -57
  116. package/lib/validation/Validators/MinValidator.cjs +0 -62
  117. package/lib/validation/Validators/PasswordValidator.cjs +0 -55
  118. package/lib/validation/Validators/PatternValidator.cjs +0 -75
  119. package/lib/validation/Validators/RequiredValidator.cjs +0 -62
  120. package/lib/validation/Validators/StepValidator.cjs +0 -57
  121. package/lib/validation/Validators/TypeValidator.cjs +0 -65
  122. package/lib/validation/Validators/URLValidator.cjs +0 -54
  123. package/lib/validation/Validators/Validator.cjs +0 -53
  124. package/lib/validation/Validators/ValidatorRegistry.cjs +0 -87
  125. package/lib/validation/Validators/constants.cjs +0 -139
  126. package/lib/validation/Validators/decorators.cjs +0 -30
  127. package/lib/validation/Validators/index.cjs +0 -71
  128. package/lib/validation/Validators/types.d.ts +0 -88
  129. package/lib/validation/decorators.cjs +0 -306
  130. package/lib/validation/types.cjs +0 -4
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.model = model;
4
+ exports.hashedBy = hashedBy;
5
+ exports.serializedBy = serializedBy;
6
+ const construction_1 = require("./construction");
7
+ const constants_1 = require("../utils/constants");
8
+ const Model_1 = require("./Model");
9
+ const reflection_1 = require("@decaf-ts/reflection");
10
+ /**
11
+ * @summary Defines a class as a Model class
12
+ * @description
13
+ *
14
+ * - Registers the class under the model registry so it can be easily rebuilt;
15
+ * - Overrides the class constructor;
16
+ * - Runs the global {@link ModelBuilderFunction} if defined;
17
+ * - Runs the optional {@link InstanceCallback} if provided;
18
+ *
19
+ * @param {InstanceCallback} [instanceCallback] optional callback that will be called with the instance upon instantiation. defaults to undefined
20
+ *
21
+ * @function model
22
+ *
23
+ * @memberOf module:decorator-validation.Model
24
+ *
25
+ */
26
+ function model(instanceCallback) {
27
+ return ((original) => {
28
+ // the new constructor behaviour
29
+ const newConstructor = function (...args) {
30
+ const instance = (0, construction_1.construct)(original, ...args);
31
+ (0, construction_1.bindModelPrototype)(instance);
32
+ // run a builder function if defined with the first argument (The ModelArg)
33
+ const builder = Model_1.Model.getBuilder();
34
+ if (builder)
35
+ builder(instance, args.length ? args[0] : undefined);
36
+ (0, reflection_1.metadata)(Model_1.Model.key(constants_1.ModelKeys.MODEL), original.name)(instance.constructor);
37
+ if (instanceCallback)
38
+ instanceCallback(instance, ...args);
39
+ return instance;
40
+ };
41
+ // copy prototype so instanceof operator still works
42
+ newConstructor.prototype = original.prototype;
43
+ // Sets the proper constructor name for type verification
44
+ Object.defineProperty(newConstructor, "name", {
45
+ writable: false,
46
+ enumerable: true,
47
+ configurable: false,
48
+ value: original.prototype.constructor.name,
49
+ });
50
+ (0, reflection_1.metadata)(Model_1.Model.key(constants_1.ModelKeys.MODEL), original.name)(original);
51
+ Model_1.Model.register(newConstructor, original.name);
52
+ // return new constructor (will override original)
53
+ return newConstructor;
54
+ });
55
+ }
56
+ function hashedBy(algorithm, ...args) {
57
+ return (0, reflection_1.metadata)(Model_1.Model.key(constants_1.ModelKeys.HASHING), {
58
+ algorithm: algorithm,
59
+ args: args,
60
+ });
61
+ }
62
+ function serializedBy(serializer, ...args) {
63
+ return (0, reflection_1.metadata)(Model_1.Model.key(constants_1.ModelKeys.SERIALIZATION), {
64
+ serializer: serializer,
65
+ args: args,
66
+ });
67
+ }
@@ -14,9 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./Validators/index.cjs"), exports);
18
- __exportStar(require("./decorators.cjs"), exports);
19
- __exportStar(require("./types.cjs"), exports);
20
- __exportStar(require("./Validation.cjs"), exports);
21
-
22
- //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy92YWxpZGF0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBNkI7QUFDN0IsK0NBQTZCO0FBQzdCLDBDQUF3QjtBQUN4QiwrQ0FBNkIiLCJmaWxlIjoidmFsaWRhdGlvbi9pbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL1ZhbGlkYXRvcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL3R5cGVzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9WYWxpZGF0aW9uXCI7XG4iXX0=
17
+ __exportStar(require("./constants"), exports);
18
+ __exportStar(require("./construction"), exports);
19
+ __exportStar(require("./decorators"), exports);
20
+ __exportStar(require("./Model"), exports);
21
+ __exportStar(require("./ModelErrorDefinition"), exports);
22
+ __exportStar(require("./Registry"), exports);
23
+ __exportStar(require("./types"), exports);
24
+ __exportStar(require("./utils"), exports);
25
+ __exportStar(require("./validation"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPropertyModel = isPropertyModel;
4
+ exports.isModel = isModel;
5
+ const constants_1 = require("../utils/constants");
6
+ const Model_1 = require("./Model");
7
+ function isPropertyModel(target, attribute) {
8
+ if (isModel(target[attribute]))
9
+ return true;
10
+ const metadata = Reflect.getMetadata(constants_1.ModelKeys.TYPE, target, attribute);
11
+ return Model_1.Model.get(metadata.name) ? metadata.name : undefined;
12
+ }
13
+ /**
14
+ * @summary For Serialization/deserialization purposes.
15
+ * @description Reads the {@link ModelKeys.ANCHOR} property of a {@link Model} to discover the class to instantiate
16
+ *
17
+ * @function isModel
18
+ * @memberOf module:decorator-validation.Validation
19
+ * @category Validation
20
+ */
21
+ function isModel(target) {
22
+ try {
23
+ return target instanceof Model_1.Model || !!Model_1.Model.getMetadata(target);
24
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
25
+ }
26
+ catch (e) {
27
+ return false;
28
+ }
29
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validate = validate;
4
+ const ModelErrorDefinition_1 = require("./ModelErrorDefinition");
5
+ const reflection_1 = require("@decaf-ts/reflection");
6
+ const constants_1 = require("../utils/constants");
7
+ const strings_1 = require("../utils/strings");
8
+ const constants_2 = require("./constants");
9
+ const Validation_1 = require("../validation/Validation");
10
+ const constants_3 = require("../validation/Validators/constants");
11
+ const utils_1 = require("./utils");
12
+ /**
13
+ * @summary Analyses the decorations of the properties and validates the obj according to them
14
+ *
15
+ * @typedef T extends Model
16
+ * @prop {T} obj Model object to validate
17
+ * @prop {string[]} [propsToIgnore] object properties to ignore in the validation
18
+ *
19
+ * @function validate
20
+ * @memberOf module:decorator-validation.Validation
21
+ * @category Validation
22
+ */
23
+ function validate(obj, ...propsToIgnore) {
24
+ const decoratedProperties = [];
25
+ for (const prop in obj)
26
+ if (Object.prototype.hasOwnProperty.call(obj, prop) &&
27
+ propsToIgnore.indexOf(prop) === -1)
28
+ decoratedProperties.push(reflection_1.Reflection.getPropertyDecorators(constants_3.ValidationKeys.REFLECT, obj, prop));
29
+ let result = undefined;
30
+ for (const decoratedProperty of decoratedProperties) {
31
+ const { prop, decorators } = decoratedProperty;
32
+ if (!decorators || !decorators.length)
33
+ continue;
34
+ const defaultTypeDecorator = decorators[0];
35
+ // tries to find any type decorators or other decorators that already enforce type (the ones with the allowed types property defined). if so, skip the default type verification
36
+ if (decorators.find((d) => {
37
+ if (d.key === constants_3.ValidationKeys.TYPE)
38
+ return true;
39
+ return !!d.props.types?.find((t) => t === defaultTypeDecorator.props.name);
40
+ })) {
41
+ decorators.shift(); // remove the design:type decorator, since the type will already be checked
42
+ }
43
+ let errs = undefined;
44
+ for (const decorator of decorators) {
45
+ const validator = Validation_1.Validation.get(decorator.key);
46
+ if (!validator) {
47
+ throw new Error(`Missing validator for ${decorator.key}`);
48
+ }
49
+ const decoratorProps = decorator.key === constants_1.ModelKeys.TYPE
50
+ ? [decorator.props]
51
+ : (decorator.props || {});
52
+ const err = validator.hasErrors(obj[prop.toString()], decoratorProps);
53
+ if (err) {
54
+ errs = errs || {};
55
+ errs[decorator.key] = err;
56
+ }
57
+ }
58
+ if (errs) {
59
+ result = result || {};
60
+ result[decoratedProperty.prop.toString()] = errs;
61
+ }
62
+ }
63
+ // tests nested classes
64
+ for (const prop of Object.keys(obj).filter((k) => !result || !result[k])) {
65
+ let err;
66
+ // if a nested Model
67
+ const allDecorators = reflection_1.Reflection.getPropertyDecorators(constants_3.ValidationKeys.REFLECT, obj, prop).decorators;
68
+ const decorators = reflection_1.Reflection.getPropertyDecorators(constants_3.ValidationKeys.REFLECT, obj, prop).decorators.filter((d) => [constants_1.ModelKeys.TYPE, constants_3.ValidationKeys.TYPE].indexOf(d.key) !== -1);
69
+ if (!decorators || !decorators.length)
70
+ continue;
71
+ const dec = decorators.pop();
72
+ const clazz = dec.props.name
73
+ ? [dec.props.name]
74
+ : Array.isArray(dec.props.customTypes)
75
+ ? dec.props.customTypes
76
+ : [dec.props.customTypes];
77
+ const reserved = Object.values(constants_2.ReservedModels).map((v) => v.toLowerCase());
78
+ for (const c of clazz) {
79
+ if (reserved.indexOf(c.toLowerCase()) === -1) {
80
+ const typeDecoratorKey = Array.isArray(obj[prop])
81
+ ? constants_3.ValidationKeys.LIST
82
+ : constants_3.ValidationKeys.TYPE;
83
+ const types = allDecorators.find((d) => d.key === typeDecoratorKey) || {};
84
+ let allowedTypes = [];
85
+ if (types && types.props) {
86
+ const customTypes = Array.isArray(obj[prop])
87
+ ? types.props.class
88
+ : types.props.customTypes;
89
+ if (customTypes)
90
+ allowedTypes = Array.isArray(customTypes)
91
+ ? customTypes.map((t) => `${t}`.toLowerCase())
92
+ : [customTypes.toLowerCase()];
93
+ }
94
+ const validate = (prop, value) => {
95
+ if (typeof value === "object" || typeof value === "function")
96
+ return (0, utils_1.isModel)(value)
97
+ ? value.hasErrors()
98
+ : allowedTypes.includes(typeof value)
99
+ ? undefined
100
+ : "Value has no validatable type";
101
+ };
102
+ switch (c) {
103
+ case Array.name:
104
+ case Set.name:
105
+ if (allDecorators.length) {
106
+ const listDec = allDecorators.find((d) => d.key === constants_3.ValidationKeys.LIST);
107
+ if (listDec) {
108
+ err = (c === Array.name
109
+ ? obj[prop]
110
+ : // If it's a Set
111
+ obj[prop].values())
112
+ .map((v) => validate(prop, v))
113
+ .filter((e) => !!e);
114
+ if (!err?.length) {
115
+ // if the result is an empty list...
116
+ err = undefined;
117
+ }
118
+ }
119
+ }
120
+ break;
121
+ default:
122
+ try {
123
+ if (obj[prop])
124
+ err = validate(prop, obj[prop]);
125
+ }
126
+ catch (e) {
127
+ console.warn((0, strings_1.sf)("Model should be validatable but its not: " + e));
128
+ }
129
+ }
130
+ }
131
+ if (err) {
132
+ result = result || {};
133
+ result[prop] = err;
134
+ }
135
+ }
136
+ }
137
+ return result ? new ModelErrorDefinition_1.ModelErrorDefinition(result) : undefined;
138
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModelKeys = void 0;
4
+ /**
5
+ * @summary Defines the various Model keys used for reflection
6
+ *
7
+ * @property {string} REFLECT prefix to all other keys
8
+ * @property {string} TYPE type key
9
+ * @property {string} PARAMS method params key
10
+ * @property {string} RETURN method return key
11
+ * @property {string} MODEL model key
12
+ * @property {string} ANCHOR anchor key. will serve as a ghost property in the model
13
+ *
14
+ * @constant ModelKeys
15
+ * @memberOf module:decorator-validation.Model
16
+ * @category Model
17
+ */
18
+ var ModelKeys;
19
+ (function (ModelKeys) {
20
+ ModelKeys["REFLECT"] = "decaf.model.";
21
+ ModelKeys["TYPE"] = "design:type";
22
+ ModelKeys["PARAMS"] = "design:paramtypes";
23
+ ModelKeys["RETURN"] = "design:returntype";
24
+ ModelKeys["MODEL"] = "model";
25
+ ModelKeys["ANCHOR"] = "__model";
26
+ ModelKeys["CONSTRUCTION"] = "constructed-by";
27
+ ModelKeys["ATTRIBUTE"] = "__attributes";
28
+ ModelKeys["HASHING"] = "hashing";
29
+ ModelKeys["SERIALIZATION"] = "serialization";
30
+ })(ModelKeys || (exports.ModelKeys = ModelKeys = {}));
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dateFromFormat = dateFromFormat;
4
+ exports.bindDateToString = bindDateToString;
5
+ exports.isValidDate = isValidDate;
6
+ exports.twoDigitPad = twoDigitPad;
7
+ exports.formatDate = formatDate;
8
+ exports.parseDate = parseDate;
9
+ require("reflect-metadata");
10
+ const constants_1 = require("../validation/Validators/constants");
11
+ const strings_1 = require("./strings");
12
+ /**
13
+ * @summary Reverses the process from {@link formatDate}
14
+ *
15
+ * @param {string} date the date string to be converted back into date
16
+ * @param {string} format the date format
17
+ * @return {Date} the date from the format or the standard new Date({@prop date}) if the string couldn't be parsed (are you sure the format matches the string?)
18
+ *
19
+ * @function dateFromFormat
20
+ * @memberOf module:decorator-validation.Utils.Dates
21
+ * @category Format
22
+ */
23
+ function dateFromFormat(date, format) {
24
+ let formatRegexp = format;
25
+ // Hour
26
+ if (formatRegexp.match(/hh/))
27
+ formatRegexp = formatRegexp.replace("hh", "(?<hour>\\d{2})");
28
+ else if (formatRegexp.match(/h/))
29
+ formatRegexp = formatRegexp.replace("h", "(?<hour>\\d{1,2})");
30
+ else if (formatRegexp.match(/HH/))
31
+ formatRegexp = formatRegexp.replace("HH", "(?<hour>\\d{2})");
32
+ else if (formatRegexp.match(/H/))
33
+ formatRegexp = formatRegexp.replace("H", "(?<hour>\\d{1,2})");
34
+ // Minutes
35
+ if (formatRegexp.match(/mm/))
36
+ formatRegexp = formatRegexp.replace("mm", "(?<minutes>\\d{2})");
37
+ else if (formatRegexp.match(/m/))
38
+ formatRegexp = formatRegexp.replace("m", "(?<minutes>\\d{1,2})");
39
+ // Seconds
40
+ if (formatRegexp.match(/ss/))
41
+ formatRegexp = formatRegexp.replace("ss", "(?<seconds>\\d{2})");
42
+ else if (formatRegexp.match(/s/))
43
+ formatRegexp = formatRegexp.replace("s", "(?<seconds>\\d{1,2})");
44
+ // Day
45
+ if (formatRegexp.match(/dd/))
46
+ formatRegexp = formatRegexp.replace("dd", "(?<day>\\d{2})");
47
+ else if (formatRegexp.match(/d/))
48
+ formatRegexp = formatRegexp.replace("d", "(?<day>\\d{1,2})");
49
+ // Day Of Week
50
+ if (formatRegexp.match(/EEEE/))
51
+ formatRegexp = formatRegexp.replace("EEEE", "(?<dayofweek>\\w+)");
52
+ // eslint-disable-next-line no-dupe-else-if
53
+ else if (formatRegexp.match(/EEEE/))
54
+ formatRegexp = formatRegexp.replace("EEE", "(?<dayofweek>\\w+)");
55
+ // Year
56
+ if (formatRegexp.match(/yyyy/))
57
+ formatRegexp = formatRegexp.replace("yyyy", "(?<year>\\d{4})");
58
+ else if (formatRegexp.match(/yy/))
59
+ formatRegexp = formatRegexp.replace("yy", "(?<year>\\d{2})");
60
+ // Month
61
+ if (formatRegexp.match(/MMMM/))
62
+ formatRegexp = formatRegexp.replace("MMMM", "(?<monthname>\\w+)");
63
+ else if (formatRegexp.match(/MMM/))
64
+ formatRegexp = formatRegexp.replace("MMM", "(?<monthnamesmall>\\w+)");
65
+ if (formatRegexp.match(/MM/))
66
+ formatRegexp = formatRegexp.replace("MM", "(?<month>\\d{2})");
67
+ else if (formatRegexp.match(/M/))
68
+ formatRegexp = formatRegexp.replace("M", "(?<month>\\d{1,2})");
69
+ // Milis and Am Pm
70
+ formatRegexp = formatRegexp
71
+ .replace("S", "(?<milis>\\d{1,3})")
72
+ .replace("aaa", "(?<ampm>\\w{2})");
73
+ const regexp = new RegExp(formatRegexp, "g");
74
+ const match = regexp.exec(date);
75
+ if (!match || !match.groups)
76
+ return new Date(date);
77
+ const safeParseInt = function (n) {
78
+ if (!n)
79
+ return 0;
80
+ const result = parseInt(n);
81
+ return isNaN(result) ? 0 : result;
82
+ };
83
+ const year = safeParseInt(match.groups.year);
84
+ const day = safeParseInt(match.groups.day);
85
+ const amPm = match.groups.ampm;
86
+ let hour = safeParseInt(match.groups.hour);
87
+ if (amPm)
88
+ hour = amPm === "PM" ? hour + 12 : hour;
89
+ const minutes = safeParseInt(match.groups.minutes);
90
+ const seconds = safeParseInt(match.groups.seconds);
91
+ const ms = safeParseInt(match.groups.milis);
92
+ const monthName = match.groups.monthname;
93
+ const monthNameSmall = match.groups.monthnamesmall;
94
+ let month = match.groups.month;
95
+ if (monthName)
96
+ month = constants_1.MONTH_NAMES.indexOf(monthName);
97
+ else if (monthNameSmall) {
98
+ const m = constants_1.MONTH_NAMES.find((m) => m.toLowerCase().startsWith(monthNameSmall.toLowerCase()));
99
+ if (!m)
100
+ return new Date(date);
101
+ month = constants_1.MONTH_NAMES.indexOf(m);
102
+ }
103
+ else
104
+ month = safeParseInt(`${month}`);
105
+ return new Date(year, month - 1, day, hour, minutes, seconds, ms);
106
+ }
107
+ /**
108
+ * @summary Binds a date format to a string
109
+ * @param {Date} [date]
110
+ * @param {string} [format]
111
+ * @memberOf module:decorator-validation.Utils.Format
112
+ * @category Utilities
113
+ */
114
+ function bindDateToString(date, format) {
115
+ if (!date)
116
+ return;
117
+ const func = () => formatDate(date, format);
118
+ Object.defineProperty(date, "toISOString", {
119
+ enumerable: false,
120
+ configurable: false,
121
+ value: func,
122
+ });
123
+ Object.defineProperty(date, "toString", {
124
+ enumerable: false,
125
+ configurable: false,
126
+ value: func,
127
+ });
128
+ // Object.setPrototypeOf(date, Date.prototype);
129
+ return date;
130
+ }
131
+ /**
132
+ * @summary Helper function to be used instead of instanceOf Date
133
+ * @param date
134
+ * @memberOf module:decorator-validation.Utils.Dates
135
+ * @category Validation
136
+ */
137
+ function isValidDate(date) {
138
+ return (date &&
139
+ Object.prototype.toString.call(date) === "[object Date]" &&
140
+ !Number.isNaN(date));
141
+ }
142
+ /**
143
+ * @summary Util function to pad numbers
144
+ * @param {number} num
145
+ *
146
+ * @return {string}
147
+ *
148
+ * @function twoDigitPad
149
+ * @memberOf module:decorator-validation.Utils.Format
150
+ * @category Format
151
+ */
152
+ function twoDigitPad(num) {
153
+ return num < 10 ? "0" + num : num.toString();
154
+ }
155
+ /**
156
+ * @summary Date Format Handling
157
+ * @description Code from {@link https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date}
158
+ *
159
+ * <pre>
160
+ * Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java),
161
+ * I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify.
162
+ * You can display date, time, AM/PM, etc.
163
+ *
164
+ * Date and Time Patterns
165
+ * yy = 2-digit year; yyyy = full year
166
+ * M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
167
+ * EEEE = full weekday name; EEE = short weekday name
168
+ * d = digit day; dd = 2-digit day
169
+ * h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
170
+ * m = minutes; mm = 2-digit minutes; aaa = AM/PM
171
+ * s = seconds; ss = 2-digit seconds
172
+ * S = miliseconds
173
+ * </pre>
174
+ *
175
+ * @param {Date} date
176
+ * @param {string} [patternStr] defaults to 'yyyy/MM/dd'
177
+ * @return {string} the formatted date
178
+ *
179
+ * @function formatDate
180
+ * @memberOf module:decorator-validation.Utils.Dates
181
+ * @category Format
182
+ */
183
+ function formatDate(date, patternStr = "yyyy/MM/dd") {
184
+ const day = date.getDate(), month = date.getMonth(), year = date.getFullYear(), hour = date.getHours(), minute = date.getMinutes(), second = date.getSeconds(), miliseconds = date.getMilliseconds(), h = hour % 12, hh = twoDigitPad(h), HH = twoDigitPad(hour), mm = twoDigitPad(minute), ss = twoDigitPad(second), aaa = hour < 12 ? "AM" : "PM", EEEE = constants_1.DAYS_OF_WEEK_NAMES[date.getDay()], EEE = EEEE.substr(0, 3), dd = twoDigitPad(day), M = month + 1, MM = twoDigitPad(M), MMMM = constants_1.MONTH_NAMES[month], MMM = MMMM.substr(0, 3), yyyy = year + "", yy = yyyy.substr(2, 2);
185
+ // checks to see if month name will be used
186
+ patternStr = patternStr
187
+ .replace("hh", hh)
188
+ .replace("h", h.toString())
189
+ .replace("HH", HH)
190
+ .replace("H", hour.toString())
191
+ .replace("mm", mm)
192
+ .replace("m", minute.toString())
193
+ .replace("ss", ss)
194
+ .replace("s", second.toString())
195
+ .replace("S", miliseconds.toString())
196
+ .replace("dd", dd)
197
+ .replace("d", day.toString())
198
+ .replace("EEEE", EEEE)
199
+ .replace("EEE", EEE)
200
+ .replace("yyyy", yyyy)
201
+ .replace("yy", yy)
202
+ .replace("aaa", aaa);
203
+ if (patternStr.indexOf("MMM") > -1) {
204
+ patternStr = patternStr.replace("MMMM", MMMM).replace("MMM", MMM);
205
+ }
206
+ else {
207
+ patternStr = patternStr.replace("MM", MM).replace("M", M.toString());
208
+ }
209
+ return patternStr;
210
+ }
211
+ /**
212
+ * @summary Parses a date from a specified format
213
+ * @param {string} format
214
+ * @param {string | Date | number} [v]
215
+ * @memberOf module:decorator-validation.Utils.Dates
216
+ * @category Format
217
+ */
218
+ function parseDate(format, v) {
219
+ let value = undefined;
220
+ if (!v)
221
+ return undefined;
222
+ if (v instanceof Date)
223
+ try {
224
+ value = dateFromFormat(formatDate(v, format), format);
225
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
226
+ }
227
+ catch (e) {
228
+ throw new Error((0, strings_1.sf)("Could not convert date {0} to format: {1}", v.toString(), format));
229
+ }
230
+ else if (typeof v === "string") {
231
+ value = dateFromFormat(v, format);
232
+ }
233
+ else if (typeof v === "number") {
234
+ const d = new Date(v);
235
+ value = dateFromFormat(formatDate(d, format), format);
236
+ }
237
+ else if (isValidDate(v)) {
238
+ try {
239
+ const d = new Date(v);
240
+ value = dateFromFormat(formatDate(d, format), format);
241
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
242
+ }
243
+ catch (e) {
244
+ throw new Error((0, strings_1.sf)("Could not convert date {0} to format: {1}", v, format));
245
+ }
246
+ }
247
+ else {
248
+ throw new Error(`Invalid value provided ${v}`);
249
+ }
250
+ return bindDateToString(value, format);
251
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prop = prop;
4
+ exports.propMetadata = propMetadata;
5
+ const reflection_1 = require("@decaf-ts/reflection");
6
+ const constants_1 = require("./constants");
7
+ function prop(key = constants_1.ModelKeys.ATTRIBUTE) {
8
+ return (model, propertyKey) => {
9
+ let props;
10
+ if (Object.prototype.hasOwnProperty.call(model, key)) {
11
+ props = model[key];
12
+ }
13
+ else {
14
+ props = model[key] = [];
15
+ }
16
+ if (!props.includes(propertyKey))
17
+ props.push(propertyKey);
18
+ };
19
+ }
20
+ function propMetadata(key, value) {
21
+ return (0, reflection_1.apply)(prop(), (0, reflection_1.metadata)(key, value));
22
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Hashing = exports.DefaultHashingMethod = void 0;
4
+ exports.hashCode = hashCode;
5
+ exports.hashSerialization = hashSerialization;
6
+ exports.hashObj = hashObj;
7
+ const serialization_1 = require("./serialization");
8
+ /**
9
+ * @summary Mimics Java's String's Hash implementation
10
+ *
11
+ * @param {string | number | symbol | Date} obj
12
+ * @return {number} hash value of obj
13
+ *
14
+ * @function hashCode
15
+ * @memberOf module:decorator-validation.Utils.Hashing
16
+ * @category Hashing
17
+ */
18
+ function hashCode(obj) {
19
+ obj = String(obj);
20
+ let hash = 0;
21
+ for (let i = 0; i < obj.length; i++) {
22
+ const character = obj.charCodeAt(i);
23
+ hash = (hash << 5) - hash + character;
24
+ hash = hash & hash; // Convert to 32bit integer
25
+ }
26
+ return hash.toString();
27
+ }
28
+ /**
29
+ * @summary Hashes an object serializing it and then hashing the string
30
+ * @description The Serialization algorithm used by default (JSON.stringify)
31
+ * is not deterministic and should not be used for hashing
32
+ *
33
+ * @param {Record<string, any>} obj
34
+ * @return {string} the resulting hash
35
+ *
36
+ * @function hashSerialization
37
+ * @memberOf module:decorator-validation.Utils.Hashing
38
+ *
39
+ * @category Hashing
40
+ */
41
+ function hashSerialization(obj) {
42
+ return hashCode(serialization_1.Serialization.serialize(obj));
43
+ }
44
+ /**
45
+ * @summary Hashes an object by combining the hash of all its properties
46
+ *
47
+ * @param {Record<string, any>} obj
48
+ * @return {string} the resulting hash
49
+ *
50
+ * @function hashObj
51
+ * @memberOf module:decorator-validation.Utils.Hashing
52
+ * @category Hashing
53
+ */
54
+ function hashObj(obj) {
55
+ const hashReducer = function (h, el) {
56
+ const elHash = hashFunction(el);
57
+ if (typeof elHash === "string")
58
+ return hashFunction((h || "") + hashFunction(el));
59
+ h = h || 0;
60
+ h = (h << 5) - h + elHash;
61
+ return h & h;
62
+ };
63
+ const func = hashCode;
64
+ const hashFunction = function (value) {
65
+ if (typeof value === "undefined")
66
+ return "";
67
+ if (["string", "number", "symbol"].indexOf(typeof value) !== -1)
68
+ return func(value.toString());
69
+ if (value instanceof Date)
70
+ return func(value.getTime());
71
+ if (Array.isArray(value))
72
+ return value.reduce(hashReducer, undefined);
73
+ return Object.values(value).reduce(hashReducer, undefined);
74
+ };
75
+ const result = Object.values(obj).reduce(hashReducer, 0);
76
+ return (typeof result === "number" ? Math.abs(result) : result).toString();
77
+ }
78
+ exports.DefaultHashingMethod = "default";
79
+ class Hashing {
80
+ static { this.current = exports.DefaultHashingMethod; }
81
+ static { this.cache = {
82
+ default: hashObj,
83
+ }; }
84
+ constructor() { }
85
+ static get(key) {
86
+ if (key in this.cache)
87
+ return this.cache[key];
88
+ throw new Error(`No hashing method registered under ${key}`);
89
+ }
90
+ static register(key, func, setDefault = false) {
91
+ if (key in this.cache)
92
+ throw new Error(`Hashing method ${key} already registered`);
93
+ this.cache[key] = func;
94
+ if (setDefault)
95
+ this.current = key;
96
+ }
97
+ static hash(obj, method, ...args) {
98
+ if (!method)
99
+ return this.get(this.current)(obj, ...args);
100
+ return this.get(method)(obj, ...args);
101
+ }
102
+ static setDefault(method) {
103
+ this.current = this.get(method);
104
+ }
105
+ }
106
+ exports.Hashing = Hashing;