@r5v/mongoose-paginate 1.0.13 → 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.
- package/README.md +204 -12
- package/dist/{types/aggregationPagingQuery.d.ts → aggregationPagingQuery.d.ts} +6 -7
- package/dist/aggregationPagingQuery.d.ts.map +1 -0
- package/dist/aggregationPagingQuery.js +11 -3
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -1
- package/dist/{types/pagingQuery.d.ts → pagingQuery.d.ts} +6 -7
- package/dist/pagingQuery.d.ts.map +1 -0
- package/dist/pagingQuery.js +8 -3
- package/dist/tests/aggregationPagingQuery.spec.d.ts +2 -0
- package/dist/tests/aggregationPagingQuery.spec.d.ts.map +1 -0
- package/dist/tests/aggregationPagingQuery.spec.js +365 -0
- package/dist/tests/buildPopulateFromString.spec.d.ts +2 -0
- package/dist/tests/buildPopulateFromString.spec.d.ts.map +1 -0
- package/dist/tests/buildPopulateFromString.spec.js +223 -0
- package/dist/tests/dotNotation.spec.d.ts.map +1 -0
- package/dist/tests/findProtectedPaths.spec.d.ts.map +1 -0
- package/dist/tests/findProtectedPaths.spec.js +128 -6
- package/dist/tests/getPathsWithRef.spec.d.ts.map +1 -0
- package/dist/tests/getPathsWithRef.spec.js +92 -18
- package/dist/tests/getPropertyFromDotNotation.spec.d.ts.map +1 -0
- package/dist/tests/insertPopulate.spec.d.ts.map +1 -0
- package/dist/tests/isJsonString.spec.d.ts +2 -0
- package/dist/tests/isJsonString.spec.d.ts.map +1 -0
- package/dist/tests/isJsonString.spec.js +116 -0
- package/dist/tests/isValidDateString.spec.d.ts +2 -0
- package/dist/tests/isValidDateString.spec.d.ts.map +1 -0
- package/dist/tests/isValidDateString.spec.js +116 -0
- package/dist/tests/pagingQuery.spec.d.ts.map +1 -0
- package/dist/tests/pagingQuery.spec.js +238 -13
- package/dist/tests/parseParams.spec.d.ts +2 -0
- package/dist/tests/parseParams.spec.d.ts.map +1 -0
- package/dist/tests/parseParams.spec.js +212 -0
- package/dist/tests/parseSortString.spec.d.ts.map +1 -0
- package/dist/tests/schemaTraversal.spec.d.ts +2 -0
- package/dist/tests/schemaTraversal.spec.d.ts.map +1 -0
- package/dist/tests/schemaTraversal.spec.js +139 -0
- package/dist/types/index.d.ts +66 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/buildPopulateFromString.d.ts +8 -0
- package/dist/utils/buildPopulateFromString.d.ts.map +1 -0
- package/dist/utils/buildPopulateFromString.js +54 -49
- package/dist/utils/dotNotation.d.ts +11 -0
- package/dist/utils/dotNotation.d.ts.map +1 -0
- package/dist/utils/dotNotation.js +2 -2
- package/dist/utils/findKeyWithValue.d.ts.map +1 -0
- package/dist/utils/findProtectedPaths.d.ts.map +1 -0
- package/dist/utils/findProtectedPaths.js +14 -56
- package/dist/utils/getPathsWithRef.d.ts +5 -0
- package/dist/utils/getPathsWithRef.d.ts.map +1 -0
- package/dist/utils/getPathsWithRef.js +59 -96
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +33 -0
- package/dist/utils/isJsonString.d.ts.map +1 -0
- package/dist/utils/isValidDateString.d.ts.map +1 -0
- package/dist/utils/parseParams.d.ts.map +1 -0
- package/dist/utils/parseParams.js +14 -12
- package/dist/utils/parsePopulateQuery.d.ts.map +1 -0
- package/dist/utils/parsePopulateQuery.js +1 -1
- package/dist/{types/utils → utils}/parseSortString.d.ts +1 -1
- package/dist/utils/parseSortString.d.ts.map +1 -0
- package/dist/utils/schemaTraversal.d.ts +9 -0
- package/dist/utils/schemaTraversal.d.ts.map +1 -0
- package/dist/utils/schemaTraversal.js +37 -0
- package/package.json +23 -2
- package/dist/types/aggregationPagingQuery.d.ts.map +0 -1
- package/dist/types/pagingQuery.d.ts.map +0 -1
- package/dist/types/tests/dotNotation.spec.d.ts.map +0 -1
- package/dist/types/tests/findProtectedPaths.spec.d.ts.map +0 -1
- package/dist/types/tests/getPathsWithRef.spec.d.ts.map +0 -1
- package/dist/types/tests/getPropertyFromDotNotation.spec.d.ts.map +0 -1
- package/dist/types/tests/insertPopulate.spec.d.ts.map +0 -1
- package/dist/types/tests/pagingQuery.spec.d.ts.map +0 -1
- package/dist/types/tests/parseSortString.spec.d.ts.map +0 -1
- package/dist/types/types/index.d.ts +0 -61
- package/dist/types/types/index.d.ts.map +0 -1
- package/dist/types/utils/buildPopulateFromString.d.ts +0 -8
- package/dist/types/utils/buildPopulateFromString.d.ts.map +0 -1
- package/dist/types/utils/dotNotation.d.ts +0 -11
- package/dist/types/utils/dotNotation.d.ts.map +0 -1
- package/dist/types/utils/findKeyWithValue.d.ts.map +0 -1
- package/dist/types/utils/findProtectedPaths.d.ts.map +0 -1
- package/dist/types/utils/getPathsWithRef.d.ts +0 -5
- package/dist/types/utils/getPathsWithRef.d.ts.map +0 -1
- package/dist/types/utils/isJsonString.d.ts.map +0 -1
- package/dist/types/utils/isValidDateString.d.ts.map +0 -1
- package/dist/types/utils/parseParams.d.ts.map +0 -1
- package/dist/types/utils/parsePopulateQuery.d.ts.map +0 -1
- package/dist/types/utils/parseSortString.d.ts.map +0 -1
- /package/dist/{types/tests → tests}/dotNotation.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/findProtectedPaths.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/getPathsWithRef.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/getPropertyFromDotNotation.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/insertPopulate.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/pagingQuery.spec.d.ts +0 -0
- /package/dist/{types/tests → tests}/parseSortString.spec.d.ts +0 -0
- /package/dist/{types/utils → utils}/findKeyWithValue.d.ts +0 -0
- /package/dist/{types/utils → utils}/findProtectedPaths.d.ts +0 -0
- /package/dist/{types/utils → utils}/isJsonString.d.ts +0 -0
- /package/dist/{types/utils → utils}/isValidDateString.d.ts +0 -0
- /package/dist/{types/utils → utils}/parseParams.d.ts +0 -0
- /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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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,38 @@ $ yarn run start
|
|
|
123
296
|
|
|
124
297
|
#### Aggregations Order of operations
|
|
125
298
|
|
|
126
|
-
1.
|
|
127
|
-
2.
|
|
128
|
-
3.
|
|
129
|
-
4.
|
|
130
|
-
5.
|
|
131
|
-
6.
|
|
132
|
-
7.
|
|
133
|
-
8.
|
|
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
|
+
|
|
139
331
|
### 1.0.13
|
|
140
332
|
- Fix issue where disablePaging was not working on aggregation query
|
|
141
333
|
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import { Model, Aggregate } from "mongoose";
|
|
2
|
-
import type {
|
|
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<
|
|
6
|
+
query: Aggregate<unknown[]> | undefined;
|
|
8
7
|
protectedPaths: string[];
|
|
9
8
|
model: Model<any>;
|
|
10
|
-
constructor(req:
|
|
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:
|
|
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:
|
|
20
|
+
typeCastObject: <T>(strOrObj: T) => T;
|
|
22
21
|
private removeProtectedFields;
|
|
23
|
-
exec: () => Promise<
|
|
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); });
|
|
@@ -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);
|
package/dist/index.d.ts
ADDED
|
@@ -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<
|
|
6
|
+
query: QueryWithHelpers<unknown, unknown> | null;
|
|
8
7
|
model: Model<any>;
|
|
9
|
-
constructor(req:
|
|
8
|
+
constructor(req: RequestLike, model: Model<any>, options?: Partial<PagingQueryOptions>);
|
|
10
9
|
private isJsonString;
|
|
11
10
|
private initQuery;
|
|
12
|
-
parseSortString: (sortString: string) => [string,
|
|
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<
|
|
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"}
|
package/dist/pagingQuery.js
CHANGED
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"aggregationPagingQuery.spec.d.ts","sourceRoot":"","sources":["../../src/tests/aggregationPagingQuery.spec.ts"],"names":[],"mappings":""}
|