@r5v/mongoose-paginate 1.0.12 → 1.0.14

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 (104) hide show
  1. package/README.md +207 -12
  2. package/dist/{types/aggregationPagingQuery.d.ts → aggregationPagingQuery.d.ts} +6 -7
  3. package/dist/aggregationPagingQuery.d.ts.map +1 -0
  4. package/dist/aggregationPagingQuery.js +13 -5
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +18 -1
  8. package/dist/{types/pagingQuery.d.ts → pagingQuery.d.ts} +6 -7
  9. package/dist/pagingQuery.d.ts.map +1 -0
  10. package/dist/pagingQuery.js +8 -3
  11. package/dist/tests/aggregationPagingQuery.spec.d.ts +2 -0
  12. package/dist/tests/aggregationPagingQuery.spec.d.ts.map +1 -0
  13. package/dist/tests/aggregationPagingQuery.spec.js +365 -0
  14. package/dist/tests/buildPopulateFromString.spec.d.ts +2 -0
  15. package/dist/tests/buildPopulateFromString.spec.d.ts.map +1 -0
  16. package/dist/tests/buildPopulateFromString.spec.js +223 -0
  17. package/dist/tests/dotNotation.spec.d.ts.map +1 -0
  18. package/dist/tests/findProtectedPaths.spec.d.ts.map +1 -0
  19. package/dist/tests/findProtectedPaths.spec.js +128 -6
  20. package/dist/tests/getPathsWithRef.spec.d.ts.map +1 -0
  21. package/dist/tests/getPathsWithRef.spec.js +92 -18
  22. package/dist/tests/getPropertyFromDotNotation.spec.d.ts.map +1 -0
  23. package/dist/tests/insertPopulate.spec.d.ts.map +1 -0
  24. package/dist/tests/isJsonString.spec.d.ts +2 -0
  25. package/dist/tests/isJsonString.spec.d.ts.map +1 -0
  26. package/dist/tests/isJsonString.spec.js +116 -0
  27. package/dist/tests/isValidDateString.spec.d.ts +2 -0
  28. package/dist/tests/isValidDateString.spec.d.ts.map +1 -0
  29. package/dist/tests/isValidDateString.spec.js +116 -0
  30. package/dist/tests/pagingQuery.spec.d.ts.map +1 -0
  31. package/dist/tests/pagingQuery.spec.js +238 -13
  32. package/dist/tests/parseParams.spec.d.ts +2 -0
  33. package/dist/tests/parseParams.spec.d.ts.map +1 -0
  34. package/dist/tests/parseParams.spec.js +212 -0
  35. package/dist/tests/parseSortString.spec.d.ts.map +1 -0
  36. package/dist/tests/schemaTraversal.spec.d.ts +2 -0
  37. package/dist/tests/schemaTraversal.spec.d.ts.map +1 -0
  38. package/dist/tests/schemaTraversal.spec.js +139 -0
  39. package/dist/types/index.d.ts +66 -3
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/dist/utils/buildPopulateFromString.d.ts +8 -0
  42. package/dist/utils/buildPopulateFromString.d.ts.map +1 -0
  43. package/dist/utils/buildPopulateFromString.js +54 -49
  44. package/dist/utils/dotNotation.d.ts +11 -0
  45. package/dist/utils/dotNotation.d.ts.map +1 -0
  46. package/dist/utils/dotNotation.js +2 -2
  47. package/dist/utils/findKeyWithValue.d.ts.map +1 -0
  48. package/dist/utils/findProtectedPaths.d.ts.map +1 -0
  49. package/dist/utils/findProtectedPaths.js +14 -56
  50. package/dist/utils/getPathsWithRef.d.ts +5 -0
  51. package/dist/utils/getPathsWithRef.d.ts.map +1 -0
  52. package/dist/utils/getPathsWithRef.js +59 -96
  53. package/dist/utils/index.d.ts +9 -0
  54. package/dist/utils/index.d.ts.map +1 -0
  55. package/dist/utils/index.js +33 -0
  56. package/dist/utils/isJsonString.d.ts.map +1 -0
  57. package/dist/utils/isValidDateString.d.ts.map +1 -0
  58. package/dist/utils/parseParams.d.ts.map +1 -0
  59. package/dist/utils/parseParams.js +14 -12
  60. package/dist/utils/parsePopulateQuery.d.ts.map +1 -0
  61. package/dist/utils/parsePopulateQuery.js +1 -1
  62. package/dist/{types/utils → utils}/parseSortString.d.ts +1 -1
  63. package/dist/utils/parseSortString.d.ts.map +1 -0
  64. package/dist/utils/schemaTraversal.d.ts +9 -0
  65. package/dist/utils/schemaTraversal.d.ts.map +1 -0
  66. package/dist/utils/schemaTraversal.js +37 -0
  67. package/package.json +23 -2
  68. package/dist/types/aggregationPagingQuery.d.ts.map +0 -1
  69. package/dist/types/pagingQuery.d.ts.map +0 -1
  70. package/dist/types/tests/dotNotation.spec.d.ts.map +0 -1
  71. package/dist/types/tests/findProtectedPaths.spec.d.ts.map +0 -1
  72. package/dist/types/tests/getPathsWithRef.spec.d.ts.map +0 -1
  73. package/dist/types/tests/getPropertyFromDotNotation.spec.d.ts.map +0 -1
  74. package/dist/types/tests/insertPopulate.spec.d.ts.map +0 -1
  75. package/dist/types/tests/pagingQuery.spec.d.ts.map +0 -1
  76. package/dist/types/tests/parseSortString.spec.d.ts.map +0 -1
  77. package/dist/types/types/index.d.ts +0 -59
  78. package/dist/types/types/index.d.ts.map +0 -1
  79. package/dist/types/utils/buildPopulateFromString.d.ts +0 -8
  80. package/dist/types/utils/buildPopulateFromString.d.ts.map +0 -1
  81. package/dist/types/utils/dotNotation.d.ts +0 -11
  82. package/dist/types/utils/dotNotation.d.ts.map +0 -1
  83. package/dist/types/utils/findKeyWithValue.d.ts.map +0 -1
  84. package/dist/types/utils/findProtectedPaths.d.ts.map +0 -1
  85. package/dist/types/utils/getPathsWithRef.d.ts +0 -5
  86. package/dist/types/utils/getPathsWithRef.d.ts.map +0 -1
  87. package/dist/types/utils/isJsonString.d.ts.map +0 -1
  88. package/dist/types/utils/isValidDateString.d.ts.map +0 -1
  89. package/dist/types/utils/parseParams.d.ts.map +0 -1
  90. package/dist/types/utils/parsePopulateQuery.d.ts.map +0 -1
  91. package/dist/types/utils/parseSortString.d.ts.map +0 -1
  92. /package/dist/{types/tests → tests}/dotNotation.spec.d.ts +0 -0
  93. /package/dist/{types/tests → tests}/findProtectedPaths.spec.d.ts +0 -0
  94. /package/dist/{types/tests → tests}/getPathsWithRef.spec.d.ts +0 -0
  95. /package/dist/{types/tests → tests}/getPropertyFromDotNotation.spec.d.ts +0 -0
  96. /package/dist/{types/tests → tests}/insertPopulate.spec.d.ts +0 -0
  97. /package/dist/{types/tests → tests}/pagingQuery.spec.d.ts +0 -0
  98. /package/dist/{types/tests → tests}/parseSortString.spec.d.ts +0 -0
  99. /package/dist/{types/utils → utils}/findKeyWithValue.d.ts +0 -0
  100. /package/dist/{types/utils → utils}/findProtectedPaths.d.ts +0 -0
  101. /package/dist/{types/utils → utils}/isJsonString.d.ts +0 -0
  102. /package/dist/{types/utils → utils}/isValidDateString.d.ts +0 -0
  103. /package/dist/{types/utils → utils}/parseParams.d.ts +0 -0
  104. /package/dist/{types/utils → utils}/parsePopulateQuery.d.ts +0 -0
package/README.md CHANGED
@@ -82,7 +82,49 @@ PagingQuery(Express.Request, mongoose.Model, options )
82
82
  | $sort | space separated mongoose sort string \n name -value | inserts sort into the query. In aggregation queries this will insert a sort after the existing pipeline | PagingQuery, AggregationPagingQuery |
83
83
  | $preSort | comma separated dot notation string \n books,-_id \| -_id,-name,address.-address1 | in aggregate queries this will insert a sort object after the initial match in the pipeline. | AggregationPagingQuery |
84
84
  | $count | comma separated dot notation string | this comma separate string will traverse the results and insert a new field with the $size of the selected key/value . this new name field will be appended with `_count` | AggregationPagingQuery |
85
- | $postFilter | Any Json Object | creates and additional filter and in aggregation queries is appended to the end of the pipeline | AggregationPagingQuery |
85
+ | $postFilter | Any Json Object | creates and additional filter and in aggregation queries is appended to the end of the pipeline | AggregationPagingQuery |
86
+
87
+ #### Example URLs
88
+
89
+ ```bash
90
+ # Basic pagination
91
+ GET /api/books?$limit=10&$skip=20
92
+
93
+ # Filter by field (JSON format)
94
+ GET /api/books?$filter={"genre":"Horror"}
95
+
96
+ # Filter with operators
97
+ GET /api/books?$filter={"price.amount":{"$gte":20,"$lte":50}}
98
+
99
+ # Sort (space-separated: field direction)
100
+ GET /api/books?$sort=price.amount%20desc
101
+ GET /api/books?$sort=title%20asc,createdAt%20desc
102
+
103
+ # Select specific fields
104
+ GET /api/books?$select=title,isbn,price
105
+
106
+ # Populate references
107
+ GET /api/books?$populate=author,publisher
108
+
109
+ # Deep populate with field selection
110
+ GET /api/books?$populate=author[firstName,lastName],publisher[name]
111
+
112
+ # Aggregation with preSort (sorts before pipeline)
113
+ GET /api/books?$preSort=createdAt%20desc
114
+
115
+ # Aggregation with postFilter (filters on computed fields)
116
+ GET /api/books?$postFilter={"priceCategory":"expensive"}
117
+
118
+ # Count array fields
119
+ GET /api/books?$count=authors,tags
120
+ # Result includes: authors_count, tags_count
121
+
122
+ # Disable paging (returns array instead of paged object)
123
+ GET /api/books?$paging=false
124
+
125
+ # Lean query (returns plain objects)
126
+ GET /api/books?$lean=true
127
+ ```
86
128
 
87
129
  #### Options
88
130
 
@@ -100,9 +142,140 @@ PagingQuery(Express.Request, mongoose.Model, options )
100
142
  | removeProtected \(REMOVED\) | boolean | auto remove protected (select: false) for root Model | AggregationPagingQuery | | false |
101
143
 
102
144
  ## Utilities
103
- |Name| Description |
104
- |:---|:-------------------------------------------------------------------------------------------------|
105
- |buildPopulate| creates a populate object from dot notation string "author\[name\].books,user.publisher\[name\]" |
145
+
146
+ All utilities can be imported directly from the main package or from the `/utils` subpath:
147
+
148
+ ```typescript
149
+ // Direct import
150
+ import { buildPopulate, parseSortString, getPropertyFromDotNotation } from '@r5v/mongoose-paginate'
151
+
152
+ // Subpath import (all utilities)
153
+ import * as utils from '@r5v/mongoose-paginate/utils'
154
+ ```
155
+
156
+ ### Populate Utilities
157
+
158
+ | Name | Signature | Description |
159
+ |:-----|:----------|:------------|
160
+ | `buildPopulate` | `(pathString: string) => PopulateItem[]` | Creates a Mongoose populate object from dot notation string. Supports deep population with field selection using bracket notation: `"author[name].books[title],publisher[name]"` |
161
+
162
+ ```typescript
163
+ import { buildPopulate } from '@r5v/mongoose-paginate'
164
+
165
+ const populate = buildPopulate('author[name,email].books[title],publisher')
166
+ // Result: [
167
+ // { path: 'author', select: 'name email', populate: [{ path: 'books', select: 'title' }] },
168
+ // { path: 'publisher' }
169
+ // ]
170
+ ```
171
+
172
+ ### Sort Utilities
173
+
174
+ | Name | Signature | Description |
175
+ |:-----|:----------|:------------|
176
+ | `parseSortString` | `(sortString: string) => [string, SortOrder][]` | Parses a sort string into Mongoose sort array format. Example: `"name -createdAt"` → `[["name", 1], ["createdAt", -1]]` |
177
+ | `parseAggregateSortString` | `(sortString: string) => {[key: string]: SortOrder}` | Parses a sort string into aggregation pipeline sort object. Example: `"name -createdAt"` → `{ name: 1, createdAt: -1 }` |
178
+
179
+ ```typescript
180
+ import { parseSortString, parseAggregateSortString } from '@r5v/mongoose-paginate'
181
+
182
+ const sortArray = parseSortString('name 1, createdAt -1')
183
+ // Result: [["name", 1], ["createdAt", -1]]
184
+
185
+ const sortObj = parseAggregateSortString('name 1, createdAt -1')
186
+ // Result: { name: 1, createdAt: -1 }
187
+ ```
188
+
189
+ ### Dot Notation Utilities
190
+
191
+ | Name | Signature | Description |
192
+ |:-----|:----------|:------------|
193
+ | `getPropertyFromDotNotation` | `(obj: any, path: string) => any` | Gets a nested property value using dot notation path |
194
+ | `dotNotationToObject` | `(dotString: string, value?: unknown) => object` | Converts a dot notation string to a nested object |
195
+ | `createObjectFromDotNotation` | `(dotNotationMap: {[key: string]: any}) => object` | Creates a nested object from multiple dot notation key-value pairs |
196
+ | `setPropertyFromDotNotation` | `(obj: Record<string, unknown>, path: string, value: unknown) => object` | Sets a nested property value (mutates original object) |
197
+ | `setPropertiesFromDotNotation` | `(obj: Record<string, unknown>, dotNotationMap: Record<string, unknown>) => object` | Sets multiple nested properties (mutates original object) |
198
+ | `setPropertyFromDotNotationImmutable` | `(obj: Record<string, unknown>, path: string, value: unknown) => object` | Sets a nested property value (returns new object) |
199
+ | `setPropertiesFromDotNotationImmutable` | `(obj: Record<string, unknown>, dotNotationMap: Record<string, unknown>) => object` | Sets multiple nested properties (returns new object) |
200
+
201
+ ```typescript
202
+ import {
203
+ getPropertyFromDotNotation,
204
+ dotNotationToObject,
205
+ setPropertyFromDotNotation
206
+ } from '@r5v/mongoose-paginate'
207
+
208
+ // Get nested value
209
+ const user = { profile: { name: 'John', address: { city: 'NYC' } } }
210
+ getPropertyFromDotNotation(user, 'profile.address.city') // 'NYC'
211
+
212
+ // Create nested object from dot notation
213
+ dotNotationToObject('user.profile.name', 'John')
214
+ // Result: { user: { profile: { name: 'John' } } }
215
+
216
+ // Set nested property
217
+ const obj = { user: { name: 'John' } }
218
+ setPropertyFromDotNotation(obj, 'user.email', 'john@example.com')
219
+ // Result: { user: { name: 'John', email: 'john@example.com' } }
220
+ ```
221
+
222
+ ### Validation Utilities
223
+
224
+ | Name | Signature | Description |
225
+ |:-----|:----------|:------------|
226
+ | `isJsonString` | `(str: string) => boolean` | Checks if a string is valid JSON |
227
+ | `isValidDateString` | `(value: string) => boolean` | Checks if a string is a valid ISO 8601 date format |
228
+
229
+ ```typescript
230
+ import { isJsonString, isValidDateString } from '@r5v/mongoose-paginate'
231
+
232
+ isJsonString('{"name": "John"}') // true
233
+ isJsonString('invalid') // false
234
+
235
+ isValidDateString('2024-01-15') // true
236
+ isValidDateString('2024-01-15T10:30:00.000Z') // true
237
+ isValidDateString('invalid-date') // false
238
+ ```
239
+
240
+ ### Schema Traversal Utilities
241
+
242
+ | Name | Signature | Description |
243
+ |:-----|:----------|:------------|
244
+ | `buildFullPath` | `(parentPath: string, childPath: string) => string` | Builds a dot-notation path from parent and child segments |
245
+ | `traverseSchemaObject` | `(obj: any, callback: (obj, path) => void, currentPath?: string) => void` | Recursively traverses a Mongoose schema object, calling callback for each node |
246
+
247
+ ```typescript
248
+ import { buildFullPath, traverseSchemaObject } from '@r5v/mongoose-paginate'
249
+
250
+ // Build dot-notation paths
251
+ buildFullPath('user', 'profile') // 'user.profile'
252
+ buildFullPath('', 'name') // 'name'
253
+ buildFullPath('parent', '') // 'parent'
254
+
255
+ // Traverse schema objects
256
+ traverseSchemaObject(schemaType, (obj, currentPath) => {
257
+ if (obj.options?.ref) {
258
+ console.log(`Found ref at ${currentPath}: ${obj.options.ref}`)
259
+ }
260
+ })
261
+ ```
262
+
263
+ ## Types
264
+
265
+ All TypeScript types are exported and can be imported:
266
+
267
+ ```typescript
268
+ import type {
269
+ PagingQueryOptions,
270
+ AggregateQueryOptions,
271
+ QueryParameters,
272
+ PagingQueryParsedRequestParams,
273
+ AggregateQueryParsedRequestParams
274
+ } from '@r5v/mongoose-paginate'
275
+
276
+ // Or from the types subpath
277
+ import type * from '@r5v/mongoose-paginate/types'
278
+ ```
106
279
 
107
280
  ## Build
108
281
 
@@ -123,19 +296,41 @@ $ yarn run start
123
296
 
124
297
  #### Aggregations Order of operations
125
298
 
126
- 1. staticFilter \| \$filter \| $match (if first item in pipeline)
127
- 2. \$preSort
128
- 3. apply pipeline
129
- 4. \$select \| project
130
- 5. remove protected fields
131
- 6. \$count
132
- 7. \$sort
133
- 8. apply options
299
+ 1. First pipeline stage (if `$search`, `$searchMeta`, or `$geoNear`)
300
+ 2. `$match` combining: `staticFilter` + `$filter` (if `enableFilter`) + first pipeline `$match` stage
301
+ 3. `$preSort` (if `enablePreSort` is true)
302
+ 4. Remaining pipeline stages
303
+ 5. `$select` / `$project`
304
+ 6. `$count` (adds `_count` fields for array sizes)
305
+ 7. `$postFilter` combining: `staticPostFilter` + `$postFilter` (if `enablePostFilter`)
306
+ 8. `$sort` (final sorting, can sort on computed fields)
307
+ 9. Apply pagination (`$skip`, `$limit`) and options
134
308
 
135
309
 
136
310
  ## NOTES
137
311
  1. removeProtected removed from aggregation query due to inconsistent results after publication
138
312
 
313
+ ### 1.0.14
314
+ - Added proper TypeScript package exports with subpaths (`/utils`, `/types`)
315
+ - Exported all utility functions (dot notation, sort parsing, validation)
316
+ - Exported all TypeScript types
317
+ - **Fixed Express Request type compatibility** - Added `RequestLike` interface to allow custom request types without index signature issues
318
+ - Fixed JSON.parse crash on malformed `$filter`/`$postFilter` parameters
319
+ - Fixed regex global flag bug in populate parsing
320
+ - Added input validation to constructors
321
+ - Improved type safety (reduced `any` usage)
322
+ - Removed deprecated `$includes` parameter
323
+ - Replaced `JSON.parse(JSON.stringify())` with `structuredClone()`
324
+ - Fixed inconsistent equality operator (`==` to `===`)
325
+ - **Fixed empty pipeline crash** - `AggregationPagingQuery.initQuery` no longer crashes when pipeline is empty
326
+ - **Refactored `buildPopulate`** - Extracted inner functions to module level for better testability
327
+ - **Refactored `findProtectedPaths`** - Removed JSON.stringify that could fail on circular references
328
+ - **Refactored `getPathsWithRef`** - Simplified input handling, removed brittle string parsing
329
+ - **Added `schemaTraversal` utility** - Shared `buildFullPath` and `traverseSchemaObject` functions for schema traversal
330
+
331
+ ### 1.0.13
332
+ - Fix issue where disablePaging was not working on aggregation query
333
+
139
334
  ### 1.0.12
140
335
  - Fix issue with AggregationPagingQuery where static post filter would not be applied if $postFilter param was not supplied
141
336
  - updated typings on AggregationPagingQuery to include enablePostFilter, enableFilter, and enablePreSort
@@ -1,25 +1,24 @@
1
1
  import { Model, Aggregate } from "mongoose";
2
- import type { Request } from "express";
3
- import type { AggregateQueryOptions, QueryParameters, AggregateQueryParsedRequestParams } from './types';
2
+ import type { AggregateQueryOptions, AggregateQueryParsedRequestParams, RequestLike } from './types';
4
3
  export declare class AggregationPagingQuery {
5
4
  params: AggregateQueryParsedRequestParams;
6
5
  options: AggregateQueryOptions;
7
- query: Aggregate<Array<any>> | undefined;
6
+ query: Aggregate<unknown[]> | undefined;
8
7
  protectedPaths: string[];
9
8
  model: Model<any>;
10
- constructor(req: Request<{}, any, any, Partial<QueryParameters>>, model: Model<any>, options: AggregateQueryOptions);
9
+ constructor(req: RequestLike, model: Model<any>, options: AggregateQueryOptions);
11
10
  findProtectedPaths: (model: Model<any>) => string[];
12
11
  parseParams: (defaultParams: import("./types").PagingQueryParsedRequestParams | AggregateQueryParsedRequestParams, params: import("qs").ParsedQs, isAggregate?: boolean) => import("./types").PagingQueryParsedRequestParams | AggregateQueryParsedRequestParams;
13
12
  isValidDateString: (value: string) => boolean;
14
13
  isJsonString: (str: string) => boolean;
15
14
  parseSortString: (sortString: string) => [string, import("mongoose").SortOrder][];
16
- parseAggregateSortString: (sortString: any) => {
15
+ parseAggregateSortString: (sortString: string) => {
17
16
  [key: string]: import("mongoose").SortOrder;
18
17
  };
19
18
  createCounts: () => void;
20
19
  initQuery: () => Promise<void>;
21
- typeCastObject: (strOrObj: any) => any;
20
+ typeCastObject: <T>(strOrObj: T) => T;
22
21
  private removeProtectedFields;
23
- exec: () => Promise<any>;
22
+ exec: () => Promise<unknown>;
24
23
  }
25
24
  //# sourceMappingURL=aggregationPagingQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregationPagingQuery.d.ts","sourceRoot":"","sources":["../src/aggregationPagingQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,EACL,SAAS,EAKZ,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAC,qBAAqB,EAAE,iCAAiC,EAAE,WAAW,EAAC,MAAM,SAAS,CAAA;AAQlG,qBAAa,sBAAsB;IAC/B,MAAM,EAAG,iCAAiC,CAYzC;IACD,OAAO,EAAE,qBAAqB,CAK7B;IACD,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAA;IACvC,cAAc,EAAE,MAAM,EAAE,CAAK;IAC7B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;gBACL,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,qBAAqB;IAiB/E,kBAAkB,kCAAqB;IACvC,WAAW,sPAAc;IACzB,iBAAiB,6BAAoB;IACrC,YAAY,2BAAe;IAC3B,eAAe,mEAAkB;IACjC,wBAAwB;;MAA2B;IACnD,YAAY,aAOX;IACD,SAAS,sBAkDR;IACD,cAAc,GAAI,CAAC,EAAE,UAAU,CAAC,KAAG,CAAC,CAmCnC;IAED,OAAO,CAAC,qBAAqB,CAS5B;IACD,IAAI,yBAgCH;CAEJ"}
@@ -36,7 +36,6 @@ class AggregationPagingQuery {
36
36
  $sort: {},
37
37
  $paging: true,
38
38
  $populate: [],
39
- $includes: [], // to be removed
40
39
  $select: "",
41
40
  $count: [],
42
41
  $postFilter: {},
@@ -84,7 +83,7 @@ class AggregationPagingQuery {
84
83
  }
85
84
  const typeCastFilter = this.typeCastObject(filterObj);
86
85
  const typeCastPostFilter = this.typeCastObject(postFilterObj);
87
- if (Object.keys(p1).some(k => ["$search", "$searchMeta", "$geoNear"].includes(k))) {
86
+ if (p1 && Object.keys(p1).some(k => ["$search", "$searchMeta", "$geoNear"].includes(k))) {
88
87
  this.query.append(p1);
89
88
  firstObj = true;
90
89
  }
@@ -94,7 +93,7 @@ class AggregationPagingQuery {
94
93
  if (this.options.enablePreSort && Object.keys($preSort).length) {
95
94
  this.query.sort($preSort);
96
95
  }
97
- if (!firstObj) {
96
+ if (!firstObj && p1) {
98
97
  this.query.append(p1);
99
98
  }
100
99
  pipes.forEach(item => { var _a; return (_a = this.query) === null || _a === void 0 ? void 0 : _a.append(item); });
@@ -150,11 +149,11 @@ class AggregationPagingQuery {
150
149
  };
151
150
  this.exec = () => __awaiter(this, void 0, void 0, function* () {
152
151
  const { $skip, $limit, $paging, $filter } = this.params;
153
- const { staticFilter } = this.options;
152
+ const { disablePaging } = this.options;
154
153
  if (!this.query) {
155
154
  throw new Error("No Query Present in AggregationQuery");
156
155
  }
157
- if (!$paging) {
156
+ if (!$paging || disablePaging) {
158
157
  this.query.skip($skip);
159
158
  this.query.limit($limit);
160
159
  return yield this.query.exec();
@@ -180,6 +179,15 @@ class AggregationPagingQuery {
180
179
  const req = yield this.query.exec();
181
180
  return req[0];
182
181
  });
182
+ if (!req || typeof req.query !== 'object') {
183
+ throw new Error('Invalid request object: must have a query property');
184
+ }
185
+ if (!model || typeof model.aggregate !== 'function') {
186
+ throw new Error('Invalid model: must be a Mongoose model');
187
+ }
188
+ if (!options || !Array.isArray(options.pipeline)) {
189
+ throw new Error('Invalid options: pipeline must be an array');
190
+ }
183
191
  this.options = Object.assign(Object.assign({}, this.options), options);
184
192
  this.model = model;
185
193
  this.params = this.parseParams(this.params, req.query, true);
@@ -0,0 +1,9 @@
1
+ export { PagingQuery } from './pagingQuery';
2
+ export { AggregationPagingQuery } from './aggregationPagingQuery';
3
+ export type { RequestLike, QueryParameters, StandardParsedRequestParams, PagingQueryParsedRequestParams, AggregateQueryParsedRequestParams, StandardQueryOptions, PagingQueryOptions, AggregateQueryOptions } from './types';
4
+ export { buildPopulate } from './utils/buildPopulateFromString';
5
+ export { parseSortString, parseAggregateSortString } from './utils/parseSortString';
6
+ export { getPropertyFromDotNotation, dotNotationToObject, createObjectFromDotNotation, setPropertyFromDotNotation, setPropertiesFromDotNotation, setPropertyFromDotNotationImmutable, setPropertiesFromDotNotationImmutable } from './utils/dotNotation';
7
+ export { isJsonString } from './utils/isJsonString';
8
+ export { isValidDateString } from './utils/isValidDateString';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AAGjE,YAAY,EACR,WAAW,EACX,eAAe,EACf,2BAA2B,EAC3B,8BAA8B,EAC9B,iCAAiC,EACjC,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACxB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AACnF,OAAO,EACH,0BAA0B,EAC1B,mBAAmB,EACnB,2BAA2B,EAC3B,0BAA0B,EAC1B,4BAA4B,EAC5B,mCAAmC,EACnC,qCAAqC,EACxC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA"}
package/dist/index.js CHANGED
@@ -1,9 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildPopulate = exports.AggregationPagingQuery = exports.PagingQuery = void 0;
3
+ exports.isValidDateString = exports.isJsonString = exports.setPropertiesFromDotNotationImmutable = exports.setPropertyFromDotNotationImmutable = exports.setPropertiesFromDotNotation = exports.setPropertyFromDotNotation = exports.createObjectFromDotNotation = exports.dotNotationToObject = exports.getPropertyFromDotNotation = exports.parseAggregateSortString = exports.parseSortString = exports.buildPopulate = exports.AggregationPagingQuery = exports.PagingQuery = void 0;
4
+ // Main classes
4
5
  var pagingQuery_1 = require("./pagingQuery");
5
6
  Object.defineProperty(exports, "PagingQuery", { enumerable: true, get: function () { return pagingQuery_1.PagingQuery; } });
6
7
  var aggregationPagingQuery_1 = require("./aggregationPagingQuery");
7
8
  Object.defineProperty(exports, "AggregationPagingQuery", { enumerable: true, get: function () { return aggregationPagingQuery_1.AggregationPagingQuery; } });
9
+ // Utilities - re-export for convenience
8
10
  var buildPopulateFromString_1 = require("./utils/buildPopulateFromString");
9
11
  Object.defineProperty(exports, "buildPopulate", { enumerable: true, get: function () { return buildPopulateFromString_1.buildPopulate; } });
12
+ var parseSortString_1 = require("./utils/parseSortString");
13
+ Object.defineProperty(exports, "parseSortString", { enumerable: true, get: function () { return parseSortString_1.parseSortString; } });
14
+ Object.defineProperty(exports, "parseAggregateSortString", { enumerable: true, get: function () { return parseSortString_1.parseAggregateSortString; } });
15
+ var dotNotation_1 = require("./utils/dotNotation");
16
+ Object.defineProperty(exports, "getPropertyFromDotNotation", { enumerable: true, get: function () { return dotNotation_1.getPropertyFromDotNotation; } });
17
+ Object.defineProperty(exports, "dotNotationToObject", { enumerable: true, get: function () { return dotNotation_1.dotNotationToObject; } });
18
+ Object.defineProperty(exports, "createObjectFromDotNotation", { enumerable: true, get: function () { return dotNotation_1.createObjectFromDotNotation; } });
19
+ Object.defineProperty(exports, "setPropertyFromDotNotation", { enumerable: true, get: function () { return dotNotation_1.setPropertyFromDotNotation; } });
20
+ Object.defineProperty(exports, "setPropertiesFromDotNotation", { enumerable: true, get: function () { return dotNotation_1.setPropertiesFromDotNotation; } });
21
+ Object.defineProperty(exports, "setPropertyFromDotNotationImmutable", { enumerable: true, get: function () { return dotNotation_1.setPropertyFromDotNotationImmutable; } });
22
+ Object.defineProperty(exports, "setPropertiesFromDotNotationImmutable", { enumerable: true, get: function () { return dotNotation_1.setPropertiesFromDotNotationImmutable; } });
23
+ var isJsonString_1 = require("./utils/isJsonString");
24
+ Object.defineProperty(exports, "isJsonString", { enumerable: true, get: function () { return isJsonString_1.isJsonString; } });
25
+ var isValidDateString_1 = require("./utils/isValidDateString");
26
+ Object.defineProperty(exports, "isValidDateString", { enumerable: true, get: function () { return isValidDateString_1.isValidDateString; } });
@@ -1,16 +1,15 @@
1
- import type { PagingQueryParsedRequestParams, PagingQueryOptions } from './types';
2
- import { Model, QueryWithHelpers } from "mongoose";
3
- import type { Request } from 'express';
1
+ import type { PagingQueryParsedRequestParams, PagingQueryOptions, RequestLike } from './types';
2
+ import { Model, QueryWithHelpers, SortOrder } from "mongoose";
4
3
  export declare class PagingQuery {
5
4
  params: PagingQueryParsedRequestParams;
6
5
  options: PagingQueryOptions;
7
- query: QueryWithHelpers<any, any> | null;
6
+ query: QueryWithHelpers<unknown, unknown> | null;
8
7
  model: Model<any>;
9
- constructor(req: Request, model: Model<any>, options?: Partial<PagingQueryOptions>);
8
+ constructor(req: RequestLike, model: Model<any>, options?: Partial<PagingQueryOptions>);
10
9
  private isJsonString;
11
10
  private initQuery;
12
- parseSortString: (sortString: string) => [string, import("mongoose").SortOrder][];
11
+ parseSortString: (sortString: string) => [string, SortOrder][];
13
12
  parseParams: (defaultParams: PagingQueryParsedRequestParams | import("./types").AggregateQueryParsedRequestParams, params: import("qs").ParsedQs, isAggregate?: boolean) => PagingQueryParsedRequestParams | import("./types").AggregateQueryParsedRequestParams;
14
- exec: () => Promise<any>;
13
+ exec: () => Promise<unknown>;
15
14
  }
16
15
  //# sourceMappingURL=pagingQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagingQuery.d.ts","sourceRoot":"","sources":["../src/pagingQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,8BAA8B,EAAE,kBAAkB,EAAE,WAAW,EAAC,MAAM,SAAS,CAAA;AAC5F,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAC,MAAM,UAAU,CAAC;AAS7D,qBAAa,WAAW;IACpB,MAAM,EAAE,8BAA8B,CASrC;IACD,OAAO,EAAE,kBAAkB,CAAK;IAChC,KAAK,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,IAAI,CAAO;IACvD,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;gBAEL,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAY1F,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAqChB;IACD,eAAe,gDAAkB;IACjC,WAAW,sPAAc;IACzB,IAAI,yBAuBH;CACJ"}
@@ -34,7 +34,6 @@ class PagingQuery {
34
34
  $sort: [],
35
35
  $paging: true,
36
36
  $populate: [],
37
- $includes: [], // to be removed
38
37
  $select: "",
39
38
  $lean: false
40
39
  };
@@ -45,7 +44,7 @@ class PagingQuery {
45
44
  const { $filter, $sort, $select, $skip, $limit, $populate, $lean } = this.params;
46
45
  const _a = this.options, { single, staticFilter, disablePaging, disableFilter } = _a, options = __rest(_a, ["single", "staticFilter", "disablePaging", "disableFilter"]);
47
46
  const filter = disableFilter ? Object.assign({}, staticFilter) : Object.assign(Object.assign({}, $filter), staticFilter);
48
- this.query = single ? this.model.findOne(filter) : this.model.find(filter);
47
+ this.query = (single ? this.model.findOne(filter) : this.model.find(filter));
49
48
  this.query.setOptions(options);
50
49
  if (disablePaging || single) {
51
50
  this.params.$paging = false;
@@ -89,11 +88,17 @@ class PagingQuery {
89
88
  skip: $skip,
90
89
  items: []
91
90
  };
92
- resObj.items = yield this.query.exec();
91
+ resObj.items = (yield this.query.exec());
93
92
  resObj.totalRows = yield this.model.countDocuments(Object.assign(Object.assign({}, $filter), staticFilter));
94
93
  resObj.rows = resObj.items.length;
95
94
  return resObj;
96
95
  });
96
+ if (!req || typeof req.query !== 'object') {
97
+ throw new Error('Invalid request object: must have a query property');
98
+ }
99
+ if (!model || typeof model.find !== 'function') {
100
+ throw new Error('Invalid model: must be a Mongoose model');
101
+ }
97
102
  this.options = options;
98
103
  this.model = model;
99
104
  this.params = this.parseParams(this.params, req.query);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=aggregationPagingQuery.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregationPagingQuery.spec.d.ts","sourceRoot":"","sources":["../../src/tests/aggregationPagingQuery.spec.ts"],"names":[],"mappings":""}