@nova-odm/expressions
Version:
Composable expression objects for Amazon DynamoDB
256 lines • 9.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serializeConditionExpression = exports.isConditionExpression = exports.isConditionExpressionSubject = exports.isConditionExpressionPredicate = exports.contains = exports.beginsWith = exports.attributeType = exports.attributeNotExists = exports.attributeExists = exports.inList = exports.between = exports.greaterThanOrEqualTo = exports.greaterThan = exports.lessThanOrEqualTo = exports.lessThan = exports.notEquals = exports.equals = void 0;
var tslib_1 = require("tslib");
var AttributePath_1 = require("./AttributePath");
var FunctionExpression_1 = require("./FunctionExpression");
/**
* Create an expression predicate asserting that the subject is equal to the
* predicate.
*/
function equals(operand) {
return {
type: 'Equals',
object: operand,
};
}
exports.equals = equals;
function notEquals(operand) {
return {
type: 'NotEquals',
object: operand,
};
}
exports.notEquals = notEquals;
function lessThan(operand) {
return {
type: 'LessThan',
object: operand,
};
}
exports.lessThan = lessThan;
function lessThanOrEqualTo(operand) {
return {
type: 'LessThanOrEqualTo',
object: operand,
};
}
exports.lessThanOrEqualTo = lessThanOrEqualTo;
function greaterThan(operand) {
return {
type: 'GreaterThan',
object: operand,
};
}
exports.greaterThan = greaterThan;
function greaterThanOrEqualTo(operand) {
return {
type: 'GreaterThanOrEqualTo',
object: operand,
};
}
exports.greaterThanOrEqualTo = greaterThanOrEqualTo;
function between(lowerBound, upperBound) {
return {
type: 'Between',
lowerBound: lowerBound,
upperBound: upperBound,
};
}
exports.between = between;
function inList() {
var operands = [];
for (var _i = 0; _i < arguments.length; _i++) {
operands[_i] = arguments[_i];
}
return {
type: 'Membership',
values: operands,
};
}
exports.inList = inList;
function attributeExists() {
return {
type: 'Function',
name: 'attribute_exists',
};
}
exports.attributeExists = attributeExists;
function attributeNotExists() {
return {
type: 'Function',
name: 'attribute_not_exists',
};
}
exports.attributeNotExists = attributeNotExists;
function attributeType(expected) {
return {
type: 'Function',
name: 'attribute_type',
expected: expected,
};
}
exports.attributeType = attributeType;
function beginsWith(expected) {
return {
type: 'Function',
name: 'begins_with',
expected: expected,
};
}
exports.beginsWith = beginsWith;
function contains(expected) {
return {
type: 'Function',
name: 'contains',
expected: expected,
};
}
exports.contains = contains;
/**
* Evaluate whether the provided value is a condition expression predicate.
*/
function isConditionExpressionPredicate(arg) {
if (arg && typeof arg === 'object') {
switch (arg.type) {
case 'Equals':
case 'NotEquals':
case 'LessThan':
case 'LessThanOrEqualTo':
case 'GreaterThan':
case 'GreaterThanOrEqualTo':
return arg.object !== undefined;
case 'Between':
return arg.lowerBound !== undefined
&& arg.upperBound !== undefined;
case 'Membership':
return Array.isArray(arg.values);
case 'Function':
switch (arg.name) {
case 'attribute_exists':
case 'attribute_not_exists':
return true;
case 'attribute_type':
case 'begins_with':
case 'contains':
return typeof arg.expected === 'string';
}
}
}
return false;
}
exports.isConditionExpressionPredicate = isConditionExpressionPredicate;
function isConditionExpressionSubject(arg) {
return Boolean(arg)
&& typeof arg === 'object'
&& (typeof arg.subject === 'string' || AttributePath_1.AttributePath.isAttributePath(arg.subject));
}
exports.isConditionExpressionSubject = isConditionExpressionSubject;
/**
* Evaluates whether the provided value is a condition expression.
*/
function isConditionExpression(arg) {
var e_1, _a;
if (FunctionExpression_1.FunctionExpression.isFunctionExpression(arg)) {
return true;
}
if (Boolean(arg) && typeof arg === 'object') {
switch (arg.type) {
case 'Not':
return isConditionExpression(arg.condition);
case 'And':
case 'Or':
if (Array.isArray(arg.conditions)) {
try {
for (var _b = tslib_1.__values(arg.conditions), _c = _b.next(); !_c.done; _c = _b.next()) {
var condition = _c.value;
if (!isConditionExpression(condition)) {
return false;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return true;
}
return false;
default:
return isConditionExpressionSubject(arg)
&& isConditionExpressionPredicate(arg);
}
}
return false;
}
exports.isConditionExpression = isConditionExpression;
/**
* Convert the provided condition expression object to a string, escaping any
* values and attributes to expression-safe placeholders whose expansion value
* will be managed by the provided ExpressionAttributes object.
*/
function serializeConditionExpression(condition, attributes) {
if (FunctionExpression_1.FunctionExpression.isFunctionExpression(condition)) {
return condition.serialize(attributes);
}
switch (condition.type) {
case 'Equals':
return serializeBinaryComparison(condition, attributes, '=');
case 'NotEquals':
return serializeBinaryComparison(condition, attributes, '<>');
case 'LessThan':
return serializeBinaryComparison(condition, attributes, '<');
case 'LessThanOrEqualTo':
return serializeBinaryComparison(condition, attributes, '<=');
case 'GreaterThan':
return serializeBinaryComparison(condition, attributes, '>');
case 'GreaterThanOrEqualTo':
return serializeBinaryComparison(condition, attributes, '>=');
case 'Between':
return "".concat(attributes.addName(condition.subject), " BETWEEN ").concat(serializeOperand(condition.lowerBound, attributes), " AND ").concat(serializeOperand(condition.upperBound, attributes));
case 'Membership':
return "".concat(attributes.addName(condition.subject), " IN (").concat(condition.values.map(function (val) { return serializeOperand(val, attributes); })
.join(', '), ")");
case 'Function':
var subject = AttributePath_1.AttributePath.isAttributePath(condition.subject)
? condition.subject
: new AttributePath_1.AttributePath(condition.subject);
switch (condition.name) {
case 'attribute_exists':
case 'attribute_not_exists':
return (new FunctionExpression_1.FunctionExpression(condition.name, subject))
.serialize(attributes);
case 'attribute_type':
case 'begins_with':
case 'contains':
return (new FunctionExpression_1.FunctionExpression(condition.name, subject, condition.expected))
.serialize(attributes);
}
case 'Not':
return "NOT (".concat(serializeConditionExpression(condition.condition, attributes), ")");
case 'And':
case 'Or':
if (condition.conditions.length === 1) {
return serializeConditionExpression(condition.conditions[0], attributes);
}
return condition.conditions
.map(function (cond) { return "(".concat(serializeConditionExpression(cond, attributes), ")"); })
.join(" ".concat(condition.type.toUpperCase(), " "));
}
}
exports.serializeConditionExpression = serializeConditionExpression;
function serializeBinaryComparison(cond, attributes, comparator) {
return "".concat(attributes.addName(cond.subject), " ").concat(comparator, " ").concat(serializeOperand(cond.object, attributes));
}
function serializeOperand(operand, attributes) {
if (FunctionExpression_1.FunctionExpression.isFunctionExpression(operand)) {
return operand.serialize(attributes);
}
return AttributePath_1.AttributePath.isAttributePath(operand)
? attributes.addName(operand)
: attributes.addValue(operand);
}
//# sourceMappingURL=ConditionExpression.js.map