@andrew_l/mongo-pagination 0.3.22 → 0.4.0

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.
Files changed (36) hide show
  1. package/dist/_chunks/QueryPaginator.d.mts +198 -0
  2. package/dist/_chunks/QueryPaginator.d.mts.map +1 -0
  3. package/dist/_chunks/withMongoosePagination.mjs +489 -0
  4. package/dist/_chunks/withMongoosePagination.mjs.map +1 -0
  5. package/dist/index.d.mts +13 -14
  6. package/dist/index.d.mts.map +1 -0
  7. package/dist/index.mjs +36 -46
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/mongoose-7.d.mts +9 -12
  10. package/dist/mongoose-7.d.mts.map +1 -0
  11. package/dist/mongoose-7.mjs +14 -27
  12. package/dist/mongoose-7.mjs.map +1 -1
  13. package/dist/mongoose-8.d.mts +9 -12
  14. package/dist/mongoose-8.d.mts.map +1 -0
  15. package/dist/mongoose-8.mjs +14 -27
  16. package/dist/mongoose-8.mjs.map +1 -1
  17. package/package.json +14 -11
  18. package/dist/index.cjs +0 -56
  19. package/dist/index.cjs.map +0 -1
  20. package/dist/index.d.cts +0 -150
  21. package/dist/index.d.ts +0 -150
  22. package/dist/mongoose-7.cjs +0 -36
  23. package/dist/mongoose-7.cjs.map +0 -1
  24. package/dist/mongoose-7.d.cts +0 -16
  25. package/dist/mongoose-7.d.ts +0 -16
  26. package/dist/mongoose-8.cjs +0 -36
  27. package/dist/mongoose-8.cjs.map +0 -1
  28. package/dist/mongoose-8.d.cts +0 -16
  29. package/dist/mongoose-8.d.ts +0 -16
  30. package/dist/shared/mongo-pagination.Ckfb2fG8.mjs +0 -663
  31. package/dist/shared/mongo-pagination.Ckfb2fG8.mjs.map +0 -1
  32. package/dist/shared/mongo-pagination.D7Mb8JCq.d.cts +0 -195
  33. package/dist/shared/mongo-pagination.D7Mb8JCq.d.mts +0 -195
  34. package/dist/shared/mongo-pagination.D7Mb8JCq.d.ts +0 -195
  35. package/dist/shared/mongo-pagination.odJCU2tV.cjs +0 -676
  36. package/dist/shared/mongo-pagination.odJCU2tV.cjs.map +0 -1
@@ -1,676 +0,0 @@
1
- 'use strict';
2
-
3
- const toolkit = require('@andrew_l/toolkit');
4
- const Kareem = require('kareem');
5
- const mongodb = require('mongodb');
6
- const tlPack = require('@andrew_l/tl-pack');
7
- const d = require('debug');
8
- const node_stream = require('node:stream');
9
-
10
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
-
12
- const Kareem__default = /*#__PURE__*/_interopDefaultCompat(Kareem);
13
- const d__default = /*#__PURE__*/_interopDefaultCompat(d);
14
-
15
- const OBJECT_ID_TOKEN = 100;
16
- const extensions = [
17
- tlPack.createExtension(OBJECT_ID_TOKEN, {
18
- encode(value) {
19
- if (value?._bsontype?.toLowerCase() === "objectid") {
20
- this.writeBytes(value.id);
21
- }
22
- },
23
- decode() {
24
- const bytes = this.readBytes();
25
- return new mongodb.ObjectId(bytes);
26
- }
27
- })
28
- ];
29
- const TokenStructure = tlPack.defineStructure({
30
- name: "PaginationToken",
31
- version: 1,
32
- checksum: true,
33
- properties: {
34
- modelNameCrc: { type: tlPack.CORE_TYPES.Int32, required: true },
35
- keys: { type: [String], required: true },
36
- sortDirection: { type: [null], required: true },
37
- sortValues: { type: [null], required: true },
38
- payload: { type: Object }
39
- }
40
- });
41
- class Token {
42
- /**
43
- * The CRC of the model name, used for verify the model.
44
- */
45
- modelNameCRC = 0;
46
- /**
47
- * The sorting direction used for pagination building pagination query.
48
- */
49
- sortDirection = {};
50
- /**
51
- * The sorting values associated with the pagination.
52
- */
53
- sortValues = {};
54
- /**
55
- * The payload of the token, which can contain any associated metadata or data (may be `null`).
56
- */
57
- payload = null;
58
- constructor(options) {
59
- if (options) {
60
- Object.assign(this, { ...options, modelName: void 0 });
61
- if (options.modelName) {
62
- this.modelNameCRC = toolkit.crc32(options.modelName);
63
- }
64
- }
65
- }
66
- /**
67
- * Retrieves the string representation of token.
68
- */
69
- stringify() {
70
- return toolkit.base62Fast.encode(this.buffer());
71
- }
72
- /**
73
- * Retrieves binary buffer representation of token.
74
- */
75
- buffer() {
76
- const struct = new TokenStructure({
77
- modelNameCrc: this.modelNameCRC,
78
- sortDirection: Object.values(this.sortDirection),
79
- sortValues: Object.values(this.sortValues),
80
- keys: Object.keys(this.sortValues),
81
- payload: this.payload
82
- });
83
- return struct.toBuffer({ extensions });
84
- }
85
- /**
86
- * Encode token from provided value
87
- */
88
- static from(value) {
89
- const buffer = Buffer.isBuffer(value) || value instanceof Uint8Array ? value : toolkit.base62Fast.decode(value);
90
- const struct = TokenStructure.fromBuffer(buffer, { extensions });
91
- const token = new Token();
92
- token.modelNameCRC = struct.modelNameCrc;
93
- token.sortDirection = {};
94
- token.sortValues = {};
95
- token.payload = struct.payload ?? {};
96
- for (let idx = 0; idx < struct.keys.length; idx++) {
97
- token.sortValues[struct.keys[idx]] = struct.sortValues[idx];
98
- token.sortDirection[struct.keys[idx]] = struct.sortDirection[idx];
99
- }
100
- return token;
101
- }
102
- }
103
- function parseToken(value) {
104
- return Token.from(value);
105
- }
106
- function createToken(options) {
107
- return new Token(options);
108
- }
109
-
110
- const debug = {
111
- init: d__default("mongo-pagination:init"),
112
- tweak: d__default("mongo-pagination:tweak"),
113
- exec: d__default("mongo-pagination:exec"),
114
- stream: d__default("mongo-pagination:query:stream")
115
- };
116
-
117
- function isEmptyObject(obj) {
118
- return !toolkit.isObject(obj) || toolkit.isEmpty(obj);
119
- }
120
- function sameKeys(...args) {
121
- return toolkit.intersection(...args.map((v) => Object.keys(v)));
122
- }
123
- function defineGetter(obj, key, getterFn) {
124
- delete obj[key];
125
- Object.defineProperty(obj, key, {
126
- get: getterFn,
127
- enumerable: true,
128
- configurable: true
129
- });
130
- }
131
- function isLastKeys(value, keys, strictOrder) {
132
- const objKeys = toolkit.isObject(value) ? Object.keys(value) : [];
133
- const lastKeys = objKeys.slice(-keys.length);
134
- if (lastKeys.length !== keys.length) {
135
- return false;
136
- }
137
- for (let idx = 0; idx < keys.length; idx++) {
138
- {
139
- if (!lastKeys.includes(keys[idx])) {
140
- return false;
141
- }
142
- }
143
- }
144
- return true;
145
- }
146
- function toObject(value) {
147
- return toolkit.isFunction(value?.toObject) ? value?.toObject() : value;
148
- }
149
-
150
- function prepareDirection(direction = 1) {
151
- const value = `${direction}`.toLowerCase();
152
- if (isMeta(direction)) return direction;
153
- switch (value) {
154
- case "ascending":
155
- case "asc":
156
- case "1":
157
- return 1;
158
- case "descending":
159
- case "desc":
160
- case "-1":
161
- return -1;
162
- default:
163
- throw new mongodb.MongoInvalidArgumentError(
164
- `Invalid sort direction: ${JSON.stringify(direction)}`
165
- );
166
- }
167
- }
168
- function isMeta(t) {
169
- return typeof t === "object" && t != null && "$meta" in t && typeof t.$meta === "string";
170
- }
171
- function isPair(t) {
172
- if (Array.isArray(t) && t.length === 2) {
173
- try {
174
- prepareDirection(t[1]);
175
- return true;
176
- } catch {
177
- return false;
178
- }
179
- }
180
- return false;
181
- }
182
- function isDeep(t) {
183
- return Array.isArray(t) && Array.isArray(t[0]);
184
- }
185
- function isMap(t) {
186
- return t instanceof Map && t.size > 0;
187
- }
188
- function pairToMap(v) {
189
- return /* @__PURE__ */ new Map([[`${v[0]}`, prepareDirection([v[1]])]]);
190
- }
191
- function deepToMap(t) {
192
- const sortEntries = t.map(([k, v]) => [
193
- `${k}`,
194
- prepareDirection(v)
195
- ]);
196
- return new Map(sortEntries);
197
- }
198
- function stringsToMap(t) {
199
- const sortEntries = t.map((key) => [`${key}`, 1]);
200
- return new Map(sortEntries);
201
- }
202
- function objectToMap(t) {
203
- const sortEntries = Object.entries(t).map(([k, v]) => [
204
- `${k}`,
205
- prepareDirection(v)
206
- ]);
207
- return new Map(sortEntries);
208
- }
209
- function mapToMap(t) {
210
- const sortEntries = Array.from(t).map(([k, v]) => [
211
- `${k}`,
212
- prepareDirection(v)
213
- ]);
214
- return new Map(sortEntries);
215
- }
216
- function formatSort(sort, direction) {
217
- if (sort == null) return void 0;
218
- if (typeof sort === "string")
219
- return /* @__PURE__ */ new Map([[sort, prepareDirection(direction)]]);
220
- if (typeof sort !== "object") {
221
- throw new mongodb.MongoInvalidArgumentError(
222
- `Invalid sort format: ${JSON.stringify(sort)} Sort must be a valid object`
223
- );
224
- }
225
- if (!Array.isArray(sort)) {
226
- return isMap(sort) ? mapToMap(sort) : Object.keys(sort).length ? objectToMap(sort) : void 0;
227
- }
228
- if (!sort.length) return void 0;
229
- if (isDeep(sort)) return deepToMap(sort);
230
- if (isPair(sort)) return pairToMap(sort);
231
- return stringsToMap(sort);
232
- }
233
-
234
- const DEF_LIMIT = 10;
235
- function createRangeFilter(sortDirection, sortValues) {
236
- const sortCmd = formatSort(sortDirection) ?? {};
237
- const keys = [];
238
- for (const [sortKey, sortValue] of sortCmd.entries()) {
239
- if (sortValues[sortKey] === void 0) continue;
240
- if (!toolkit.isNumber(sortValue)) continue;
241
- keys.push(sortKey);
242
- }
243
- const op = (sortKey) => {
244
- const direction = sortCmd.get(sortKey);
245
- return direction === 1 ? "$gt" : "$lt";
246
- };
247
- const val = (sortKey) => sortValues[sortKey];
248
- if (keys.length === 0) {
249
- return {};
250
- } else if (keys.length === 1) {
251
- const sortKey = keys[0];
252
- return {
253
- [sortKey]: {
254
- [op(sortKey)]: val(sortKey)
255
- }
256
- };
257
- }
258
- const $or = [];
259
- const keysAmount = keys.length;
260
- for (let i = 0; i < keysAmount; i++) {
261
- const sortKey = keys[i];
262
- if (i === 0) {
263
- $or.push({
264
- [sortKey]: { [op(sortKey)]: val(sortKey) }
265
- });
266
- } else {
267
- const filter = {};
268
- keys.slice(0, i).map((sortKey3) => {
269
- filter[sortKey3] = { $eq: val(sortKey3) };
270
- });
271
- const sortKey2 = keys[i];
272
- filter[sortKey2] = {
273
- [op(sortKey2)]: val(sortKey2)
274
- };
275
- $or.push(filter);
276
- }
277
- }
278
- if ($or.length === 1) return $or[0];
279
- return { $or };
280
- }
281
- function mergeFilters(first, second) {
282
- switch (true) {
283
- // Just return second
284
- case isEmptyObject(first):
285
- return toolkit.deepClone(second);
286
- // Just return first
287
- case isEmptyObject(second):
288
- return toolkit.deepClone(first);
289
- // Just assign when no conflicts
290
- case sameKeys(first, second).length === 0:
291
- return Object.assign(toolkit.deepClone(first), toolkit.deepClone(second));
292
- // Merge with $and way
293
- case Array.isArray(first.$and):
294
- first = toolkit.deepClone(first);
295
- second = toolkit.deepClone(second);
296
- if (Object.keys(second).length === 1 && second.$and) {
297
- first.$and.push(...second.$and);
298
- } else {
299
- first.$and.push(second);
300
- }
301
- return first;
302
- // Regular merge via $and wrapping
303
- default:
304
- return {
305
- $and: [toolkit.deepClone(first), toolkit.deepClone(second)]
306
- };
307
- }
308
- }
309
- function tweakQuery({
310
- paginationFields,
311
- token,
312
- query
313
- }) {
314
- let queryOptions = toolkit.deepClone(query.getOptions());
315
- let queryFilter = toolkit.deepClone(query.getFilter());
316
- paginationFields = toolkit.deepClone(paginationFields);
317
- if (queryOptions.sort) {
318
- const sortMap = formatSort(queryOptions.sort);
319
- if (sortMap) {
320
- queryOptions.sort = Object.fromEntries(sortMap.entries());
321
- }
322
- }
323
- if (token) {
324
- if (!isEmptyObject(token.sortDirection)) {
325
- debug.tweak(
326
- "set from token [queryOptions.sort] = %o",
327
- token.sortDirection
328
- );
329
- queryOptions.sort = token.sortDirection;
330
- }
331
- if (!isEmptyObject(token.sortValues)) {
332
- const rangeFilter = createRangeFilter(
333
- queryOptions.sort,
334
- token.sortValues
335
- );
336
- debug.tweak(
337
- "range conditions:\n sortDirection = %o\n sortValues = %o\n result = %o",
338
- queryOptions.sort,
339
- token.sortValues,
340
- rangeFilter
341
- );
342
- queryFilter = mergeFilters(queryFilter, rangeFilter);
343
- }
344
- }
345
- if (isEmptyObject(queryOptions.sort)) {
346
- queryOptions.sort = { _id: -1 };
347
- debug.tweak("set default [queryOptions.sort] = %o", queryOptions.sort);
348
- }
349
- if (!Array.isArray(paginationFields) || !paginationFields.length) {
350
- paginationFields = Object.keys(queryOptions.sort);
351
- debug.tweak("set default [paginationFields] = %o", paginationFields);
352
- }
353
- if (!isLastKeys(queryOptions.sort, paginationFields)) {
354
- const expectedKeys = paginationFields.join(", ");
355
- throw new mongodb.MongoInvalidArgumentError(
356
- `The query sort keys must ends with "${expectedKeys}".`
357
- );
358
- }
359
- if (!queryOptions.limit) {
360
- queryOptions.limit = DEF_LIMIT + 1;
361
- debug.tweak("set default [queryOptions.limit] = %d", queryOptions.limit);
362
- } else {
363
- queryOptions.limit = Math.max(queryOptions.limit || DEF_LIMIT, 1) + 1;
364
- }
365
- query.setOptions(queryOptions);
366
- query.setFilter(queryFilter);
367
- return paginationFields;
368
- }
369
-
370
- class QueryAdapterMongoose {
371
- constructor(query) {
372
- this.query = query;
373
- }
374
- getModelName() {
375
- return this.query.model.modelName;
376
- }
377
- getOptions() {
378
- const options = this.query.getOptions();
379
- return {
380
- limit: options.limit,
381
- sort: options.sort
382
- };
383
- }
384
- getFilter() {
385
- return this.query.getFilter();
386
- }
387
- setOptions({ limit, sort }) {
388
- this.query.setOptions(toolkit.cleanEmpty({ limit, sort }));
389
- }
390
- setFilter(filter) {
391
- this.query.setQuery(filter);
392
- }
393
- toArray() {
394
- return this.query.exec();
395
- }
396
- stream() {
397
- return this.query.cursor();
398
- }
399
- }
400
-
401
- class Filter extends node_stream.Transform {
402
- constructor(has, options) {
403
- super({
404
- autoDestroy: true,
405
- objectMode: true,
406
- ...options,
407
- readableObjectMode: true,
408
- writableObjectMode: true,
409
- highWaterMark: 16
410
- });
411
- this.has = has;
412
- this._count = -1;
413
- }
414
- _count = 0;
415
- _transform(chunk, encoding, next) {
416
- const result = this.has(chunk, ++this._count);
417
- if (typeof result === "boolean") {
418
- if (result) {
419
- return next(null, chunk);
420
- } else {
421
- return next();
422
- }
423
- }
424
- if ("then" in result) {
425
- return void result.then((r) => {
426
- if (r) next(null, chunk);
427
- }).catch(next);
428
- }
429
- next();
430
- }
431
- }
432
- function streamFilter(fn, options) {
433
- return new Filter(fn, options);
434
- }
435
-
436
- class QueryPaginator {
437
- constructor(query, {
438
- paginationFields = [],
439
- postQuery,
440
- preQuery,
441
- next: previousToken,
442
- debugQuery = false
443
- } = {}) {
444
- this.query = query;
445
- this.paginationFields = paginationFields;
446
- this.debugQuery = debugQuery;
447
- this.next = createToken({
448
- modelName: query.getModelName(),
449
- sortDirection: {},
450
- sortValues: {},
451
- payload: {}
452
- });
453
- if (previousToken) {
454
- try {
455
- this.previous = Token.from(previousToken);
456
- this.paginationFields = Object.keys(this.previous.sortValues);
457
- debug.init("parse previous = %o", this.previous);
458
- debug.init(
459
- "set from previous [paginationFields] = %o",
460
- this.paginationFields
461
- );
462
- } catch (orignErr) {
463
- const err = new mongodb.MongoInvalidArgumentError(
464
- "Failed to parse next pagination cursor.",
465
- { cause: toolkit.toError(orignErr) }
466
- );
467
- throw err;
468
- }
469
- const modelNameCRC = toolkit.crc32(query.getModelName());
470
- debug.init(
471
- "compare model name: previous = %d, query = %d",
472
- this.previous.modelNameCRC,
473
- modelNameCRC
474
- );
475
- if (modelNameCRC !== this.previous.modelNameCRC) {
476
- throw new mongodb.MongoInvalidArgumentError(
477
- "The model name of next cursor token is not equal with query model name. Expected: " + this.query.getModelName()
478
- );
479
- }
480
- }
481
- if (preQuery) this.pre("query", preQuery);
482
- if (postQuery) this.post("query", postQuery);
483
- defineGetter(this.next, "sortDirection", () => {
484
- const sortMap = formatSort(this.query.getOptions().sort);
485
- return sortMap ? Object.fromEntries(sortMap.entries()) : {};
486
- });
487
- defineGetter(this.next, "sortValues", () => {
488
- if (!this.resLastItem) {
489
- return {};
490
- }
491
- return toolkit.pick(this.resLastItem, this.paginationFields);
492
- });
493
- debug.init("with options = %o", arguments[1]);
494
- }
495
- hooks = new Kareem__default();
496
- next;
497
- previous;
498
- resHasNext = false;
499
- resLastItem = null;
500
- paginationFields;
501
- tweaked = false;
502
- debugQuery = false;
503
- getMetadata = () => this.metadata;
504
- /**
505
- * Retrieves metadata about the current state of pagination.
506
- */
507
- get metadata() {
508
- return {
509
- hasNext: this.hasNext,
510
- next: this.nextTokenString
511
- };
512
- }
513
- /**
514
- * Indicates whether there is a next page available.
515
- */
516
- get hasNext() {
517
- return this.resHasNext;
518
- }
519
- /**
520
- * Retrieves the token for the next page.
521
- */
522
- get nextToken() {
523
- return this.next;
524
- }
525
- /**
526
- * Retrieves the string representation of the next page token.
527
- * If there is no next page, returns `null`.
528
- */
529
- get nextTokenString() {
530
- if (!this.resHasNext) {
531
- return null;
532
- }
533
- return this.next.stringify();
534
- }
535
- /**
536
- * Retrieves the token for the previous page.
537
- */
538
- get prevToken() {
539
- return this.previous || null;
540
- }
541
- /**
542
- * Retrieves the string representation of the previous page token.
543
- */
544
- get prevTokenString() {
545
- return this.previous ? this.previous.stringify() : null;
546
- }
547
- getQuery() {
548
- return this.query;
549
- }
550
- pre(hookName, fn) {
551
- this.hooks.pre(hookName, fn);
552
- return this;
553
- }
554
- post(hookName, fn) {
555
- this.hooks.post(hookName, fn);
556
- return this;
557
- }
558
- stream() {
559
- return new Promise((resolve, reject) => {
560
- this.hooks.execPre("query", this, [], (error) => {
561
- if (error) return reject(error);
562
- try {
563
- this.maybeTweak();
564
- } catch (err) {
565
- return reject(err);
566
- }
567
- const limit = this.query.getOptions().limit;
568
- const filter = streamFilter((item, index) => {
569
- if (index + 1 === limit) {
570
- this.resHasNext = true;
571
- debug.stream(
572
- "has next:\n cutoff_idx = %d\n next = %j",
573
- index,
574
- this.next
575
- );
576
- return false;
577
- } else {
578
- this.resLastItem = toObject(item);
579
- }
580
- return true;
581
- });
582
- const stream = this.query.stream().pipe(filter);
583
- resolve(stream);
584
- });
585
- });
586
- }
587
- /** @internal */
588
- maybeTweak() {
589
- if (!this.tweaked) {
590
- this.tweak();
591
- }
592
- return this;
593
- }
594
- /** @internal */
595
- tweak() {
596
- this.paginationFields = tweakQuery({
597
- query: this.query,
598
- paginationFields: this.paginationFields,
599
- token: this.previous
600
- });
601
- this.tweaked = true;
602
- return this;
603
- }
604
- /** @internal */
605
- _handleResult(items) {
606
- const limit = this.query.getOptions().limit;
607
- if (items.length === limit) {
608
- items.pop();
609
- this.resHasNext = true;
610
- }
611
- this.resLastItem = toObject(items.at(-1));
612
- if (this.resHasNext) {
613
- debug.exec(
614
- "has next:\n cutoff_idx = %d\n next = %j",
615
- limit - 1,
616
- this.next
617
- );
618
- }
619
- const metadata = this.getMetadata();
620
- return { metadata, items };
621
- }
622
- /**
623
- * Executes the query and returns the results along with pagination metadata.
624
- */
625
- exec() {
626
- return new Promise((resolve, reject) => {
627
- this.hooks.execPre("query", this, [], (preHookErr) => {
628
- if (preHookErr) {
629
- return reject(preHookErr);
630
- }
631
- if (this.debugQuery) {
632
- console.info("pre tweak", {
633
- queryFilter: this.query.getFilter(),
634
- getOptions: this.query.getOptions(),
635
- prevToken: this.prevToken
636
- });
637
- }
638
- this.maybeTweak();
639
- if (this.debugQuery) {
640
- console.info("post tweak", {
641
- queryFilter: this.query.getFilter(),
642
- getOptions: this.query.getOptions(),
643
- prevToken: this.prevToken
644
- });
645
- }
646
- this.query.toArray().then((items) => {
647
- const result = this._handleResult(items);
648
- this.hooks.execPost("query", this, [], (postHookErr) => {
649
- if (postHookErr) {
650
- return reject(postHookErr);
651
- }
652
- return resolve(result);
653
- });
654
- }).catch(reject);
655
- });
656
- });
657
- }
658
- then = (onfulfilled, onrejected) => this.exec().then(onfulfilled, onrejected);
659
- cath = (onrejected) => this.exec().catch(onrejected);
660
- finally = (onfinally) => this.exec().finally(onfinally);
661
- }
662
-
663
- function withMongoosePagination(query, options) {
664
- const adapter = new QueryAdapterMongoose(query);
665
- const pagin = new QueryPaginator(adapter, options);
666
- return pagin;
667
- }
668
-
669
- exports.QueryPaginator = QueryPaginator;
670
- exports.createRangeFilter = createRangeFilter;
671
- exports.createToken = createToken;
672
- exports.mergeFilters = mergeFilters;
673
- exports.parseToken = parseToken;
674
- exports.tweakQuery = tweakQuery;
675
- exports.withMongoosePagination = withMongoosePagination;
676
- //# sourceMappingURL=mongo-pagination.odJCU2tV.cjs.map