dynamodb-toolbox
Version:
Lightweight and type-safe query builder for DynamoDB and TypeScript.
122 lines (121 loc) • 4.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.schemaParser = schemaParser;
const index_js_1 = require("../../../errors/index.js");
const formatArrayPath_js_1 = require("../../../schema/actions/utils/formatArrayPath.js");
const cloneDeep_js_1 = require("../../../utils/cloneDeep.js");
const isFunction_js_1 = require("../../../utils/validation/isFunction.js");
const any_js_1 = require("./any.js");
const anyOf_js_1 = require("./anyOf.js");
const list_js_1 = require("./list.js");
const map_js_1 = require("./map.js");
const primitive_js_1 = require("./primitive.js");
const record_js_1 = require("./record.js");
const set_js_1 = require("./set.js");
const utils_js_1 = require("./utils.js");
function* schemaParser(schema, inputValue, options = {}) {
const { mode = 'put', fill = true, transform = true, defined = false,
/**
* @debt type "Maybe there's a way not to have to cast here"
*/
parseExtension = utils_js_1.defaultParseExtension, valuePath } = options;
let filledValue = inputValue;
let nextFill = fill;
if (nextFill && filledValue === undefined) {
let defaultedValue = undefined;
const modeDefault = getDefaulter(schema, mode);
defaultedValue = (0, isFunction_js_1.isFunction)(modeDefault) ? modeDefault() : (0, cloneDeep_js_1.cloneDeep)(modeDefault);
const itemInput = yield defaultedValue;
let linkedValue = defaultedValue;
if (linkedValue === undefined && itemInput !== undefined) {
const modeLink = getModeLink(schema, mode);
linkedValue = ((0, isFunction_js_1.isFunction)(modeLink) ? modeLink(itemInput) : linkedValue);
}
yield linkedValue;
filledValue = linkedValue;
nextFill = false;
}
const nextOpts = { ...options, fill: nextFill };
const { isExtension, extensionParser, unextendedInput } = parseExtension(schema, filledValue, {
transform,
valuePath
});
if (isExtension) {
if (nextFill) {
// parseExtension does not fill values
// If fill was set to `true` and input was defined, we yield it twice for fill steps
const defaultedValue = filledValue;
yield defaultedValue;
const linkedValue = defaultedValue;
yield linkedValue;
}
return yield* extensionParser();
}
if (unextendedInput === undefined) {
const path = valuePath !== undefined ? (0, formatArrayPath_js_1.formatArrayPath)(valuePath) : undefined;
// We don't need to fill
if ((0, utils_js_1.isRequired)(schema, mode) || defined) {
throw new index_js_1.DynamoDBToolboxError('parsing.attributeRequired', {
message: `Attribute${path !== undefined ? ` '${path}'` : ''} is required.`,
path
});
}
const parsedValue = unextendedInput;
if (transform) {
yield parsedValue;
}
else {
return parsedValue;
}
const transformedValue = parsedValue;
return transformedValue;
}
switch (schema.type) {
case 'any':
return yield* (0, any_js_1.anySchemaParser)(schema, unextendedInput, nextOpts);
case 'null':
case 'boolean':
case 'number':
case 'string':
case 'binary':
return yield* (0, primitive_js_1.primitiveSchemaParser)(schema, unextendedInput, nextOpts);
case 'set':
return yield* (0, set_js_1.setSchemaParser)(schema, unextendedInput, nextOpts);
case 'list':
return yield* (0, list_js_1.listSchemaParser)(schema, unextendedInput, nextOpts);
case 'map':
return yield* (0, map_js_1.mapSchemaParser)(schema, unextendedInput, nextOpts);
case 'record':
return yield* (0, record_js_1.recordSchemaParser)(schema, unextendedInput, nextOpts);
case 'anyOf':
return yield* (0, anyOf_js_1.anyOfSchemaParser)(schema, unextendedInput, nextOpts);
}
}
const getDefaulter = (schema, mode) => {
const { props } = schema;
if (props.key) {
return props.keyDefault;
}
switch (mode) {
case 'key':
return props.keyDefault;
case 'put':
return props.putDefault;
case 'update':
return props.updateDefault;
}
};
const getModeLink = (schema, mode) => {
const { props } = schema;
if (props.key) {
return props.keyLink;
}
switch (mode) {
case 'key':
return props.keyLink;
case 'put':
return props.putLink;
case 'update':
return props.updateLink;
}
};