@visactor/vbi 0.4.16 → 0.4.17
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/features/dimensions/dim-builder.d.ts +10 -10
- package/dist/builder/features/dimensions/dim-node-builder.d.ts +4 -0
- package/dist/builder/features/dimensions/dimension-utils.d.ts +4 -0
- package/dist/builder/features/havingFilter/having-builder.d.ts +3 -3
- package/dist/builder/features/measures/mea-builder.d.ts +9 -9
- package/dist/builder/features/measures/mea-node-builder.d.ts +4 -0
- package/dist/builder/features/measures/measure-utils.d.ts +4 -0
- package/dist/builder/features/whereFilter/where-builder.d.ts +3 -3
- package/dist/builder/index.d.ts +1 -1
- package/dist/builder/modules/apply-update.d.ts +2 -0
- package/dist/builder/modules/build-vquery.d.ts +4 -0
- package/dist/builder/modules/build-vseed.d.ts +8 -0
- package/dist/builder/modules/build.d.ts +3 -0
- package/dist/builder/modules/create-builder-features.d.ts +14 -0
- package/dist/builder/modules/encode-state-as-update.d.ts +2 -0
- package/dist/builder/modules/get-schema.d.ts +5 -0
- package/dist/builder/modules/index.d.ts +8 -0
- package/dist/builder/modules/is-empty.d.ts +2 -0
- package/dist/builder/vbi-builder.d.ts +7 -6
- package/dist/index.cjs +548 -412
- package/dist/index.d.ts +2 -1
- package/dist/index.js +546 -410
- package/dist/types/builder/VBIInterface.d.ts +1 -0
- package/dist/types/dsl/dimensions/dimensions.d.ts +2 -0
- package/dist/types/dsl/measures/measures.d.ts +2 -0
- package/dist/types/dsl/vbi/vbi.d.ts +2 -0
- package/dist/vbi/create-vbi.d.ts +14 -0
- package/dist/vbi/from/from-vbi-dsl-input.d.ts +3 -0
- package/dist/vbi/from/set-base-dsl-fields.d.ts +3 -0
- package/dist/vbi/generate-empty-dsl.d.ts +3 -0
- package/dist/vbi/normalize/ensure-having-group.d.ts +2 -0
- package/dist/vbi/normalize/ensure-where-group.d.ts +2 -0
- package/dist/vbi/normalize/ensure-y-array.d.ts +3 -0
- package/dist/vbi/normalize/to-y-map.d.ts +3 -0
- package/dist/vbi/normalize/types.d.ts +5 -0
- package/dist/vbi.d.ts +14 -0
- package/package.json +5 -5
- package/dist/builder/vbi.d.ts +0 -16
package/dist/index.js
CHANGED
|
@@ -1,12 +1,247 @@
|
|
|
1
1
|
import { Array as external_yjs_Array, Doc, Map as external_yjs_Map, UndoManager, applyUpdate, encodeStateAsUpdate } from "yjs";
|
|
2
|
+
import { pipe } from "remeda";
|
|
2
3
|
import { ChartTypeEnum, findTreeNodesBy, preorderTraverse } from "@visactor/vseed";
|
|
3
4
|
import { v4 } from "uuid";
|
|
4
|
-
|
|
5
|
+
const connectorMap = new Map();
|
|
6
|
+
const registerConnector = (id, connector)=>{
|
|
7
|
+
connectorMap.set(id, connector);
|
|
8
|
+
};
|
|
9
|
+
const getConnector = async (id)=>{
|
|
10
|
+
const connector = connectorMap.get(id);
|
|
11
|
+
if (!connector) throw new Error(`connector ${id} not registered`);
|
|
12
|
+
if ('function' == typeof connector) return connector();
|
|
13
|
+
return connector;
|
|
14
|
+
};
|
|
15
|
+
const applyUpdateToDoc = (doc, update, transactionOrigin)=>{
|
|
16
|
+
applyUpdate(doc, update, transactionOrigin);
|
|
17
|
+
};
|
|
18
|
+
const encodeDocStateAsUpdate = (doc, targetStateVector)=>encodeStateAsUpdate(doc, targetStateVector);
|
|
19
|
+
const buildVBIDSL = (dsl)=>dsl.toJSON();
|
|
20
|
+
const buildSelect = (queryDSL, context)=>{
|
|
21
|
+
const { vbiDSL } = context;
|
|
22
|
+
const measures = vbiDSL.measures;
|
|
23
|
+
const dimensions = vbiDSL.dimensions;
|
|
24
|
+
const result = {
|
|
25
|
+
...queryDSL
|
|
26
|
+
};
|
|
27
|
+
const measureNodes = measures.filter((measure)=>MeasuresBuilder.isMeasureNode(measure));
|
|
28
|
+
const measureSelects = measureNodes.map((measure)=>({
|
|
29
|
+
field: measure.field,
|
|
30
|
+
alias: measure.alias,
|
|
31
|
+
aggr: measure.aggregate
|
|
32
|
+
}));
|
|
33
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
34
|
+
const dimensionSelects = dimensionNodes.map((dimension)=>({
|
|
35
|
+
field: dimension.field,
|
|
36
|
+
alias: dimension.alias
|
|
37
|
+
}));
|
|
38
|
+
result.select = measureSelects.concat(dimensionSelects);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
const buildGroupBy = (queryDSL, context)=>{
|
|
42
|
+
const result = {
|
|
43
|
+
...queryDSL
|
|
44
|
+
};
|
|
45
|
+
const { vbiDSL } = context;
|
|
46
|
+
const dimensions = vbiDSL.dimensions;
|
|
47
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
48
|
+
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
const buildWhere = (queryDSL, context)=>{
|
|
52
|
+
const { vbiDSL } = context;
|
|
53
|
+
const whereFilter = vbiDSL.whereFilter;
|
|
54
|
+
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
55
|
+
const result = {
|
|
56
|
+
...queryDSL
|
|
57
|
+
};
|
|
58
|
+
result.where = mapGroupToCondition(whereFilter);
|
|
59
|
+
return result;
|
|
60
|
+
};
|
|
61
|
+
function isWhereGroup(clause) {
|
|
62
|
+
return 'op' in clause && 'conditions' in clause;
|
|
63
|
+
}
|
|
64
|
+
function mapClauseToCondition(clause) {
|
|
65
|
+
if (isWhereGroup(clause)) return [
|
|
66
|
+
mapGroupToCondition(clause)
|
|
67
|
+
];
|
|
68
|
+
return mapFilterToCondition(clause);
|
|
69
|
+
}
|
|
70
|
+
function mapGroupToCondition(group) {
|
|
71
|
+
return {
|
|
72
|
+
op: group.op,
|
|
73
|
+
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function mapFilterToCondition(filter) {
|
|
77
|
+
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
78
|
+
return handleSimpleFilter(filter);
|
|
79
|
+
}
|
|
80
|
+
function handleBetweenFilter(filter) {
|
|
81
|
+
const value = normalizeBetweenValue(filter.value);
|
|
82
|
+
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
83
|
+
field: filter.field,
|
|
84
|
+
op: '<' === value.leftOp ? '>' : '>=',
|
|
85
|
+
value: value.min
|
|
86
|
+
} : void 0;
|
|
87
|
+
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
88
|
+
field: filter.field,
|
|
89
|
+
op: '<' === value.rightOp ? '<' : '<=',
|
|
90
|
+
value: value.max
|
|
91
|
+
} : void 0;
|
|
92
|
+
if ('not between' === filter.op) {
|
|
93
|
+
const outsideConditions = [
|
|
94
|
+
lowerCondition && invertLowerBound(lowerCondition),
|
|
95
|
+
upperCondition && invertUpperBound(upperCondition)
|
|
96
|
+
].filter(Boolean);
|
|
97
|
+
if (outsideConditions.length <= 1) return outsideConditions;
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
op: 'or',
|
|
101
|
+
conditions: outsideConditions
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
return [
|
|
106
|
+
lowerCondition,
|
|
107
|
+
upperCondition
|
|
108
|
+
].filter(Boolean);
|
|
109
|
+
}
|
|
110
|
+
function normalizeBetweenValue(value) {
|
|
111
|
+
if (Array.isArray(value)) return {
|
|
112
|
+
min: value[0],
|
|
113
|
+
max: value[1],
|
|
114
|
+
leftOp: '<=',
|
|
115
|
+
rightOp: '<='
|
|
116
|
+
};
|
|
117
|
+
if ('object' == typeof value && null !== value) return value;
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
120
|
+
function invertLowerBound(condition) {
|
|
121
|
+
return {
|
|
122
|
+
field: condition.field,
|
|
123
|
+
op: '>' === condition.op ? '<=' : '<',
|
|
124
|
+
value: condition.value
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function invertUpperBound(condition) {
|
|
128
|
+
return {
|
|
129
|
+
field: condition.field,
|
|
130
|
+
op: '<' === condition.op ? '>=' : '>',
|
|
131
|
+
value: condition.value
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function handleSimpleFilter(filter) {
|
|
135
|
+
let mappedOp = filter.op ?? '=';
|
|
136
|
+
const value = filter.value;
|
|
137
|
+
if (Array.isArray(value)) {
|
|
138
|
+
if ('=' === mappedOp) mappedOp = 'in';
|
|
139
|
+
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
140
|
+
}
|
|
141
|
+
return [
|
|
142
|
+
{
|
|
143
|
+
field: filter.field,
|
|
144
|
+
op: mappedOp,
|
|
145
|
+
value
|
|
146
|
+
}
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
const buildHaving = (queryDSL, context)=>{
|
|
150
|
+
const { vbiDSL } = context;
|
|
151
|
+
const havingFilter = vbiDSL.havingFilter;
|
|
152
|
+
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
153
|
+
const result = {
|
|
154
|
+
...queryDSL
|
|
155
|
+
};
|
|
156
|
+
result.having = {
|
|
157
|
+
op: havingFilter.op,
|
|
158
|
+
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
159
|
+
};
|
|
160
|
+
return result;
|
|
161
|
+
};
|
|
162
|
+
function isHavingGroup(clause) {
|
|
163
|
+
return 'op' in clause && 'conditions' in clause;
|
|
164
|
+
}
|
|
165
|
+
function buildHaving_mapClauseToCondition(clause) {
|
|
166
|
+
if (isHavingGroup(clause)) return [
|
|
167
|
+
buildHaving_mapGroupToCondition(clause)
|
|
168
|
+
];
|
|
169
|
+
return buildHaving_mapFilterToCondition(clause);
|
|
170
|
+
}
|
|
171
|
+
function buildHaving_mapGroupToCondition(group) {
|
|
172
|
+
return {
|
|
173
|
+
op: group.op,
|
|
174
|
+
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function buildHaving_mapFilterToCondition(filter) {
|
|
178
|
+
const mappedOp = filter.op ?? '=';
|
|
179
|
+
return [
|
|
180
|
+
{
|
|
181
|
+
field: filter.field,
|
|
182
|
+
op: mappedOp,
|
|
183
|
+
value: filter.value
|
|
184
|
+
}
|
|
185
|
+
];
|
|
186
|
+
}
|
|
187
|
+
const buildLimit = (queryDSL, context)=>{
|
|
188
|
+
const result = {
|
|
189
|
+
...queryDSL
|
|
190
|
+
};
|
|
191
|
+
const limit = context.vbiDSL.limit ?? 1000;
|
|
192
|
+
result.limit = limit;
|
|
193
|
+
return result;
|
|
194
|
+
};
|
|
195
|
+
const buildVQuery = (vbiDSL, builder)=>{
|
|
196
|
+
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
197
|
+
vbiDSL,
|
|
198
|
+
builder
|
|
199
|
+
});
|
|
200
|
+
return pipe({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
201
|
+
};
|
|
202
|
+
const buildVQueryDSL = (dsl, builder)=>{
|
|
203
|
+
const vbiDSL = buildVBIDSL(dsl);
|
|
204
|
+
return buildVQuery(vbiDSL, builder);
|
|
205
|
+
};
|
|
206
|
+
const buildVSeedDSL = async ({ vbiDSL, queryDSL })=>{
|
|
207
|
+
const connectorId = vbiDSL.connectorId;
|
|
208
|
+
const connector = await getConnector(connectorId);
|
|
209
|
+
const schema = await connector.discoverSchema();
|
|
210
|
+
const queryResult = await connector.query({
|
|
211
|
+
queryDSL,
|
|
212
|
+
schema,
|
|
213
|
+
connectorId
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
chartType: vbiDSL.chartType,
|
|
217
|
+
dataset: queryResult.dataset,
|
|
218
|
+
theme: vbiDSL.theme,
|
|
219
|
+
locale: vbiDSL.locale
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
const getCollectionLength = (value)=>{
|
|
223
|
+
if (value instanceof external_yjs_Array) return value.length;
|
|
224
|
+
if (Array.isArray(value)) return value.length;
|
|
225
|
+
return 0;
|
|
226
|
+
};
|
|
227
|
+
const isEmptyVBIDSL = (dsl)=>{
|
|
228
|
+
const dimensionsLength = getCollectionLength(dsl.get('dimensions'));
|
|
229
|
+
const measuresLength = getCollectionLength(dsl.get('measures'));
|
|
230
|
+
return 0 === dimensionsLength && 0 === measuresLength;
|
|
231
|
+
};
|
|
232
|
+
const getBuilderSchema = async (dsl)=>{
|
|
233
|
+
const connectorId = dsl.get('connectorId');
|
|
234
|
+
const connector = await getConnector(connectorId);
|
|
235
|
+
return connector.discoverSchema();
|
|
236
|
+
};
|
|
5
237
|
class MeasureNodeBuilder {
|
|
6
238
|
yMap;
|
|
7
239
|
constructor(yMap){
|
|
8
240
|
this.yMap = yMap;
|
|
9
241
|
}
|
|
242
|
+
getId() {
|
|
243
|
+
return this.yMap.get('id');
|
|
244
|
+
}
|
|
10
245
|
getField() {
|
|
11
246
|
return this.yMap.get('field');
|
|
12
247
|
}
|
|
@@ -26,13 +261,46 @@ class MeasureNodeBuilder {
|
|
|
26
261
|
return this.yMap.toJSON();
|
|
27
262
|
}
|
|
28
263
|
}
|
|
264
|
+
const id_id = {
|
|
265
|
+
uuid: ()=>v4()
|
|
266
|
+
};
|
|
267
|
+
function isVBIFilter(clause) {
|
|
268
|
+
return 'field' in clause;
|
|
269
|
+
}
|
|
270
|
+
function isVBIWhereGroup(clause) {
|
|
271
|
+
return 'conditions' in clause;
|
|
272
|
+
}
|
|
273
|
+
function isVBIHavingFilter(clause) {
|
|
274
|
+
return 'field' in clause;
|
|
275
|
+
}
|
|
276
|
+
function isVBIHavingGroup(clause) {
|
|
277
|
+
return 'conditions' in clause;
|
|
278
|
+
}
|
|
279
|
+
const getOrCreateMeasures = (dsl)=>{
|
|
280
|
+
const measures = dsl.get('measures');
|
|
281
|
+
if (measures instanceof external_yjs_Array) return measures;
|
|
282
|
+
const yMeasures = new external_yjs_Array();
|
|
283
|
+
dsl.set('measures', yMeasures);
|
|
284
|
+
return yMeasures;
|
|
285
|
+
};
|
|
286
|
+
const normalizeMeasureNodeIds = (measures)=>{
|
|
287
|
+
measures.toArray().forEach((item)=>{
|
|
288
|
+
if (item instanceof external_yjs_Map && 'string' == typeof item.get('field') && !item.get('id')) item.set('id', id_id.uuid());
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
const locateMeasureIndexById = (measures, measureId)=>measures.toArray().findIndex((item)=>item.get('id') === measureId);
|
|
29
292
|
class MeasuresBuilder {
|
|
30
293
|
dsl;
|
|
31
|
-
constructor(
|
|
294
|
+
constructor(doc, dsl){
|
|
32
295
|
this.dsl = dsl;
|
|
296
|
+
doc.transact(()=>{
|
|
297
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
298
|
+
normalizeMeasureNodeIds(measures);
|
|
299
|
+
});
|
|
33
300
|
}
|
|
34
301
|
add(field, callback) {
|
|
35
302
|
const measure = {
|
|
303
|
+
id: id_id.uuid(),
|
|
36
304
|
alias: field,
|
|
37
305
|
field,
|
|
38
306
|
encoding: 'yAxis',
|
|
@@ -42,45 +310,50 @@ class MeasuresBuilder {
|
|
|
42
310
|
};
|
|
43
311
|
const yMap = new external_yjs_Map();
|
|
44
312
|
for (const [key, value] of Object.entries(measure))yMap.set(key, value);
|
|
45
|
-
this.dsl
|
|
313
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
314
|
+
measures.push([
|
|
46
315
|
yMap
|
|
47
316
|
]);
|
|
48
317
|
const node = new MeasureNodeBuilder(yMap);
|
|
49
318
|
callback(node);
|
|
50
319
|
return this;
|
|
51
320
|
}
|
|
52
|
-
remove(
|
|
53
|
-
const measures = this.dsl
|
|
54
|
-
const index = measures
|
|
55
|
-
if (-1 !== index)
|
|
321
|
+
remove(id) {
|
|
322
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
323
|
+
const index = locateMeasureIndexById(measures, id);
|
|
324
|
+
if (-1 !== index) measures.delete(index, 1);
|
|
56
325
|
return this;
|
|
57
326
|
}
|
|
58
|
-
update(
|
|
59
|
-
const measures = this.dsl
|
|
60
|
-
const index = measures
|
|
61
|
-
if (-1 === index) throw new Error(`Measure with
|
|
327
|
+
update(id, callback) {
|
|
328
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
329
|
+
const index = locateMeasureIndexById(measures, id);
|
|
330
|
+
if (-1 === index) throw new Error(`Measure with id "${id}" not found`);
|
|
62
331
|
const measureYMap = measures.get(index);
|
|
63
332
|
const node = new MeasureNodeBuilder(measureYMap);
|
|
64
333
|
callback(node);
|
|
65
334
|
return this;
|
|
66
335
|
}
|
|
67
|
-
find(
|
|
68
|
-
const measures = this.dsl
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
336
|
+
find(predicate) {
|
|
337
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
338
|
+
const items = measures.toArray();
|
|
339
|
+
for(let index = 0; index < items.length; index++){
|
|
340
|
+
const node = new MeasureNodeBuilder(items[index]);
|
|
341
|
+
if (predicate(node, index)) return node;
|
|
342
|
+
}
|
|
72
343
|
}
|
|
73
344
|
findAll() {
|
|
74
|
-
const measures = this.dsl
|
|
345
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
75
346
|
return measures.toArray().map((yMap)=>new MeasureNodeBuilder(yMap));
|
|
76
347
|
}
|
|
77
348
|
toJSON() {
|
|
78
|
-
|
|
349
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
350
|
+
return measures.toJSON();
|
|
79
351
|
}
|
|
80
352
|
observe(callback) {
|
|
81
|
-
this.dsl
|
|
353
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
354
|
+
measures.observe(callback);
|
|
82
355
|
return ()=>{
|
|
83
|
-
|
|
356
|
+
measures.unobserve(callback);
|
|
84
357
|
};
|
|
85
358
|
}
|
|
86
359
|
static isMeasureNode(node) {
|
|
@@ -95,6 +368,9 @@ class DimensionNodeBuilder {
|
|
|
95
368
|
constructor(yMap){
|
|
96
369
|
this.yMap = yMap;
|
|
97
370
|
}
|
|
371
|
+
getId() {
|
|
372
|
+
return this.yMap.get('id');
|
|
373
|
+
}
|
|
98
374
|
getField() {
|
|
99
375
|
return this.yMap.get('field');
|
|
100
376
|
}
|
|
@@ -106,57 +382,80 @@ class DimensionNodeBuilder {
|
|
|
106
382
|
return this.yMap.toJSON();
|
|
107
383
|
}
|
|
108
384
|
}
|
|
385
|
+
const getOrCreateDimensions = (dsl)=>{
|
|
386
|
+
const dimensions = dsl.get('dimensions');
|
|
387
|
+
if (dimensions instanceof external_yjs_Array) return dimensions;
|
|
388
|
+
const yDimensions = new external_yjs_Array();
|
|
389
|
+
dsl.set('dimensions', yDimensions);
|
|
390
|
+
return yDimensions;
|
|
391
|
+
};
|
|
392
|
+
const normalizeDimensionNodeIds = (dimensions)=>{
|
|
393
|
+
dimensions.toArray().forEach((item)=>{
|
|
394
|
+
if (item instanceof external_yjs_Map && 'string' == typeof item.get('field') && !item.get('id')) item.set('id', id_id.uuid());
|
|
395
|
+
});
|
|
396
|
+
};
|
|
397
|
+
const locateDimensionIndexById = (dimensions, dimensionId)=>dimensions.toArray().findIndex((item)=>item.get('id') === dimensionId);
|
|
109
398
|
class DimensionsBuilder {
|
|
110
399
|
dsl;
|
|
111
|
-
constructor(
|
|
400
|
+
constructor(doc, dsl){
|
|
112
401
|
this.dsl = dsl;
|
|
402
|
+
doc.transact(()=>{
|
|
403
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
404
|
+
normalizeDimensionNodeIds(dimensions);
|
|
405
|
+
});
|
|
113
406
|
}
|
|
114
407
|
add(field, callback) {
|
|
115
408
|
const dimension = {
|
|
409
|
+
id: id_id.uuid(),
|
|
116
410
|
alias: field,
|
|
117
411
|
field
|
|
118
412
|
};
|
|
119
413
|
const yMap = new external_yjs_Map();
|
|
120
414
|
for (const [key, value] of Object.entries(dimension))yMap.set(key, value);
|
|
121
|
-
this.dsl
|
|
415
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
416
|
+
dimensions.push([
|
|
122
417
|
yMap
|
|
123
418
|
]);
|
|
124
419
|
const node = new DimensionNodeBuilder(yMap);
|
|
125
420
|
callback(node);
|
|
126
421
|
return this;
|
|
127
422
|
}
|
|
128
|
-
remove(
|
|
129
|
-
const dimensions = this.dsl
|
|
130
|
-
const index = dimensions
|
|
131
|
-
if (-1 !== index)
|
|
423
|
+
remove(id) {
|
|
424
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
425
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
426
|
+
if (-1 !== index) dimensions.delete(index, 1);
|
|
132
427
|
return this;
|
|
133
428
|
}
|
|
134
|
-
update(
|
|
135
|
-
const dimensions = this.dsl
|
|
136
|
-
const index = dimensions
|
|
137
|
-
if (-1 === index) throw new Error(`Dimension with
|
|
429
|
+
update(id, callback) {
|
|
430
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
431
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
432
|
+
if (-1 === index) throw new Error(`Dimension with id "${id}" not found`);
|
|
138
433
|
const dimensionYMap = dimensions.get(index);
|
|
139
434
|
const node = new DimensionNodeBuilder(dimensionYMap);
|
|
140
435
|
callback(node);
|
|
141
436
|
return this;
|
|
142
437
|
}
|
|
143
|
-
find(
|
|
144
|
-
const dimensions = this.dsl
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
438
|
+
find(predicate) {
|
|
439
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
440
|
+
const items = dimensions.toArray();
|
|
441
|
+
for(let index = 0; index < items.length; index++){
|
|
442
|
+
const node = new DimensionNodeBuilder(items[index]);
|
|
443
|
+
if (predicate(node, index)) return node;
|
|
444
|
+
}
|
|
148
445
|
}
|
|
149
446
|
findAll() {
|
|
150
|
-
const dimensions = this.dsl
|
|
447
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
151
448
|
return dimensions.toArray().map((yMap)=>new DimensionNodeBuilder(yMap));
|
|
152
449
|
}
|
|
153
450
|
toJSON() {
|
|
154
|
-
|
|
451
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
452
|
+
return dimensions.toJSON();
|
|
155
453
|
}
|
|
156
454
|
observe(callback) {
|
|
157
|
-
this.dsl
|
|
455
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
456
|
+
dimensions.observe(callback);
|
|
158
457
|
return ()=>{
|
|
159
|
-
|
|
458
|
+
dimensions.unobserve(callback);
|
|
160
459
|
};
|
|
161
460
|
}
|
|
162
461
|
static isDimensionNode(node) {
|
|
@@ -215,21 +514,6 @@ class ChartTypeBuilder {
|
|
|
215
514
|
];
|
|
216
515
|
}
|
|
217
516
|
}
|
|
218
|
-
const id_id = {
|
|
219
|
-
uuid: ()=>v4()
|
|
220
|
-
};
|
|
221
|
-
function isVBIFilter(clause) {
|
|
222
|
-
return 'field' in clause;
|
|
223
|
-
}
|
|
224
|
-
function isVBIWhereGroup(clause) {
|
|
225
|
-
return 'conditions' in clause;
|
|
226
|
-
}
|
|
227
|
-
function isVBIHavingFilter(clause) {
|
|
228
|
-
return 'field' in clause;
|
|
229
|
-
}
|
|
230
|
-
function isVBIHavingGroup(clause) {
|
|
231
|
-
return 'conditions' in clause;
|
|
232
|
-
}
|
|
233
517
|
function createWhereGroup(op = 'and', groupId = 'root') {
|
|
234
518
|
const yMap = new external_yjs_Map();
|
|
235
519
|
yMap.set('id', groupId);
|
|
@@ -237,7 +521,7 @@ function createWhereGroup(op = 'and', groupId = 'root') {
|
|
|
237
521
|
yMap.set('conditions', new external_yjs_Array());
|
|
238
522
|
return yMap;
|
|
239
523
|
}
|
|
240
|
-
function
|
|
524
|
+
function where_utils_isWhereGroup(yMap) {
|
|
241
525
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
242
526
|
}
|
|
243
527
|
function findEntry(collection, entryId) {
|
|
@@ -249,7 +533,7 @@ function findEntry(collection, entryId) {
|
|
|
249
533
|
index,
|
|
250
534
|
item
|
|
251
535
|
};
|
|
252
|
-
if (
|
|
536
|
+
if (where_utils_isWhereGroup(item)) {
|
|
253
537
|
const nestedCollection = item.get('conditions');
|
|
254
538
|
const nestedMatch = findEntry(nestedCollection, entryId);
|
|
255
539
|
if (nestedMatch) return nestedMatch;
|
|
@@ -411,13 +695,21 @@ class WhereFilterBuilder {
|
|
|
411
695
|
}
|
|
412
696
|
return this;
|
|
413
697
|
}
|
|
414
|
-
find(
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
698
|
+
find(predicate) {
|
|
699
|
+
const traverse = (collection)=>{
|
|
700
|
+
const items = collection.toArray();
|
|
701
|
+
for(let index = 0; index < items.length; index++){
|
|
702
|
+
const yMap = items[index];
|
|
703
|
+
const entry = WhereFilterBuilder.isGroup(yMap) ? new WhereGroupBuilder(yMap) : new WhereFilterNodeBuilder(yMap);
|
|
704
|
+
if (predicate(entry, index)) return entry;
|
|
705
|
+
if (WhereFilterBuilder.isGroup(yMap)) {
|
|
706
|
+
const nestedCollection = yMap.get('conditions');
|
|
707
|
+
const nestedMatch = traverse(nestedCollection);
|
|
708
|
+
if (nestedMatch) return nestedMatch;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
};
|
|
712
|
+
return traverse(this.getConditions());
|
|
421
713
|
}
|
|
422
714
|
clear() {
|
|
423
715
|
const conditions = this.getConditions();
|
|
@@ -434,7 +726,7 @@ class WhereFilterBuilder {
|
|
|
434
726
|
};
|
|
435
727
|
}
|
|
436
728
|
static isGroup(yMap) {
|
|
437
|
-
return
|
|
729
|
+
return where_utils_isWhereGroup(yMap);
|
|
438
730
|
}
|
|
439
731
|
static isNode(yMap) {
|
|
440
732
|
return void 0 !== yMap.get('field');
|
|
@@ -447,7 +739,7 @@ function createHavingGroup(op = 'and', groupId = 'root') {
|
|
|
447
739
|
yMap.set('conditions', new external_yjs_Array());
|
|
448
740
|
return yMap;
|
|
449
741
|
}
|
|
450
|
-
function
|
|
742
|
+
function having_utils_isHavingGroup(yMap) {
|
|
451
743
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
452
744
|
}
|
|
453
745
|
function having_utils_findEntry(collection, entryId) {
|
|
@@ -459,7 +751,7 @@ function having_utils_findEntry(collection, entryId) {
|
|
|
459
751
|
index,
|
|
460
752
|
item
|
|
461
753
|
};
|
|
462
|
-
if (
|
|
754
|
+
if (having_utils_isHavingGroup(item)) {
|
|
463
755
|
const nestedCollection = item.get('conditions');
|
|
464
756
|
const nestedMatch = having_utils_findEntry(nestedCollection, entryId);
|
|
465
757
|
if (nestedMatch) return nestedMatch;
|
|
@@ -617,13 +909,21 @@ class HavingFilterBuilder {
|
|
|
617
909
|
}
|
|
618
910
|
return this;
|
|
619
911
|
}
|
|
620
|
-
find(
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
912
|
+
find(predicate) {
|
|
913
|
+
const traverse = (collection)=>{
|
|
914
|
+
const items = collection.toArray();
|
|
915
|
+
for(let index = 0; index < items.length; index++){
|
|
916
|
+
const yMap = items[index];
|
|
917
|
+
const entry = HavingFilterBuilder.isGroup(yMap) ? new HavingGroupBuilder(yMap) : new HavingFilterNodeBuilder(yMap);
|
|
918
|
+
if (predicate(entry, index)) return entry;
|
|
919
|
+
if (HavingFilterBuilder.isGroup(yMap)) {
|
|
920
|
+
const nestedCollection = yMap.get('conditions');
|
|
921
|
+
const nestedMatch = traverse(nestedCollection);
|
|
922
|
+
if (nestedMatch) return nestedMatch;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
return traverse(this.getConditions());
|
|
627
927
|
}
|
|
628
928
|
clear() {
|
|
629
929
|
const conditions = this.getConditions();
|
|
@@ -640,7 +940,7 @@ class HavingFilterBuilder {
|
|
|
640
940
|
};
|
|
641
941
|
}
|
|
642
942
|
static isGroup(yMap) {
|
|
643
|
-
return
|
|
943
|
+
return having_utils_isHavingGroup(yMap);
|
|
644
944
|
}
|
|
645
945
|
static isNode(yMap) {
|
|
646
946
|
return void 0 !== yMap.get('field');
|
|
@@ -739,202 +1039,20 @@ class undo_manager_UndoManager {
|
|
|
739
1039
|
this.manager.clear(clearUndoStack, clearRedoStack);
|
|
740
1040
|
}
|
|
741
1041
|
}
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
aggr: measure.aggregate
|
|
754
|
-
}));
|
|
755
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
756
|
-
const dimensionSelects = dimensionNodes.map((dimension)=>({
|
|
757
|
-
field: dimension.field,
|
|
758
|
-
alias: dimension.alias
|
|
759
|
-
}));
|
|
760
|
-
result.select = measureSelects.concat(dimensionSelects);
|
|
761
|
-
return result;
|
|
762
|
-
};
|
|
763
|
-
const buildGroupBy = (queryDSL, context)=>{
|
|
764
|
-
const result = {
|
|
765
|
-
...queryDSL
|
|
766
|
-
};
|
|
767
|
-
const { vbiDSL } = context;
|
|
768
|
-
const dimensions = vbiDSL.dimensions;
|
|
769
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
770
|
-
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
771
|
-
return result;
|
|
772
|
-
};
|
|
773
|
-
const buildWhere = (queryDSL, context)=>{
|
|
774
|
-
const { vbiDSL } = context;
|
|
775
|
-
const whereFilter = vbiDSL.whereFilter;
|
|
776
|
-
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
777
|
-
const result = {
|
|
778
|
-
...queryDSL
|
|
779
|
-
};
|
|
780
|
-
result.where = mapGroupToCondition(whereFilter);
|
|
781
|
-
return result;
|
|
782
|
-
};
|
|
783
|
-
function buildWhere_isWhereGroup(clause) {
|
|
784
|
-
return 'op' in clause && 'conditions' in clause;
|
|
785
|
-
}
|
|
786
|
-
function mapClauseToCondition(clause) {
|
|
787
|
-
if (buildWhere_isWhereGroup(clause)) return [
|
|
788
|
-
mapGroupToCondition(clause)
|
|
789
|
-
];
|
|
790
|
-
return mapFilterToCondition(clause);
|
|
791
|
-
}
|
|
792
|
-
function mapGroupToCondition(group) {
|
|
793
|
-
return {
|
|
794
|
-
op: group.op,
|
|
795
|
-
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
796
|
-
};
|
|
797
|
-
}
|
|
798
|
-
function mapFilterToCondition(filter) {
|
|
799
|
-
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
800
|
-
return handleSimpleFilter(filter);
|
|
801
|
-
}
|
|
802
|
-
function handleBetweenFilter(filter) {
|
|
803
|
-
const value = normalizeBetweenValue(filter.value);
|
|
804
|
-
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
805
|
-
field: filter.field,
|
|
806
|
-
op: '<' === value.leftOp ? '>' : '>=',
|
|
807
|
-
value: value.min
|
|
808
|
-
} : void 0;
|
|
809
|
-
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
810
|
-
field: filter.field,
|
|
811
|
-
op: '<' === value.rightOp ? '<' : '<=',
|
|
812
|
-
value: value.max
|
|
813
|
-
} : void 0;
|
|
814
|
-
if ('not between' === filter.op) {
|
|
815
|
-
const outsideConditions = [
|
|
816
|
-
lowerCondition && invertLowerBound(lowerCondition),
|
|
817
|
-
upperCondition && invertUpperBound(upperCondition)
|
|
818
|
-
].filter(Boolean);
|
|
819
|
-
if (outsideConditions.length <= 1) return outsideConditions;
|
|
820
|
-
return [
|
|
821
|
-
{
|
|
822
|
-
op: 'or',
|
|
823
|
-
conditions: outsideConditions
|
|
824
|
-
}
|
|
825
|
-
];
|
|
826
|
-
}
|
|
827
|
-
return [
|
|
828
|
-
lowerCondition,
|
|
829
|
-
upperCondition
|
|
830
|
-
].filter(Boolean);
|
|
831
|
-
}
|
|
832
|
-
function normalizeBetweenValue(value) {
|
|
833
|
-
if (Array.isArray(value)) return {
|
|
834
|
-
min: value[0],
|
|
835
|
-
max: value[1],
|
|
836
|
-
leftOp: '<=',
|
|
837
|
-
rightOp: '<='
|
|
838
|
-
};
|
|
839
|
-
if ('object' == typeof value && null !== value) return value;
|
|
840
|
-
return {};
|
|
841
|
-
}
|
|
842
|
-
function invertLowerBound(condition) {
|
|
843
|
-
return {
|
|
844
|
-
field: condition.field,
|
|
845
|
-
op: '>' === condition.op ? '<=' : '<',
|
|
846
|
-
value: condition.value
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
function invertUpperBound(condition) {
|
|
850
|
-
return {
|
|
851
|
-
field: condition.field,
|
|
852
|
-
op: '<' === condition.op ? '>=' : '>',
|
|
853
|
-
value: condition.value
|
|
854
|
-
};
|
|
855
|
-
}
|
|
856
|
-
function handleSimpleFilter(filter) {
|
|
857
|
-
let mappedOp = filter.op ?? '=';
|
|
858
|
-
const value = filter.value;
|
|
859
|
-
if (Array.isArray(value)) {
|
|
860
|
-
if ('=' === mappedOp) mappedOp = 'in';
|
|
861
|
-
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
862
|
-
}
|
|
863
|
-
return [
|
|
864
|
-
{
|
|
865
|
-
field: filter.field,
|
|
866
|
-
op: mappedOp,
|
|
867
|
-
value
|
|
868
|
-
}
|
|
869
|
-
];
|
|
870
|
-
}
|
|
871
|
-
const buildHaving = (queryDSL, context)=>{
|
|
872
|
-
const { vbiDSL } = context;
|
|
873
|
-
const havingFilter = vbiDSL.havingFilter;
|
|
874
|
-
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
875
|
-
const result = {
|
|
876
|
-
...queryDSL
|
|
877
|
-
};
|
|
878
|
-
result.having = {
|
|
879
|
-
op: havingFilter.op,
|
|
880
|
-
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
881
|
-
};
|
|
882
|
-
return result;
|
|
883
|
-
};
|
|
884
|
-
function buildHaving_isHavingGroup(clause) {
|
|
885
|
-
return 'op' in clause && 'conditions' in clause;
|
|
886
|
-
}
|
|
887
|
-
function buildHaving_mapClauseToCondition(clause) {
|
|
888
|
-
if (buildHaving_isHavingGroup(clause)) return [
|
|
889
|
-
buildHaving_mapGroupToCondition(clause)
|
|
890
|
-
];
|
|
891
|
-
return buildHaving_mapFilterToCondition(clause);
|
|
892
|
-
}
|
|
893
|
-
function buildHaving_mapGroupToCondition(group) {
|
|
894
|
-
return {
|
|
895
|
-
op: group.op,
|
|
896
|
-
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
function buildHaving_mapFilterToCondition(filter) {
|
|
900
|
-
const mappedOp = filter.op ?? '=';
|
|
901
|
-
return [
|
|
902
|
-
{
|
|
903
|
-
field: filter.field,
|
|
904
|
-
op: mappedOp,
|
|
905
|
-
value: filter.value
|
|
906
|
-
}
|
|
907
|
-
];
|
|
908
|
-
}
|
|
909
|
-
const buildLimit = (queryDSL, context)=>{
|
|
910
|
-
const result = {
|
|
911
|
-
...queryDSL
|
|
912
|
-
};
|
|
913
|
-
const limit = context.vbiDSL.limit ?? 1000;
|
|
914
|
-
result.limit = limit;
|
|
915
|
-
return result;
|
|
916
|
-
};
|
|
917
|
-
const buildVQuery = (vbiDSL, builder)=>{
|
|
918
|
-
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
919
|
-
vbiDSL,
|
|
920
|
-
builder
|
|
921
|
-
});
|
|
922
|
-
return pipe({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
923
|
-
};
|
|
924
|
-
const connectorMap = new Map();
|
|
925
|
-
const registerConnector = (id, connector)=>{
|
|
926
|
-
connectorMap.set(id, connector);
|
|
927
|
-
};
|
|
928
|
-
const getConnector = async (id)=>{
|
|
929
|
-
const connector = connectorMap.get(id);
|
|
930
|
-
if (!connector) throw new Error(`connector ${id} not registered`);
|
|
931
|
-
if ('function' == typeof connector) return connector();
|
|
932
|
-
return connector;
|
|
933
|
-
};
|
|
1042
|
+
const createBuilderFeatures = (doc, dsl)=>({
|
|
1043
|
+
undoManager: new undo_manager_UndoManager(dsl),
|
|
1044
|
+
chartType: new ChartTypeBuilder(doc, dsl),
|
|
1045
|
+
measures: new MeasuresBuilder(doc, dsl),
|
|
1046
|
+
dimensions: new DimensionsBuilder(doc, dsl),
|
|
1047
|
+
havingFilter: new HavingFilterBuilder(doc, dsl),
|
|
1048
|
+
whereFilter: new WhereFilterBuilder(doc, dsl),
|
|
1049
|
+
theme: new ThemeBuilder(doc, dsl),
|
|
1050
|
+
locale: new LocaleBuilder(doc, dsl),
|
|
1051
|
+
limit: new LimitBuilder(doc, dsl)
|
|
1052
|
+
});
|
|
934
1053
|
class VBIBuilder {
|
|
935
1054
|
doc;
|
|
936
1055
|
dsl;
|
|
937
|
-
undoManager;
|
|
938
1056
|
chartType;
|
|
939
1057
|
measures;
|
|
940
1058
|
dimensions;
|
|
@@ -943,162 +1061,180 @@ class VBIBuilder {
|
|
|
943
1061
|
theme;
|
|
944
1062
|
locale;
|
|
945
1063
|
limit;
|
|
1064
|
+
undoManager;
|
|
946
1065
|
constructor(doc){
|
|
947
1066
|
this.doc = doc;
|
|
948
1067
|
this.dsl = doc.getMap('dsl');
|
|
949
|
-
|
|
950
|
-
this.
|
|
951
|
-
this.
|
|
952
|
-
this.
|
|
953
|
-
this.
|
|
954
|
-
this.
|
|
955
|
-
this.
|
|
956
|
-
this.
|
|
957
|
-
this.
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
encodeStateAsUpdate(targetStateVector) {
|
|
963
|
-
return encodeStateAsUpdate(this.doc, targetStateVector);
|
|
964
|
-
}
|
|
1068
|
+
const features = createBuilderFeatures(doc, this.dsl);
|
|
1069
|
+
this.undoManager = features.undoManager;
|
|
1070
|
+
this.chartType = features.chartType;
|
|
1071
|
+
this.measures = features.measures;
|
|
1072
|
+
this.dimensions = features.dimensions;
|
|
1073
|
+
this.havingFilter = features.havingFilter;
|
|
1074
|
+
this.whereFilter = features.whereFilter;
|
|
1075
|
+
this.theme = features.theme;
|
|
1076
|
+
this.locale = features.locale;
|
|
1077
|
+
this.limit = features.limit;
|
|
1078
|
+
}
|
|
1079
|
+
applyUpdate = (update, transactionOrigin)=>applyUpdateToDoc(this.doc, update, transactionOrigin);
|
|
1080
|
+
encodeStateAsUpdate = (targetStateVector)=>encodeDocStateAsUpdate(this.doc, targetStateVector);
|
|
965
1081
|
buildVSeed = async ()=>{
|
|
966
1082
|
const vbiDSL = this.build();
|
|
967
|
-
const connectorId = vbiDSL.connectorId;
|
|
968
|
-
const connector = await getConnector(vbiDSL.connectorId);
|
|
969
1083
|
const queryDSL = this.buildVQuery();
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
queryDSL
|
|
973
|
-
schema,
|
|
974
|
-
connectorId
|
|
1084
|
+
return buildVSeedDSL({
|
|
1085
|
+
vbiDSL,
|
|
1086
|
+
queryDSL
|
|
975
1087
|
});
|
|
976
|
-
return {
|
|
977
|
-
chartType: vbiDSL.chartType,
|
|
978
|
-
dataset: queryResult.dataset,
|
|
979
|
-
theme: vbiDSL.theme,
|
|
980
|
-
locale: vbiDSL.locale
|
|
981
|
-
};
|
|
982
|
-
};
|
|
983
|
-
buildVQuery = ()=>{
|
|
984
|
-
const vbiDSL = this.build();
|
|
985
|
-
return buildVQuery(vbiDSL, this);
|
|
986
|
-
};
|
|
987
|
-
build = ()=>this.dsl.toJSON();
|
|
988
|
-
getSchema = async ()=>{
|
|
989
|
-
const connectorId = this.dsl.get('connectorId');
|
|
990
|
-
const con = await getConnector(connectorId);
|
|
991
|
-
const result = await con.discoverSchema();
|
|
992
|
-
return result;
|
|
993
1088
|
};
|
|
1089
|
+
buildVQuery = ()=>buildVQueryDSL(this.dsl, this);
|
|
1090
|
+
build = ()=>buildVBIDSL(this.dsl);
|
|
1091
|
+
isEmpty = ()=>isEmptyVBIDSL(this.dsl);
|
|
1092
|
+
getSchema = async ()=>getBuilderSchema(this.dsl);
|
|
994
1093
|
}
|
|
1094
|
+
const shouldEnsureIdForObject = (obj, ensureId)=>{
|
|
1095
|
+
if (true === ensureId) return true;
|
|
1096
|
+
if ('field' === ensureId) return 'string' == typeof obj.field;
|
|
1097
|
+
return false;
|
|
1098
|
+
};
|
|
1099
|
+
const toYMap = (obj, ensureId = false)=>{
|
|
1100
|
+
const yMap = new external_yjs_Map();
|
|
1101
|
+
if (shouldEnsureIdForObject(obj, ensureId) && !obj.id) yMap.set('id', id_id.uuid());
|
|
1102
|
+
for (const [key, value] of Object.entries(obj)){
|
|
1103
|
+
if (('conditions' === key || 'children' === key) && Array.isArray(value)) {
|
|
1104
|
+
const yArr = new external_yjs_Array();
|
|
1105
|
+
for (const child of value){
|
|
1106
|
+
if (child instanceof external_yjs_Map) {
|
|
1107
|
+
yArr.push([
|
|
1108
|
+
child
|
|
1109
|
+
]);
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
if ('object' == typeof child && null !== child) {
|
|
1113
|
+
yArr.push([
|
|
1114
|
+
toYMap(child, ensureId)
|
|
1115
|
+
]);
|
|
1116
|
+
continue;
|
|
1117
|
+
}
|
|
1118
|
+
yArr.push([
|
|
1119
|
+
child
|
|
1120
|
+
]);
|
|
1121
|
+
}
|
|
1122
|
+
yMap.set(key, yArr);
|
|
1123
|
+
continue;
|
|
1124
|
+
}
|
|
1125
|
+
yMap.set(key, value);
|
|
1126
|
+
}
|
|
1127
|
+
return yMap;
|
|
1128
|
+
};
|
|
1129
|
+
const ensureYArray = (arr, ensureId = false)=>{
|
|
1130
|
+
if (!arr) return new external_yjs_Array();
|
|
1131
|
+
if (arr instanceof external_yjs_Array) return arr;
|
|
1132
|
+
const yArr = new external_yjs_Array();
|
|
1133
|
+
for (const item of arr){
|
|
1134
|
+
if (item instanceof external_yjs_Map) {
|
|
1135
|
+
yArr.push([
|
|
1136
|
+
item
|
|
1137
|
+
]);
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if ('object' == typeof item && null !== item) {
|
|
1141
|
+
yArr.push([
|
|
1142
|
+
toYMap(item, ensureId)
|
|
1143
|
+
]);
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
yArr.push([
|
|
1147
|
+
item
|
|
1148
|
+
]);
|
|
1149
|
+
}
|
|
1150
|
+
return yArr;
|
|
1151
|
+
};
|
|
1152
|
+
const getDefaultWhereFilter = ()=>({
|
|
1153
|
+
id: 'root',
|
|
1154
|
+
op: 'and',
|
|
1155
|
+
conditions: []
|
|
1156
|
+
});
|
|
1157
|
+
const isFilterGroupInput = (value)=>'object' == typeof value && null !== value;
|
|
1158
|
+
const ensureWhereGroup = (whereFilter)=>{
|
|
1159
|
+
const sourceWhereFilter = whereFilter instanceof external_yjs_Map || isFilterGroupInput(whereFilter) ? whereFilter : getDefaultWhereFilter();
|
|
1160
|
+
const whereGroup = sourceWhereFilter instanceof external_yjs_Map ? sourceWhereFilter : createWhereGroup();
|
|
1161
|
+
if (sourceWhereFilter instanceof external_yjs_Map) {
|
|
1162
|
+
if (!(whereGroup.get('conditions') instanceof external_yjs_Array)) whereGroup.set('conditions', new external_yjs_Array());
|
|
1163
|
+
if (!whereGroup.get('id')) whereGroup.set('id', 'root');
|
|
1164
|
+
if (!whereGroup.get('op')) whereGroup.set('op', 'and');
|
|
1165
|
+
return whereGroup;
|
|
1166
|
+
}
|
|
1167
|
+
whereGroup.set('id', sourceWhereFilter.id ?? 'root');
|
|
1168
|
+
whereGroup.set('op', sourceWhereFilter.op ?? 'and');
|
|
1169
|
+
whereGroup.set('conditions', ensureYArray(sourceWhereFilter.conditions, true));
|
|
1170
|
+
return whereGroup;
|
|
1171
|
+
};
|
|
1172
|
+
const getDefaultHavingFilter = ()=>({
|
|
1173
|
+
id: 'root',
|
|
1174
|
+
op: 'and',
|
|
1175
|
+
conditions: []
|
|
1176
|
+
});
|
|
1177
|
+
const ensure_having_group_isFilterGroupInput = (value)=>'object' == typeof value && null !== value;
|
|
1178
|
+
const ensureHavingGroup = (havingFilter)=>{
|
|
1179
|
+
const sourceHavingFilter = havingFilter instanceof external_yjs_Map || ensure_having_group_isFilterGroupInput(havingFilter) ? havingFilter : getDefaultHavingFilter();
|
|
1180
|
+
const havingGroup = sourceHavingFilter instanceof external_yjs_Map ? sourceHavingFilter : createHavingGroup();
|
|
1181
|
+
if (sourceHavingFilter instanceof external_yjs_Map) {
|
|
1182
|
+
if (!(havingGroup.get('conditions') instanceof external_yjs_Array)) havingGroup.set('conditions', new external_yjs_Array());
|
|
1183
|
+
if (!havingGroup.get('id')) havingGroup.set('id', 'root');
|
|
1184
|
+
if (!havingGroup.get('op')) havingGroup.set('op', 'and');
|
|
1185
|
+
return havingGroup;
|
|
1186
|
+
}
|
|
1187
|
+
havingGroup.set('id', sourceHavingFilter.id ?? 'root');
|
|
1188
|
+
havingGroup.set('op', sourceHavingFilter.op ?? 'and');
|
|
1189
|
+
havingGroup.set('conditions', ensureYArray(sourceHavingFilter.conditions, true));
|
|
1190
|
+
return havingGroup;
|
|
1191
|
+
};
|
|
1192
|
+
const setBaseDSLFields = (dsl, vbi)=>{
|
|
1193
|
+
if (vbi.connectorId) dsl.set('connectorId', vbi.connectorId);
|
|
1194
|
+
if (vbi.chartType) dsl.set('chartType', vbi.chartType);
|
|
1195
|
+
if (vbi.theme) dsl.set('theme', vbi.theme);
|
|
1196
|
+
if (vbi.limit) dsl.set('limit', vbi.limit);
|
|
1197
|
+
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
1198
|
+
if (void 0 !== vbi.version) dsl.set('version', vbi.version);
|
|
1199
|
+
};
|
|
1200
|
+
const fromVBIDSLInput = (vbi)=>{
|
|
1201
|
+
const doc = new Doc();
|
|
1202
|
+
const dsl = doc.getMap('dsl');
|
|
1203
|
+
doc.transact(()=>{
|
|
1204
|
+
setBaseDSLFields(dsl, vbi);
|
|
1205
|
+
dsl.set('whereFilter', ensureWhereGroup(vbi.whereFilter));
|
|
1206
|
+
dsl.set('havingFilter', ensureHavingGroup(vbi.havingFilter));
|
|
1207
|
+
dsl.set('measures', ensureYArray(vbi.measures, 'field'));
|
|
1208
|
+
dsl.set('dimensions', ensureYArray(vbi.dimensions, 'field'));
|
|
1209
|
+
});
|
|
1210
|
+
return new VBIBuilder(doc);
|
|
1211
|
+
};
|
|
1212
|
+
const generateEmptyDSL = (connectorId)=>({
|
|
1213
|
+
connectorId,
|
|
1214
|
+
chartType: 'table',
|
|
1215
|
+
measures: [],
|
|
1216
|
+
dimensions: [],
|
|
1217
|
+
whereFilter: {
|
|
1218
|
+
id: 'root',
|
|
1219
|
+
op: 'and',
|
|
1220
|
+
conditions: []
|
|
1221
|
+
},
|
|
1222
|
+
havingFilter: {
|
|
1223
|
+
id: 'root',
|
|
1224
|
+
op: 'and',
|
|
1225
|
+
conditions: []
|
|
1226
|
+
},
|
|
1227
|
+
theme: 'light',
|
|
1228
|
+
locale: 'zh-CN',
|
|
1229
|
+
version: 0
|
|
1230
|
+
});
|
|
995
1231
|
const createVBI = ()=>({
|
|
996
1232
|
connectorMap: connectorMap,
|
|
997
1233
|
registerConnector: registerConnector,
|
|
998
1234
|
getConnector: getConnector,
|
|
999
|
-
generateEmptyDSL:
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
measures: [],
|
|
1003
|
-
dimensions: [],
|
|
1004
|
-
whereFilter: {
|
|
1005
|
-
id: 'root',
|
|
1006
|
-
op: 'and',
|
|
1007
|
-
conditions: []
|
|
1008
|
-
},
|
|
1009
|
-
havingFilter: {
|
|
1010
|
-
id: 'root',
|
|
1011
|
-
op: 'and',
|
|
1012
|
-
conditions: []
|
|
1013
|
-
},
|
|
1014
|
-
theme: 'light',
|
|
1015
|
-
locale: 'zh-CN',
|
|
1016
|
-
version: 0
|
|
1017
|
-
}),
|
|
1018
|
-
from: (vbi)=>{
|
|
1019
|
-
const doc = new Doc();
|
|
1020
|
-
const dsl = doc.getMap('dsl');
|
|
1021
|
-
doc.transact(()=>{
|
|
1022
|
-
if (vbi.connectorId) dsl.set('connectorId', vbi.connectorId);
|
|
1023
|
-
if (vbi.chartType) dsl.set('chartType', vbi.chartType);
|
|
1024
|
-
if (vbi.theme) dsl.set('theme', vbi.theme);
|
|
1025
|
-
if (vbi.limit) dsl.set('limit', vbi.limit);
|
|
1026
|
-
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
1027
|
-
if (void 0 !== vbi.version) dsl.set('version', vbi.version);
|
|
1028
|
-
const toYMap = (obj, ensureId = false)=>{
|
|
1029
|
-
const yMap = new external_yjs_Map();
|
|
1030
|
-
if (ensureId && !obj.id) yMap.set('id', id_id.uuid());
|
|
1031
|
-
for (const [key, value] of Object.entries(obj))if ('conditions' === key && Array.isArray(value)) {
|
|
1032
|
-
const yArr = new external_yjs_Array();
|
|
1033
|
-
value.forEach((child)=>{
|
|
1034
|
-
if (child instanceof external_yjs_Map) yArr.push([
|
|
1035
|
-
child
|
|
1036
|
-
]);
|
|
1037
|
-
else if ('object' == typeof child && null !== child) yArr.push([
|
|
1038
|
-
toYMap(child, true)
|
|
1039
|
-
]);
|
|
1040
|
-
else yArr.push([
|
|
1041
|
-
child
|
|
1042
|
-
]);
|
|
1043
|
-
});
|
|
1044
|
-
yMap.set(key, yArr);
|
|
1045
|
-
} else yMap.set(key, value);
|
|
1046
|
-
return yMap;
|
|
1047
|
-
};
|
|
1048
|
-
const ensureYArray = (arr, ensureId = false)=>{
|
|
1049
|
-
if (!arr) return new external_yjs_Array();
|
|
1050
|
-
if (arr instanceof external_yjs_Array) return arr;
|
|
1051
|
-
const yArr = new external_yjs_Array();
|
|
1052
|
-
arr.forEach((item)=>{
|
|
1053
|
-
if (item instanceof external_yjs_Map) yArr.push([
|
|
1054
|
-
item
|
|
1055
|
-
]);
|
|
1056
|
-
else if ('object' == typeof item && null !== item) yArr.push([
|
|
1057
|
-
toYMap(item, ensureId)
|
|
1058
|
-
]);
|
|
1059
|
-
else yArr.push([
|
|
1060
|
-
item
|
|
1061
|
-
]);
|
|
1062
|
-
});
|
|
1063
|
-
return yArr;
|
|
1064
|
-
};
|
|
1065
|
-
const whereFilter = vbi.whereFilter ?? {
|
|
1066
|
-
id: 'root',
|
|
1067
|
-
op: 'and',
|
|
1068
|
-
conditions: []
|
|
1069
|
-
};
|
|
1070
|
-
const whereGroup = whereFilter instanceof external_yjs_Map ? whereFilter : createWhereGroup();
|
|
1071
|
-
if (whereFilter instanceof external_yjs_Map) {
|
|
1072
|
-
if (!(whereGroup.get('conditions') instanceof external_yjs_Array)) whereGroup.set('conditions', new external_yjs_Array());
|
|
1073
|
-
if (!whereGroup.get('id')) whereGroup.set('id', 'root');
|
|
1074
|
-
if (!whereGroup.get('op')) whereGroup.set('op', 'and');
|
|
1075
|
-
} else {
|
|
1076
|
-
whereGroup.set('id', whereFilter.id ?? 'root');
|
|
1077
|
-
whereGroup.set('op', whereFilter.op ?? 'and');
|
|
1078
|
-
whereGroup.set('conditions', ensureYArray(whereFilter.conditions, true));
|
|
1079
|
-
}
|
|
1080
|
-
dsl.set('whereFilter', whereGroup);
|
|
1081
|
-
const havingFilter = vbi.havingFilter ?? {
|
|
1082
|
-
id: 'root',
|
|
1083
|
-
op: 'and',
|
|
1084
|
-
conditions: []
|
|
1085
|
-
};
|
|
1086
|
-
const havingGroup = havingFilter instanceof external_yjs_Map ? havingFilter : createHavingGroup();
|
|
1087
|
-
if (havingFilter instanceof external_yjs_Map) {
|
|
1088
|
-
if (!(havingGroup.get('conditions') instanceof external_yjs_Array)) havingGroup.set('conditions', new external_yjs_Array());
|
|
1089
|
-
if (!havingGroup.get('id')) havingGroup.set('id', 'root');
|
|
1090
|
-
if (!havingGroup.get('op')) havingGroup.set('op', 'and');
|
|
1091
|
-
} else {
|
|
1092
|
-
havingGroup.set('id', havingFilter.id ?? 'root');
|
|
1093
|
-
havingGroup.set('op', havingFilter.op ?? 'and');
|
|
1094
|
-
havingGroup.set('conditions', ensureYArray(havingFilter.conditions, true));
|
|
1095
|
-
}
|
|
1096
|
-
dsl.set('havingFilter', havingGroup);
|
|
1097
|
-
dsl.set('measures', ensureYArray(vbi.measures));
|
|
1098
|
-
dsl.set('dimensions', ensureYArray(vbi.dimensions));
|
|
1099
|
-
});
|
|
1100
|
-
return new VBIBuilder(doc);
|
|
1101
|
-
}
|
|
1235
|
+
generateEmptyDSL: generateEmptyDSL,
|
|
1236
|
+
from: fromVBIDSLInput,
|
|
1237
|
+
create: fromVBIDSLInput
|
|
1102
1238
|
});
|
|
1103
1239
|
const VBI = createVBI();
|
|
1104
1240
|
export { ChartTypeBuilder, DimensionsBuilder, HavingFilterBuilder, LimitBuilder, LocaleBuilder, MeasuresBuilder, ThemeBuilder, undo_manager_UndoManager as UndoManager, VBI, VBIBuilder, WhereFilterBuilder, buildVQuery, findTreeNodesBy, id_id as id, isVBIFilter, isVBIHavingFilter, isVBIHavingGroup, isVBIWhereGroup, preorderTraverse };
|