@webtypen/webframez-core 0.3.104 → 0.3.105

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.
@@ -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,7 @@ export declare class Datatable {
37
37
  autoApplyFilter: "begin" | "end" | null;
38
38
  autoApplySearch: "begin" | "end" | null;
39
39
  logAggregation: boolean;
40
+ collation: Record<string, any> | ((req: Request) => Record<string, any> | Promise<Record<string, any>>);
40
41
  defaultUnwind?: string | null;
41
42
  disablePerPageConfig: boolean;
42
43
  selectable: boolean;
@@ -77,6 +78,8 @@ export declare class Datatable {
77
78
  }[] | null>;
78
79
  getAggregation(req: Request): Promise<any>;
79
80
  getSubAggregation(req: Request): Promise<any>;
81
+ /** Filtered source for whole-result statistics; presentation and pagination are excluded. */
82
+ getStatisticsAggregation(req: Request): Promise<any[]>;
80
83
  getCollection(req: Request): Promise<any>;
81
84
  getData(req: Request, context?: DatatableColumnContext): Promise<{
82
85
  page: number;
@@ -43,6 +43,7 @@ class Datatable {
43
43
  this.autoApplyFilter = "begin";
44
44
  this.autoApplySearch = null;
45
45
  this.logAggregation = false;
46
+ this.collation = { locale: "de", strength: 2 };
46
47
  this.defaultUnwind = null;
47
48
  this.disablePerPageConfig = false;
48
49
  this.selectable = false;
@@ -252,10 +253,7 @@ class Datatable {
252
253
  const results = yield DBConnection_1.DBConnection.documentStore(connection)
253
254
  .collection(yield this.getCollection(req))
254
255
  .aggregate(aggregation, {
255
- collation: {
256
- locale: "de",
257
- strength: 2,
258
- },
256
+ collation: typeof this.collation === "function" ? yield this.collation(req) : this.collation,
259
257
  })
260
258
  .toArray();
261
259
  if (!results[0]) {
@@ -353,6 +351,17 @@ class Datatable {
353
351
  return typeof this.subAggregation === "function" ? yield this.subAggregation(req, yield this.getColumnContext(req)) : this.subAggregation;
354
352
  });
355
353
  }
354
+ /** Filtered source for whole-result statistics; presentation and pagination are excluded. */
355
+ getStatisticsAggregation(req) {
356
+ return __awaiter(this, void 0, void 0, function* () {
357
+ return [...(yield this.getAggregation(req)) || [], ...(yield this.getSubAggregation(req)) || []]
358
+ .filter(stage => !stage.skipStats && !stage.$sort && stage.$skip === undefined && stage.$limit === undefined)
359
+ .map((_a) => {
360
+ var { skipStats } = _a, stage = __rest(_a, ["skipStats"]);
361
+ return stage;
362
+ });
363
+ });
364
+ }
356
365
  getCollection(req) {
357
366
  return __awaiter(this, void 0, void 0, function* () {
358
367
  if (this.collection && typeof this.collection === "function") {
@@ -373,15 +382,15 @@ class Datatable {
373
382
  let hasSkip = false;
374
383
  let hasLimit = false;
375
384
  if (aggregationDef && aggregationDef.length > 0) {
376
- for (let entry of aggregationDef) {
385
+ for (const definition of aggregationDef) {
386
+ const { skipStats } = definition, entry = __rest(definition, ["skipStats"]);
377
387
  if (entry.$skip !== undefined) {
378
388
  hasSkip = true;
379
389
  }
380
390
  if (entry.$limit !== undefined) {
381
391
  hasLimit = true;
382
392
  }
383
- if (entry.skipStats) {
384
- delete entry.skipStats;
393
+ if (skipStats) {
385
394
  aggregation.push(entry);
386
395
  }
387
396
  else {
@@ -391,15 +400,15 @@ class Datatable {
391
400
  }
392
401
  }
393
402
  if (subAggregationDef && subAggregationDef.length > 0) {
394
- for (let entry of subAggregationDef) {
403
+ for (const definition of subAggregationDef) {
404
+ const { skipStats } = definition, entry = __rest(definition, ["skipStats"]);
395
405
  if (entry.$skip !== undefined) {
396
406
  hasSkip = true;
397
407
  }
398
408
  if (entry.$limit !== undefined) {
399
409
  hasLimit = true;
400
410
  }
401
- if (entry.skipStats) {
402
- delete entry.skipStats;
411
+ if (skipStats) {
403
412
  subAggregation.push(entry);
404
413
  }
405
414
  else {
@@ -423,10 +432,7 @@ class Datatable {
423
432
  const results = yield DBConnection_1.DBConnection.documentStore(connection)
424
433
  .collection(yield this.getCollection(req))
425
434
  .aggregate(aggr, {
426
- collation: {
427
- locale: "de",
428
- strength: 2,
429
- },
435
+ collation: typeof this.collation === "function" ? yield this.collation(req) : this.collation,
430
436
  })
431
437
  .toArray();
432
438
  const sumsAfter = [];
@@ -514,9 +520,9 @@ class Datatable {
514
520
  const aggregation = [];
515
521
  const aggregationDef = yield this.getAggregation(req);
516
522
  if (aggregationDef && aggregationDef.length > 0) {
517
- for (let entry of aggregationDef) {
518
- if (entry.skipStats) {
519
- delete entry.skipStats;
523
+ for (const definition of aggregationDef) {
524
+ const { skipStats } = definition, entry = __rest(definition, ["skipStats"]);
525
+ if (skipStats) {
520
526
  aggregation.push(entry);
521
527
  }
522
528
  else {
@@ -126,3 +126,15 @@ 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-core",
3
- "version": "0.3.104",
3
+ "version": "0.3.105",
4
4
  "description": "The core package of the typescript based webframez (web-framework) by webtypen.de",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "license": "MIT",