lemon-core
Version:
Lemon Serverless Micro-Service Platform
246 lines • 9.62 kB
JavaScript
"use strict";
// origin from: https://github.com/baseprime/dynamodb @20191106
// Copyright (c) 2016 Ryan Fitzgerald
/**
* `query.ts`
* - query
*
*
* @author Steve Jung <steve@lemoncloud.io>
* @date 2019-11-20 refactoring to ts via origin
*
* @copyright (C) lemoncloud.io 2019 - All Rights Reserved.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = __importDefault(require("lodash"));
const expressions = __importStar(require("./expressions"));
const utils = __importStar(require("./utils"));
const internals = {};
internals.keyCondition = function (keyName, schema, query) {
const f = function (operator) {
return function ( /*values*/) {
const copy = [].slice.call(arguments);
const existingValueKeys = lodash_1.default.keys(query.request.ExpressionAttributeValues);
const args = [keyName, operator, existingValueKeys].concat(copy);
const cond = expressions.buildFilterExpression.apply(null, args);
return query.addKeyCondition(cond);
};
};
return {
equals: f('='),
eq: f('='),
lte: f('<='),
lt: f('<'),
gte: f('>='),
gt: f('>'),
beginsWith: f('begins_with'),
between: f('BETWEEN'),
};
};
internals.queryFilter = function (keyName, schema, query) {
const f = function (operator) {
return function ( /*values*/) {
const copy = [].slice.call(arguments);
const existingValueKeys = lodash_1.default.keys(query.request.ExpressionAttributeValues);
const args = [keyName, operator, existingValueKeys].concat(copy);
const cond = expressions.buildFilterExpression.apply(null, args);
return query.addFilterCondition(cond);
};
};
return {
equals: f('='),
eq: f('='),
ne: f('<>'),
lte: f('<='),
lt: f('<'),
gte: f('>='),
gt: f('>'),
null: f('attribute_not_exists'),
exists: f('attribute_exists'),
contains: f('contains'),
notContains: f('NOT contains'),
in: f('IN'),
beginsWith: f('begins_with'),
between: f('BETWEEN'),
};
};
internals.isUsingGlobalIndex = function (query) {
return query.request.IndexName && query.table.schema.globalIndexes[query.request.IndexName];
};
/**
* class: `Query`
*/
class Query {
constructor(hashKey, table, serializer) {
this.limit = function (num) {
if (num <= 0) {
throw new Error('Limit must be greater than 0');
}
this.request.Limit = num;
return this;
};
this.filterExpression = function (expression) {
this.request.FilterExpression = expression;
return this;
};
this.expressionAttributeValues = function (data) {
this.request.ExpressionAttributeValues = data;
return this;
};
this.expressionAttributeNames = function (data) {
this.request.ExpressionAttributeNames = data;
return this;
};
this.projectionExpression = function (data) {
this.request.ProjectionExpression = data;
return this;
};
this.usingIndex = function (name) {
this.request.IndexName = name;
return this;
};
this.consistentRead = function (read) {
if (!lodash_1.default.isBoolean(read)) {
read = true;
}
this.request.ConsistentRead = read;
return this;
};
this.addKeyCondition = function (condition) {
internals.addExpressionAttributes(this.request, condition);
if (lodash_1.default.isString(this.request.KeyConditionExpression)) {
this.request.KeyConditionExpression =
this.request.KeyConditionExpression + ' AND (' + condition.statement + ')';
}
else {
this.request.KeyConditionExpression = '(' + condition.statement + ')';
}
return this;
};
this.addFilterCondition = function (condition) {
internals.addExpressionAttributes(this.request, condition);
if (lodash_1.default.isString(this.request.FilterExpression)) {
this.request.FilterExpression = this.request.FilterExpression + ' AND (' + condition.statement + ')';
}
else {
this.request.FilterExpression = '(' + condition.statement + ')';
}
return this;
};
this.startKey = function (hashKey, rangeKey) {
this.request.ExclusiveStartKey = this.serializer.buildKey(hashKey, rangeKey, this.table.schema);
return this;
};
this.attributes = function (attrs) {
if (!lodash_1.default.isArray(attrs)) {
attrs = [attrs];
}
const expressionAttributeNames = lodash_1.default.reduce(attrs, function (result, attr) {
const path = '#' + attr;
result[path] = attr;
return result;
}, {});
this.request.ProjectionExpression = lodash_1.default.keys(expressionAttributeNames).join(',');
this.request.ExpressionAttributeNames = lodash_1.default.merge({}, expressionAttributeNames, this.request.ExpressionAttributeNames);
return this;
};
this.ascending = function () {
this.request.ScanIndexForward = true;
return this;
};
this.descending = function () {
this.request.ScanIndexForward = false;
return this;
};
this.select = function (value) {
this.request.Select = value;
return this;
};
this.returnConsumedCapacity = function (value) {
if (lodash_1.default.isUndefined(value)) {
value = 'TOTAL';
}
this.request.ReturnConsumedCapacity = value;
return this;
};
this.loadAll = function () {
this.options.loadAll = true;
return this;
};
this.where = function (keyName) {
return internals.keyCondition(keyName, this.table.schema, this);
};
this.filter = function (keyName) {
return internals.queryFilter(keyName, this.table.schema, this);
};
this.exec = function (callback) {
const self = this;
this.addKeyCondition(this.buildKey());
const runQuery = function (params, callback) {
self.table.runQuery(params, callback);
};
return utils.paginatedRequest(self, runQuery, callback);
};
this.buildKey = function () {
let key = this.table.schema.hashKey;
if (internals.isUsingGlobalIndex(this)) {
key = this.table.schema.globalIndexes[this.request.IndexName].hashKey;
}
const existingValueKeys = lodash_1.default.keys(this.request.ExpressionAttributeValues);
return expressions.buildFilterExpression(key, '=', existingValueKeys, this.hashKey);
};
this.buildRequest = function () {
return lodash_1.default.merge({}, this.request, { TableName: this.table.tableName() });
};
this.hashKey = hashKey;
this.table = table;
this.serializer = serializer;
this.options = { loadAll: false };
this.request = {};
}
}
internals.addExpressionAttributes = function (request, condition) {
const expressionAttributeNames = lodash_1.default.merge({}, condition.attributeNames, request.ExpressionAttributeNames);
const expressionAttributeValues = lodash_1.default.merge({}, condition.attributeValues, request.ExpressionAttributeValues);
if (!lodash_1.default.isEmpty(expressionAttributeNames)) {
request.ExpressionAttributeNames = expressionAttributeNames;
}
if (!lodash_1.default.isEmpty(expressionAttributeValues)) {
request.ExpressionAttributeValues = expressionAttributeValues;
}
};
internals.formatAttributeValue = function (val) {
if (lodash_1.default.isDate(val)) {
return val.toISOString();
}
return val;
};
//! export default.
exports.default = Query;
//# sourceMappingURL=query.js.map