Skip to content

Commit 240dc62

Browse files
committed
chore: update dependencies and enhance TypeScript configuration
Signed-off-by: Alejandro Dominguez <adborroto90@gmail.com>
1 parent 54a54b7 commit 240dc62

File tree

8 files changed

+114
-26
lines changed

8 files changed

+114
-26
lines changed

package-lock.json

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
},
4040
"homepage": "https://github.com/mixmaxhq/mongo-cursor-pagination#readme",
4141
"dependencies": {
42-
"@types/express": "^5.0.0",
42+
"@types/express": "^4.17.21",
4343
"base64-url": "^2.2.0",
4444
"bson": "^4.7.2",
4545
"object-path": "^0.11.8",
@@ -54,7 +54,7 @@
5454
"@mixmaxhq/semantic-release-config": "^2.0.0",
5555
"@mixmaxhq/ts-config": "^1.2.1",
5656
"@types/jest": "^29.5.12",
57-
"@types/node": "^22.7.4",
57+
"@types/node": "^18.19.70",
5858
"@typescript-eslint/eslint-plugin": "^4.33.0",
5959
"@typescript-eslint/parser": "^4.33.0",
6060
"cz-conventional-changelog": "^3.2.0",

src/aggregate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default async function aggregate(
4343
aggregationPipeline = params.aggregation.concat([{ $match }, { $sort }, { $limit }]);
4444
}
4545

46-
const options: Record<string, any> = { ...params.options };
46+
const options: Record<string, any> = { ...(params.options || {}) };
4747

4848
// Handle collation
4949
const isCollationNull = params.collation === null;

src/find.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default async function findWithPagination(
3434
let response;
3535
if (params.sortCaseInsensitive) {
3636
// For case-insensitive sorting, we need to work with an aggregation:
37-
response = aggregate(
37+
response = await aggregate(
3838
collection,
3939
Object.assign({}, params, {
4040
aggregation: params.query ? [{ $match: params.query }] : [],

src/search.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { Collection, Document } from 'mongodb';
22
import _ from 'underscore';
33
import config from './config';
4-
import bsonUrlEncoding from './utils/bsonUrlEncoding';
4+
import bsonUrlEncoding, { Encodable } from './utils/bsonUrlEncoding';
55

66
export interface SearchParams {
77
query?: Record<string, any>;
88
limit?: number;
99
fields?: Record<string, number>;
10-
next?: string;
10+
next?: Encodable;
1111
}
1212

1313
export interface SearchResponse<T = Document> {
@@ -35,7 +35,7 @@ export default async function search<T = Document>(
3535
params: SearchParams
3636
): Promise<SearchResponse<T>> {
3737
if (params.next) {
38-
params.next = bsonUrlEncoding.decode(params.next) as string;
38+
params.next = bsonUrlEncoding.decode(params.next as string);
3939
}
4040

4141
params = _.defaults(params, {

src/utils/sanitizeParams.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ export default async function sanitizeParams(
5252
if (doc) {
5353
// Handle usage of dot notation in paginatedField
5454
let prop = getPropertyViaDotNotation(params.paginatedField, doc);
55-
if (params.sortCaseInsensitive) prop = (prop as string).toLowerCase();
55+
if (params.sortCaseInsensitive && typeof prop === 'string') {
56+
prop = prop.toLowerCase();
57+
}
5658
params.next = [prop, params.after];
5759
}
5860
} else {
@@ -77,7 +79,10 @@ export default async function sanitizeParams(
7779
if (doc) {
7880
// Handle usage of dot notation in paginatedField
7981
let prop = getPropertyViaDotNotation(params.paginatedField, doc);
80-
if (params.sortCaseInsensitive) prop = (prop as string).toLowerCase();
82+
if (params.sortCaseInsensitive && typeof prop === 'string') {
83+
prop = prop.toLowerCase();
84+
}
85+
8186
params.previous = [prop, params.before];
8287
}
8388
} else {

test/utils/sanitizeParams.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Collection } from 'mongodb';
2+
import sanitizeParams from '../../src/utils/sanitizeParams';
3+
import bsonUrlEncoding from '../../src/utils/bsonUrlEncoding';
4+
import config from '../../src/config';
5+
6+
describe('sanitizeParams', () => {
7+
let collection: Collection;
8+
9+
beforeEach(() => {
10+
collection = ({
11+
findOne: jest.fn(),
12+
} as unknown) as Collection;
13+
});
14+
15+
it('should decode previous and next params', async () => {
16+
const params = {
17+
previous: bsonUrlEncoding.encode([1, 'test']),
18+
next: bsonUrlEncoding.encode([1, 'test_next']),
19+
};
20+
const sanitizedParams = await sanitizeParams(collection, params);
21+
expect(sanitizedParams.previous).toEqual([1, 'test']);
22+
expect(sanitizedParams.next).toEqual([1, 'test_next']);
23+
});
24+
25+
it('should set default limit and paginatedField', async () => {
26+
const params = {};
27+
const sanitizedParams = await sanitizeParams(collection, params);
28+
expect(sanitizedParams.limit).toBe(50);
29+
expect(sanitizedParams.paginatedField).toBe('_id');
30+
});
31+
32+
it('should limit the number of results', async () => {
33+
const params = { limit: 0 };
34+
let sanitizedParams = await sanitizeParams(collection, params);
35+
expect(sanitizedParams.limit).toBe(1);
36+
37+
params.limit = 2000;
38+
sanitizedParams = await sanitizeParams(collection, params);
39+
expect(sanitizedParams.limit).toBe(config.MAX_LIMIT);
40+
});
41+
42+
it('should handle `after` param', async () => {
43+
const params = { after: 'some_id' };
44+
const sanitizedParams = await sanitizeParams(collection, params);
45+
expect(sanitizedParams.next).toBe('some_id');
46+
});
47+
48+
it('should handle `before` param', async () => {
49+
const params = { before: 'some_id' };
50+
const sanitizedParams = await sanitizeParams(collection, params);
51+
expect(sanitizedParams.previous).toBe('some_id');
52+
});
53+
54+
it('should include paginatedField in query fields', async () => {
55+
const params = { fields: { name: 1 } };
56+
const sanitizedParams = await sanitizeParams(collection, params);
57+
expect(sanitizedParams.fields).toEqual({ _id: 1, name: 1 });
58+
});
59+
60+
it('should handle `sortCaseInsensitive` param', async () => {
61+
const params = {
62+
paginatedField: 'name',
63+
sortCaseInsensitive: true,
64+
before: 'some_id',
65+
};
66+
const mockDoc = { _id: 'some_id', name: 'John' };
67+
(collection.findOne as jest.Mock).mockResolvedValueOnce(mockDoc);
68+
69+
const paramsWithBefore = {
70+
...params,
71+
before: 'some_id',
72+
};
73+
const sanitizedParamsWithBefore = await sanitizeParams(collection, paramsWithBefore);
74+
expect(sanitizedParamsWithBefore.previous).toEqual(['john', 'some_id']);
75+
76+
expect(collection.findOne).toHaveBeenCalledWith({ _id: 'some_id' }, { name: true, _id: false });
77+
});
78+
});

tsconfig.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
{
22
"extends": "@mixmaxhq/ts-config/tsconfig.json",
33
"compilerOptions": {
4-
"outDir": "dist/node"
4+
"outDir": "dist/node",
5+
"declaration": true,
6+
"sourceMap": true,
7+
"removeComments": true,
8+
"importHelpers": true,
9+
"skipLibCheck": true
510
},
611
"include": [
712
"./src/**/*"

0 commit comments

Comments
 (0)