@nerdware/ddb-single-table
Version:
A schema-based DynamoDB modeling tool, high-level API, and type-generator built to supercharge single-table designs!⚡
74 lines (73 loc) • 3.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateUpdateExpression = void 0;
const ts_type_safety_utils_1 = require("@nerdware/ts-type-safety-utils");
const buildAttrPathTokens_js_1 = require("./buildAttrPathTokens.js");
/**
* This function uses the provided `itemAttributes` to generate the following `updateItem` args:
*
* - `UpdateExpression` (may include `"SET"` and/or `"REMOVE"` clauses)
* - `ExpressionAttributeNames`
* - `ExpressionAttributeValues`
*
* `UpdateExpression` Clauses:
* - The `"SET"` clause includes all attributes which are _not_ explicitly `undefined`.
* - The `"REMOVE"` clause includes all attributes which are explicitly set to `undefined`.
* - If {@link GenerateUpdateExpressionOpts|nullHandling} is `"REMOVE"` (default), then
* attributes with `null` values are added to the `"REMOVE"` clause, otherwise they are
* added to the `"SET"` clause.
*/
const generateUpdateExpression = (itemAttributes, { nullHandling } = {}) => {
const shouldAddToRemoveClause = nullHandling !== "SET"
? (value) => value === undefined || value === null
: (value) => value === undefined;
const updateExpressionClauses = { SET: [], REMOVE: [] };
const ExpressionAttributeNames = {};
const ExpressionAttributeValues = {};
const recurse = (value, path) => {
if ((0, ts_type_safety_utils_1.isObjectLike)(value)
&& !(0, ts_type_safety_utils_1.isDate)(value)
&& !(0, ts_type_safety_utils_1.isBuffer)(value)
&& !(value instanceof Set) //
) {
if ((0, ts_type_safety_utils_1.isArray)(value)) {
value.forEach((arrayElement, index) => {
recurse(arrayElement, [...path, index]);
});
}
else {
for (const key of Object.keys(value)) {
const keyValue = value[key];
recurse(keyValue, [...path, key]);
}
}
}
else {
const { namePath, valueToken } = (0, buildAttrPathTokens_js_1.buildAttrPathTokens)(path, ExpressionAttributeNames);
// Derive and append the appropriate UpdateExpression clause
if (shouldAddToRemoveClause(value)) {
updateExpressionClauses.REMOVE.push(namePath);
}
else {
updateExpressionClauses.SET.push(`${namePath} = ${valueToken}`);
ExpressionAttributeValues[valueToken] = value;
}
}
};
recurse(itemAttributes, []);
// Combine the clauses into UpdateExpression
const UpdateExpression = [
...(updateExpressionClauses.SET.length > 0
? [`SET ${updateExpressionClauses.SET.join(", ")}`]
: []),
...(updateExpressionClauses.REMOVE.length > 0
? [`REMOVE ${updateExpressionClauses.REMOVE.join(", ")}`]
: []),
].join(" ");
return {
UpdateExpression,
ExpressionAttributeNames,
ExpressionAttributeValues,
};
};
exports.generateUpdateExpression = generateUpdateExpression;