core-services-sdk 1.3.38 → 1.3.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "core-services-sdk",
3
- "version": "1.3.38",
3
+ "version": "1.3.40",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "types": "types/index.d.ts",
@@ -35,7 +35,7 @@ export class HttpError extends Error {
35
35
  constructor(error = {}) {
36
36
  const { code, status, message, extendInfo } = error
37
37
 
38
- super(message || (status && httpStatus[status]) || code || 'Unknown error')
38
+ super(message || code || httpStatus[status] || 'Unknown error')
39
39
 
40
40
  this.code = code
41
41
  this.status = status
@@ -1,7 +1,7 @@
1
1
  import { ObjectId } from 'mongodb'
2
2
 
3
3
  /**
4
- * Pagination with SQL-like ascending/descending
4
+ * Pagination with SQL-like ascending/descending and total count
5
5
  *
6
6
  * @param {import('mongodb').Collection} collection
7
7
  * @param {Object} options
@@ -25,24 +25,74 @@ export async function paginate(
25
25
  const query = { ...filter }
26
26
  const sort = { [cursorField]: order === 'asc' ? 1 : -1 }
27
27
 
28
+ // Cursor filtering
28
29
  if (cursor) {
29
30
  if (cursorField === '_id') {
30
31
  cursor = new ObjectId(cursor)
31
32
  }
32
-
33
33
  query[cursorField] = order === 'asc' ? { $gt: cursor } : { $lt: cursor }
34
34
  }
35
35
 
36
+ // Fetch results
36
37
  const results = await collection
37
38
  .find(query, { projection })
38
39
  .sort(sort)
39
40
  .limit(limit)
40
41
  .toArray()
41
42
 
43
+ // Get total count (for the original filter, not including cursor)
44
+ const totalCount = await collection.countDocuments(filter)
45
+
46
+ const paginationEdges =
47
+ results.length > 0
48
+ ? await getPaginationEdges({
49
+ order,
50
+ filter,
51
+ results,
52
+ collection,
53
+ cursorField,
54
+ })
55
+ : { hasNext: false, hasPrevious: false }
56
+
57
+ const { hasNext, hasPrevious } = paginationEdges
42
58
  return {
43
59
  order,
60
+ totalCount,
44
61
  list: results,
45
- previous: results.length ? results[0][cursorField] : null,
46
- next: results.length ? results[results.length - 1][cursorField] : null,
62
+ previous: hasPrevious && results.length ? results[0][cursorField] : null,
63
+ next:
64
+ hasNext && results.length
65
+ ? results[results.length - 1][cursorField]
66
+ : null,
67
+ }
68
+ }
69
+
70
+ export async function getPaginationEdges({
71
+ order,
72
+ filter,
73
+ results,
74
+ collection,
75
+ cursorField,
76
+ }) {
77
+ const first = results[0][cursorField]
78
+ const last = results[results.length - 1][cursorField]
79
+
80
+ // Check if there are items before the first
81
+ const hasPrevious =
82
+ (await collection.countDocuments({
83
+ ...filter,
84
+ [cursorField]: order === 'asc' ? { $lt: first } : { $gt: first },
85
+ })) > 0
86
+
87
+ // Check if there are items after the last
88
+ const hasNext =
89
+ (await collection.countDocuments({
90
+ ...filter,
91
+ [cursorField]: order === 'asc' ? { $gt: last } : { $lt: last },
92
+ })) > 0
93
+
94
+ return {
95
+ hasNext,
96
+ hasPrevious,
47
97
  }
48
98
  }
@@ -21,11 +21,11 @@ describe('HttpError', () => {
21
21
 
22
22
  it('should fallback to default message from status if message is missing', () => {
23
23
  const error = new HttpError({
24
- code: 'BAD_REQUEST',
24
+ code: 'Missing parameter x',
25
25
  status: httpStatus.BAD_REQUEST,
26
26
  })
27
27
 
28
- expect(error.message).toBe(httpStatus[httpStatus.BAD_REQUEST])
28
+ expect(error.message).toBe('Missing parameter x')
29
29
  expect(error.extendInfo).toBeUndefined()
30
30
  })
31
31
 
@@ -54,7 +54,7 @@ describe('paginate - Integration', () => {
54
54
 
55
55
  expect(result.list).toHaveLength(5)
56
56
  expect(result.next).toBeDefined()
57
- expect(result.previous).toBeDefined()
57
+ expect(result.previous).toBeNull()
58
58
  })
59
59
 
60
60
  it('returns empty when no docs match filter', async () => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Pagination with SQL-like ascending/descending
2
+ * Pagination with SQL-like ascending/descending and total count
3
3
  *
4
4
  * @param {import('mongodb').Collection} collection
5
5
  * @param {Object} options
@@ -27,8 +27,25 @@ export function paginate(
27
27
  },
28
28
  ): Promise<{
29
29
  order: 'asc' | 'desc'
30
+ totalCount: number
30
31
  list: import('mongodb').WithId<import('bson').Document>[]
31
32
  previous: any
32
33
  next: any
33
34
  }>
35
+ export function getPaginationEdges({
36
+ order,
37
+ filter,
38
+ results,
39
+ collection,
40
+ cursorField,
41
+ }: {
42
+ order: any
43
+ filter: any
44
+ results: any
45
+ collection: any
46
+ cursorField: any
47
+ }): Promise<{
48
+ hasNext: boolean
49
+ hasPrevious: boolean
50
+ }>
34
51
  import { ObjectId } from 'mongodb'