UNPKG

dynamodb-toolbox

Version:

Lightweight and type-safe query builder for DynamoDB and TypeScript.

122 lines (121 loc) 4.73 kB
"use strict"; 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; } };