You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.7 KiB
JavaScript

"use strict";
const isDecimalStringNumber = require("./value-checks/string-number/is-decimal");
const isNegative = require("./value-checks/is-negative");
const fromDate = require("./type-adapters/from-date");
const fromTemporal = require("./type-adapters/from-temporal");
const getValueType = require("./get-value-type");
const coders = require("./coders");
// const forbiddenTypes = new Set([
// "function", "symbol"
// ]);
const allowedValueTypes = {
bytes: { bytes: true },
string: { string: true },
boolean: { boolean: true },
decimal: { string: true },
date: {
date: (value) => fromDate(value),
temporalTime: (value) => fromTemporal(value)
},
duration: {
temporalDuration: true // TODO: Convert to internal data structure
},
integer: {
integer: (value) => BigInt(value),
bigint: true,
// TODO: Allow string inputs here, eventually?
},
float: { float: true },
json: {
array: true,
object: true,
string: true,
integer: true,
float: true
}
};
// FIXME: Deal with index key length restrictions, as well as value blob length restrictions?
module.exports = function encodeField(options) {
let { name, value, fieldType, required, signed, ... coderOptions } = options;
let typeConverters = allowedValueTypes[fieldType];
let valueType = getValueType(value);
let isNumericType = (fieldType === "integer" || fieldType === "float" || fieldType === "decimal");
// FIXME: Error types
if (fieldType === "json" || fieldType === "float") {
throw new Error(`Property '${name}' is of the '${fieldType}' type, but support for this is not yet implemented`);
} else if (required === true && valueType === "null") {
throw new Error(`Property '${name}' is required`);
} else if (typeConverters[valueType] == null) {
let typeString = Object.keys(typeConverters).map((type) => `'${type}'`).join(", ");
throw new Error(`Value for property '${name}' should be one of types [${typeString}], but encountered '${valueType}' instead`);
} else {
let valueHandler = typeConverters[valueType];
let normalizedValue = (valueHandler === true)
? value
: valueHandler(value);
if (fieldType === "decimal" && !isDecimalStringNumber(normalizedValue)) {
throw new Error(`Value for property '${name}' must be a string decimal`);
} else if (typeof normalizedValue === "number" && Number.isNaN(normalizedValue)) {
throw new Error(`NaN is not an allowed value for property '${name}'`);
} else if (isNumericType && !signed && isNegative(normalizedValue)) {
// FIXME: Check number range as well?
throw new Error(`Value for property '${name}' is negative, but this is not allowed`);
} else {
return coders.encode(fieldType, normalizedValue, coderOptions);
}
}
};