@webtypen/webframez-core 0.3.104 → 0.3.106
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/dist/Database/Model.js +1 -1
- package/dist/Datatable/Datatable.d.ts +4 -0
- package/dist/Datatable/Datatable.js +35 -29
- package/docs/datatables.md +23 -0
- package/package.json +1 -1
package/dist/Database/Model.js
CHANGED
|
@@ -267,7 +267,7 @@ class Model {
|
|
|
267
267
|
type: "aggregation",
|
|
268
268
|
table: collection ? collection : model ? model.__table : undefined,
|
|
269
269
|
aggregation: aggregation,
|
|
270
|
-
}, model.__connection);
|
|
270
|
+
}, model.__connection, options);
|
|
271
271
|
});
|
|
272
272
|
}
|
|
273
273
|
buildRelationship(model, foreignKey, localKey) {
|
|
@@ -37,6 +37,8 @@ export declare class Datatable {
|
|
|
37
37
|
autoApplyFilter: "begin" | "end" | null;
|
|
38
38
|
autoApplySearch: "begin" | "end" | null;
|
|
39
39
|
logAggregation: boolean;
|
|
40
|
+
deferPresentation: boolean;
|
|
41
|
+
collation: Record<string, any> | ((req: Request) => Record<string, any> | Promise<Record<string, any>>);
|
|
40
42
|
defaultUnwind?: string | null;
|
|
41
43
|
disablePerPageConfig: boolean;
|
|
42
44
|
selectable: boolean;
|
|
@@ -77,6 +79,8 @@ export declare class Datatable {
|
|
|
77
79
|
}[] | null>;
|
|
78
80
|
getAggregation(req: Request): Promise<any>;
|
|
79
81
|
getSubAggregation(req: Request): Promise<any>;
|
|
82
|
+
/** Filtered source for whole-result statistics; presentation and pagination are excluded. */
|
|
83
|
+
getStatisticsAggregation(req: Request): Promise<any[]>;
|
|
80
84
|
getCollection(req: Request): Promise<any>;
|
|
81
85
|
getData(req: Request, context?: DatatableColumnContext): Promise<{
|
|
82
86
|
page: number;
|
|
@@ -43,6 +43,8 @@ class Datatable {
|
|
|
43
43
|
this.autoApplyFilter = "begin";
|
|
44
44
|
this.autoApplySearch = null;
|
|
45
45
|
this.logAggregation = false;
|
|
46
|
+
this.deferPresentation = false;
|
|
47
|
+
this.collation = { locale: "de", strength: 2 };
|
|
46
48
|
this.defaultUnwind = null;
|
|
47
49
|
this.disablePerPageConfig = false;
|
|
48
50
|
this.selectable = false;
|
|
@@ -252,10 +254,7 @@ class Datatable {
|
|
|
252
254
|
const results = yield DBConnection_1.DBConnection.documentStore(connection)
|
|
253
255
|
.collection(yield this.getCollection(req))
|
|
254
256
|
.aggregate(aggregation, {
|
|
255
|
-
collation:
|
|
256
|
-
locale: "de",
|
|
257
|
-
strength: 2,
|
|
258
|
-
},
|
|
257
|
+
collation: typeof this.collation === "function" ? yield this.collation(req) : this.collation,
|
|
259
258
|
})
|
|
260
259
|
.toArray();
|
|
261
260
|
if (!results[0]) {
|
|
@@ -353,6 +352,17 @@ class Datatable {
|
|
|
353
352
|
return typeof this.subAggregation === "function" ? yield this.subAggregation(req, yield this.getColumnContext(req)) : this.subAggregation;
|
|
354
353
|
});
|
|
355
354
|
}
|
|
355
|
+
/** Filtered source for whole-result statistics; presentation and pagination are excluded. */
|
|
356
|
+
getStatisticsAggregation(req) {
|
|
357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
358
|
+
return [...(yield this.getAggregation(req)) || [], ...(yield this.getSubAggregation(req)) || []]
|
|
359
|
+
.filter(stage => !stage.skipStats && !stage.$sort && stage.$skip === undefined && stage.$limit === undefined)
|
|
360
|
+
.map((_a) => {
|
|
361
|
+
var { skipStats } = _a, stage = __rest(_a, ["skipStats"]);
|
|
362
|
+
return stage;
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
}
|
|
356
366
|
getCollection(req) {
|
|
357
367
|
return __awaiter(this, void 0, void 0, function* () {
|
|
358
368
|
if (this.collection && typeof this.collection === "function") {
|
|
@@ -373,16 +383,21 @@ class Datatable {
|
|
|
373
383
|
let hasSkip = false;
|
|
374
384
|
let hasLimit = false;
|
|
375
385
|
if (aggregationDef && aggregationDef.length > 0) {
|
|
376
|
-
for (
|
|
386
|
+
for (const definition of aggregationDef) {
|
|
387
|
+
const { skipStats } = definition, entry = __rest(definition, ["skipStats"]);
|
|
377
388
|
if (entry.$skip !== undefined) {
|
|
378
389
|
hasSkip = true;
|
|
379
390
|
}
|
|
380
391
|
if (entry.$limit !== undefined) {
|
|
381
392
|
hasLimit = true;
|
|
382
393
|
}
|
|
383
|
-
if (
|
|
384
|
-
|
|
385
|
-
|
|
394
|
+
if (skipStats) {
|
|
395
|
+
if (this.deferPresentation && !entry.$sort && entry.$skip === undefined && entry.$limit === undefined) {
|
|
396
|
+
subAggregation.push(entry);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
aggregation.push(entry);
|
|
400
|
+
}
|
|
386
401
|
}
|
|
387
402
|
else {
|
|
388
403
|
aggregation.push(entry);
|
|
@@ -391,15 +406,15 @@ class Datatable {
|
|
|
391
406
|
}
|
|
392
407
|
}
|
|
393
408
|
if (subAggregationDef && subAggregationDef.length > 0) {
|
|
394
|
-
for (
|
|
409
|
+
for (const definition of subAggregationDef) {
|
|
410
|
+
const { skipStats } = definition, entry = __rest(definition, ["skipStats"]);
|
|
395
411
|
if (entry.$skip !== undefined) {
|
|
396
412
|
hasSkip = true;
|
|
397
413
|
}
|
|
398
414
|
if (entry.$limit !== undefined) {
|
|
399
415
|
hasLimit = true;
|
|
400
416
|
}
|
|
401
|
-
if (
|
|
402
|
-
delete entry.skipStats;
|
|
417
|
+
if (skipStats) {
|
|
403
418
|
subAggregation.push(entry);
|
|
404
419
|
}
|
|
405
420
|
else {
|
|
@@ -423,10 +438,7 @@ class Datatable {
|
|
|
423
438
|
const results = yield DBConnection_1.DBConnection.documentStore(connection)
|
|
424
439
|
.collection(yield this.getCollection(req))
|
|
425
440
|
.aggregate(aggr, {
|
|
426
|
-
collation:
|
|
427
|
-
locale: "de",
|
|
428
|
-
strength: 2,
|
|
429
|
-
},
|
|
441
|
+
collation: typeof this.collation === "function" ? yield this.collation(req) : this.collation,
|
|
430
442
|
})
|
|
431
443
|
.toArray();
|
|
432
444
|
const sumsAfter = [];
|
|
@@ -511,23 +523,17 @@ class Datatable {
|
|
|
511
523
|
}
|
|
512
524
|
getTotalData(req) {
|
|
513
525
|
return __awaiter(this, void 0, void 0, function* () {
|
|
514
|
-
const aggregation = []
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
delete entry.skipStats;
|
|
520
|
-
aggregation.push(entry);
|
|
521
|
-
}
|
|
522
|
-
else {
|
|
523
|
-
aggregation.push(entry);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
526
|
+
const aggregation = [...(yield this.getAggregation(req)) || [], ...(yield this.getSubAggregation(req)) || []]
|
|
527
|
+
.map((_a) => {
|
|
528
|
+
var { skipStats } = _a, stage = __rest(_a, ["skipStats"]);
|
|
529
|
+
return stage;
|
|
530
|
+
});
|
|
527
531
|
const connection = yield DBConnection_1.DBConnection.getConnection();
|
|
528
532
|
return yield DBConnection_1.DBConnection.documentStore(connection)
|
|
529
533
|
.collection(yield this.getCollection(req))
|
|
530
|
-
.aggregate(
|
|
534
|
+
.aggregate(aggregation, {
|
|
535
|
+
collation: typeof this.collation === "function" ? yield this.collation(req) : this.collation,
|
|
536
|
+
})
|
|
531
537
|
.toArray();
|
|
532
538
|
});
|
|
533
539
|
}
|
package/docs/datatables.md
CHANGED
|
@@ -126,3 +126,26 @@ creates an optional column catalog from nested DataBuilder/DataSchema fields.
|
|
|
126
126
|
The `prepare(column, field, path)` callback can attach inline or lazy display
|
|
127
127
|
options, change the mapping, or return null to omit a field. Plugin installation,
|
|
128
128
|
tenant checks and relation hydration belong in the host adapter.
|
|
129
|
+
|
|
130
|
+
## Statistics and collation
|
|
131
|
+
|
|
132
|
+
`getStatisticsAggregation(req)` returns the filtered aggregation and sub-aggregation,
|
|
133
|
+
excluding stages marked `skipStats: true`, sorting and pagination. It does not mutate
|
|
134
|
+
stage definitions. Keep tenant and filter dependencies unmarked; calculate statistic-only
|
|
135
|
+
fields in the statistics service instead of depending on presentation projections.
|
|
136
|
+
|
|
137
|
+
`collation` defaults to `{ locale: "de", strength: 2 }` for compatibility. It can be
|
|
138
|
+
an object or an async request callback. Tables sorting numeric/date fields can return
|
|
139
|
+
`{ locale: "simple" }` to use matching binary indexes. Keep language collation for
|
|
140
|
+
text sorting or filters that depend on it; collation applies to the entire data query.
|
|
141
|
+
|
|
142
|
+
Exports (`getTotalData`) execute both aggregation phases with the same collation as
|
|
143
|
+
the table, without injecting page limits. Explicit limits in the table definition
|
|
144
|
+
remain effective, including bounded notification exports.
|
|
145
|
+
|
|
146
|
+
Tables can opt into `deferPresentation = true` to execute aggregation stages marked
|
|
147
|
+
`skipStats: true` after pagination, before explicit `subAggregation`. Sort/skip/limit
|
|
148
|
+
stages stay in the selection phase. Only mark cardinality-preserving display stages:
|
|
149
|
+
any join or calculation required by a filter, sort, or later selection stage must
|
|
150
|
+
remain unmarked. Exports retain all stages in their original order. The default is
|
|
151
|
+
false, so existing definitions keep their behavior until explicitly reviewed.
|
package/package.json
CHANGED