dynamodb-toolbox
Version:
A simple set of tools for working with Amazon DynamoDB and the DocumentClient.
98 lines (97 loc) • 4.92 kB
JavaScript
;
/**
* DynamoDB Toolbox: A simple set of tools for working with Amazon DynamoDB
* @author Jeremy Daly <jeremy@jeremydaly.com>
* @license MIT
*/
Object.defineProperty(exports, "__esModule", { value: true });
const utils_js_1 = require("./utils.js");
// Performs type validation/coercion
exports.default = () => (mapping, field, value) => {
// Evaluate function expressions
// TODO: should this happen here?
// let value = typeof input === 'function' ? input(data) : input
var _a, _b, _c, _d;
// return if undefined or null
if (!(0, utils_js_1.hasValue)(value))
return value;
switch (mapping.type) {
case 'string':
return typeof value === 'string' || mapping.coerce
? String(value)
: (0, utils_js_1.error)(`'${field}' must be of type string`);
case 'boolean':
return typeof value === 'boolean' || mapping.coerce
? (0, utils_js_1.toBool)(value)
: (0, utils_js_1.error)(`'${field}' must be of type boolean`);
case 'number': {
if (typeof value === 'number') {
return Number.isFinite(value) ? value : (0, utils_js_1.error)(`'${field}' must be a finite number`);
}
if (!mapping.coerce) {
return (0, utils_js_1.error)(`'${field}' must be of type number`);
}
const coercedValue = Number(value);
return typeof value === 'string' && Number.isFinite(coercedValue) && value.length > 0
? coercedValue
: (0, utils_js_1.error)(`Could not convert '${Array.isArray(value) ? `[${value}]` : value}' to a number for '${field}'`);
}
case 'bigint':
return (0, utils_js_1.toDynamoBigInt)(typeof value === 'bigint' || mapping.coerce
? BigInt(value)
: (0, utils_js_1.error)(`'${field}' must be of type bigint`));
case 'list':
return Array.isArray(value)
? value
: mapping.coerce
? String(value)
.split(',')
.map(x => x.trim())
: (0, utils_js_1.error)(`'${field}' must be a list (array)`);
case 'map':
return (value === null || value === void 0 ? void 0 : value.constructor) === Object ? value : (0, utils_js_1.error)(`'${field}' must be a map (object)`);
case 'set':
if (value instanceof Set) {
if (mapping.setType === 'bigint') {
value = Array.from(value).map((n) => (0, utils_js_1.toDynamoBigInt)(n));
}
return (!mapping.setType ||
value.size === 0
|| (0, utils_js_1.isArrayOfSameType)([...value])
? value
: (0, utils_js_1.error)(`'${field}' must be a valid set containing only ${mapping.setType} types`));
}
else if (Array.isArray(value)) {
const expectedSetType = (_b = (_a = mapping.setType) === null || _a === void 0 ? void 0 : _a.toLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a);
const actualSetType = (_d = (_c = (0, utils_js_1.typeOf)(value[0])) === null || _c === void 0 ? void 0 : _c.toLowerCase) === null || _d === void 0 ? void 0 : _d.call(_c);
if (mapping.setType === 'bigint') {
value = value.map((n) => (0, utils_js_1.toDynamoBigInt)(n));
}
return (!mapping.setType ||
value.length === 0 ||
(expectedSetType === actualSetType && (0, utils_js_1.isArrayOfSameType)(value))
? new Set(value)
: (0, utils_js_1.error)(`'${field}' must be a valid set (array) containing only ${expectedSetType !== null && expectedSetType !== void 0 ? expectedSetType : actualSetType} types`));
}
else if (mapping.coerce) {
if (value instanceof Set)
return value;
const arrayVal = String(value)
.split(',')
.map((x) => x.trim());
const expectedSetType = mapping.setType;
const actualSetType = (0, utils_js_1.typeOf)(arrayVal[0]);
return (!mapping.setType ||
arrayVal.length === 0 ||
(expectedSetType === actualSetType && (0, utils_js_1.isArrayOfSameType)(arrayVal))
? new Set(arrayVal)
: (0, utils_js_1.error)(`'${field}' must be a valid set (array) of type ${mapping.setType}`));
}
else {
return (0, utils_js_1.error)(`'${field}' must be a valid set (array)`);
}
default:
// TODO: Binary validation
return value;
}
};