querier-ts 2.5.4 → 2.7.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.
- package/CHANGELOG.md +28 -0
- package/README.md +89 -10
- package/dist/cjs/index.cjs +85 -32
- package/dist/esm/index.d.ts +59 -16
- package/dist/esm/index.js +85 -32
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v2.7.0
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fixes
|
|
8
|
+
- [ ] Code refactoring
|
|
9
|
+
- [x] New features
|
|
10
|
+
- [ ] Build and packaging updates
|
|
11
|
+
- [ ] Breaking changes
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
- Added new overload to `orderBy()` method, allowing to specify a function that returns the values to be sorted and the order to be applied.
|
|
16
|
+
|
|
17
|
+
## v2.6.0
|
|
18
|
+
|
|
19
|
+
### Summary
|
|
20
|
+
|
|
21
|
+
- [ ] Bug fixes
|
|
22
|
+
- [ ] Code refactoring
|
|
23
|
+
- [x] New features
|
|
24
|
+
- [ ] Build and packaging updates
|
|
25
|
+
- [ ] Breaking changes
|
|
26
|
+
|
|
27
|
+
### New features
|
|
28
|
+
|
|
29
|
+
- Added `limitPerGroup()` and `top()` methods to `Query`.
|
|
30
|
+
|
|
3
31
|
## v2.5.4
|
|
4
32
|
|
|
5
33
|
### Summary
|
package/README.md
CHANGED
|
@@ -165,7 +165,28 @@ const lastId = Query.from(users)
|
|
|
165
165
|
|
|
166
166
|
---
|
|
167
167
|
|
|
168
|
-
###
|
|
168
|
+
### Paginating results
|
|
169
|
+
|
|
170
|
+
#### `skip(numberOfRows)`
|
|
171
|
+
|
|
172
|
+
Skips the first results.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
.skip(5)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Example:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
const secondId = Query.from(users)
|
|
182
|
+
.select('id')
|
|
183
|
+
.skip(1)
|
|
184
|
+
.scalar();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
> Passing a non-integer or a negative number will throw an `InvalidArgumentError`.
|
|
188
|
+
|
|
189
|
+
---
|
|
169
190
|
|
|
170
191
|
#### `limit(limit)`
|
|
171
192
|
|
|
@@ -179,24 +200,82 @@ Limits the number of results returned.
|
|
|
179
200
|
|
|
180
201
|
---
|
|
181
202
|
|
|
182
|
-
#### `
|
|
203
|
+
#### `limitPerGroup(key | fn, limit)`
|
|
183
204
|
|
|
184
|
-
|
|
205
|
+
Limits the number of rows per group.
|
|
206
|
+
|
|
207
|
+
- `key`: The property name to group by.
|
|
208
|
+
- `fn`: A function that maps each row to a grouping value.
|
|
209
|
+
- `limit`: The maximum number of rows to keep per group.
|
|
210
|
+
|
|
211
|
+
> ⚠️ The rows kept depend on the current ordering of the query.
|
|
212
|
+
> Use `orderBy()` beforehand to control which rows are selected.
|
|
213
|
+
|
|
214
|
+
Examples:
|
|
185
215
|
|
|
186
216
|
```ts
|
|
187
|
-
|
|
217
|
+
// with key
|
|
218
|
+
const countries = Query.from(addresses)
|
|
219
|
+
.orderBy('-createdAt')
|
|
220
|
+
.limitPerGroup('country', 2)
|
|
221
|
+
.column('country'); // ['Argentina', 'Argentina', 'Brazil', 'Brazil', 'Chile', 'Chile']
|
|
222
|
+
|
|
223
|
+
// with callback
|
|
224
|
+
const countries = Query.from(addresses)
|
|
225
|
+
.orderBy('-createdAt')
|
|
226
|
+
.limitPerGroup((row) => row.country, 2)
|
|
227
|
+
.column('country');
|
|
188
228
|
```
|
|
189
229
|
|
|
190
|
-
|
|
230
|
+
> Passing a non-integer or a negative number to `limit` will throw an `InvalidArgumentError`.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
#### `top(limit, options?)`
|
|
235
|
+
|
|
236
|
+
Keeps the top N rows, optionally partitioned by a key or callback.
|
|
237
|
+
|
|
238
|
+
- `limit`: The maximum number of rows to keep.
|
|
239
|
+
- `options.partitionBy`: A property name or function to define groups.
|
|
240
|
+
- `options.orderBy`: A column or list of columns to define ordering.
|
|
241
|
+
|
|
242
|
+
If `partitionBy` is provided, the limit is applied per group.
|
|
243
|
+
|
|
244
|
+
The rows kept depend on the ordering. Use `orderBy` (either here or before)
|
|
245
|
+
to control which rows are selected.
|
|
246
|
+
|
|
247
|
+
Examples:
|
|
191
248
|
|
|
192
249
|
```ts
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
.
|
|
196
|
-
.
|
|
250
|
+
// top N globally
|
|
251
|
+
const ids = Query.from(addresses)
|
|
252
|
+
.orderBy('-createdAt')
|
|
253
|
+
.top(3)
|
|
254
|
+
.column('id'); // [6, 5, 4]
|
|
255
|
+
|
|
256
|
+
// top N per group (key)
|
|
257
|
+
const countries = Query.from(addresses)
|
|
258
|
+
.top(2, {
|
|
259
|
+
partitionBy: 'country',
|
|
260
|
+
orderBy: '-createdAt',
|
|
261
|
+
})
|
|
262
|
+
.column('country'); // ['Argentina', 'Argentina', 'Brazil', 'Brazil', 'Chile', 'Chile']
|
|
263
|
+
|
|
264
|
+
// top N per group (callback)
|
|
265
|
+
const countries = Query.from(addresses)
|
|
266
|
+
.top(1, {
|
|
267
|
+
partitionBy: (row) => row.country,
|
|
268
|
+
orderBy: '-createdAt',
|
|
269
|
+
})
|
|
270
|
+
.column('country'); // ['Argentina', 'Brazil', 'Chile']
|
|
271
|
+
|
|
272
|
+
// without orderBy (keeps original order)
|
|
273
|
+
const countries = Query.from(addresses)
|
|
274
|
+
.top(1, { partitionBy: 'country' })
|
|
275
|
+
.column('country'); // ['Brazil', 'Chile', 'Argentina']
|
|
197
276
|
```
|
|
198
277
|
|
|
199
|
-
> Passing a non-integer or a negative number will throw an `InvalidArgumentError`.
|
|
278
|
+
> Passing a non-integer or a negative number to `limit` will throw an `InvalidArgumentError`.
|
|
200
279
|
|
|
201
280
|
---
|
|
202
281
|
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -185,6 +185,21 @@ function getObjectPropertyNames(obj) {
|
|
|
185
185
|
);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
// src/utils/functions/sort/sort-values.ts
|
|
189
|
+
function sortValues(a, b, order) {
|
|
190
|
+
if (a == null && b == null) return 0;
|
|
191
|
+
if (a == null) return 1 * order;
|
|
192
|
+
if (b == null) return -1 * order;
|
|
193
|
+
if (a < b) return -1 * order;
|
|
194
|
+
if (a > b) return 1 * order;
|
|
195
|
+
return 0;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/utils/functions/sort/sort-by-callback.ts
|
|
199
|
+
function sortByCallback(callback, sortOrder) {
|
|
200
|
+
return (a, b) => sortValues(callback(a), callback(b), sortOrder);
|
|
201
|
+
}
|
|
202
|
+
|
|
188
203
|
// src/utils/functions/sort/sort-by-property.ts
|
|
189
204
|
function sortByProperty(property) {
|
|
190
205
|
let sortOrder = 1;
|
|
@@ -197,12 +212,7 @@ function sortByProperty(property) {
|
|
|
197
212
|
return (a, b) => {
|
|
198
213
|
const valueA = a[key];
|
|
199
214
|
const valueB = b[key];
|
|
200
|
-
|
|
201
|
-
if (valueA == null) return 1 * sortOrder;
|
|
202
|
-
if (valueB == null) return -1 * sortOrder;
|
|
203
|
-
if (valueA < valueB) return -1 * sortOrder;
|
|
204
|
-
if (valueA > valueB) return 1 * sortOrder;
|
|
205
|
-
return 0;
|
|
215
|
+
return sortValues(valueA, valueB, sortOrder);
|
|
206
216
|
};
|
|
207
217
|
}
|
|
208
218
|
|
|
@@ -339,32 +349,19 @@ var _Query = class _Query {
|
|
|
339
349
|
this.filterRows(condition, { ignoreNullValues: true });
|
|
340
350
|
return this;
|
|
341
351
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
* // ✅ "age" will be ordered
|
|
356
|
-
* const query = Query.from(users)
|
|
357
|
-
* .select('name', 'age')
|
|
358
|
-
* .orderBy('-age');
|
|
359
|
-
* ```
|
|
360
|
-
*
|
|
361
|
-
* @param columns Ascending or descending columns. To mark a field as
|
|
362
|
-
* descending, prefix it with `-`.
|
|
363
|
-
*
|
|
364
|
-
* @returns Current query.
|
|
365
|
-
*/
|
|
366
|
-
orderBy(...columns) {
|
|
367
|
-
this.#rows = this.#rows.sort(sortByProperties(...columns));
|
|
352
|
+
orderBy(...arg) {
|
|
353
|
+
if (arg.length === 0) {
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
if (isFunction(arg[0])) {
|
|
357
|
+
this.#rows = this.#rows.sort(
|
|
358
|
+
sortByCallback(arg[0], arg[1] === "desc" ? -1 : 1)
|
|
359
|
+
);
|
|
360
|
+
} else {
|
|
361
|
+
this.#rows = this.#rows.sort(
|
|
362
|
+
sortByProperties(...arg)
|
|
363
|
+
);
|
|
364
|
+
}
|
|
368
365
|
return this;
|
|
369
366
|
}
|
|
370
367
|
skip(numberOfRows) {
|
|
@@ -375,6 +372,52 @@ var _Query = class _Query {
|
|
|
375
372
|
this.#limit = limit;
|
|
376
373
|
return this;
|
|
377
374
|
}
|
|
375
|
+
limitPerGroup(arg, limit) {
|
|
376
|
+
const counts = /* @__PURE__ */ new Map();
|
|
377
|
+
const result = [];
|
|
378
|
+
const rows = this.#rows;
|
|
379
|
+
const isFn = isFunction(arg);
|
|
380
|
+
for (let i = 0; i < rows.length; i++) {
|
|
381
|
+
const row = rows[i];
|
|
382
|
+
const group = isFn ? arg(row) : row[arg];
|
|
383
|
+
const count = counts.get(group) ?? 0;
|
|
384
|
+
if (count < limit) {
|
|
385
|
+
result.push(row);
|
|
386
|
+
counts.set(group, count + 1);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
this.#rows = result;
|
|
390
|
+
return this;
|
|
391
|
+
}
|
|
392
|
+
top(limit, options) {
|
|
393
|
+
const rows = this.getLimitedRows();
|
|
394
|
+
if (rows.length === 0) {
|
|
395
|
+
return this;
|
|
396
|
+
}
|
|
397
|
+
const { partitionBy, orderBy } = options ?? {};
|
|
398
|
+
if (orderBy) {
|
|
399
|
+
const columns = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
400
|
+
this.#rows = rows.sort(sortByProperties(...columns));
|
|
401
|
+
}
|
|
402
|
+
if (!partitionBy) {
|
|
403
|
+
this.#rows = rows.slice(0, limit);
|
|
404
|
+
return this;
|
|
405
|
+
}
|
|
406
|
+
const isFn = isFunction(partitionBy);
|
|
407
|
+
const counts = /* @__PURE__ */ new Map();
|
|
408
|
+
const result = [];
|
|
409
|
+
for (let i = 0; i < rows.length; i++) {
|
|
410
|
+
const row = rows[i];
|
|
411
|
+
const group = isFn ? partitionBy(row) : row[partitionBy];
|
|
412
|
+
const count = counts.get(group) ?? 0;
|
|
413
|
+
if (count < limit) {
|
|
414
|
+
result.push(row);
|
|
415
|
+
counts.set(group, count + 1);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
this.#rows = result;
|
|
419
|
+
return this;
|
|
420
|
+
}
|
|
378
421
|
/**
|
|
379
422
|
* Returns all results.
|
|
380
423
|
*
|
|
@@ -616,6 +659,16 @@ __decorateClass([
|
|
|
616
659
|
__decorateParam(0, integer),
|
|
617
660
|
__decorateParam(0, min(0))
|
|
618
661
|
], _Query.prototype, "limit");
|
|
662
|
+
__decorateClass([
|
|
663
|
+
validateNumbers,
|
|
664
|
+
__decorateParam(1, integer),
|
|
665
|
+
__decorateParam(1, min(0))
|
|
666
|
+
], _Query.prototype, "limitPerGroup");
|
|
667
|
+
__decorateClass([
|
|
668
|
+
validateNumbers,
|
|
669
|
+
__decorateParam(0, integer),
|
|
670
|
+
__decorateParam(0, min(0))
|
|
671
|
+
], _Query.prototype, "top");
|
|
619
672
|
var Query = _Query;
|
|
620
673
|
|
|
621
674
|
exports.Query = Query;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -154,28 +154,21 @@ declare class Query<T extends object> {
|
|
|
154
154
|
/**
|
|
155
155
|
* Adds ordering to the results.
|
|
156
156
|
*
|
|
157
|
-
* This method should be called after `select()`; otherwise, the ordering will
|
|
158
|
-
* be applied only to the selected columns.
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```ts
|
|
162
|
-
* // ❌ "age" will not be ordered, because it is not part of the selected columns
|
|
163
|
-
* const query = Query.from(users)
|
|
164
|
-
* .orderBy('-age')
|
|
165
|
-
* .select('name');
|
|
166
|
-
*
|
|
167
|
-
* // ✅ "age" will be ordered
|
|
168
|
-
* const query = Query.from(users)
|
|
169
|
-
* .select('name', 'age')
|
|
170
|
-
* .orderBy('-age');
|
|
171
|
-
* ```
|
|
172
|
-
*
|
|
173
157
|
* @param columns Ascending or descending columns. To mark a field as
|
|
174
158
|
* descending, prefix it with `-`.
|
|
175
159
|
*
|
|
176
160
|
* @returns Current query.
|
|
177
161
|
*/
|
|
178
162
|
orderBy(...columns: OrderingColumn<T>[]): this;
|
|
163
|
+
/**
|
|
164
|
+
* Adds ordering to the results.
|
|
165
|
+
*
|
|
166
|
+
* @param fn Function to map each row to a value.
|
|
167
|
+
* @param order Sort order. Defaults to `asc`.
|
|
168
|
+
*
|
|
169
|
+
* @returns Current query.
|
|
170
|
+
*/
|
|
171
|
+
orderBy<TReturn>(fn: (row: T) => TReturn, order?: 'asc' | 'desc'): this;
|
|
179
172
|
/**
|
|
180
173
|
* Defines the number of rows to skip.
|
|
181
174
|
*
|
|
@@ -197,6 +190,56 @@ declare class Query<T extends object> {
|
|
|
197
190
|
* @throws {InvalidArgumentError} If the given limit is less than 0.
|
|
198
191
|
*/
|
|
199
192
|
limit(limit: number): this;
|
|
193
|
+
/**
|
|
194
|
+
* Limits the number of rows per group.
|
|
195
|
+
*
|
|
196
|
+
* @param key Key to group by.
|
|
197
|
+
* @param limit Maximum number of rows per group.
|
|
198
|
+
*
|
|
199
|
+
* @returns Current query.
|
|
200
|
+
*/
|
|
201
|
+
limitPerGroup<K extends keyof T>(key: K, limit: number): this;
|
|
202
|
+
/**
|
|
203
|
+
* Limits the number of rows per group using a callback.
|
|
204
|
+
*
|
|
205
|
+
* @param fn Function to define the group key.
|
|
206
|
+
* @param limit Maximum number of rows per group.
|
|
207
|
+
*
|
|
208
|
+
* @returns Current query.
|
|
209
|
+
*/
|
|
210
|
+
limitPerGroup<TValue>(fn: (row: T) => TValue, limit: number): this;
|
|
211
|
+
/**
|
|
212
|
+
* Keep the top N rows.
|
|
213
|
+
*
|
|
214
|
+
* @param limit Maximum number of rows per group.
|
|
215
|
+
*
|
|
216
|
+
* @returns Current query.
|
|
217
|
+
*/
|
|
218
|
+
top(limit: number): this;
|
|
219
|
+
/**
|
|
220
|
+
* Keep the top N rows, optionally partitioned by a key or callback.
|
|
221
|
+
*
|
|
222
|
+
* @param limit Maximum number of rows per group (or globally if no partition is provided).
|
|
223
|
+
* @param options Options to define partitioning and ordering.
|
|
224
|
+
*
|
|
225
|
+
* @returns Current query.
|
|
226
|
+
*/
|
|
227
|
+
top<K extends keyof T>(limit: number, options: {
|
|
228
|
+
partitionBy: K;
|
|
229
|
+
orderBy?: OrderingColumn<T> | OrderingColumn<T>[];
|
|
230
|
+
}): this;
|
|
231
|
+
/**
|
|
232
|
+
* Keep the top N rows, optionally partitioned by a key or callback.
|
|
233
|
+
*
|
|
234
|
+
* @param limit Maximum number of rows per group (or globally if no partition is provided).
|
|
235
|
+
* @param options Options to define partitioning and ordering.
|
|
236
|
+
*
|
|
237
|
+
* @returns Current query.
|
|
238
|
+
*/
|
|
239
|
+
top<TValue>(limit: number, options: {
|
|
240
|
+
partitionBy: (row: T) => TValue;
|
|
241
|
+
orderBy?: OrderingColumn<T> | OrderingColumn<T>[];
|
|
242
|
+
}): this;
|
|
200
243
|
/**
|
|
201
244
|
* Returns all results.
|
|
202
245
|
*
|
package/dist/esm/index.js
CHANGED
|
@@ -183,6 +183,21 @@ function getObjectPropertyNames(obj) {
|
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
// src/utils/functions/sort/sort-values.ts
|
|
187
|
+
function sortValues(a, b, order) {
|
|
188
|
+
if (a == null && b == null) return 0;
|
|
189
|
+
if (a == null) return 1 * order;
|
|
190
|
+
if (b == null) return -1 * order;
|
|
191
|
+
if (a < b) return -1 * order;
|
|
192
|
+
if (a > b) return 1 * order;
|
|
193
|
+
return 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/utils/functions/sort/sort-by-callback.ts
|
|
197
|
+
function sortByCallback(callback, sortOrder) {
|
|
198
|
+
return (a, b) => sortValues(callback(a), callback(b), sortOrder);
|
|
199
|
+
}
|
|
200
|
+
|
|
186
201
|
// src/utils/functions/sort/sort-by-property.ts
|
|
187
202
|
function sortByProperty(property) {
|
|
188
203
|
let sortOrder = 1;
|
|
@@ -195,12 +210,7 @@ function sortByProperty(property) {
|
|
|
195
210
|
return (a, b) => {
|
|
196
211
|
const valueA = a[key];
|
|
197
212
|
const valueB = b[key];
|
|
198
|
-
|
|
199
|
-
if (valueA == null) return 1 * sortOrder;
|
|
200
|
-
if (valueB == null) return -1 * sortOrder;
|
|
201
|
-
if (valueA < valueB) return -1 * sortOrder;
|
|
202
|
-
if (valueA > valueB) return 1 * sortOrder;
|
|
203
|
-
return 0;
|
|
213
|
+
return sortValues(valueA, valueB, sortOrder);
|
|
204
214
|
};
|
|
205
215
|
}
|
|
206
216
|
|
|
@@ -337,32 +347,19 @@ var _Query = class _Query {
|
|
|
337
347
|
this.filterRows(condition, { ignoreNullValues: true });
|
|
338
348
|
return this;
|
|
339
349
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
* // ✅ "age" will be ordered
|
|
354
|
-
* const query = Query.from(users)
|
|
355
|
-
* .select('name', 'age')
|
|
356
|
-
* .orderBy('-age');
|
|
357
|
-
* ```
|
|
358
|
-
*
|
|
359
|
-
* @param columns Ascending or descending columns. To mark a field as
|
|
360
|
-
* descending, prefix it with `-`.
|
|
361
|
-
*
|
|
362
|
-
* @returns Current query.
|
|
363
|
-
*/
|
|
364
|
-
orderBy(...columns) {
|
|
365
|
-
this.#rows = this.#rows.sort(sortByProperties(...columns));
|
|
350
|
+
orderBy(...arg) {
|
|
351
|
+
if (arg.length === 0) {
|
|
352
|
+
return this;
|
|
353
|
+
}
|
|
354
|
+
if (isFunction(arg[0])) {
|
|
355
|
+
this.#rows = this.#rows.sort(
|
|
356
|
+
sortByCallback(arg[0], arg[1] === "desc" ? -1 : 1)
|
|
357
|
+
);
|
|
358
|
+
} else {
|
|
359
|
+
this.#rows = this.#rows.sort(
|
|
360
|
+
sortByProperties(...arg)
|
|
361
|
+
);
|
|
362
|
+
}
|
|
366
363
|
return this;
|
|
367
364
|
}
|
|
368
365
|
skip(numberOfRows) {
|
|
@@ -373,6 +370,52 @@ var _Query = class _Query {
|
|
|
373
370
|
this.#limit = limit;
|
|
374
371
|
return this;
|
|
375
372
|
}
|
|
373
|
+
limitPerGroup(arg, limit) {
|
|
374
|
+
const counts = /* @__PURE__ */ new Map();
|
|
375
|
+
const result = [];
|
|
376
|
+
const rows = this.#rows;
|
|
377
|
+
const isFn = isFunction(arg);
|
|
378
|
+
for (let i = 0; i < rows.length; i++) {
|
|
379
|
+
const row = rows[i];
|
|
380
|
+
const group = isFn ? arg(row) : row[arg];
|
|
381
|
+
const count = counts.get(group) ?? 0;
|
|
382
|
+
if (count < limit) {
|
|
383
|
+
result.push(row);
|
|
384
|
+
counts.set(group, count + 1);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
this.#rows = result;
|
|
388
|
+
return this;
|
|
389
|
+
}
|
|
390
|
+
top(limit, options) {
|
|
391
|
+
const rows = this.getLimitedRows();
|
|
392
|
+
if (rows.length === 0) {
|
|
393
|
+
return this;
|
|
394
|
+
}
|
|
395
|
+
const { partitionBy, orderBy } = options ?? {};
|
|
396
|
+
if (orderBy) {
|
|
397
|
+
const columns = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
398
|
+
this.#rows = rows.sort(sortByProperties(...columns));
|
|
399
|
+
}
|
|
400
|
+
if (!partitionBy) {
|
|
401
|
+
this.#rows = rows.slice(0, limit);
|
|
402
|
+
return this;
|
|
403
|
+
}
|
|
404
|
+
const isFn = isFunction(partitionBy);
|
|
405
|
+
const counts = /* @__PURE__ */ new Map();
|
|
406
|
+
const result = [];
|
|
407
|
+
for (let i = 0; i < rows.length; i++) {
|
|
408
|
+
const row = rows[i];
|
|
409
|
+
const group = isFn ? partitionBy(row) : row[partitionBy];
|
|
410
|
+
const count = counts.get(group) ?? 0;
|
|
411
|
+
if (count < limit) {
|
|
412
|
+
result.push(row);
|
|
413
|
+
counts.set(group, count + 1);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
this.#rows = result;
|
|
417
|
+
return this;
|
|
418
|
+
}
|
|
376
419
|
/**
|
|
377
420
|
* Returns all results.
|
|
378
421
|
*
|
|
@@ -614,6 +657,16 @@ __decorateClass([
|
|
|
614
657
|
__decorateParam(0, integer),
|
|
615
658
|
__decorateParam(0, min(0))
|
|
616
659
|
], _Query.prototype, "limit");
|
|
660
|
+
__decorateClass([
|
|
661
|
+
validateNumbers,
|
|
662
|
+
__decorateParam(1, integer),
|
|
663
|
+
__decorateParam(1, min(0))
|
|
664
|
+
], _Query.prototype, "limitPerGroup");
|
|
665
|
+
__decorateClass([
|
|
666
|
+
validateNumbers,
|
|
667
|
+
__decorateParam(0, integer),
|
|
668
|
+
__decorateParam(0, min(0))
|
|
669
|
+
], _Query.prototype, "top");
|
|
617
670
|
var Query = _Query;
|
|
618
671
|
|
|
619
672
|
export { Query };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querier-ts",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.7.0",
|
|
5
5
|
"description": "A lightweight, type-safe in-memory query engine for JavaScript and TypeScript",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@eslint/js": "^10.0.1",
|
|
63
|
-
"@vitest/coverage-v8": "^4.1.
|
|
63
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
64
64
|
"eslint": "^10.2.0",
|
|
65
65
|
"eslint-config-prettier": "^10.1.8",
|
|
66
66
|
"eslint-plugin-prettier": "^5.5.5",
|
|
@@ -68,12 +68,12 @@
|
|
|
68
68
|
"husky": "^9.1.7",
|
|
69
69
|
"jiti": "^2.6.1",
|
|
70
70
|
"lint-staged": "^16.4.0",
|
|
71
|
-
"prettier": "^3.8.
|
|
71
|
+
"prettier": "^3.8.2",
|
|
72
72
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
73
73
|
"tsup": "^8.5.1",
|
|
74
74
|
"typescript": "~5.9.3",
|
|
75
|
-
"typescript-eslint": "^8.58.
|
|
76
|
-
"vitest": "^4.1.
|
|
75
|
+
"typescript-eslint": "^8.58.1",
|
|
76
|
+
"vitest": "^4.1.4"
|
|
77
77
|
},
|
|
78
78
|
"packageManager": "pnpm@10.33.0"
|
|
79
79
|
}
|