@lucaspaganini/value-objects
Version:
TypeScript first validation and class creation library
140 lines • 4.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VOObject = void 0;
var utils_1 = require("../utils");
var errors_1 = require("./errors");
var functions_1 = require("./functions");
/**
* Function to create an object wrapper over a given map of value
* object constructors. Useful if you have different classes and
* want to aggregate them.
*
* @template Schema Object mapping to value object constructors.
* @param schema Object mapping to value object constructors.
* @param options Customizations for the returned class constructor.
* @return Class constructor that accepts an object mapping it's keys
* and values to what the inner value object constructors expect.
* Calling {@link VOObjectInstance.valueOf} calls `valueOf()` for all it's inner instances
* and returns them in an object.
*
* @example
* ```typescript
* class Email extends VOString({ ... }) {
* getHost(): string { ... }
* }
*
* class Name extends VOString({ ... }) {}
*
* class Password extends VOString({ ... }) {}
*
* class User extends VOObject({
* name: Name,
* email: Email,
* password: Password
* }) {}
*
* new User({
* name: 'Lucas',
* email: 'me@lucaspaganini.com',
* password: 'Secret123'
* }); // OK
*
* new User({
* name: 'Lucas',
* email: 123,
* password: 'Secret123'
* }); // Compilation error: `.email` expects a string
*
* new User({
* name: 'Lucas',
* email: 'lucaspaganini.com',
* password: 'Secret123'
* }); // Runtime error: `.email` Value doesn't match pattern
*
* const user = new User({
* name: 'Lucas',
* email: 'me@lucaspaganini.com',
* password: 'Secret123'
* });
*
* user.valueOf(); // { name: 'Lucas', email: 'me@lucaspaganini.com', password: 'Secret123' }
* user.email.getHost(); // lucaspaganini.com
* ```
*
* @example
* ```typescript
* class Test {
* constructor(shouldThrow: boolean) {
* if (shouldThrow) throw Error('I was instructed to throw');
* }
* }
* new Test(false); // OK
* new Test(true); // Runtime error: I was instructed to throw
*
* class TestsObject extends VoObject({
* aaa: Test,
* bbb: Test,
* ccc: Test
* }, { maxErrors: 2 }) {}
* new TestsArray({ aaa: false, bbb: false, ccc: false }); // OK
* new TestsArray({ aaa: true, bbb: true, ccc: true }); // Runtime error: ["I was instructed to throw", "I was instructed to throw"]
* ```
*/
var VOObject = function (schema, options) {
var _a;
if (options === void 0) { options = {}; }
if (utils_1.isDefined(options.maxErrors)) {
if (typeof options.maxErrors !== 'number')
throw new errors_1.RawTypeError('number', typeof options.maxErrors, 'options.maxErrors');
if (!Number.isInteger(options.maxErrors))
throw new errors_1.NotIntegerError(options.maxErrors, 'options.maxErrors');
if (options.maxErrors < 0)
throw new errors_1.MinSizeError(options.maxErrors, 0);
}
var maxErrors = (_a = options.maxErrors) !== null && _a !== void 0 ? _a : 1;
return /** @class */ (function () {
function class_1(raw) {
if (utils_1.isNil(raw))
throw new errors_1.RawTypeError('object', typeof raw, 'raw');
var errors = [];
var _loop_1 = function (prop, VO) {
var fromRaw = functions_1.makeFromRawInit(VO);
var either = fromRaw(raw[prop]);
if (utils_1.isLeft(either)) {
var errorsWithProp = either.left.map(function (e) {
if (errors_1.VOError.is(e))
e.path.push(prop);
return e;
});
errors.push.apply(errors, errorsWithProp);
if (errors.length >= maxErrors)
throw errors;
}
else {
;
this_1[prop] = either.right;
}
};
var this_1 = this;
for (var _i = 0, _a = Object.entries(schema); _i < _a.length; _i++) {
var _b = _a[_i], prop = _b[0], VO = _b[1];
_loop_1(prop, VO);
}
if (errors.length > 0)
throw errors;
}
class_1.prototype.valueOf = function () {
var _this = this;
return Object.keys(schema).reduce(function (acc, key) {
acc[key] = _this[key].valueOf();
return acc;
}, {});
};
class_1.prototype.toRaw = function () {
return this.valueOf();
};
return class_1;
}());
};
exports.VOObject = VOObject;
//# sourceMappingURL=object.js.map