@visactor/vbi 0.0.0 → 0.4.13

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.
Files changed (29) hide show
  1. package/LICENSE +21 -0
  2. package/dist/builder/sub-builders/havingFilters/having-builder.d.ts +33 -20
  3. package/dist/builder/sub-builders/havingFilters/having-group-builder.d.ts +48 -0
  4. package/dist/builder/sub-builders/havingFilters/having-node-builder.d.ts +8 -0
  5. package/dist/builder/sub-builders/havingFilters/index.d.ts +1 -0
  6. package/dist/builder/sub-builders/index.d.ts +1 -1
  7. package/dist/builder/sub-builders/whereFilters/index.d.ts +1 -0
  8. package/dist/builder/sub-builders/whereFilters/where-builder.d.ts +30 -17
  9. package/dist/builder/sub-builders/whereFilters/where-group-builder.d.ts +48 -0
  10. package/dist/builder/sub-builders/whereFilters/where-node-builder.d.ts +8 -0
  11. package/dist/index.cjs +424 -129
  12. package/dist/index.js +406 -120
  13. package/dist/pipeline/index.d.ts +1 -1
  14. package/dist/pipeline/vqueryDSL/buildGroupBy.d.ts +2 -0
  15. package/dist/pipeline/vqueryDSL/buildHaving.d.ts +2 -0
  16. package/dist/pipeline/vqueryDSL/buildLimit.d.ts +2 -0
  17. package/dist/pipeline/vqueryDSL/buildSelect.d.ts +2 -0
  18. package/dist/pipeline/vqueryDSL/buildWhere.d.ts +2 -0
  19. package/dist/pipeline/vqueryDSL/index.d.ts +4 -1
  20. package/dist/pipeline/vqueryDSL/types.d.ts +7 -0
  21. package/dist/types/dsl/havingFilters/having.d.ts +12 -7
  22. package/dist/types/dsl/index.d.ts +4 -2
  23. package/dist/types/dsl/vbi/vbi.d.ts +2 -10
  24. package/dist/types/dsl/whereFilters/filters.d.ts +12 -1
  25. package/dist/types/index.d.ts +0 -1
  26. package/dist/utils/id.d.ts +3 -0
  27. package/dist/utils/index.d.ts +1 -0
  28. package/package.json +38 -23
  29. package/dist/pipeline/vqueryDSL/buildVQuery.d.ts +0 -4
package/dist/index.cjs CHANGED
@@ -24,16 +24,19 @@ var __webpack_require__ = {};
24
24
  var __webpack_exports__ = {};
25
25
  __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
- zVBIHavingFilter: ()=>zVBIHavingFilter,
28
- zVBIHavingArray: ()=>zVBIHavingArray,
27
+ preorderTraverse: ()=>vseed_namespaceObject.preorderTraverse,
28
+ isVBIHavingGroup: ()=>isVBIHavingGroup,
29
29
  MeasuresBuilder: ()=>MeasuresBuilder,
30
30
  DimensionsBuilder: ()=>DimensionsBuilder,
31
31
  VBIBuilder: ()=>VBIBuilder,
32
32
  ChartTypeBuilder: ()=>ChartTypeBuilder,
33
+ isVBIFilter: ()=>isVBIFilter,
33
34
  VBI: ()=>VBI,
34
- preorderTraverse: ()=>vseed_namespaceObject.preorderTraverse,
35
+ isVBIWhereGroup: ()=>isVBIWhereGroup,
36
+ isVBIHavingFilter: ()=>isVBIHavingFilter,
35
37
  buildVQuery: ()=>buildVQuery,
36
- findTreeNodesBy: ()=>vseed_namespaceObject.findTreeNodesBy
38
+ findTreeNodesBy: ()=>vseed_namespaceObject.findTreeNodesBy,
39
+ id: ()=>id_id
37
40
  });
38
41
  const external_yjs_namespaceObject = require("yjs");
39
42
  class DimensionNodeBuilder {
@@ -200,20 +203,90 @@ class MeasuresBuilder {
200
203
  return 'children' in node;
201
204
  }
202
205
  }
206
+ const vseed_namespaceObject = require("@visactor/vseed");
207
+ const external_uuid_namespaceObject = require("uuid");
208
+ const id_id = {
209
+ uuid: ()=>(0, external_uuid_namespaceObject.v4)()
210
+ };
203
211
  class HavingFiltersNodeBuilder {
204
212
  yMap;
205
213
  constructor(yMap){
206
214
  this.yMap = yMap;
207
215
  }
216
+ getId() {
217
+ return this.yMap.get('id');
218
+ }
208
219
  getField() {
209
220
  return this.yMap.get('field');
210
221
  }
222
+ getOperator() {
223
+ return this.yMap.get('op');
224
+ }
211
225
  setValue(value) {
212
226
  this.yMap.set('value', value);
213
227
  return this;
214
228
  }
215
229
  setOperator(operator) {
216
- this.yMap.set('operator', operator);
230
+ this.yMap.set('op', operator);
231
+ return this;
232
+ }
233
+ toJson() {
234
+ return this.yMap.toJSON();
235
+ }
236
+ }
237
+ class HavingGroupBuilder {
238
+ yMap;
239
+ constructor(yMap){
240
+ this.yMap = yMap;
241
+ }
242
+ getId() {
243
+ return this.yMap.get('id');
244
+ }
245
+ getOperator() {
246
+ return this.yMap.get('op');
247
+ }
248
+ setOperator(op) {
249
+ this.yMap.set('op', op);
250
+ return this;
251
+ }
252
+ add(field, callback) {
253
+ const yMap = new external_yjs_namespaceObject.Map();
254
+ yMap.set('id', id_id.uuid());
255
+ yMap.set('field', field);
256
+ const conditions = this.yMap.get('conditions');
257
+ conditions.push([
258
+ yMap
259
+ ]);
260
+ const node = new HavingFiltersNodeBuilder(yMap);
261
+ callback(node);
262
+ return this;
263
+ }
264
+ addGroup(op, callback) {
265
+ const yMap = new external_yjs_namespaceObject.Map();
266
+ yMap.set('id', id_id.uuid());
267
+ yMap.set('op', op);
268
+ yMap.set('conditions', new external_yjs_namespaceObject.Array());
269
+ const conditions = this.yMap.get('conditions');
270
+ conditions.push([
271
+ yMap
272
+ ]);
273
+ const group = new HavingGroupBuilder(yMap);
274
+ callback(group);
275
+ return this;
276
+ }
277
+ remove(idOrIndex) {
278
+ const conditions = this.yMap.get('conditions');
279
+ if ('number' == typeof idOrIndex) {
280
+ if (idOrIndex >= 0 && idOrIndex < conditions.length) conditions.delete(idOrIndex, 1);
281
+ } else {
282
+ const index = conditions.toArray().findIndex((item)=>item.get('id') === idOrIndex);
283
+ if (-1 !== index) conditions.delete(index, 1);
284
+ }
285
+ return this;
286
+ }
287
+ clear() {
288
+ const conditions = this.yMap.get('conditions');
289
+ conditions.delete(0, conditions.length);
217
290
  return this;
218
291
  }
219
292
  toJson() {
@@ -222,54 +295,76 @@ class HavingFiltersNodeBuilder {
222
295
  }
223
296
  class HavingFiltersBuilder {
224
297
  dsl;
225
- constructor(_doc, dsl){
298
+ doc;
299
+ constructor(doc, dsl){
300
+ this.doc = doc;
226
301
  this.dsl = dsl;
302
+ if (!this.dsl.get('havingFilters')) this.doc.transact(()=>{
303
+ this.dsl.set('havingFilters', new external_yjs_namespaceObject.Array());
304
+ });
227
305
  }
228
306
  add(field, callback) {
229
- if (!field || 'string' != typeof field) throw new Error('Field is required and must be a string');
230
- const defaultFilter = {
231
- field,
232
- operator: 'eq',
233
- value: null
234
- };
235
307
  const yMap = new external_yjs_namespaceObject.Map();
236
- for (const [key, value] of Object.entries(defaultFilter))yMap.set(key, value);
308
+ yMap.set('id', id_id.uuid());
309
+ yMap.set('field', field);
237
310
  this.dsl.get('havingFilters').push([
238
311
  yMap
239
312
  ]);
240
- const filterNode = new HavingFiltersNodeBuilder(yMap);
241
- callback(filterNode);
313
+ const node = new HavingFiltersNodeBuilder(yMap);
314
+ callback(node);
242
315
  return this;
243
316
  }
244
- update(field, callback) {
317
+ addGroup(op, callback) {
318
+ const yMap = new external_yjs_namespaceObject.Map();
319
+ yMap.set('id', id_id.uuid());
320
+ yMap.set('op', op);
321
+ yMap.set('conditions', new external_yjs_namespaceObject.Array());
322
+ this.dsl.get('havingFilters').push([
323
+ yMap
324
+ ]);
325
+ const group = new HavingGroupBuilder(yMap);
326
+ callback(group);
327
+ return this;
328
+ }
329
+ update(id, callback) {
245
330
  const havingFilters = this.dsl.get('havingFilters');
246
- const index = havingFilters.toArray().findIndex((item)=>item.get('field') === field);
247
- if (-1 === index) throw new Error(`Having filter with field "${field}" not found`);
331
+ const index = havingFilters.toArray().findIndex((item)=>item.get('id') === id);
332
+ if (-1 === index) throw new Error(`Having filter with id ${id} not found`);
248
333
  const filterYMap = havingFilters.get(index);
249
334
  const node = new HavingFiltersNodeBuilder(filterYMap);
250
335
  callback(node);
251
336
  return this;
252
337
  }
253
- remove(field) {
254
- if (!field || 'string' != typeof field) console.error('[HavingFiltersBuilder] Invalid field name:', field);
338
+ updateGroup(id, callback) {
255
339
  const havingFilters = this.dsl.get('havingFilters');
256
- const index = havingFilters.toArray().findIndex((item)=>item.get('field') === field);
257
- if (-1 !== index) this.dsl.get('havingFilters').delete(index, 1);
340
+ const index = havingFilters.toArray().findIndex((item)=>item.get('id') === id);
341
+ if (-1 === index) throw new Error(`Having group with id ${id} not found`);
342
+ const yMap = havingFilters.get(index);
343
+ if (!HavingFiltersBuilder.isGroup(yMap)) throw new Error(`Item with id ${id} is not a group`);
344
+ const group = new HavingGroupBuilder(yMap);
345
+ callback(group);
258
346
  return this;
259
347
  }
260
- find(field) {
348
+ remove(idOrIndex) {
261
349
  const havingFilters = this.dsl.get('havingFilters');
262
- const index = havingFilters.toArray().findIndex((item)=>item.get('field') === field);
263
- if (-1 === index) return;
264
- return new HavingFiltersNodeBuilder(havingFilters.get(index));
350
+ if ('number' == typeof idOrIndex) {
351
+ if (idOrIndex >= 0 && idOrIndex < havingFilters.length) havingFilters.delete(idOrIndex, 1);
352
+ } else {
353
+ const index = havingFilters.toArray().findIndex((item)=>item.get('id') === idOrIndex);
354
+ if (-1 !== index) havingFilters.delete(index, 1);
355
+ }
356
+ return this;
265
357
  }
266
- findAll() {
358
+ find(id) {
267
359
  const havingFilters = this.dsl.get('havingFilters');
268
- return havingFilters.toArray().map((yMap)=>new HavingFiltersNodeBuilder(yMap));
360
+ const yMap = havingFilters.toArray().find((item)=>item.get('id') === id);
361
+ if (!yMap) return;
362
+ if (HavingFiltersBuilder.isGroup(yMap)) return new HavingGroupBuilder(yMap);
363
+ return new HavingFiltersNodeBuilder(yMap);
269
364
  }
270
365
  clear() {
271
366
  const havingFilters = this.dsl.get('havingFilters');
272
- if (havingFilters.length > 0) havingFilters.delete(0, havingFilters.length);
367
+ havingFilters.delete(0, havingFilters.length);
273
368
  return this;
274
369
  }
275
370
  toJson() {
@@ -281,8 +376,13 @@ class HavingFiltersBuilder {
281
376
  this.dsl.get('havingFilters').unobserve(callback);
282
377
  };
283
378
  }
379
+ static isGroup(yMap) {
380
+ return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
381
+ }
382
+ static isNode(yMap) {
383
+ return void 0 !== yMap.get('field');
384
+ }
284
385
  }
285
- const vseed_namespaceObject = require("@visactor/vseed");
286
386
  class ChartTypeBuilder {
287
387
  dsl;
288
388
  constructor(_doc, dsl){
@@ -337,11 +437,17 @@ class WhereFilterNodeBuilder {
337
437
  constructor(yMap){
338
438
  this.yMap = yMap;
339
439
  }
440
+ getId() {
441
+ return this.yMap.get('id');
442
+ }
340
443
  getField() {
341
444
  return this.yMap.get('field');
342
445
  }
446
+ getOperator() {
447
+ return this.yMap.get('op');
448
+ }
343
449
  setOperator(operator) {
344
- this.yMap.set('operator', operator);
450
+ this.yMap.set('op', operator);
345
451
  return this;
346
452
  }
347
453
  setValue(value) {
@@ -352,6 +458,65 @@ class WhereFilterNodeBuilder {
352
458
  return this.yMap.toJSON();
353
459
  }
354
460
  }
461
+ class WhereGroupBuilder {
462
+ yMap;
463
+ constructor(yMap){
464
+ this.yMap = yMap;
465
+ }
466
+ getId() {
467
+ return this.yMap.get('id');
468
+ }
469
+ getOperator() {
470
+ return this.yMap.get('op');
471
+ }
472
+ setOperator(op) {
473
+ this.yMap.set('op', op);
474
+ return this;
475
+ }
476
+ add(field, callback) {
477
+ const yMap = new external_yjs_namespaceObject.Map();
478
+ yMap.set('id', id_id.uuid());
479
+ yMap.set('field', field);
480
+ const conditions = this.yMap.get('conditions');
481
+ conditions.push([
482
+ yMap
483
+ ]);
484
+ const node = new WhereFilterNodeBuilder(yMap);
485
+ callback(node);
486
+ return this;
487
+ }
488
+ addGroup(op, callback) {
489
+ const yMap = new external_yjs_namespaceObject.Map();
490
+ yMap.set('id', id_id.uuid());
491
+ yMap.set('op', op);
492
+ yMap.set('conditions', new external_yjs_namespaceObject.Array());
493
+ const conditions = this.yMap.get('conditions');
494
+ conditions.push([
495
+ yMap
496
+ ]);
497
+ const group = new WhereGroupBuilder(yMap);
498
+ callback(group);
499
+ return this;
500
+ }
501
+ remove(idOrIndex) {
502
+ const conditions = this.yMap.get('conditions');
503
+ if ('number' == typeof idOrIndex) {
504
+ if (idOrIndex >= 0 && idOrIndex < conditions.length) conditions.delete(idOrIndex, 1);
505
+ } else {
506
+ const index = conditions.toArray().findIndex((item)=>item.get('id') === idOrIndex);
507
+ if (-1 !== index) conditions.delete(index, 1);
508
+ }
509
+ return this;
510
+ }
511
+ clear() {
512
+ const conditions = this.yMap.get('conditions');
513
+ conditions.delete(0, conditions.length);
514
+ return this;
515
+ }
516
+ toJson() {
517
+ return this.yMap.toJSON();
518
+ }
519
+ }
355
520
  class WhereFiltersBuilder {
356
521
  dsl;
357
522
  doc;
@@ -363,11 +528,9 @@ class WhereFiltersBuilder {
363
528
  });
364
529
  }
365
530
  add(field, callback) {
366
- const filter = {
367
- field
368
- };
369
531
  const yMap = new external_yjs_namespaceObject.Map();
370
- for (const [key, value] of Object.entries(filter))yMap.set(key, value);
532
+ yMap.set('id', id_id.uuid());
533
+ yMap.set('field', field);
371
534
  this.dsl.get('whereFilters').push([
372
535
  yMap
373
536
  ]);
@@ -375,31 +538,53 @@ class WhereFiltersBuilder {
375
538
  callback(node);
376
539
  return this;
377
540
  }
378
- update(field, callback) {
541
+ addGroup(op, callback) {
542
+ const yMap = new external_yjs_namespaceObject.Map();
543
+ yMap.set('id', id_id.uuid());
544
+ yMap.set('op', op);
545
+ yMap.set('conditions', new external_yjs_namespaceObject.Array());
546
+ this.dsl.get('whereFilters').push([
547
+ yMap
548
+ ]);
549
+ const group = new WhereGroupBuilder(yMap);
550
+ callback(group);
551
+ return this;
552
+ }
553
+ update(id, callback) {
379
554
  const whereFilters = this.dsl.get('whereFilters');
380
- const index = whereFilters.toArray().findIndex((item)=>item.get('field') === field);
381
- if (-1 === index) throw new Error(`Where filter with field ${field} not found`);
555
+ const index = whereFilters.toArray().findIndex((item)=>item.get('id') === id);
556
+ if (-1 === index) throw new Error(`Where filter with id ${id} not found`);
382
557
  const filterYMap = whereFilters.get(index);
383
558
  const node = new WhereFilterNodeBuilder(filterYMap);
384
559
  callback(node);
385
560
  return this;
386
561
  }
387
- remove(field) {
562
+ updateGroup(id, callback) {
388
563
  const whereFilters = this.dsl.get('whereFilters');
389
- const index = whereFilters.toArray().findIndex((item)=>item.get('field') === field);
390
- if (-1 === index) return this;
391
- whereFilters.delete(index, 1);
564
+ const index = whereFilters.toArray().findIndex((item)=>item.get('id') === id);
565
+ if (-1 === index) throw new Error(`Where group with id ${id} not found`);
566
+ const yMap = whereFilters.get(index);
567
+ if (!WhereFiltersBuilder.isGroup(yMap)) throw new Error(`Item with id ${id} is not a group`);
568
+ const group = new WhereGroupBuilder(yMap);
569
+ callback(group);
392
570
  return this;
393
571
  }
394
- find(field) {
572
+ remove(idOrIndex) {
395
573
  const whereFilters = this.dsl.get('whereFilters');
396
- const index = whereFilters.toArray().findIndex((item)=>item.get('field') === field);
397
- if (-1 === index) return;
398
- return new WhereFilterNodeBuilder(whereFilters.get(index));
574
+ if ('number' == typeof idOrIndex) {
575
+ if (idOrIndex >= 0 && idOrIndex < whereFilters.length) whereFilters.delete(idOrIndex, 1);
576
+ } else {
577
+ const index = whereFilters.toArray().findIndex((item)=>item.get('id') === idOrIndex);
578
+ if (-1 !== index) whereFilters.delete(index, 1);
579
+ }
580
+ return this;
399
581
  }
400
- findAll() {
582
+ find(id) {
401
583
  const whereFilters = this.dsl.get('whereFilters');
402
- return whereFilters.toArray().map((yMap)=>new WhereFilterNodeBuilder(yMap));
584
+ const yMap = whereFilters.toArray().find((item)=>item.get('id') === id);
585
+ if (!yMap) return;
586
+ if (WhereFiltersBuilder.isGroup(yMap)) return new WhereGroupBuilder(yMap);
587
+ return new WhereFilterNodeBuilder(yMap);
403
588
  }
404
589
  clear() {
405
590
  const whereFilters = this.dsl.get('whereFilters');
@@ -415,63 +600,14 @@ class WhereFiltersBuilder {
415
600
  this.dsl.get('whereFilters').unobserve(callback);
416
601
  };
417
602
  }
603
+ static isGroup(yMap) {
604
+ return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
605
+ }
606
+ static isNode(yMap) {
607
+ return void 0 !== yMap.get('field');
608
+ }
418
609
  }
419
- const external_zod_namespaceObject = require("zod");
420
- const zVBIHavingFilter = external_zod_namespaceObject.z.object({
421
- field: external_zod_namespaceObject.z.string(),
422
- operator: external_zod_namespaceObject.z.string().optional(),
423
- value: external_zod_namespaceObject.z.any().optional()
424
- });
425
- const zVBIHavingArray = external_zod_namespaceObject.z.array(zVBIHavingFilter);
426
610
  const external_remeda_namespaceObject = require("remeda");
427
- const buildVQuery = (vbiDSL, builder)=>{
428
- const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
429
- vbiDSL,
430
- builder
431
- });
432
- return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildOrderBy), wrapper(buildLimit));
433
- };
434
- const buildWhere = (queryDSL, context)=>{
435
- const { vbiDSL } = context;
436
- const whereFilters = vbiDSL.whereFilters || [];
437
- if (0 === whereFilters.length) return queryDSL;
438
- const result = {
439
- ...queryDSL
440
- };
441
- result.where = {
442
- op: 'and',
443
- conditions: whereFilters.flatMap((filter)=>{
444
- if ('between' === filter.operator && filter.value && 'object' == typeof filter.value && !Array.isArray(filter.value)) {
445
- const conditions = [];
446
- if (void 0 !== filter.value.min && null !== filter.value.min && '' !== filter.value.min) conditions.push({
447
- field: filter.field,
448
- op: '<' === filter.value.leftOp ? '>' : '>=',
449
- value: filter.value.min
450
- });
451
- if (void 0 !== filter.value.max && null !== filter.value.max && '' !== filter.value.max) conditions.push({
452
- field: filter.field,
453
- op: '<' === filter.value.rightOp ? '<' : '<=',
454
- value: filter.value.max
455
- });
456
- return conditions;
457
- }
458
- let mappedOp = filter.operator ?? '=';
459
- if (Array.isArray(filter.value)) {
460
- if ('=' === mappedOp) mappedOp = 'in';
461
- if ('!=' === mappedOp) mappedOp = 'not in';
462
- }
463
- return [
464
- {
465
- field: filter.field,
466
- op: mappedOp,
467
- value: filter.value
468
- }
469
- ];
470
- })
471
- };
472
- return result;
473
- };
474
- const buildOrderBy = (queryDSL, context)=>queryDSL;
475
611
  const buildSelect = (queryDSL, context)=>{
476
612
  const { vbiDSL } = context;
477
613
  const measures = vbiDSL.measures;
@@ -503,14 +639,68 @@ const buildGroupBy = (queryDSL, context)=>{
503
639
  result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
504
640
  return result;
505
641
  };
506
- const buildLimit = (queryDSL, context)=>{
642
+ const buildWhere = (queryDSL, context)=>{
643
+ const { vbiDSL } = context;
644
+ const whereFilters = vbiDSL.whereFilters || [];
645
+ if (0 === whereFilters.length) return queryDSL;
507
646
  const result = {
508
647
  ...queryDSL
509
648
  };
510
- const limit = context.vbiDSL.limit ?? 1000;
511
- result.limit = limit;
649
+ result.where = {
650
+ op: 'and',
651
+ conditions: whereFilters.flatMap(mapClauseToCondition)
652
+ };
512
653
  return result;
513
654
  };
655
+ function isWhereGroup(clause) {
656
+ return 'op' in clause && 'conditions' in clause;
657
+ }
658
+ function mapClauseToCondition(clause) {
659
+ if (isWhereGroup(clause)) return [
660
+ mapGroupToCondition(clause)
661
+ ];
662
+ return mapFilterToCondition(clause);
663
+ }
664
+ function mapGroupToCondition(group) {
665
+ return {
666
+ op: group.op,
667
+ conditions: group.conditions.flatMap(mapClauseToCondition)
668
+ };
669
+ }
670
+ function mapFilterToCondition(filter) {
671
+ if ('between' === filter.op) return handleBetweenFilter(filter);
672
+ return handleSimpleFilter(filter);
673
+ }
674
+ function handleBetweenFilter(filter) {
675
+ const conditions = [];
676
+ const value = filter.value;
677
+ if (void 0 !== value.min && null !== value.min && '' !== value.min) conditions.push({
678
+ field: filter.field,
679
+ op: '<' === value.leftOp ? '>' : '>=',
680
+ value: value.min
681
+ });
682
+ if (void 0 !== value.max && null !== value.max && '' !== value.max) conditions.push({
683
+ field: filter.field,
684
+ op: '<' === value.rightOp ? '<' : '<=',
685
+ value: value.max
686
+ });
687
+ return conditions;
688
+ }
689
+ function handleSimpleFilter(filter) {
690
+ let mappedOp = filter.op ?? '=';
691
+ const value = filter.value;
692
+ if (Array.isArray(value)) {
693
+ if ('=' === mappedOp) mappedOp = 'in';
694
+ if ('!=' === mappedOp) mappedOp = 'not in';
695
+ }
696
+ return [
697
+ {
698
+ field: filter.field,
699
+ op: mappedOp,
700
+ value
701
+ }
702
+ ];
703
+ }
514
704
  const buildHaving = (queryDSL, context)=>{
515
705
  const { vbiDSL } = context;
516
706
  const havingFilters = vbiDSL.havingFilters || [];
@@ -520,17 +710,50 @@ const buildHaving = (queryDSL, context)=>{
520
710
  };
521
711
  result.having = {
522
712
  op: 'and',
523
- conditions: havingFilters.map((filter)=>{
524
- const mappedOp = filter.operator ?? '=';
525
- return {
526
- field: filter.field,
527
- op: mappedOp,
528
- value: filter.value
529
- };
530
- })
713
+ conditions: havingFilters.flatMap(buildHaving_mapClauseToCondition)
714
+ };
715
+ return result;
716
+ };
717
+ function isHavingGroup(clause) {
718
+ return 'op' in clause && 'conditions' in clause;
719
+ }
720
+ function buildHaving_mapClauseToCondition(clause) {
721
+ if (isHavingGroup(clause)) return [
722
+ buildHaving_mapGroupToCondition(clause)
723
+ ];
724
+ return buildHaving_mapFilterToCondition(clause);
725
+ }
726
+ function buildHaving_mapGroupToCondition(group) {
727
+ return {
728
+ op: group.op,
729
+ conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
730
+ };
731
+ }
732
+ function buildHaving_mapFilterToCondition(filter) {
733
+ const mappedOp = filter.op ?? '=';
734
+ return [
735
+ {
736
+ field: filter.field,
737
+ op: mappedOp,
738
+ value: filter.value
739
+ }
740
+ ];
741
+ }
742
+ const buildLimit = (queryDSL, context)=>{
743
+ const result = {
744
+ ...queryDSL
531
745
  };
746
+ const limit = context.vbiDSL.limit ?? 1000;
747
+ result.limit = limit;
532
748
  return result;
533
749
  };
750
+ const buildVQuery = (vbiDSL, builder)=>{
751
+ const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
752
+ vbiDSL,
753
+ builder
754
+ });
755
+ return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
756
+ };
534
757
  const connectorMap = new Map();
535
758
  const registerConnector = (id, connector)=>{
536
759
  connectorMap.set(id, connector);
@@ -633,7 +856,27 @@ const createVBI = ()=>({
633
856
  if (vbi.limit) dsl.set('limit', vbi.limit);
634
857
  if (vbi.locale) dsl.set('locale', vbi.locale);
635
858
  if (vbi.version) dsl.set('version', vbi.version);
636
- const ensureYArray = (arr)=>{
859
+ const toYMap = (obj, ensureId = false)=>{
860
+ const yMap = new external_yjs_namespaceObject.Map();
861
+ if (ensureId && !obj.id) yMap.set('id', id_id.uuid());
862
+ for (const [key, value] of Object.entries(obj))if ('conditions' === key && Array.isArray(value)) {
863
+ const yArr = new external_yjs_namespaceObject.Array();
864
+ value.forEach((child)=>{
865
+ if (child instanceof external_yjs_namespaceObject.Map) yArr.push([
866
+ child
867
+ ]);
868
+ else if ('object' == typeof child && null !== child) yArr.push([
869
+ toYMap(child, true)
870
+ ]);
871
+ else yArr.push([
872
+ child
873
+ ]);
874
+ });
875
+ yMap.set(key, yArr);
876
+ } else yMap.set(key, value);
877
+ return yMap;
878
+ };
879
+ const ensureYArray = (arr, ensureId = false)=>{
637
880
  if (!arr) return new external_yjs_namespaceObject.Array();
638
881
  if (arr instanceof external_yjs_namespaceObject.Array) return arr;
639
882
  const yArr = new external_yjs_namespaceObject.Array();
@@ -641,20 +884,17 @@ const createVBI = ()=>({
641
884
  if (item instanceof external_yjs_namespaceObject.Map) yArr.push([
642
885
  item
643
886
  ]);
644
- else if ('object' == typeof item && null !== item) {
645
- const yMap = new external_yjs_namespaceObject.Map();
646
- for (const [key, value] of Object.entries(item))yMap.set(key, value);
647
- yArr.push([
648
- yMap
649
- ]);
650
- } else yArr.push([
887
+ else if ('object' == typeof item && null !== item) yArr.push([
888
+ toYMap(item, ensureId)
889
+ ]);
890
+ else yArr.push([
651
891
  item
652
892
  ]);
653
893
  });
654
894
  return yArr;
655
895
  };
656
- dsl.set('whereFilters', ensureYArray(vbi.whereFilters));
657
- dsl.set('havingFilters', ensureYArray(vbi.havingFilters));
896
+ dsl.set('whereFilters', ensureYArray(vbi.whereFilters, true));
897
+ dsl.set('havingFilters', ensureYArray(vbi.havingFilters, true));
658
898
  dsl.set('measures', ensureYArray(vbi.measures));
659
899
  dsl.set('dimensions', ensureYArray(vbi.dimensions));
660
900
  });
@@ -662,6 +902,55 @@ const createVBI = ()=>({
662
902
  }
663
903
  });
664
904
  const VBI = createVBI();
905
+ const external_zod_namespaceObject = require("zod");
906
+ const zVBIFilter = external_zod_namespaceObject.z.object({
907
+ id: external_zod_namespaceObject.z.string(),
908
+ field: external_zod_namespaceObject.z.string(),
909
+ op: external_zod_namespaceObject.z.string().optional(),
910
+ value: external_zod_namespaceObject.z.any().optional()
911
+ });
912
+ const zVBIWhereGroup = external_zod_namespaceObject.z.lazy(()=>external_zod_namespaceObject.z.object({
913
+ id: external_zod_namespaceObject.z.string(),
914
+ op: external_zod_namespaceObject.z["enum"]([
915
+ 'and',
916
+ 'or'
917
+ ]),
918
+ conditions: external_zod_namespaceObject.z.array(zVBIWhereClause)
919
+ }));
920
+ const zVBIWhereClause = external_zod_namespaceObject.z.lazy(()=>external_zod_namespaceObject.z.union([
921
+ zVBIFilter,
922
+ zVBIWhereGroup
923
+ ]));
924
+ function isVBIFilter(clause) {
925
+ return 'field' in clause;
926
+ }
927
+ function isVBIWhereGroup(clause) {
928
+ return 'conditions' in clause;
929
+ }
930
+ const zVBIHavingFilter = external_zod_namespaceObject.z.object({
931
+ id: external_zod_namespaceObject.z.string(),
932
+ field: external_zod_namespaceObject.z.string(),
933
+ op: external_zod_namespaceObject.z.string().optional(),
934
+ value: external_zod_namespaceObject.z.any().optional()
935
+ });
936
+ const zVBIHavingGroup = external_zod_namespaceObject.z.lazy(()=>external_zod_namespaceObject.z.object({
937
+ id: external_zod_namespaceObject.z.string(),
938
+ op: external_zod_namespaceObject.z["enum"]([
939
+ 'and',
940
+ 'or'
941
+ ]),
942
+ conditions: external_zod_namespaceObject.z.array(zVBIHavingClause)
943
+ }));
944
+ const zVBIHavingClause = external_zod_namespaceObject.z.lazy(()=>external_zod_namespaceObject.z.union([
945
+ zVBIHavingFilter,
946
+ zVBIHavingGroup
947
+ ]));
948
+ function isVBIHavingFilter(clause) {
949
+ return 'field' in clause;
950
+ }
951
+ function isVBIHavingGroup(clause) {
952
+ return 'conditions' in clause;
953
+ }
665
954
  exports.ChartTypeBuilder = __webpack_exports__.ChartTypeBuilder;
666
955
  exports.DimensionsBuilder = __webpack_exports__.DimensionsBuilder;
667
956
  exports.MeasuresBuilder = __webpack_exports__.MeasuresBuilder;
@@ -669,9 +958,12 @@ exports.VBI = __webpack_exports__.VBI;
669
958
  exports.VBIBuilder = __webpack_exports__.VBIBuilder;
670
959
  exports.buildVQuery = __webpack_exports__.buildVQuery;
671
960
  exports.findTreeNodesBy = __webpack_exports__.findTreeNodesBy;
961
+ exports.id = __webpack_exports__.id;
962
+ exports.isVBIFilter = __webpack_exports__.isVBIFilter;
963
+ exports.isVBIHavingFilter = __webpack_exports__.isVBIHavingFilter;
964
+ exports.isVBIHavingGroup = __webpack_exports__.isVBIHavingGroup;
965
+ exports.isVBIWhereGroup = __webpack_exports__.isVBIWhereGroup;
672
966
  exports.preorderTraverse = __webpack_exports__.preorderTraverse;
673
- exports.zVBIHavingArray = __webpack_exports__.zVBIHavingArray;
674
- exports.zVBIHavingFilter = __webpack_exports__.zVBIHavingFilter;
675
967
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
676
968
  "ChartTypeBuilder",
677
969
  "DimensionsBuilder",
@@ -680,9 +972,12 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
680
972
  "VBIBuilder",
681
973
  "buildVQuery",
682
974
  "findTreeNodesBy",
683
- "preorderTraverse",
684
- "zVBIHavingArray",
685
- "zVBIHavingFilter"
975
+ "id",
976
+ "isVBIFilter",
977
+ "isVBIHavingFilter",
978
+ "isVBIHavingGroup",
979
+ "isVBIWhereGroup",
980
+ "preorderTraverse"
686
981
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
687
982
  Object.defineProperty(exports, '__esModule', {
688
983
  value: true