@qrvey/data-persistence
Advanced tools
Comparing version 0.0.2 to 0.0.3-Rev-1
@@ -5,3 +5,3 @@ "use strict"; | ||
const constants_1 = require("../utils/constants"); | ||
function buildFilter(attribute, value, operator = 'EQUAL') { | ||
function buildFilter(attribute, value, operator = 'EQUAL', { omitPrimary = false } = {}) { | ||
return { | ||
@@ -11,2 +11,3 @@ attribute, | ||
value, | ||
omitPrimary, | ||
}; | ||
@@ -13,0 +14,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.METHOD_TO_QUERY = void 0; | ||
exports.buildAggFunctionAlias = exports.METHOD_TO_QUERY = void 0; | ||
var METHOD_TO_QUERY; | ||
@@ -10,2 +10,6 @@ (function (METHOD_TO_QUERY) { | ||
})(METHOD_TO_QUERY || (exports.METHOD_TO_QUERY = METHOD_TO_QUERY = {})); | ||
function buildAggFunctionAlias(aggregateFunction) { | ||
return `AGG_FN_${aggregateFunction}`; | ||
} | ||
exports.buildAggFunctionAlias = buildAggFunctionAlias; | ||
//# sourceMappingURL=queryHelpers.js.map |
@@ -40,5 +40,10 @@ "use strict"; | ||
} | ||
buildFilter(attribute, value, operator = 'EQUAL') { | ||
return (0, crudHelpers_1.buildFilter)(attribute, value, operator); | ||
findCount(options) { | ||
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars | ||
const { pagination } = options, findAllOptions = __rest(options, ["pagination"]); | ||
return this.crudService.findCount(findAllOptions); | ||
} | ||
buildFilter(attribute, value, operator = 'EQUAL', options = {}) { | ||
return (0, crudHelpers_1.buildFilter)(attribute, value, operator, options); | ||
} | ||
buildQueryIndex(indexName, columns) { | ||
@@ -45,0 +50,0 @@ return (0, crudHelpers_1.buildQueryIndex)(indexName, columns); |
@@ -41,10 +41,82 @@ "use strict"; | ||
} | ||
find(options = {}) { | ||
var _a, _b, _c, _d; | ||
const query = new queryBuilder_service_1.default(options.useScan); | ||
if ((_a = options.index) === null || _a === void 0 ? void 0 : _a.indexName) | ||
query.usingIndex((_b = options.index) === null || _b === void 0 ? void 0 : _b.indexName); | ||
this.applySorting(query, options.sorting, (_c = options.index) === null || _c === void 0 ? void 0 : _c.indexName); | ||
this.applyPagination(query, options.pagination); | ||
if (options.consistentRead) | ||
query.consistentRead(options.consistentRead); | ||
if (options.fields) | ||
query.projection(options.fields); | ||
this.applyFilters(query, options); | ||
return this.fetchResults(query.get(), (_d = options.pagination) === null || _d === void 0 ? void 0 : _d.limit, options.useScan).then((res) => { | ||
var _a, _b; | ||
const pagination = {}; | ||
if (res.lastEvaluatedKey) | ||
pagination.from = res.lastEvaluatedKey; | ||
if ((_a = options.pagination) === null || _a === void 0 ? void 0 : _a.limit) | ||
pagination.limit = (_b = options.pagination) === null || _b === void 0 ? void 0 : _b.limit; | ||
return { | ||
items: res.items, | ||
pagination, | ||
count: res.items.length, | ||
}; | ||
}); | ||
} | ||
async fetchResults(command, limit = 100, useScan = false) { | ||
var _a, _b, _c, _d, _e; | ||
let results = []; | ||
let LastEvaluatedKey = {}; | ||
do { | ||
if (this.isNotEmptyObject(LastEvaluatedKey)) | ||
command.ExclusiveStartKey = LastEvaluatedKey; | ||
const result = await (useScan | ||
? this.dynamoDbClientService.scan(command) | ||
: this.dynamoDbClientService.query(command)); | ||
command.Limit = ((_a = command.Limit) !== null && _a !== void 0 ? _a : 0) - ((_c = (_b = result.Items) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0); | ||
const rows = (_d = result.Items) !== null && _d !== void 0 ? _d : []; | ||
results = [...results, ...rows]; | ||
LastEvaluatedKey = (_e = result.LastEvaluatedKey) !== null && _e !== void 0 ? _e : {}; | ||
} while (results.length < limit && | ||
this.isNotEmptyObject(LastEvaluatedKey)); | ||
const lastEvaluatedKey = this.isNotEmptyObject(LastEvaluatedKey) | ||
? this.encryptPaginationKey(LastEvaluatedKey) | ||
: null; | ||
return { items: results, lastEvaluatedKey }; | ||
} | ||
applyPagination(query, pagination) { | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.limit) | ||
query.limit(pagination.limit); | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.from) | ||
query.startKey(this.decryptPaginationKey(pagination.from)); | ||
} | ||
async findAll(options = {}, allResults = []) { | ||
const { items, pagination } = await this.find(options); | ||
allResults.push(...items); | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.from) | ||
await this.findAll(Object.assign(Object.assign({}, options), { pagination }), allResults); | ||
return { | ||
items: allResults, | ||
pagination: null, | ||
count: allResults.length, | ||
}; | ||
} | ||
async findCount(options = {}) { | ||
const { items } = await this.find(options); | ||
return items.length; | ||
} | ||
async findItem(options) { | ||
var _a; | ||
var _a, _b, _c; | ||
const query = new queryBuilder_service_1.default(); | ||
if ((_a = options.index) === null || _a === void 0 ? void 0 : _a.indexName) | ||
query.usingIndex((_b = options.index) === null || _b === void 0 ? void 0 : _b.indexName); | ||
this.applyFilters(query, options); | ||
if (options.fields) | ||
query.projection(options.fields); | ||
query.limit(1); | ||
const command = query.get(); | ||
const result = await this.dynamoDbClientService.query(command); | ||
if ((result === null || result === void 0 ? void 0 : result.Items) && ((_a = result.Items) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||
if ((result === null || result === void 0 ? void 0 : result.Items) && ((_c = result.Items) === null || _c === void 0 ? void 0 : _c.length) > 0) { | ||
return result.Items[0]; | ||
@@ -75,3 +147,4 @@ } | ||
options.filters.forEach((filter) => { | ||
const isWhereProperty = whereProperties.includes(filter.attribute); | ||
const isWhereProperty = whereProperties.includes(filter.attribute) && | ||
!filter.omitPrimary; | ||
isWhereProperty && !options.useScan | ||
@@ -108,66 +181,2 @@ ? this.applyWhereFilter(query, filter) | ||
} | ||
async fetchResults(command, limit = 100, useScan = false) { | ||
var _a, _b, _c, _d, _e; | ||
let results = []; | ||
let LastEvaluatedKey = {}; | ||
do { | ||
if (this.isNotEmptyObject(LastEvaluatedKey)) | ||
command.ExclusiveStartKey = LastEvaluatedKey; | ||
const result = await (useScan | ||
? this.dynamoDbClientService.scan(command) | ||
: this.dynamoDbClientService.query(command)); | ||
command.Limit = ((_a = command.Limit) !== null && _a !== void 0 ? _a : 0) - ((_c = (_b = result.Items) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0); | ||
results = (_d = result.Items) !== null && _d !== void 0 ? _d : []; | ||
LastEvaluatedKey = (_e = result.LastEvaluatedKey) !== null && _e !== void 0 ? _e : {}; | ||
} while (results.length < limit && | ||
this.isNotEmptyObject(LastEvaluatedKey)); | ||
const lastEvaluatedKey = this.isNotEmptyObject(LastEvaluatedKey) | ||
? this.encryptPaginationKey(LastEvaluatedKey) | ||
: null; | ||
return { items: results, lastEvaluatedKey }; | ||
} | ||
applyPagination(query, pagination) { | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.limit) | ||
query.limit(pagination.limit); | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.from) | ||
query.startKey(this.decryptPaginationKey(pagination.from)); | ||
} | ||
find(options = {}) { | ||
var _a, _b, _c, _d; | ||
const query = new queryBuilder_service_1.default(options.useScan); | ||
if ((_a = options.index) === null || _a === void 0 ? void 0 : _a.indexName) { | ||
query.usingIndex((_b = options.index) === null || _b === void 0 ? void 0 : _b.indexName); | ||
} | ||
this.applySorting(query, options.sorting, (_c = options.index) === null || _c === void 0 ? void 0 : _c.indexName); | ||
this.applyPagination(query, options.pagination); | ||
if (options.consistentRead) | ||
query.consistentRead(options.consistentRead); | ||
if (options.fields) | ||
query.projection(options.fields); | ||
this.applyFilters(query, options); | ||
return this.fetchResults(query.get(), (_d = options.pagination) === null || _d === void 0 ? void 0 : _d.limit, options.useScan).then((res) => { | ||
var _a, _b; | ||
const pagination = {}; | ||
if (res.lastEvaluatedKey) | ||
pagination.from = res.lastEvaluatedKey; | ||
if ((_a = options.pagination) === null || _a === void 0 ? void 0 : _a.limit) | ||
pagination.limit = (_b = options.pagination) === null || _b === void 0 ? void 0 : _b.limit; | ||
return { | ||
items: res.items, | ||
pagination, | ||
count: res.items.length, | ||
}; | ||
}); | ||
} | ||
async findAll(options = {}, allResults = []) { | ||
const { items, pagination } = await this.find(options); | ||
allResults.push(...items); | ||
if (pagination === null || pagination === void 0 ? void 0 : pagination.from) | ||
await this.findAll(Object.assign(Object.assign({}, options), { pagination }), allResults); | ||
return { | ||
items: allResults, | ||
pagination: null, | ||
count: allResults.length, | ||
}; | ||
} | ||
async update(filters, data, { replace = false }) { | ||
@@ -174,0 +183,0 @@ const savedRecord = await this.findItem({ |
@@ -11,3 +11,3 @@ "use strict"; | ||
get connectionString() { | ||
return process.env.PG_CONNECTION_STRING; | ||
return process.env.MULTIPLATFORM_PG_CONNECTION_STRING; | ||
} | ||
@@ -14,0 +14,0 @@ async getClient() { |
@@ -12,2 +12,3 @@ "use strict"; | ||
const tableHelper_1 = require("../../../helpers/tableHelper"); | ||
const queryHelpers_1 = require("../../../helpers/queryHelpers"); | ||
class PostgresqlClientService extends query_service_1.default { | ||
@@ -108,3 +109,5 @@ constructor(tableSchema) { | ||
} | ||
getSelectClause(fields) { | ||
getSelectClause(aggregateFunction, fields = []) { | ||
if (aggregateFunction) | ||
return `CAST(${aggregateFunction}(1) AS INTEGER) AS "${(0, queryHelpers_1.buildAggFunctionAlias)(aggregateFunction)}"`; | ||
if (!(fields === null || fields === void 0 ? void 0 : fields.length)) | ||
@@ -114,7 +117,9 @@ return '*'; | ||
} | ||
async findCommand(options) { | ||
let query = `SELECT ${this.getSelectClause(options === null || options === void 0 ? void 0 : options.fields)} FROM ${pg_format_1.default.ident(this.dbSchema)}.${pg_format_1.default.ident(this.tableName)}`; | ||
query = this.addFiltersToQuery(query, options === null || options === void 0 ? void 0 : options.filters); | ||
query = this.addOrderByToQuery(query, options === null || options === void 0 ? void 0 : options.sorting); | ||
query = this.addPaginationToQuery(query, options === null || options === void 0 ? void 0 : options.pagination); | ||
async findCommand(options = {}) { | ||
let query = `SELECT ${this.getSelectClause(options.aggregateFunction, options.fields)} FROM ${pg_format_1.default.ident(this.dbSchema)}.${pg_format_1.default.ident(this.tableName)}`; | ||
query = this.addFiltersToQuery(query, options.filters); | ||
if (!options.aggregateFunction) { | ||
query = this.addOrderByToQuery(query, options.sorting); | ||
query = this.addPaginationToQuery(query, options.pagination); | ||
} | ||
return (await this.runQuery(query)).rows; | ||
@@ -121,0 +126,0 @@ } |
@@ -11,2 +11,4 @@ "use strict"; | ||
const tableHelper_1 = require("../../../helpers/tableHelper"); | ||
const constants_1 = require("../../../utils/constants"); | ||
const queryHelpers_1 = require("../../../helpers/queryHelpers"); | ||
class PostgreSqlCrudService extends postgreSqlClient_service_1.default { | ||
@@ -51,14 +53,25 @@ constructor(tableSchema) { | ||
} | ||
find(findOptions) { | ||
async processQueryResult(findOptions, omitPagination = false) { | ||
const { pagination } = findOptions; | ||
return this.findCommand(findOptions).then((items) => { | ||
return { items, pagination, count: items.length }; | ||
}); | ||
const rows = await this.findCommand(findOptions); | ||
const items = rows.map((row) => this.getItem(row)); | ||
const result = { | ||
items, | ||
pagination: omitPagination ? null : pagination, | ||
count: items.length, | ||
}; | ||
return result; | ||
} | ||
findAll(findOptions) { | ||
return this.findCommand(findOptions).then((rows) => { | ||
const items = rows.map((row) => this.getItem(row)); | ||
return { items, pagination: null, count: items.length }; | ||
}); | ||
async find(findOptions) { | ||
return this.processQueryResult(findOptions); | ||
} | ||
async findAll(findOptions) { | ||
return this.processQueryResult(findOptions, true); | ||
} | ||
async findCount(findOptions) { | ||
const items = await this.findCommand(Object.assign(Object.assign({}, findOptions), { aggregateFunction: constants_1.AGGREGATE_FUNCTIONS.COUNT })); | ||
const aggFunctionProperty = (0, queryHelpers_1.buildAggFunctionAlias)(constants_1.AGGREGATE_FUNCTIONS.COUNT); | ||
const item = items.length ? items[0] : {}; | ||
return item[aggFunctionProperty] || 0; | ||
} | ||
async update(filters, data) { | ||
@@ -65,0 +78,0 @@ const savedRecord = await this.findItem({ filters }); |
@@ -9,5 +9,5 @@ "use strict"; | ||
constructor(usePool) { | ||
const connectionString = process.env.PG_CONNECTION_STRING || ''; | ||
const connectionString = process.env.MULTIPLATFORM_PG_CONNECTION_STRING || ''; | ||
if (!connectionString) { | ||
throw new Error('PG_CONNECTION_STRING environment variable must be configured'); | ||
throw new Error('MULTIPLATFORM_PG_CONNECTION_STRING environment variable must be configured'); | ||
} | ||
@@ -14,0 +14,0 @@ this.connectionService = new connection_service_1.default(usePool); |
@@ -21,2 +21,3 @@ "use strict"; | ||
__exportStar(require("./connectionClosingMode.type"), exports); | ||
__exportStar(require("./aggregateFunction.type"), exports); | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const constants_1 = require("../utils/constants"); | ||
const VALID_SORT_DIRECTIONS = Object.values(constants_1.SORT_DIRECTIONS); | ||
//# sourceMappingURL=sortDirection.type.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DEFAULT_PG_SCHEMA = exports.POSTGRES_FILTER_OPERATOR_MAP = exports.FilterOperator = exports.FILTER_LOGIC_OPERATORS = exports.CONNECTION_CLOSING_MODES = exports.SORT_DIRECTIONS = exports.DYNAMODB_OPERATORS = exports.FILTER_OPERATOR_MAP = void 0; | ||
exports.AGGREGATE_FUNCTIONS = exports.DEFAULT_PG_SCHEMA = exports.POSTGRES_FILTER_OPERATOR_MAP = exports.FilterOperator = exports.FILTER_LOGIC_OPERATORS = exports.CONNECTION_CLOSING_MODES = exports.SORT_DIRECTIONS = exports.DYNAMODB_OPERATORS = exports.FILTER_OPERATOR_MAP = void 0; | ||
exports.FILTER_OPERATOR_MAP = { | ||
@@ -68,2 +68,6 @@ CONTAINS: 'contains', | ||
exports.DEFAULT_PG_SCHEMA = 'public'; | ||
var AGGREGATE_FUNCTIONS; | ||
(function (AGGREGATE_FUNCTIONS) { | ||
AGGREGATE_FUNCTIONS["COUNT"] = "COUNT"; | ||
})(AGGREGATE_FUNCTIONS || (exports.AGGREGATE_FUNCTIONS = AGGREGATE_FUNCTIONS = {})); | ||
//# sourceMappingURL=constants.js.map |
interface IFilter { | ||
attribute: string; | ||
operator?: string; | ||
value: any; | ||
value: unknown; | ||
omitPrimary?: boolean; | ||
} | ||
@@ -25,2 +26,3 @@ | ||
filters?: IFilter[] | ICompoundFilter; | ||
aggregateFunction?: AggregateFunction; | ||
sorting?: ISorting[]; | ||
@@ -37,4 +39,20 @@ pagination?: IFindPagination; | ||
pagination?: IFindPagination | null; | ||
count: number; | ||
} | ||
interface IUpdateOptions { | ||
replace?: boolean; | ||
} | ||
interface ICrudService<T> { | ||
create(entity: T): Promise<T>; | ||
findItem(options?: IFindOptions): Promise<T | null>; | ||
find(options?: IFindOptions): Promise<IFindResult<T>>; | ||
findAll(options?: IFindOptions): Promise<IFindResult<T>>; | ||
findCount(options?: IFindOptions): Promise<number>; | ||
update(filters: IFilter[] | ICompoundFilter, data: Partial<T>, options?: IUpdateOptions): Promise<any | null>; | ||
remove(filters: IFilter[] | ICompoundFilter): Promise<void>; | ||
runQuery(queryCommand: any): Promise<any>; | ||
} | ||
declare enum SORT_DIRECTIONS { | ||
@@ -48,5 +66,7 @@ ASC = "ASC", | ||
} | ||
declare enum AGGREGATE_FUNCTIONS { | ||
COUNT = "COUNT" | ||
} | ||
declare const VALID_SORT_DIRECTIONS: SORT_DIRECTIONS[]; | ||
type SortDirection = (typeof VALID_SORT_DIRECTIONS)[number]; | ||
type SortDirection = keyof typeof SORT_DIRECTIONS; | ||
@@ -66,5 +86,9 @@ interface ITableName { | ||
type FilterInput = string | IFilter[] | ICompoundFilter[] | ICompoundFilter; | ||
declare const VALID_FILTER_LOGIC_OPERATORS: FILTER_LOGIC_OPERATORS[]; | ||
type FilterLogicOperator = (typeof VALID_FILTER_LOGIC_OPERATORS)[number]; | ||
type AggregateFunction = keyof typeof AGGREGATE_FUNCTIONS; | ||
interface ISorting { | ||
@@ -91,6 +115,8 @@ column: string; | ||
findAll(options: IFindOptions): Promise<IFindResult<T>>; | ||
buildFilter(attribute: string, value: string, operator?: string): { | ||
findCount(options: IFindOptions): Promise<number>; | ||
buildFilter(attribute: string, value: string, operator?: string, options?: {}): { | ||
attribute: string; | ||
operator: string; | ||
value: string; | ||
omitPrimary: boolean; | ||
}; | ||
@@ -104,6 +130,9 @@ buildQueryIndex(indexName: string, columns: string[]): { | ||
declare function buildFilter(attribute: string, value: string, operator?: string): { | ||
declare function buildFilter(attribute: string, value: string, operator?: string, { omitPrimary }?: { | ||
omitPrimary?: boolean | undefined; | ||
}): { | ||
attribute: string; | ||
operator: string; | ||
value: string; | ||
omitPrimary: boolean; | ||
}; | ||
@@ -116,2 +145,2 @@ declare function buildQueryIndex(indexName: string, columns: string[]): { | ||
export { CrudSchema, CrudService, IFindOptions, buildFilter, buildQueryIndex, buildSort }; | ||
export { AggregateFunction, CrudSchema, CrudService, FilterInput, ICrudService, IFilter, IFindOptions, IFindPagination, ISorting, SortDirection, buildFilter, buildQueryIndex, buildSort }; |
@@ -5,3 +5,3 @@ { | ||
"main": "dist/cjs/index.js", | ||
"version": "0.0.2", | ||
"version": "0.0.3-Rev-1", | ||
"license": "MIT", | ||
@@ -34,7 +34,21 @@ "exports": { | ||
"peerDependencies": { | ||
"@aws-sdk/client-dynamodb": "^3.433.0", | ||
"@aws-sdk/lib-dynamodb": "^3.433.0", | ||
"pg": "^8.11.4", | ||
"pg-format": "^1.0.4" | ||
"@aws-sdk/client-dynamodb": "3.x", | ||
"@aws-sdk/lib-dynamodb": "3.x", | ||
"pg": "8.11.4", | ||
"pg-format": "1.0.4" | ||
}, | ||
"peerDependenciesMeta": { | ||
"@aws-sdk/client-dynamodb": { | ||
"optional": true | ||
}, | ||
"@aws-sdk/lib-dynamodb": { | ||
"optional": true | ||
}, | ||
"pg": { | ||
"optional": true | ||
}, | ||
"pg-format": { | ||
"optional": true | ||
} | ||
}, | ||
"devDependencies": { | ||
@@ -41,0 +55,0 @@ "@types/jest": "^29.5.5", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
100163
83
1339