@visactor/vbi 0.4.12 → 0.4.14
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/builder/index.d.ts +1 -0
- package/dist/builder/sub-builders/havingFilters/having-builder.d.ts +33 -20
- package/dist/builder/sub-builders/havingFilters/having-group-builder.d.ts +48 -0
- package/dist/builder/sub-builders/havingFilters/having-node-builder.d.ts +8 -0
- package/dist/builder/sub-builders/havingFilters/index.d.ts +1 -0
- package/dist/builder/sub-builders/index.d.ts +1 -1
- package/dist/builder/sub-builders/whereFilters/index.d.ts +1 -0
- package/dist/builder/sub-builders/whereFilters/where-builder.d.ts +30 -17
- package/dist/builder/sub-builders/whereFilters/where-group-builder.d.ts +48 -0
- package/dist/builder/sub-builders/whereFilters/where-node-builder.d.ts +8 -0
- package/dist/builder/undo-manager.d.ts +37 -0
- package/dist/builder/vbi-builder.d.ts +2 -1
- package/dist/index.cjs +446 -130
- package/dist/index.js +428 -121
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/vqueryDSL/buildGroupBy.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/buildHaving.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/buildLimit.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/buildSelect.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/buildWhere.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/index.d.ts +4 -1
- package/dist/pipeline/vqueryDSL/types.d.ts +7 -0
- package/dist/types/builder/VBIInterface.d.ts +2 -1
- package/dist/types/dsl/havingFilters/having.d.ts +12 -7
- package/dist/types/dsl/index.d.ts +4 -2
- package/dist/types/dsl/vbi/vbi.d.ts +2 -10
- package/dist/types/dsl/whereFilters/filters.d.ts +12 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/utils/id.d.ts +3 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +12 -10
- package/dist/pipeline/vqueryDSL/buildVQuery.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Array as external_yjs_Array, Doc, Map as external_yjs_Map, UndoManager, applyUpdate, encodeStateAsUpdate } from "yjs";
|
|
2
2
|
import { ChartTypeEnum, findTreeNodesBy, preorderTraverse } from "@visactor/vseed";
|
|
3
|
-
import {
|
|
3
|
+
import { v4 } from "uuid";
|
|
4
4
|
import { pipe } from "remeda";
|
|
5
|
+
import { z } from "zod";
|
|
5
6
|
class DimensionNodeBuilder {
|
|
6
7
|
yMap;
|
|
7
8
|
constructor(yMap){
|
|
@@ -166,20 +167,88 @@ class MeasuresBuilder {
|
|
|
166
167
|
return 'children' in node;
|
|
167
168
|
}
|
|
168
169
|
}
|
|
170
|
+
const id_id = {
|
|
171
|
+
uuid: ()=>v4()
|
|
172
|
+
};
|
|
169
173
|
class HavingFiltersNodeBuilder {
|
|
170
174
|
yMap;
|
|
171
175
|
constructor(yMap){
|
|
172
176
|
this.yMap = yMap;
|
|
173
177
|
}
|
|
178
|
+
getId() {
|
|
179
|
+
return this.yMap.get('id');
|
|
180
|
+
}
|
|
174
181
|
getField() {
|
|
175
182
|
return this.yMap.get('field');
|
|
176
183
|
}
|
|
184
|
+
getOperator() {
|
|
185
|
+
return this.yMap.get('op');
|
|
186
|
+
}
|
|
177
187
|
setValue(value) {
|
|
178
188
|
this.yMap.set('value', value);
|
|
179
189
|
return this;
|
|
180
190
|
}
|
|
181
191
|
setOperator(operator) {
|
|
182
|
-
this.yMap.set('
|
|
192
|
+
this.yMap.set('op', operator);
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
toJson() {
|
|
196
|
+
return this.yMap.toJSON();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
class HavingGroupBuilder {
|
|
200
|
+
yMap;
|
|
201
|
+
constructor(yMap){
|
|
202
|
+
this.yMap = yMap;
|
|
203
|
+
}
|
|
204
|
+
getId() {
|
|
205
|
+
return this.yMap.get('id');
|
|
206
|
+
}
|
|
207
|
+
getOperator() {
|
|
208
|
+
return this.yMap.get('op');
|
|
209
|
+
}
|
|
210
|
+
setOperator(op) {
|
|
211
|
+
this.yMap.set('op', op);
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
add(field, callback) {
|
|
215
|
+
const yMap = new external_yjs_Map();
|
|
216
|
+
yMap.set('id', id_id.uuid());
|
|
217
|
+
yMap.set('field', field);
|
|
218
|
+
const conditions = this.yMap.get('conditions');
|
|
219
|
+
conditions.push([
|
|
220
|
+
yMap
|
|
221
|
+
]);
|
|
222
|
+
const node = new HavingFiltersNodeBuilder(yMap);
|
|
223
|
+
callback(node);
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
addGroup(op, callback) {
|
|
227
|
+
const yMap = new external_yjs_Map();
|
|
228
|
+
yMap.set('id', id_id.uuid());
|
|
229
|
+
yMap.set('op', op);
|
|
230
|
+
yMap.set('conditions', new external_yjs_Array());
|
|
231
|
+
const conditions = this.yMap.get('conditions');
|
|
232
|
+
conditions.push([
|
|
233
|
+
yMap
|
|
234
|
+
]);
|
|
235
|
+
const group = new HavingGroupBuilder(yMap);
|
|
236
|
+
callback(group);
|
|
237
|
+
return this;
|
|
238
|
+
}
|
|
239
|
+
remove(idOrIndex) {
|
|
240
|
+
const conditions = this.yMap.get('conditions');
|
|
241
|
+
if ('number' == typeof idOrIndex) {
|
|
242
|
+
if (idOrIndex >= 0 && idOrIndex < conditions.length) conditions.delete(idOrIndex, 1);
|
|
243
|
+
} else {
|
|
244
|
+
const index = conditions.toArray().findIndex((item)=>item.get('id') === idOrIndex);
|
|
245
|
+
if (-1 !== index) conditions.delete(index, 1);
|
|
246
|
+
}
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
clear() {
|
|
250
|
+
const conditions = this.yMap.get('conditions');
|
|
251
|
+
conditions.delete(0, conditions.length);
|
|
183
252
|
return this;
|
|
184
253
|
}
|
|
185
254
|
toJson() {
|
|
@@ -188,54 +257,76 @@ class HavingFiltersNodeBuilder {
|
|
|
188
257
|
}
|
|
189
258
|
class HavingFiltersBuilder {
|
|
190
259
|
dsl;
|
|
191
|
-
|
|
260
|
+
doc;
|
|
261
|
+
constructor(doc, dsl){
|
|
262
|
+
this.doc = doc;
|
|
192
263
|
this.dsl = dsl;
|
|
264
|
+
if (!this.dsl.get('havingFilters')) this.doc.transact(()=>{
|
|
265
|
+
this.dsl.set('havingFilters', new external_yjs_Array());
|
|
266
|
+
});
|
|
193
267
|
}
|
|
194
268
|
add(field, callback) {
|
|
195
|
-
if (!field || 'string' != typeof field) throw new Error('Field is required and must be a string');
|
|
196
|
-
const defaultFilter = {
|
|
197
|
-
field,
|
|
198
|
-
operator: 'eq',
|
|
199
|
-
value: null
|
|
200
|
-
};
|
|
201
269
|
const yMap = new external_yjs_Map();
|
|
202
|
-
|
|
270
|
+
yMap.set('id', id_id.uuid());
|
|
271
|
+
yMap.set('field', field);
|
|
203
272
|
this.dsl.get('havingFilters').push([
|
|
204
273
|
yMap
|
|
205
274
|
]);
|
|
206
|
-
const
|
|
207
|
-
callback(
|
|
275
|
+
const node = new HavingFiltersNodeBuilder(yMap);
|
|
276
|
+
callback(node);
|
|
208
277
|
return this;
|
|
209
278
|
}
|
|
210
|
-
|
|
279
|
+
addGroup(op, callback) {
|
|
280
|
+
const yMap = new external_yjs_Map();
|
|
281
|
+
yMap.set('id', id_id.uuid());
|
|
282
|
+
yMap.set('op', op);
|
|
283
|
+
yMap.set('conditions', new external_yjs_Array());
|
|
284
|
+
this.dsl.get('havingFilters').push([
|
|
285
|
+
yMap
|
|
286
|
+
]);
|
|
287
|
+
const group = new HavingGroupBuilder(yMap);
|
|
288
|
+
callback(group);
|
|
289
|
+
return this;
|
|
290
|
+
}
|
|
291
|
+
update(id, callback) {
|
|
211
292
|
const havingFilters = this.dsl.get('havingFilters');
|
|
212
|
-
const index = havingFilters.toArray().findIndex((item)=>item.get('
|
|
213
|
-
if (-1 === index) throw new Error(`Having filter with
|
|
293
|
+
const index = havingFilters.toArray().findIndex((item)=>item.get('id') === id);
|
|
294
|
+
if (-1 === index) throw new Error(`Having filter with id ${id} not found`);
|
|
214
295
|
const filterYMap = havingFilters.get(index);
|
|
215
296
|
const node = new HavingFiltersNodeBuilder(filterYMap);
|
|
216
297
|
callback(node);
|
|
217
298
|
return this;
|
|
218
299
|
}
|
|
219
|
-
|
|
220
|
-
if (!field || 'string' != typeof field) console.error('[HavingFiltersBuilder] Invalid field name:', field);
|
|
300
|
+
updateGroup(id, callback) {
|
|
221
301
|
const havingFilters = this.dsl.get('havingFilters');
|
|
222
|
-
const index = havingFilters.toArray().findIndex((item)=>item.get('
|
|
223
|
-
if (-1
|
|
302
|
+
const index = havingFilters.toArray().findIndex((item)=>item.get('id') === id);
|
|
303
|
+
if (-1 === index) throw new Error(`Having group with id ${id} not found`);
|
|
304
|
+
const yMap = havingFilters.get(index);
|
|
305
|
+
if (!HavingFiltersBuilder.isGroup(yMap)) throw new Error(`Item with id ${id} is not a group`);
|
|
306
|
+
const group = new HavingGroupBuilder(yMap);
|
|
307
|
+
callback(group);
|
|
224
308
|
return this;
|
|
225
309
|
}
|
|
226
|
-
|
|
310
|
+
remove(idOrIndex) {
|
|
227
311
|
const havingFilters = this.dsl.get('havingFilters');
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
312
|
+
if ('number' == typeof idOrIndex) {
|
|
313
|
+
if (idOrIndex >= 0 && idOrIndex < havingFilters.length) havingFilters.delete(idOrIndex, 1);
|
|
314
|
+
} else {
|
|
315
|
+
const index = havingFilters.toArray().findIndex((item)=>item.get('id') === idOrIndex);
|
|
316
|
+
if (-1 !== index) havingFilters.delete(index, 1);
|
|
317
|
+
}
|
|
318
|
+
return this;
|
|
231
319
|
}
|
|
232
|
-
|
|
320
|
+
find(id) {
|
|
233
321
|
const havingFilters = this.dsl.get('havingFilters');
|
|
234
|
-
|
|
322
|
+
const yMap = havingFilters.toArray().find((item)=>item.get('id') === id);
|
|
323
|
+
if (!yMap) return;
|
|
324
|
+
if (HavingFiltersBuilder.isGroup(yMap)) return new HavingGroupBuilder(yMap);
|
|
325
|
+
return new HavingFiltersNodeBuilder(yMap);
|
|
235
326
|
}
|
|
236
327
|
clear() {
|
|
237
328
|
const havingFilters = this.dsl.get('havingFilters');
|
|
238
|
-
|
|
329
|
+
havingFilters.delete(0, havingFilters.length);
|
|
239
330
|
return this;
|
|
240
331
|
}
|
|
241
332
|
toJson() {
|
|
@@ -247,6 +338,12 @@ class HavingFiltersBuilder {
|
|
|
247
338
|
this.dsl.get('havingFilters').unobserve(callback);
|
|
248
339
|
};
|
|
249
340
|
}
|
|
341
|
+
static isGroup(yMap) {
|
|
342
|
+
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
343
|
+
}
|
|
344
|
+
static isNode(yMap) {
|
|
345
|
+
return void 0 !== yMap.get('field');
|
|
346
|
+
}
|
|
250
347
|
}
|
|
251
348
|
class ChartTypeBuilder {
|
|
252
349
|
dsl;
|
|
@@ -302,11 +399,17 @@ class WhereFilterNodeBuilder {
|
|
|
302
399
|
constructor(yMap){
|
|
303
400
|
this.yMap = yMap;
|
|
304
401
|
}
|
|
402
|
+
getId() {
|
|
403
|
+
return this.yMap.get('id');
|
|
404
|
+
}
|
|
305
405
|
getField() {
|
|
306
406
|
return this.yMap.get('field');
|
|
307
407
|
}
|
|
408
|
+
getOperator() {
|
|
409
|
+
return this.yMap.get('op');
|
|
410
|
+
}
|
|
308
411
|
setOperator(operator) {
|
|
309
|
-
this.yMap.set('
|
|
412
|
+
this.yMap.set('op', operator);
|
|
310
413
|
return this;
|
|
311
414
|
}
|
|
312
415
|
setValue(value) {
|
|
@@ -317,6 +420,65 @@ class WhereFilterNodeBuilder {
|
|
|
317
420
|
return this.yMap.toJSON();
|
|
318
421
|
}
|
|
319
422
|
}
|
|
423
|
+
class WhereGroupBuilder {
|
|
424
|
+
yMap;
|
|
425
|
+
constructor(yMap){
|
|
426
|
+
this.yMap = yMap;
|
|
427
|
+
}
|
|
428
|
+
getId() {
|
|
429
|
+
return this.yMap.get('id');
|
|
430
|
+
}
|
|
431
|
+
getOperator() {
|
|
432
|
+
return this.yMap.get('op');
|
|
433
|
+
}
|
|
434
|
+
setOperator(op) {
|
|
435
|
+
this.yMap.set('op', op);
|
|
436
|
+
return this;
|
|
437
|
+
}
|
|
438
|
+
add(field, callback) {
|
|
439
|
+
const yMap = new external_yjs_Map();
|
|
440
|
+
yMap.set('id', id_id.uuid());
|
|
441
|
+
yMap.set('field', field);
|
|
442
|
+
const conditions = this.yMap.get('conditions');
|
|
443
|
+
conditions.push([
|
|
444
|
+
yMap
|
|
445
|
+
]);
|
|
446
|
+
const node = new WhereFilterNodeBuilder(yMap);
|
|
447
|
+
callback(node);
|
|
448
|
+
return this;
|
|
449
|
+
}
|
|
450
|
+
addGroup(op, callback) {
|
|
451
|
+
const yMap = new external_yjs_Map();
|
|
452
|
+
yMap.set('id', id_id.uuid());
|
|
453
|
+
yMap.set('op', op);
|
|
454
|
+
yMap.set('conditions', new external_yjs_Array());
|
|
455
|
+
const conditions = this.yMap.get('conditions');
|
|
456
|
+
conditions.push([
|
|
457
|
+
yMap
|
|
458
|
+
]);
|
|
459
|
+
const group = new WhereGroupBuilder(yMap);
|
|
460
|
+
callback(group);
|
|
461
|
+
return this;
|
|
462
|
+
}
|
|
463
|
+
remove(idOrIndex) {
|
|
464
|
+
const conditions = this.yMap.get('conditions');
|
|
465
|
+
if ('number' == typeof idOrIndex) {
|
|
466
|
+
if (idOrIndex >= 0 && idOrIndex < conditions.length) conditions.delete(idOrIndex, 1);
|
|
467
|
+
} else {
|
|
468
|
+
const index = conditions.toArray().findIndex((item)=>item.get('id') === idOrIndex);
|
|
469
|
+
if (-1 !== index) conditions.delete(index, 1);
|
|
470
|
+
}
|
|
471
|
+
return this;
|
|
472
|
+
}
|
|
473
|
+
clear() {
|
|
474
|
+
const conditions = this.yMap.get('conditions');
|
|
475
|
+
conditions.delete(0, conditions.length);
|
|
476
|
+
return this;
|
|
477
|
+
}
|
|
478
|
+
toJson() {
|
|
479
|
+
return this.yMap.toJSON();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
320
482
|
class WhereFiltersBuilder {
|
|
321
483
|
dsl;
|
|
322
484
|
doc;
|
|
@@ -328,11 +490,9 @@ class WhereFiltersBuilder {
|
|
|
328
490
|
});
|
|
329
491
|
}
|
|
330
492
|
add(field, callback) {
|
|
331
|
-
const filter = {
|
|
332
|
-
field
|
|
333
|
-
};
|
|
334
493
|
const yMap = new external_yjs_Map();
|
|
335
|
-
|
|
494
|
+
yMap.set('id', id_id.uuid());
|
|
495
|
+
yMap.set('field', field);
|
|
336
496
|
this.dsl.get('whereFilters').push([
|
|
337
497
|
yMap
|
|
338
498
|
]);
|
|
@@ -340,31 +500,53 @@ class WhereFiltersBuilder {
|
|
|
340
500
|
callback(node);
|
|
341
501
|
return this;
|
|
342
502
|
}
|
|
343
|
-
|
|
503
|
+
addGroup(op, callback) {
|
|
504
|
+
const yMap = new external_yjs_Map();
|
|
505
|
+
yMap.set('id', id_id.uuid());
|
|
506
|
+
yMap.set('op', op);
|
|
507
|
+
yMap.set('conditions', new external_yjs_Array());
|
|
508
|
+
this.dsl.get('whereFilters').push([
|
|
509
|
+
yMap
|
|
510
|
+
]);
|
|
511
|
+
const group = new WhereGroupBuilder(yMap);
|
|
512
|
+
callback(group);
|
|
513
|
+
return this;
|
|
514
|
+
}
|
|
515
|
+
update(id, callback) {
|
|
344
516
|
const whereFilters = this.dsl.get('whereFilters');
|
|
345
|
-
const index = whereFilters.toArray().findIndex((item)=>item.get('
|
|
346
|
-
if (-1 === index) throw new Error(`Where filter with
|
|
517
|
+
const index = whereFilters.toArray().findIndex((item)=>item.get('id') === id);
|
|
518
|
+
if (-1 === index) throw new Error(`Where filter with id ${id} not found`);
|
|
347
519
|
const filterYMap = whereFilters.get(index);
|
|
348
520
|
const node = new WhereFilterNodeBuilder(filterYMap);
|
|
349
521
|
callback(node);
|
|
350
522
|
return this;
|
|
351
523
|
}
|
|
352
|
-
|
|
524
|
+
updateGroup(id, callback) {
|
|
353
525
|
const whereFilters = this.dsl.get('whereFilters');
|
|
354
|
-
const index = whereFilters.toArray().findIndex((item)=>item.get('
|
|
355
|
-
if (-1 === index)
|
|
356
|
-
whereFilters.
|
|
526
|
+
const index = whereFilters.toArray().findIndex((item)=>item.get('id') === id);
|
|
527
|
+
if (-1 === index) throw new Error(`Where group with id ${id} not found`);
|
|
528
|
+
const yMap = whereFilters.get(index);
|
|
529
|
+
if (!WhereFiltersBuilder.isGroup(yMap)) throw new Error(`Item with id ${id} is not a group`);
|
|
530
|
+
const group = new WhereGroupBuilder(yMap);
|
|
531
|
+
callback(group);
|
|
357
532
|
return this;
|
|
358
533
|
}
|
|
359
|
-
|
|
534
|
+
remove(idOrIndex) {
|
|
360
535
|
const whereFilters = this.dsl.get('whereFilters');
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
536
|
+
if ('number' == typeof idOrIndex) {
|
|
537
|
+
if (idOrIndex >= 0 && idOrIndex < whereFilters.length) whereFilters.delete(idOrIndex, 1);
|
|
538
|
+
} else {
|
|
539
|
+
const index = whereFilters.toArray().findIndex((item)=>item.get('id') === idOrIndex);
|
|
540
|
+
if (-1 !== index) whereFilters.delete(index, 1);
|
|
541
|
+
}
|
|
542
|
+
return this;
|
|
364
543
|
}
|
|
365
|
-
|
|
544
|
+
find(id) {
|
|
366
545
|
const whereFilters = this.dsl.get('whereFilters');
|
|
367
|
-
|
|
546
|
+
const yMap = whereFilters.toArray().find((item)=>item.get('id') === id);
|
|
547
|
+
if (!yMap) return;
|
|
548
|
+
if (WhereFiltersBuilder.isGroup(yMap)) return new WhereGroupBuilder(yMap);
|
|
549
|
+
return new WhereFilterNodeBuilder(yMap);
|
|
368
550
|
}
|
|
369
551
|
clear() {
|
|
370
552
|
const whereFilters = this.dsl.get('whereFilters');
|
|
@@ -380,61 +562,34 @@ class WhereFiltersBuilder {
|
|
|
380
562
|
this.dsl.get('whereFilters').unobserve(callback);
|
|
381
563
|
};
|
|
382
564
|
}
|
|
565
|
+
static isGroup(yMap) {
|
|
566
|
+
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
567
|
+
}
|
|
568
|
+
static isNode(yMap) {
|
|
569
|
+
return void 0 !== yMap.get('field');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
class undo_manager_UndoManager {
|
|
573
|
+
manager;
|
|
574
|
+
constructor(scope){
|
|
575
|
+
this.manager = new UndoManager(scope);
|
|
576
|
+
}
|
|
577
|
+
undo() {
|
|
578
|
+
return null !== this.manager.undo();
|
|
579
|
+
}
|
|
580
|
+
redo() {
|
|
581
|
+
return null !== this.manager.redo();
|
|
582
|
+
}
|
|
583
|
+
canUndo() {
|
|
584
|
+
return this.manager.canUndo();
|
|
585
|
+
}
|
|
586
|
+
canRedo() {
|
|
587
|
+
return this.manager.canRedo();
|
|
588
|
+
}
|
|
589
|
+
clear(clearUndoStack, clearRedoStack) {
|
|
590
|
+
this.manager.clear(clearUndoStack, clearRedoStack);
|
|
591
|
+
}
|
|
383
592
|
}
|
|
384
|
-
const zVBIHavingFilter = z.object({
|
|
385
|
-
field: z.string(),
|
|
386
|
-
operator: z.string().optional(),
|
|
387
|
-
value: z.any().optional()
|
|
388
|
-
});
|
|
389
|
-
const zVBIHavingArray = z.array(zVBIHavingFilter);
|
|
390
|
-
const buildVQuery = (vbiDSL, builder)=>{
|
|
391
|
-
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
392
|
-
vbiDSL,
|
|
393
|
-
builder
|
|
394
|
-
});
|
|
395
|
-
return pipe({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildOrderBy), wrapper(buildLimit));
|
|
396
|
-
};
|
|
397
|
-
const buildWhere = (queryDSL, context)=>{
|
|
398
|
-
const { vbiDSL } = context;
|
|
399
|
-
const whereFilters = vbiDSL.whereFilters || [];
|
|
400
|
-
if (0 === whereFilters.length) return queryDSL;
|
|
401
|
-
const result = {
|
|
402
|
-
...queryDSL
|
|
403
|
-
};
|
|
404
|
-
result.where = {
|
|
405
|
-
op: 'and',
|
|
406
|
-
conditions: whereFilters.flatMap((filter)=>{
|
|
407
|
-
if ('between' === filter.operator && filter.value && 'object' == typeof filter.value && !Array.isArray(filter.value)) {
|
|
408
|
-
const conditions = [];
|
|
409
|
-
if (void 0 !== filter.value.min && null !== filter.value.min && '' !== filter.value.min) conditions.push({
|
|
410
|
-
field: filter.field,
|
|
411
|
-
op: '<' === filter.value.leftOp ? '>' : '>=',
|
|
412
|
-
value: filter.value.min
|
|
413
|
-
});
|
|
414
|
-
if (void 0 !== filter.value.max && null !== filter.value.max && '' !== filter.value.max) conditions.push({
|
|
415
|
-
field: filter.field,
|
|
416
|
-
op: '<' === filter.value.rightOp ? '<' : '<=',
|
|
417
|
-
value: filter.value.max
|
|
418
|
-
});
|
|
419
|
-
return conditions;
|
|
420
|
-
}
|
|
421
|
-
let mappedOp = filter.operator ?? '=';
|
|
422
|
-
if (Array.isArray(filter.value)) {
|
|
423
|
-
if ('=' === mappedOp) mappedOp = 'in';
|
|
424
|
-
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
425
|
-
}
|
|
426
|
-
return [
|
|
427
|
-
{
|
|
428
|
-
field: filter.field,
|
|
429
|
-
op: mappedOp,
|
|
430
|
-
value: filter.value
|
|
431
|
-
}
|
|
432
|
-
];
|
|
433
|
-
})
|
|
434
|
-
};
|
|
435
|
-
return result;
|
|
436
|
-
};
|
|
437
|
-
const buildOrderBy = (queryDSL, context)=>queryDSL;
|
|
438
593
|
const buildSelect = (queryDSL, context)=>{
|
|
439
594
|
const { vbiDSL } = context;
|
|
440
595
|
const measures = vbiDSL.measures;
|
|
@@ -466,14 +621,68 @@ const buildGroupBy = (queryDSL, context)=>{
|
|
|
466
621
|
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
467
622
|
return result;
|
|
468
623
|
};
|
|
469
|
-
const
|
|
624
|
+
const buildWhere = (queryDSL, context)=>{
|
|
625
|
+
const { vbiDSL } = context;
|
|
626
|
+
const whereFilters = vbiDSL.whereFilters || [];
|
|
627
|
+
if (0 === whereFilters.length) return queryDSL;
|
|
470
628
|
const result = {
|
|
471
629
|
...queryDSL
|
|
472
630
|
};
|
|
473
|
-
|
|
474
|
-
|
|
631
|
+
result.where = {
|
|
632
|
+
op: 'and',
|
|
633
|
+
conditions: whereFilters.flatMap(mapClauseToCondition)
|
|
634
|
+
};
|
|
475
635
|
return result;
|
|
476
636
|
};
|
|
637
|
+
function isWhereGroup(clause) {
|
|
638
|
+
return 'op' in clause && 'conditions' in clause;
|
|
639
|
+
}
|
|
640
|
+
function mapClauseToCondition(clause) {
|
|
641
|
+
if (isWhereGroup(clause)) return [
|
|
642
|
+
mapGroupToCondition(clause)
|
|
643
|
+
];
|
|
644
|
+
return mapFilterToCondition(clause);
|
|
645
|
+
}
|
|
646
|
+
function mapGroupToCondition(group) {
|
|
647
|
+
return {
|
|
648
|
+
op: group.op,
|
|
649
|
+
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function mapFilterToCondition(filter) {
|
|
653
|
+
if ('between' === filter.op) return handleBetweenFilter(filter);
|
|
654
|
+
return handleSimpleFilter(filter);
|
|
655
|
+
}
|
|
656
|
+
function handleBetweenFilter(filter) {
|
|
657
|
+
const conditions = [];
|
|
658
|
+
const value = filter.value;
|
|
659
|
+
if (void 0 !== value.min && null !== value.min && '' !== value.min) conditions.push({
|
|
660
|
+
field: filter.field,
|
|
661
|
+
op: '<' === value.leftOp ? '>' : '>=',
|
|
662
|
+
value: value.min
|
|
663
|
+
});
|
|
664
|
+
if (void 0 !== value.max && null !== value.max && '' !== value.max) conditions.push({
|
|
665
|
+
field: filter.field,
|
|
666
|
+
op: '<' === value.rightOp ? '<' : '<=',
|
|
667
|
+
value: value.max
|
|
668
|
+
});
|
|
669
|
+
return conditions;
|
|
670
|
+
}
|
|
671
|
+
function handleSimpleFilter(filter) {
|
|
672
|
+
let mappedOp = filter.op ?? '=';
|
|
673
|
+
const value = filter.value;
|
|
674
|
+
if (Array.isArray(value)) {
|
|
675
|
+
if ('=' === mappedOp) mappedOp = 'in';
|
|
676
|
+
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
677
|
+
}
|
|
678
|
+
return [
|
|
679
|
+
{
|
|
680
|
+
field: filter.field,
|
|
681
|
+
op: mappedOp,
|
|
682
|
+
value
|
|
683
|
+
}
|
|
684
|
+
];
|
|
685
|
+
}
|
|
477
686
|
const buildHaving = (queryDSL, context)=>{
|
|
478
687
|
const { vbiDSL } = context;
|
|
479
688
|
const havingFilters = vbiDSL.havingFilters || [];
|
|
@@ -483,17 +692,50 @@ const buildHaving = (queryDSL, context)=>{
|
|
|
483
692
|
};
|
|
484
693
|
result.having = {
|
|
485
694
|
op: 'and',
|
|
486
|
-
conditions: havingFilters.
|
|
487
|
-
const mappedOp = filter.operator ?? '=';
|
|
488
|
-
return {
|
|
489
|
-
field: filter.field,
|
|
490
|
-
op: mappedOp,
|
|
491
|
-
value: filter.value
|
|
492
|
-
};
|
|
493
|
-
})
|
|
695
|
+
conditions: havingFilters.flatMap(buildHaving_mapClauseToCondition)
|
|
494
696
|
};
|
|
495
697
|
return result;
|
|
496
698
|
};
|
|
699
|
+
function isHavingGroup(clause) {
|
|
700
|
+
return 'op' in clause && 'conditions' in clause;
|
|
701
|
+
}
|
|
702
|
+
function buildHaving_mapClauseToCondition(clause) {
|
|
703
|
+
if (isHavingGroup(clause)) return [
|
|
704
|
+
buildHaving_mapGroupToCondition(clause)
|
|
705
|
+
];
|
|
706
|
+
return buildHaving_mapFilterToCondition(clause);
|
|
707
|
+
}
|
|
708
|
+
function buildHaving_mapGroupToCondition(group) {
|
|
709
|
+
return {
|
|
710
|
+
op: group.op,
|
|
711
|
+
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function buildHaving_mapFilterToCondition(filter) {
|
|
715
|
+
const mappedOp = filter.op ?? '=';
|
|
716
|
+
return [
|
|
717
|
+
{
|
|
718
|
+
field: filter.field,
|
|
719
|
+
op: mappedOp,
|
|
720
|
+
value: filter.value
|
|
721
|
+
}
|
|
722
|
+
];
|
|
723
|
+
}
|
|
724
|
+
const buildLimit = (queryDSL, context)=>{
|
|
725
|
+
const result = {
|
|
726
|
+
...queryDSL
|
|
727
|
+
};
|
|
728
|
+
const limit = context.vbiDSL.limit ?? 1000;
|
|
729
|
+
result.limit = limit;
|
|
730
|
+
return result;
|
|
731
|
+
};
|
|
732
|
+
const buildVQuery = (vbiDSL, builder)=>{
|
|
733
|
+
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
734
|
+
vbiDSL,
|
|
735
|
+
builder
|
|
736
|
+
});
|
|
737
|
+
return pipe({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
738
|
+
};
|
|
497
739
|
const connectorMap = new Map();
|
|
498
740
|
const registerConnector = (id, connector)=>{
|
|
499
741
|
connectorMap.set(id, connector);
|
|
@@ -516,7 +758,7 @@ class VBIBuilder {
|
|
|
516
758
|
constructor(doc){
|
|
517
759
|
this.doc = doc;
|
|
518
760
|
this.dsl = doc.getMap('dsl');
|
|
519
|
-
this.undoManager = new
|
|
761
|
+
this.undoManager = new undo_manager_UndoManager(this.dsl);
|
|
520
762
|
this.chartType = new ChartTypeBuilder(doc, this.dsl);
|
|
521
763
|
this.measures = new MeasuresBuilder(doc, this.dsl);
|
|
522
764
|
this.dimensions = new DimensionsBuilder(doc, this.dsl);
|
|
@@ -596,7 +838,27 @@ const createVBI = ()=>({
|
|
|
596
838
|
if (vbi.limit) dsl.set('limit', vbi.limit);
|
|
597
839
|
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
598
840
|
if (vbi.version) dsl.set('version', vbi.version);
|
|
599
|
-
const
|
|
841
|
+
const toYMap = (obj, ensureId = false)=>{
|
|
842
|
+
const yMap = new external_yjs_Map();
|
|
843
|
+
if (ensureId && !obj.id) yMap.set('id', id_id.uuid());
|
|
844
|
+
for (const [key, value] of Object.entries(obj))if ('conditions' === key && Array.isArray(value)) {
|
|
845
|
+
const yArr = new external_yjs_Array();
|
|
846
|
+
value.forEach((child)=>{
|
|
847
|
+
if (child instanceof external_yjs_Map) yArr.push([
|
|
848
|
+
child
|
|
849
|
+
]);
|
|
850
|
+
else if ('object' == typeof child && null !== child) yArr.push([
|
|
851
|
+
toYMap(child, true)
|
|
852
|
+
]);
|
|
853
|
+
else yArr.push([
|
|
854
|
+
child
|
|
855
|
+
]);
|
|
856
|
+
});
|
|
857
|
+
yMap.set(key, yArr);
|
|
858
|
+
} else yMap.set(key, value);
|
|
859
|
+
return yMap;
|
|
860
|
+
};
|
|
861
|
+
const ensureYArray = (arr, ensureId = false)=>{
|
|
600
862
|
if (!arr) return new external_yjs_Array();
|
|
601
863
|
if (arr instanceof external_yjs_Array) return arr;
|
|
602
864
|
const yArr = new external_yjs_Array();
|
|
@@ -604,20 +866,17 @@ const createVBI = ()=>({
|
|
|
604
866
|
if (item instanceof external_yjs_Map) yArr.push([
|
|
605
867
|
item
|
|
606
868
|
]);
|
|
607
|
-
else if ('object' == typeof item && null !== item)
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
yMap
|
|
612
|
-
]);
|
|
613
|
-
} else yArr.push([
|
|
869
|
+
else if ('object' == typeof item && null !== item) yArr.push([
|
|
870
|
+
toYMap(item, ensureId)
|
|
871
|
+
]);
|
|
872
|
+
else yArr.push([
|
|
614
873
|
item
|
|
615
874
|
]);
|
|
616
875
|
});
|
|
617
876
|
return yArr;
|
|
618
877
|
};
|
|
619
|
-
dsl.set('whereFilters', ensureYArray(vbi.whereFilters));
|
|
620
|
-
dsl.set('havingFilters', ensureYArray(vbi.havingFilters));
|
|
878
|
+
dsl.set('whereFilters', ensureYArray(vbi.whereFilters, true));
|
|
879
|
+
dsl.set('havingFilters', ensureYArray(vbi.havingFilters, true));
|
|
621
880
|
dsl.set('measures', ensureYArray(vbi.measures));
|
|
622
881
|
dsl.set('dimensions', ensureYArray(vbi.dimensions));
|
|
623
882
|
});
|
|
@@ -625,4 +884,52 @@ const createVBI = ()=>({
|
|
|
625
884
|
}
|
|
626
885
|
});
|
|
627
886
|
const VBI = createVBI();
|
|
628
|
-
|
|
887
|
+
const zVBIFilter = z.object({
|
|
888
|
+
id: z.string(),
|
|
889
|
+
field: z.string(),
|
|
890
|
+
op: z.string().optional(),
|
|
891
|
+
value: z.any().optional()
|
|
892
|
+
});
|
|
893
|
+
const zVBIWhereGroup = z.lazy(()=>z.object({
|
|
894
|
+
id: z.string(),
|
|
895
|
+
op: z["enum"]([
|
|
896
|
+
'and',
|
|
897
|
+
'or'
|
|
898
|
+
]),
|
|
899
|
+
conditions: z.array(zVBIWhereClause)
|
|
900
|
+
}));
|
|
901
|
+
const zVBIWhereClause = z.lazy(()=>z.union([
|
|
902
|
+
zVBIFilter,
|
|
903
|
+
zVBIWhereGroup
|
|
904
|
+
]));
|
|
905
|
+
function isVBIFilter(clause) {
|
|
906
|
+
return 'field' in clause;
|
|
907
|
+
}
|
|
908
|
+
function isVBIWhereGroup(clause) {
|
|
909
|
+
return 'conditions' in clause;
|
|
910
|
+
}
|
|
911
|
+
const zVBIHavingFilter = z.object({
|
|
912
|
+
id: z.string(),
|
|
913
|
+
field: z.string(),
|
|
914
|
+
op: z.string().optional(),
|
|
915
|
+
value: z.any().optional()
|
|
916
|
+
});
|
|
917
|
+
const zVBIHavingGroup = z.lazy(()=>z.object({
|
|
918
|
+
id: z.string(),
|
|
919
|
+
op: z["enum"]([
|
|
920
|
+
'and',
|
|
921
|
+
'or'
|
|
922
|
+
]),
|
|
923
|
+
conditions: z.array(zVBIHavingClause)
|
|
924
|
+
}));
|
|
925
|
+
const zVBIHavingClause = z.lazy(()=>z.union([
|
|
926
|
+
zVBIHavingFilter,
|
|
927
|
+
zVBIHavingGroup
|
|
928
|
+
]));
|
|
929
|
+
function isVBIHavingFilter(clause) {
|
|
930
|
+
return 'field' in clause;
|
|
931
|
+
}
|
|
932
|
+
function isVBIHavingGroup(clause) {
|
|
933
|
+
return 'conditions' in clause;
|
|
934
|
+
}
|
|
935
|
+
export { ChartTypeBuilder, DimensionsBuilder, MeasuresBuilder, VBI, VBIBuilder, buildVQuery, findTreeNodesBy, id_id as id, isVBIFilter, isVBIHavingFilter, isVBIHavingGroup, isVBIWhereGroup, preorderTraverse };
|