flongo 1.6.0 → 1.8.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/README.md +11 -0
- package/dist/cache/cacheKeyGenerator.js +10 -0
- package/dist/flongo.d.ts +3 -1
- package/dist/flongo.js +13 -1
- package/dist/flongoQuery.d.ts +39 -6
- package/dist/flongoQuery.js +66 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,6 +105,17 @@ const results = await collection.getAll(
|
|
|
105
105
|
query.orderBy('createdAt', SortDirection.Descending),
|
|
106
106
|
{ offset: 0, count: 20 }
|
|
107
107
|
);
|
|
108
|
+
|
|
109
|
+
// Compound (multi-field) sort with a unique tiebreaker.
|
|
110
|
+
// Appending `_id` makes skip/limit pagination deterministic, so pages never
|
|
111
|
+
// overlap or skip documents when the primary sort key has ties.
|
|
112
|
+
const page = await collection.getAll(
|
|
113
|
+
new FlongoQuery()
|
|
114
|
+
.where('status').eq('accepted')
|
|
115
|
+
.orderBy('featured', SortDirection.Descending)
|
|
116
|
+
.thenBy('_id', SortDirection.Ascending), // => sort: { featured: -1, _id: 1 }
|
|
117
|
+
{ offset: 0, count: 24 }
|
|
118
|
+
);
|
|
108
119
|
```
|
|
109
120
|
|
|
110
121
|
### Collection Operations
|
|
@@ -72,6 +72,16 @@ class CacheKeyGenerator {
|
|
|
72
72
|
direction: query.orderDirection || types_1.SortDirection.Ascending
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
+
// Include the full ordered sort list only when tiebreakers are present, so
|
|
76
|
+
// queries differing only by a tiebreaker (e.g. `{ featured: -1 }` vs
|
|
77
|
+
// `{ featured: -1, _id: 1 }`) hash to distinct keys. Single-sort queries
|
|
78
|
+
// keep their previous key shape (just `order`) for cache continuity.
|
|
79
|
+
if (query.sorts && query.sorts.length > 1) {
|
|
80
|
+
normalized.sorts = query.sorts.map(sort => ({
|
|
81
|
+
field: sort.field,
|
|
82
|
+
direction: sort.direction || types_1.SortDirection.Ascending
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
75
85
|
if (query.orQueries && query.orQueries.length > 0) {
|
|
76
86
|
normalized.or = query.orQueries
|
|
77
87
|
.map(q => this.normalizeQuery(q))
|
package/dist/flongo.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Db, MongoClient } from "mongodb";
|
|
1
|
+
import { Db, MongoClient, MongoClientOptions } from "mongodb";
|
|
2
2
|
export declare let flongoClient: MongoClient;
|
|
3
3
|
export declare let flongoDb: Db;
|
|
4
4
|
export interface FlongoConfig {
|
|
5
5
|
connectionString: string;
|
|
6
6
|
dbName: string;
|
|
7
|
+
clientOptions?: MongoClientOptions;
|
|
7
8
|
}
|
|
8
9
|
export declare function initializeFlongo(config: FlongoConfig): void;
|
|
10
|
+
export declare function connectFlongo(config: FlongoConfig): Promise<void>;
|
|
9
11
|
//# sourceMappingURL=flongo.d.ts.map
|
package/dist/flongo.js
CHANGED
|
@@ -2,9 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.flongoDb = exports.flongoClient = void 0;
|
|
4
4
|
exports.initializeFlongo = initializeFlongo;
|
|
5
|
+
exports.connectFlongo = connectFlongo;
|
|
5
6
|
const mongodb_1 = require("mongodb");
|
|
7
|
+
const defaultClientOptions = {
|
|
8
|
+
serverSelectionTimeoutMS: 10000,
|
|
9
|
+
heartbeatFrequencyMS: 15000,
|
|
10
|
+
socketTimeoutMS: 30000,
|
|
11
|
+
maxIdleTimeMS: 60000,
|
|
12
|
+
};
|
|
6
13
|
function initializeFlongo(config) {
|
|
7
|
-
|
|
14
|
+
const options = { ...defaultClientOptions, ...config.clientOptions };
|
|
15
|
+
exports.flongoClient = new mongodb_1.MongoClient(config.connectionString, options);
|
|
8
16
|
exports.flongoDb = exports.flongoClient.db(config.dbName);
|
|
9
17
|
}
|
|
18
|
+
async function connectFlongo(config) {
|
|
19
|
+
initializeFlongo(config);
|
|
20
|
+
await exports.flongoClient.connect();
|
|
21
|
+
}
|
|
10
22
|
//# sourceMappingURL=flongo.js.map
|
package/dist/flongoQuery.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bounds, Coordinates, Pagination, ColExpression, ColRange, ICollectionQuery, Logic, SortDirection } from "./types";
|
|
1
|
+
import { Bounds, Coordinates, Pagination, ColExpression, ColRange, ICollectionQuery, Logic, Sort, SortDirection } from "./types";
|
|
2
2
|
import { Document, Filter, FindOptions } from "mongodb";
|
|
3
3
|
/**
|
|
4
4
|
* FlongoQuery provides a fluent, chainable interface for building MongoDB queries
|
|
@@ -19,10 +19,21 @@ export declare class FlongoQuery implements ICollectionQuery {
|
|
|
19
19
|
expressions: ColExpression[];
|
|
20
20
|
/** Array of range queries (currently unused but reserved for future features) */
|
|
21
21
|
ranges: ColRange[];
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Ordered list of sort keys. The first entry is the primary sort, subsequent
|
|
24
|
+
* entries act as tiebreakers (in order). Populated by `orderBy()`/`thenBy()`.
|
|
25
|
+
*/
|
|
26
|
+
sorts: Sort[];
|
|
27
|
+
/**
|
|
28
|
+
* Primary sort field, derived from `sorts[0]`.
|
|
29
|
+
* @deprecated Retained for backward compatibility; use `sorts`.
|
|
30
|
+
*/
|
|
31
|
+
get orderField(): string | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Primary sort direction, derived from `sorts[0]`.
|
|
34
|
+
* @deprecated Retained for backward compatibility; use `sorts`.
|
|
35
|
+
*/
|
|
36
|
+
get orderDirection(): SortDirection | undefined;
|
|
26
37
|
/** Array of queries to be combined with OR logic */
|
|
27
38
|
orQueries: FlongoQuery[];
|
|
28
39
|
/** Array of queries to be combined with AND logic */
|
|
@@ -224,12 +235,34 @@ export declare class FlongoQuery implements ICollectionQuery {
|
|
|
224
235
|
*/
|
|
225
236
|
near(center: Coordinates, maxDistanceMeters: number): FlongoQuery;
|
|
226
237
|
/**
|
|
227
|
-
* Sets the field and direction
|
|
238
|
+
* Sets the primary sort field and direction, resetting any previously
|
|
239
|
+
* configured sort keys (including tiebreakers added via `thenBy`).
|
|
228
240
|
* @param field - Field name to sort by
|
|
229
241
|
* @param direction - Sort direction (ascending or descending)
|
|
230
242
|
* @returns This query instance for chaining
|
|
231
243
|
*/
|
|
232
244
|
orderBy(field?: string, direction?: SortDirection): FlongoQuery;
|
|
245
|
+
/**
|
|
246
|
+
* Appends a secondary (tertiary, …) sort key used as a tiebreaker after the
|
|
247
|
+
* primary `orderBy` field. Sort keys are applied in the order they are added,
|
|
248
|
+
* which is what makes deterministic pagination possible (e.g. appending a
|
|
249
|
+
* unique `_id` tiebreaker so `skip`/`limit` pages don't overlap).
|
|
250
|
+
*
|
|
251
|
+
* If called before any `orderBy`, the field becomes the primary sort.
|
|
252
|
+
* If the same field is added more than once, the latest direction wins
|
|
253
|
+
* (the field keeps its original position in the sort order).
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* new FlongoQuery()
|
|
257
|
+
* .orderBy('featured', SortDirection.Descending)
|
|
258
|
+
* .thenBy('_id', SortDirection.Ascending);
|
|
259
|
+
* // => sort: { featured: -1, _id: 1 }
|
|
260
|
+
*
|
|
261
|
+
* @param field - Field name to sort by
|
|
262
|
+
* @param direction - Sort direction (ascending or descending)
|
|
263
|
+
* @returns This query instance for chaining
|
|
264
|
+
*/
|
|
265
|
+
thenBy(field?: string, direction?: SortDirection): FlongoQuery;
|
|
233
266
|
/**
|
|
234
267
|
* Adds a sub-query with AND logic
|
|
235
268
|
* @param query - Sub-query to combine with AND logic
|
package/dist/flongoQuery.js
CHANGED
|
@@ -26,11 +26,30 @@ class FlongoQuery {
|
|
|
26
26
|
this.expressions = [];
|
|
27
27
|
/** Array of range queries (currently unused but reserved for future features) */
|
|
28
28
|
this.ranges = [];
|
|
29
|
+
/**
|
|
30
|
+
* Ordered list of sort keys. The first entry is the primary sort, subsequent
|
|
31
|
+
* entries act as tiebreakers (in order). Populated by `orderBy()`/`thenBy()`.
|
|
32
|
+
*/
|
|
33
|
+
this.sorts = [];
|
|
29
34
|
/** Array of queries to be combined with OR logic */
|
|
30
35
|
this.orQueries = [];
|
|
31
36
|
/** Array of queries to be combined with AND logic */
|
|
32
37
|
this.andQueries = [];
|
|
33
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Primary sort field, derived from `sorts[0]`.
|
|
41
|
+
* @deprecated Retained for backward compatibility; use `sorts`.
|
|
42
|
+
*/
|
|
43
|
+
get orderField() {
|
|
44
|
+
return this.sorts[0]?.field;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Primary sort direction, derived from `sorts[0]`.
|
|
48
|
+
* @deprecated Retained for backward compatibility; use `sorts`.
|
|
49
|
+
*/
|
|
50
|
+
get orderDirection() {
|
|
51
|
+
return this.sorts[0]?.direction;
|
|
52
|
+
}
|
|
34
53
|
/**
|
|
35
54
|
* Gets the most recently added expression for method chaining
|
|
36
55
|
* @private
|
|
@@ -352,14 +371,47 @@ class FlongoQuery {
|
|
|
352
371
|
// SORTING
|
|
353
372
|
// ===========================================
|
|
354
373
|
/**
|
|
355
|
-
* Sets the field and direction
|
|
374
|
+
* Sets the primary sort field and direction, resetting any previously
|
|
375
|
+
* configured sort keys (including tiebreakers added via `thenBy`).
|
|
356
376
|
* @param field - Field name to sort by
|
|
357
377
|
* @param direction - Sort direction (ascending or descending)
|
|
358
378
|
* @returns This query instance for chaining
|
|
359
379
|
*/
|
|
360
380
|
orderBy(field, direction) {
|
|
361
|
-
this.
|
|
362
|
-
this
|
|
381
|
+
this.sorts = field ? [{ field, direction }] : [];
|
|
382
|
+
return this;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Appends a secondary (tertiary, …) sort key used as a tiebreaker after the
|
|
386
|
+
* primary `orderBy` field. Sort keys are applied in the order they are added,
|
|
387
|
+
* which is what makes deterministic pagination possible (e.g. appending a
|
|
388
|
+
* unique `_id` tiebreaker so `skip`/`limit` pages don't overlap).
|
|
389
|
+
*
|
|
390
|
+
* If called before any `orderBy`, the field becomes the primary sort.
|
|
391
|
+
* If the same field is added more than once, the latest direction wins
|
|
392
|
+
* (the field keeps its original position in the sort order).
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* new FlongoQuery()
|
|
396
|
+
* .orderBy('featured', SortDirection.Descending)
|
|
397
|
+
* .thenBy('_id', SortDirection.Ascending);
|
|
398
|
+
* // => sort: { featured: -1, _id: 1 }
|
|
399
|
+
*
|
|
400
|
+
* @param field - Field name to sort by
|
|
401
|
+
* @param direction - Sort direction (ascending or descending)
|
|
402
|
+
* @returns This query instance for chaining
|
|
403
|
+
*/
|
|
404
|
+
thenBy(field, direction) {
|
|
405
|
+
if (!field) {
|
|
406
|
+
return this;
|
|
407
|
+
}
|
|
408
|
+
const existing = this.sorts.find((s) => s.field === field);
|
|
409
|
+
if (existing) {
|
|
410
|
+
existing.direction = direction;
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
this.sorts.push({ field, direction });
|
|
414
|
+
}
|
|
363
415
|
return this;
|
|
364
416
|
}
|
|
365
417
|
// ===========================================
|
|
@@ -486,11 +538,17 @@ class FlongoQuery {
|
|
|
486
538
|
mongodbOptions.skip = pagination.offset;
|
|
487
539
|
mongodbOptions.limit = pagination.count;
|
|
488
540
|
}
|
|
489
|
-
// Add sorting if specified
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
541
|
+
// Add sorting if specified. Iterate sort keys in order so MongoDB honors the
|
|
542
|
+
// insertion order of the resulting `sort` object's keys (primary first, then
|
|
543
|
+
// tiebreakers). Entries without a direction are skipped, preserving the prior
|
|
544
|
+
// behavior where a field set with no direction produced no sort.
|
|
545
|
+
const sortKeys = this.sorts.filter((s) => s.field && s.direction);
|
|
546
|
+
if (sortKeys.length) {
|
|
547
|
+
const sort = {};
|
|
548
|
+
for (const s of sortKeys) {
|
|
549
|
+
sort[s.field] = s.direction === types_1.SortDirection.Ascending ? 1 : -1;
|
|
550
|
+
}
|
|
551
|
+
mongodbOptions.sort = sort;
|
|
494
552
|
}
|
|
495
553
|
return mongodbOptions;
|
|
496
554
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FlongoCollection, FlongoCollectionOptions } from "./flongoCollection";
|
|
2
2
|
export { FlongoQuery, FlongoQueryBuilder } from "./flongoQuery";
|
|
3
|
-
export { initializeFlongo, FlongoConfig, flongoClient, flongoDb } from "./flongo";
|
|
3
|
+
export { initializeFlongo, connectFlongo, FlongoConfig, flongoClient, flongoDb } from "./flongo";
|
|
4
4
|
export { Error404, Error400 } from "./errors";
|
|
5
|
-
export { Entity, DbRecord, Pagination, Coordinates, Bounds, Event, EventName, EventRecord, Logic, SortDirection, ColRange, ColExpression, ICollectionQuery, ICollection, Repository, CacheOptions, CachedCollectionOptions } from "./types";
|
|
5
|
+
export { Entity, DbRecord, Pagination, Coordinates, Bounds, Event, EventName, EventRecord, Logic, SortDirection, Sort, ColRange, ColExpression, ICollectionQuery, ICollection, Repository, CacheOptions, CachedCollectionOptions } from "./types";
|
|
6
6
|
export { CacheStore, CacheEntry, CacheStats, CacheStoreOptions, BaseCacheStore, MemoryCache, MemoryCacheOptions, CacheKeyGenerator, CacheKeyOptions, InvalidationStrategy, InvalidationRule, InvalidationOptions, CacheInvalidator, TTLStrategy, LRUStrategy, CacheConfig, CacheProviderConfig, CacheConfiguration, createDefaultConfig, createProductionConfig, createDevelopmentConfig, DetailedCacheStats, CacheMetrics, CacheStatsCollector, CacheMonitor, getGlobalCacheMonitor, resetGlobalCacheMonitor } from "./cache";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Main exports for flongo package
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.resetGlobalCacheMonitor = exports.getGlobalCacheMonitor = exports.CacheMonitor = exports.CacheStatsCollector = exports.createDevelopmentConfig = exports.createProductionConfig = exports.createDefaultConfig = exports.CacheConfiguration = exports.LRUStrategy = exports.TTLStrategy = exports.CacheInvalidator = exports.InvalidationStrategy = exports.CacheKeyGenerator = exports.MemoryCache = exports.BaseCacheStore = exports.ColExpression = exports.ColRange = exports.SortDirection = exports.Logic = exports.EventName = exports.Error400 = exports.Error404 = exports.flongoDb = exports.flongoClient = exports.initializeFlongo = exports.FlongoQueryBuilder = exports.FlongoQuery = exports.FlongoCollection = void 0;
|
|
4
|
+
exports.resetGlobalCacheMonitor = exports.getGlobalCacheMonitor = exports.CacheMonitor = exports.CacheStatsCollector = exports.createDevelopmentConfig = exports.createProductionConfig = exports.createDefaultConfig = exports.CacheConfiguration = exports.LRUStrategy = exports.TTLStrategy = exports.CacheInvalidator = exports.InvalidationStrategy = exports.CacheKeyGenerator = exports.MemoryCache = exports.BaseCacheStore = exports.ColExpression = exports.ColRange = exports.SortDirection = exports.Logic = exports.EventName = exports.Error400 = exports.Error404 = exports.flongoDb = exports.flongoClient = exports.connectFlongo = exports.initializeFlongo = exports.FlongoQueryBuilder = exports.FlongoQuery = exports.FlongoCollection = void 0;
|
|
5
5
|
var flongoCollection_1 = require("./flongoCollection");
|
|
6
6
|
Object.defineProperty(exports, "FlongoCollection", { enumerable: true, get: function () { return flongoCollection_1.FlongoCollection; } });
|
|
7
7
|
var flongoQuery_1 = require("./flongoQuery");
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "FlongoQuery", { enumerable: true, get: function
|
|
|
9
9
|
Object.defineProperty(exports, "FlongoQueryBuilder", { enumerable: true, get: function () { return flongoQuery_1.FlongoQueryBuilder; } });
|
|
10
10
|
var flongo_1 = require("./flongo");
|
|
11
11
|
Object.defineProperty(exports, "initializeFlongo", { enumerable: true, get: function () { return flongo_1.initializeFlongo; } });
|
|
12
|
+
Object.defineProperty(exports, "connectFlongo", { enumerable: true, get: function () { return flongo_1.connectFlongo; } });
|
|
12
13
|
Object.defineProperty(exports, "flongoClient", { enumerable: true, get: function () { return flongo_1.flongoClient; } });
|
|
13
14
|
Object.defineProperty(exports, "flongoDb", { enumerable: true, get: function () { return flongo_1.flongoDb; } });
|
|
14
15
|
var errors_1 = require("./errors");
|
package/dist/types.d.ts
CHANGED
|
@@ -58,10 +58,19 @@ export declare class ColExpression {
|
|
|
58
58
|
val: any;
|
|
59
59
|
constructor(key: string);
|
|
60
60
|
}
|
|
61
|
+
/** A single sort key: a field paired with a direction. */
|
|
62
|
+
export interface Sort {
|
|
63
|
+
field: string;
|
|
64
|
+
direction?: SortDirection;
|
|
65
|
+
}
|
|
61
66
|
export type ICollectionQuery = {
|
|
62
67
|
expressions: ColExpression[];
|
|
63
68
|
ranges: ColRange[];
|
|
69
|
+
/** Ordered list of sort keys. The first entry is the primary sort. */
|
|
70
|
+
sorts?: Sort[];
|
|
71
|
+
/** @deprecated Primary sort field; derived from `sorts[0]`. Use `sorts`. */
|
|
64
72
|
orderField?: string;
|
|
73
|
+
/** @deprecated Primary sort direction; derived from `sorts[0]`. Use `sorts`. */
|
|
65
74
|
orderDirection?: SortDirection;
|
|
66
75
|
orQueries: ICollectionQuery[];
|
|
67
76
|
andQueries: ICollectionQuery[];
|