lemon-core
Version:
Lemon Serverless Micro-Service Platform
153 lines • 6.71 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CosmosQueryService = exports.QueryService = exports.QueryBuilder = void 0;
/**
* `cosmos-query-service.ts`
* - common service to query with pkey+sort via cosmos
*
*
* @author Ian Kim <ian@lemoncloud.io>
* @date 2023-08-16 initial version with `cosmosDB` package.
*
* @copyright (C) 2023 LemonCloud Co Ltd. - All Rights Reserved.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const engine_1 = require("../../engine/");
const cosmos_service_1 = require("./cosmos-service");
const NS = engine_1.$U.NS('CMQR', 'green'); // NAMESPACE TO BE PRINTED.
function isComparisonCondition(c) {
return 'comparator' in c;
}
function isBetweenCondition(c) {
return 'from' in c && 'to' in c;
}
function isExistenceCondition(c) {
return 'exists' in c;
}
function isStringCondition(c) {
return 'operator' in c;
}
class QueryBuilder {
buildConditionExpression(condition) {
return __awaiter(this, void 0, void 0, function* () {
if (isComparisonCondition(condition)) {
const valueExpression = condition.value === null
? 'null'
: typeof condition.value === 'number'
? condition.value
: `'${condition.value}'`;
return `c['${condition.key}'] ${condition.comparator} ${valueExpression}`;
}
if (isStringCondition(condition)) {
if (condition.operator === 'begins_with')
return `STARTSWITH(c['${condition.key}'], '${condition.value}')`;
if (condition.operator === 'contains')
return `CONTAINS(c['${condition.key}'], '${condition.value}')`;
}
if (isBetweenCondition(condition)) {
return `c['${condition.key}'] >= ${condition.from} AND c['${condition.key}'] <= ${condition.to}`;
}
if (isExistenceCondition(condition)) {
return condition.exists ? `IS_DEFINED(c['${condition.key}'])` : `NOT IS_DEFINED(c['${condition.key}'])`;
}
});
}
buildQueryByConditions(conditions) {
return __awaiter(this, void 0, void 0, function* () {
if (conditions) {
const queryParts = Object.values(conditions).map((condition) => __awaiter(this, void 0, void 0, function* () {
if (condition.hasOwnProperty('or')) {
const orConditions = condition.or.map((orCondition) => __awaiter(this, void 0, void 0, function* () {
return yield this.buildConditionExpression(orCondition);
}));
return `(${(yield Promise.all(orConditions)).join(' OR ')})`;
}
if (condition.hasOwnProperty('not')) {
const notCondition = condition.not;
const notExpression = yield this.buildConditionExpression(notCondition);
return `NOT (${notExpression})`;
}
return yield this.buildConditionExpression(condition);
}));
const queryString = `SELECT * FROM c WHERE ${(yield Promise.all(queryParts)).join(' AND ')}`;
return queryString;
}
return 'SELECT * FROM c';
});
}
}
exports.QueryBuilder = QueryBuilder;
class QueryService {
// Add constructor that takes options as a parameter
constructor(options) {
this.options = options;
}
queryItems(query, limit, last) {
return __awaiter(this, void 0, void 0, function* () {
const { databaseName, tableName } = this.options;
const { client } = yield cosmos_service_1.CosmosService.instance();
const querySpec = {
query,
};
// cosmos DB needs continuation token for pagination
const { resources: queryResult, continuationToken } = yield client
.database(databaseName)
.container(tableName)
.items.query(querySpec, { continuationToken: last, maxItemCount: limit })
.fetchNext();
return {
queryResult,
continuationToken: continuationToken || undefined,
};
});
}
}
exports.QueryService = QueryService;
class CosmosQueryService {
constructor(options) {
/**
* say hello of identity.
*/
this.hello = () => `cosmos-query-service:${this.options.tableName}`;
// eslint-disable-next-line prettier/prettier
(0, engine_1._inf)(NS, `CosmosQueryService(${options.tableName}/${options.idName}${options.sortName ? '/' : ''}${options.sortName || ''})...`);
if (!options.tableName)
throw new Error('.tableName is required');
if (!options.idName)
throw new Error('.idName is required');
this.options = options;
// Initialize the queryService
this.queryService = new QueryService(options);
this.queryBuilder = new QueryBuilder();
}
/**
* Read items by conditions using dynamic query
*/
scan(limit, last, conditions) {
return __awaiter(this, void 0, void 0, function* () {
const queryString = yield this.queryBuilder.buildQueryByConditions(conditions);
const { queryResult, continuationToken } = yield this.queryService.queryItems(queryString, limit, last);
if (queryResult.length >= 0) {
return {
list: queryResult,
total: queryResult.length,
last: continuationToken,
};
}
else {
throw new Error('error');
}
});
}
}
exports.CosmosQueryService = CosmosQueryService;
//# sourceMappingURL=cosmos-query-service.js.map
;