@jeroenhuinink/tsmapper
Version:
JSON to Typescript object mapper
198 lines • 9.06 kB
JavaScript
;
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createExplicitMapper = exports.createMapper = void 0;
/**
* Default set of functions that are used to map values from the source to the target.
*/
var defaultMapFunctions = {
string: function (val) { return String(val); },
number: function (val) { return Number(val); },
boolean: function (val) { return !!val; },
date: function (val) {
return new Date(String(val));
},
isodate: function (val) {
return new Date(String(val)).toISOString();
},
symbol: function (val) { return Symbol(val); },
undefined: function (val) { return String(val); },
object: function (val) { return JSON.stringify(val); },
function: function (val) { return val; },
};
/**
* Errors throw by the Mapper
*/
var MapperError = /** @class */ (function (_super) {
__extends(MapperError, _super);
function MapperError(message, source) {
var _this = _super.call(this, "".concat(message, " in: ").concat(JSON.stringify(source))) || this;
_this.source = source;
return _this;
}
return MapperError;
}(Error));
/**
* The Mapper implementation
*/
var MapperInstance = /** @class */ (function () {
function MapperInstance(name, options) {
var map = (options === null || options === void 0 ? void 0 : options.map) || {};
this.fields = [];
this.name = name;
this.mapFunctions = __assign(__assign({}, defaultMapFunctions), map);
}
MapperInstance.prototype.field = function (name, options) {
var mapperField = __assign(__assign({}, options), {
/* Fields are mandatory (non-optional) by default */
optional: options.optional || false,
/* If no key is present, the name is used as the key */
key: options.key || name, name: name });
/* If there is a enum option it is a type object */
if ('enum' in options) {
mapperField.type = 'enum';
mapperField.enum = options.enum;
}
/* If there is a mapper option it is a type object */
if ('mapper' in options) {
mapperField.type = 'object';
}
/* If there is an itemType option it is of type array */
if ('itemType' in options) {
mapperField.type = 'array';
if (!options.itemType.type) {
mapperField.itemType.type = 'object';
}
}
this.fields.push(mapperField);
return this;
};
/**
*
* The function that performs the actual map from the source to the target.
*
* @param source
* @returns target
*/
MapperInstance.prototype.map = function (source) {
var _this = this;
return this.fields.reduce(function (result, field) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
var name = field.name, key = field.key, defaultValue = field.default, optional = field.optional;
switch (field.type) {
case 'enum':
if (!(key in source)) {
if (!defaultValue) {
throw new MapperError("".concat(_this.name, ": Property \"").concat(key, "\" not found"), source);
}
return __assign(__assign({}, result), (_a = {}, _a[name] = defaultValue, _a));
}
var enumArray = field.enum;
var enumValue = source[key];
if (typeof enumValue === 'number') {
if (!(enumValue in enumArray)) {
throw new MapperError("".concat(_this.name, ": Value ").concat(enumValue, " not allowed for property \"").concat(key, "\""), source);
}
return __assign(__assign({}, result), (_b = {}, _b[name] = enumArray[enumValue], _b));
}
if (!enumArray.includes(String(enumValue))) {
throw new MapperError("".concat(_this.name, ": Value \"").concat(enumValue, "\" not allowed for property \"").concat(key, "\""), source);
}
return __assign(__assign({}, result), (_c = {}, _c[name] = String(enumValue), _c));
case 'array':
if (!(key in source)) {
if (defaultValue) {
return __assign(__assign({}, result), (_d = {}, _d[name] = defaultValue, _d));
}
if (!optional) {
throw new MapperError("".concat(_this.name, ": Property \"").concat(key, "\" not found"), source);
}
return result;
}
switch (field.itemType.type) {
case 'enum':
var itemMap_1 = field.itemType.map;
return __assign(__assign({}, result), (_e = {}, _e[name] = source[key].map(function (item) { return itemMap_1(item); }), _e));
default:
var itemMapper_1 = field.itemType.mapper;
return __assign(__assign({}, result), (_f = {}, _f[name] = source[key].map(function (item) { return itemMapper_1.map(item); }), _f));
}
case 'object':
// eslint-disable-next-line no-case-declarations
var mapper = field.mapper;
if (!(key in source) || !source[key]) {
if (defaultValue) {
return __assign(__assign({}, result), (_g = {}, _g[name] = defaultValue, _g));
}
if (!optional) {
throw new MapperError("".concat(_this.name, ": Property \"").concat(key, "\" not found or undefined"), source);
}
return result;
}
try {
return __assign(__assign({}, result), (_h = {}, _h[name] = mapper.map(source[key]), _h));
}
catch (error) {
throw new MapperError("".concat(_this.name, ": Mapper failed for property ").concat(key, " with error \"").concat(error.message, "\""), source);
}
default:
var type = field.type;
var value = source[key];
var map = field.map || _this.mapFunctions[type || typeof defaultValue];
if (value === undefined || value === null) {
if (defaultValue !== undefined) {
return __assign(__assign({}, result), (_j = {}, _j[name] = map(defaultValue, source), _j));
}
if (optional) {
return result;
}
throw new MapperError("".concat(_this.name, ": Property \"").concat(key, "\" not found"), source);
}
return __assign(__assign({}, result), (_k = {}, _k[name] = map(value, source), _k));
}
}, {});
};
return MapperInstance;
}());
/**
*
* @param name Specify a name for your mapper. This name will be used in error messages.
* @param options Mapper options
* @returns
*/
function createMapper(name, options) {
if (name === void 0) { name = 'Mapper'; }
return new MapperInstance(name, options);
}
exports.createMapper = createMapper;
function createExplicitMapper(name, options) {
if (name === void 0) { name = 'Mapper'; }
return new MapperInstance(name, options);
}
exports.createExplicitMapper = createExplicitMapper;
//# sourceMappingURL=tsmapper.js.map