Skip to content

Commit

Permalink
Merge pull request #95 from ExWeiv/dev
Browse files Browse the repository at this point in the history
New TS Update for Stronger Type Support with Generics and ID Converting for Filters
  • Loading branch information
loeiks authored Jul 24, 2024
2 parents bfdc2b3 + 855c9bb commit ca8bdac
Show file tree
Hide file tree
Showing 142 changed files with 1,384 additions and 1,082 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ In this file you can find what's changed in each version. (Versions with -dev, -

---

### 4.8.0

- Better type support added for many functions with optional type parameters. Now optionally you can use TS generics to generate dynamically generated types for many functions but not for all.
- Now all _id fields are automatically converted into ObjectId type including sub documents, arrays etc. Any _id field with valid ObjectId string will be converted into ObjectId type when passing to MongoDB driver.
- Planning of better TS type support and schema validation feature started. We will add schema validation feature with the future updates.
- Some BUG Fixes

### 4.7.1

- Examples included in documentation.
Expand Down
69 changes: 56 additions & 13 deletions app/lib/Filter/data_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports.WeivDataFilter = void 0;
const lodash_1 = require("lodash");
const validator_1 = require("../Helpers/validator");
const error_manager_1 = require("../Errors/error_manager");
const id_converters_1 = require("../Functions/id_converters");
class WeivDataFilter {
constructor() {
this.filters = {};
Expand All @@ -18,12 +19,18 @@ class WeivDataFilter {
this.filters["$and"].push((0, validator_1.copyOwnPropsOnly)(query.filters));
return this;
}
between(propertyName, rangeStart, rangeEnd) {
between(propertyName, rangeStart, rangeEnd, convertIds) {
if (!propertyName || typeof propertyName !== "string" || !rangeStart || !rangeEnd) {
(0, error_manager_1.kaptanLogar)("00020", `propertyName, rangeStart and rangeEnd must have valid values to work with between method!`);
}
if (!this.memoizedBetween) {
this.memoizedBetween = (0, lodash_1.memoize)((propertyName, rangeStart, rangeEnd) => {
if (propertyName === "_id" || convertIds) {
return this.addFilter(propertyName, {
$gte: (0, id_converters_1.convertIdToObjectId)(rangeStart),
$lte: (0, id_converters_1.convertIdToObjectId)(rangeEnd),
});
}
return this.addFilter(propertyName, {
$gte: rangeStart,
$lte: rangeEnd,
Expand Down Expand Up @@ -63,12 +70,17 @@ class WeivDataFilter {
this.memoizedEndsWith(propertyName, string);
return this;
}
eq(propertyName, value) {
eq(propertyName, value, convertIds) {
if (!propertyName || value === undefined || typeof propertyName !== "string") {
(0, error_manager_1.kaptanLogar)("00020", `propertyName and value parameter must be valid to work with eq method!`);
}
if (!this.memoizedEq) {
this.memoizedEq = (0, lodash_1.memoize)((propertyName, value) => {
if (propertyName === "_id" || convertIds) {
return this.addFilter(propertyName, {
$eq: (0, id_converters_1.convertIdToObjectId)(value),
});
}
return this.addFilter(propertyName, {
$eq: value,
});
Expand Down Expand Up @@ -101,32 +113,58 @@ class WeivDataFilter {
this.memoizedGt(propertyName, value);
return this;
}
hasAll(propertyName, value) {
hasAll(propertyName, value, convertIds) {
if (!propertyName || !value || typeof propertyName !== "string") {
(0, error_manager_1.kaptanLogar)("00020", `propertyName and value parameter must be valid to work with hasAll method!`);
}
if (!Array.isArray(value)) {
value = [value];
}
if (!this.memoizedHasAll) {
this.memoizedHasAll = (0, lodash_1.memoize)((propertyName, value) => {
return this.addFilter(propertyName, { $all: value });
});
if (propertyName === "_id" || convertIds) {
let values = [];
for (const v of value) {
values.push((0, id_converters_1.convertIdToObjectId)(v));
}
if (!this.memoizedHasAll) {
this.memoizedHasAll = (0, lodash_1.memoize)((propertyName, values) => {
return this.addFilter(propertyName, { $all: values });
});
}
}
else {
if (!this.memoizedHasAll) {
this.memoizedHasAll = (0, lodash_1.memoize)((propertyName, value) => {
return this.addFilter(propertyName, { $all: value });
});
}
}
this.memoizedHasAll(propertyName, value);
return this;
}
hasSome(propertyName, value) {
hasSome(propertyName, value, convertIds) {
if (!propertyName || !value || typeof propertyName !== "string") {
(0, error_manager_1.kaptanLogar)("00020", `propertyName and value parameter must be valid to work with hasSome method!`);
}
if (!Array.isArray(value)) {
value = [value];
}
if (!this.memoizedHasSome) {
this.memoizedHasSome = (0, lodash_1.memoize)((propertyName, value) => {
return this.addFilter(propertyName, { $in: value });
});
if (propertyName === "_id" || convertIds) {
let values = [];
for (const v of value) {
values.push((0, id_converters_1.convertIdToObjectId)(v));
}
if (!this.memoizedHasSome) {
this.memoizedHasSome = (0, lodash_1.memoize)((propertyName, values) => {
return this.addFilter(propertyName, { $in: values });
});
}
}
else {
if (!this.memoizedHasSome) {
this.memoizedHasSome = (0, lodash_1.memoize)((propertyName, value) => {
return this.addFilter(propertyName, { $in: value });
});
}
}
this.memoizedHasSome(propertyName, value);
return this;
Expand Down Expand Up @@ -179,12 +217,17 @@ class WeivDataFilter {
this.memoizedLt(propertyName, value);
return this;
}
ne(propertyName, value) {
ne(propertyName, value, convertIds) {
if (!propertyName || value === undefined || typeof propertyName !== "string") {
(0, error_manager_1.kaptanLogar)("00020", `propertyName and value parameter must be valid to work with ne method!`);
}
if (!this.memoizedNe) {
this.memoizedNe = (0, lodash_1.memoize)((propertyName, value) => {
if (propertyName === "_id" || convertIds) {
return this.addFilter(propertyName, {
$ne: (0, id_converters_1.convertIdToObjectId)(value),
});
}
return this.addFilter(propertyName, { $ne: value });
});
}
Expand Down
6 changes: 3 additions & 3 deletions app/lib/Helpers/internal_id_converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports.convertDocumentIDs = convertDocumentIDs;
exports.recursivelyConvertIds = recursivelyConvertIds;
exports.convertToStringId = convertToStringId;
const mongodb_1 = require("mongodb");
function convertDocumentIDs(doc, returnType = "String") {
function convertDocumentIDs(doc, returnType = 'String') {
if (Array.isArray(doc)) {
for (let i = 0; i < doc.length; i++) {
convertDocumentIDs(doc[i], returnType);
Expand All @@ -29,8 +29,8 @@ function convertDocumentIDs(doc, returnType = "String") {
}
return doc;
}
function recursivelyConvertIds(docs) {
docs.forEach(doc => convertDocumentIDs(doc));
function recursivelyConvertIds(docs, returnType = 'String') {
docs.forEach(doc => convertDocumentIDs(doc, returnType));
return docs;
}
function convertToStringId(id, encoding) {
Expand Down
10 changes: 6 additions & 4 deletions app/lib/Query/query_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class QueryResult extends Query {
(0, error_manager_1.kaptanLogar)("00004", `${err}`);
}
}
async distnict(propertyName, options) {
async distinct(propertyName, options) {
try {
if (!propertyName || typeof propertyName !== "string") {
(0, error_manager_1.kaptanLogar)("00001", `propertyName is not string or not a valid value!`);
Expand All @@ -133,7 +133,9 @@ class QueryResult extends Query {
const { suppressAuth, readConcern, convertIds } = options;
await this._handleConnection_(suppressAuth);
const pipeline = [];
pipeline.push(this._filters);
if (Object.keys(this._filters.$match).length > 0) {
pipeline.push(this._filters);
}
pipeline.push({ $group: { _id: `$${propertyName}` } });
pipeline.push({ $project: { distnict: "$_id", _id: 0 } });
const aggregationCursor = this._collection.aggregate(pipeline, { readConcern });
Expand All @@ -151,11 +153,11 @@ class QueryResult extends Query {
hasPrev: () => this.__hasPrev__(),
next: async () => {
this._currentPage++;
return this.distnict(propertyName, options);
return this.distinct(propertyName, options);
},
prev: async () => {
this._currentPage--;
return this.distnict(propertyName, options);
return this.distinct(propertyName, options);
},
_filters: this._filters,
_pipeline: pipeline
Expand Down
9 changes: 5 additions & 4 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@exweiv/weiv-data",
"version": "4.7.1",
"version": "4.8.0",
"description": "Custom API Library for Wix sites to connect MongoDB. Designed to easily switch from wix-data APIs.",
"main": "./lib/index.js",
"files": [
Expand Down Expand Up @@ -35,7 +35,6 @@
"lodash": "^4.17.21",
"mongodb": "^6.8.0",
"node-cache": "^5.1.2",
"typescript": "^5.5.3",
"uuid": "^10.0.0"
},
"devDependencies": {
Expand All @@ -44,7 +43,8 @@
"@types/node": "^20.14.11",
"@types/uuid": "^10.0.0",
"typedoc": "^0.26.4",
"typedoc-plugin-extras": "^3.1.0"
"typedoc-plugin-extras": "^3.1.0",
"typescript": "^5.5.3"
},
"publishConfig": {
"access": "public",
Expand Down
4 changes: 2 additions & 2 deletions app/src/Aggregate/aggregate_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export class AggregateResult extends Aggregate {
private _pageSize: number = 50;
private _currentPage: number = 1;

async run(options: WeivDataAggregateRunOptions): Promise<WeivDataAggregateResult> {
async run(options: WeivDataAggregateRunOptions): Promise<WeivDataAggregateResult<Item>> {
try {
const { readConcern, suppressAuth, convertIds } = options || {};
await this._handleConnection_(suppressAuth);
Expand All @@ -250,7 +250,7 @@ export class AggregateResult extends Aggregate {
const items: Item[] = await this._collection.aggregate(pipeline, { readConcern }).toArray();
const length: number = items.length;
const hasNext: () => boolean = () => this._currentPage * this._pageSize < items.length;
const next: () => Promise<WeivDataAggregateResult> = async () => {
const next: () => Promise<WeivDataAggregateResult<Item>> = async () => {
try {
this._currentPage++;
return await this.run(options)
Expand Down
Loading

0 comments on commit ca8bdac

Please sign in to comment.