@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.cjs
CHANGED
|
@@ -44,12 +44,248 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
44
44
|
LocaleBuilder: ()=>LocaleBuilder,
|
|
45
45
|
UndoManager: ()=>UndoManager
|
|
46
46
|
});
|
|
47
|
+
const connectorMap = new Map();
|
|
48
|
+
const registerConnector = (id, connector)=>{
|
|
49
|
+
connectorMap.set(id, connector);
|
|
50
|
+
};
|
|
51
|
+
const getConnector = async (id)=>{
|
|
52
|
+
const connector = connectorMap.get(id);
|
|
53
|
+
if (!connector) throw new Error(`connector ${id} not registered`);
|
|
54
|
+
if ('function' == typeof connector) return connector();
|
|
55
|
+
return connector;
|
|
56
|
+
};
|
|
47
57
|
const external_yjs_namespaceObject = require("yjs");
|
|
58
|
+
const applyUpdateToDoc = (doc, update, transactionOrigin)=>{
|
|
59
|
+
external_yjs_namespaceObject.applyUpdate(doc, update, transactionOrigin);
|
|
60
|
+
};
|
|
61
|
+
const encodeDocStateAsUpdate = (doc, targetStateVector)=>external_yjs_namespaceObject.encodeStateAsUpdate(doc, targetStateVector);
|
|
62
|
+
const buildVBIDSL = (dsl)=>dsl.toJSON();
|
|
63
|
+
const external_remeda_namespaceObject = require("remeda");
|
|
64
|
+
const buildSelect = (queryDSL, context)=>{
|
|
65
|
+
const { vbiDSL } = context;
|
|
66
|
+
const measures = vbiDSL.measures;
|
|
67
|
+
const dimensions = vbiDSL.dimensions;
|
|
68
|
+
const result = {
|
|
69
|
+
...queryDSL
|
|
70
|
+
};
|
|
71
|
+
const measureNodes = measures.filter((measure)=>MeasuresBuilder.isMeasureNode(measure));
|
|
72
|
+
const measureSelects = measureNodes.map((measure)=>({
|
|
73
|
+
field: measure.field,
|
|
74
|
+
alias: measure.alias,
|
|
75
|
+
aggr: measure.aggregate
|
|
76
|
+
}));
|
|
77
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
78
|
+
const dimensionSelects = dimensionNodes.map((dimension)=>({
|
|
79
|
+
field: dimension.field,
|
|
80
|
+
alias: dimension.alias
|
|
81
|
+
}));
|
|
82
|
+
result.select = measureSelects.concat(dimensionSelects);
|
|
83
|
+
return result;
|
|
84
|
+
};
|
|
85
|
+
const buildGroupBy = (queryDSL, context)=>{
|
|
86
|
+
const result = {
|
|
87
|
+
...queryDSL
|
|
88
|
+
};
|
|
89
|
+
const { vbiDSL } = context;
|
|
90
|
+
const dimensions = vbiDSL.dimensions;
|
|
91
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
92
|
+
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
const buildWhere = (queryDSL, context)=>{
|
|
96
|
+
const { vbiDSL } = context;
|
|
97
|
+
const whereFilter = vbiDSL.whereFilter;
|
|
98
|
+
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
99
|
+
const result = {
|
|
100
|
+
...queryDSL
|
|
101
|
+
};
|
|
102
|
+
result.where = mapGroupToCondition(whereFilter);
|
|
103
|
+
return result;
|
|
104
|
+
};
|
|
105
|
+
function isWhereGroup(clause) {
|
|
106
|
+
return 'op' in clause && 'conditions' in clause;
|
|
107
|
+
}
|
|
108
|
+
function mapClauseToCondition(clause) {
|
|
109
|
+
if (isWhereGroup(clause)) return [
|
|
110
|
+
mapGroupToCondition(clause)
|
|
111
|
+
];
|
|
112
|
+
return mapFilterToCondition(clause);
|
|
113
|
+
}
|
|
114
|
+
function mapGroupToCondition(group) {
|
|
115
|
+
return {
|
|
116
|
+
op: group.op,
|
|
117
|
+
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function mapFilterToCondition(filter) {
|
|
121
|
+
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
122
|
+
return handleSimpleFilter(filter);
|
|
123
|
+
}
|
|
124
|
+
function handleBetweenFilter(filter) {
|
|
125
|
+
const value = normalizeBetweenValue(filter.value);
|
|
126
|
+
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
127
|
+
field: filter.field,
|
|
128
|
+
op: '<' === value.leftOp ? '>' : '>=',
|
|
129
|
+
value: value.min
|
|
130
|
+
} : void 0;
|
|
131
|
+
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
132
|
+
field: filter.field,
|
|
133
|
+
op: '<' === value.rightOp ? '<' : '<=',
|
|
134
|
+
value: value.max
|
|
135
|
+
} : void 0;
|
|
136
|
+
if ('not between' === filter.op) {
|
|
137
|
+
const outsideConditions = [
|
|
138
|
+
lowerCondition && invertLowerBound(lowerCondition),
|
|
139
|
+
upperCondition && invertUpperBound(upperCondition)
|
|
140
|
+
].filter(Boolean);
|
|
141
|
+
if (outsideConditions.length <= 1) return outsideConditions;
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
op: 'or',
|
|
145
|
+
conditions: outsideConditions
|
|
146
|
+
}
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
return [
|
|
150
|
+
lowerCondition,
|
|
151
|
+
upperCondition
|
|
152
|
+
].filter(Boolean);
|
|
153
|
+
}
|
|
154
|
+
function normalizeBetweenValue(value) {
|
|
155
|
+
if (Array.isArray(value)) return {
|
|
156
|
+
min: value[0],
|
|
157
|
+
max: value[1],
|
|
158
|
+
leftOp: '<=',
|
|
159
|
+
rightOp: '<='
|
|
160
|
+
};
|
|
161
|
+
if ('object' == typeof value && null !== value) return value;
|
|
162
|
+
return {};
|
|
163
|
+
}
|
|
164
|
+
function invertLowerBound(condition) {
|
|
165
|
+
return {
|
|
166
|
+
field: condition.field,
|
|
167
|
+
op: '>' === condition.op ? '<=' : '<',
|
|
168
|
+
value: condition.value
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function invertUpperBound(condition) {
|
|
172
|
+
return {
|
|
173
|
+
field: condition.field,
|
|
174
|
+
op: '<' === condition.op ? '>=' : '>',
|
|
175
|
+
value: condition.value
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function handleSimpleFilter(filter) {
|
|
179
|
+
let mappedOp = filter.op ?? '=';
|
|
180
|
+
const value = filter.value;
|
|
181
|
+
if (Array.isArray(value)) {
|
|
182
|
+
if ('=' === mappedOp) mappedOp = 'in';
|
|
183
|
+
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
184
|
+
}
|
|
185
|
+
return [
|
|
186
|
+
{
|
|
187
|
+
field: filter.field,
|
|
188
|
+
op: mappedOp,
|
|
189
|
+
value
|
|
190
|
+
}
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
const buildHaving = (queryDSL, context)=>{
|
|
194
|
+
const { vbiDSL } = context;
|
|
195
|
+
const havingFilter = vbiDSL.havingFilter;
|
|
196
|
+
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
197
|
+
const result = {
|
|
198
|
+
...queryDSL
|
|
199
|
+
};
|
|
200
|
+
result.having = {
|
|
201
|
+
op: havingFilter.op,
|
|
202
|
+
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
203
|
+
};
|
|
204
|
+
return result;
|
|
205
|
+
};
|
|
206
|
+
function isHavingGroup(clause) {
|
|
207
|
+
return 'op' in clause && 'conditions' in clause;
|
|
208
|
+
}
|
|
209
|
+
function buildHaving_mapClauseToCondition(clause) {
|
|
210
|
+
if (isHavingGroup(clause)) return [
|
|
211
|
+
buildHaving_mapGroupToCondition(clause)
|
|
212
|
+
];
|
|
213
|
+
return buildHaving_mapFilterToCondition(clause);
|
|
214
|
+
}
|
|
215
|
+
function buildHaving_mapGroupToCondition(group) {
|
|
216
|
+
return {
|
|
217
|
+
op: group.op,
|
|
218
|
+
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function buildHaving_mapFilterToCondition(filter) {
|
|
222
|
+
const mappedOp = filter.op ?? '=';
|
|
223
|
+
return [
|
|
224
|
+
{
|
|
225
|
+
field: filter.field,
|
|
226
|
+
op: mappedOp,
|
|
227
|
+
value: filter.value
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
const buildLimit = (queryDSL, context)=>{
|
|
232
|
+
const result = {
|
|
233
|
+
...queryDSL
|
|
234
|
+
};
|
|
235
|
+
const limit = context.vbiDSL.limit ?? 1000;
|
|
236
|
+
result.limit = limit;
|
|
237
|
+
return result;
|
|
238
|
+
};
|
|
239
|
+
const buildVQuery = (vbiDSL, builder)=>{
|
|
240
|
+
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
241
|
+
vbiDSL,
|
|
242
|
+
builder
|
|
243
|
+
});
|
|
244
|
+
return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
245
|
+
};
|
|
246
|
+
const buildVQueryDSL = (dsl, builder)=>{
|
|
247
|
+
const vbiDSL = buildVBIDSL(dsl);
|
|
248
|
+
return buildVQuery(vbiDSL, builder);
|
|
249
|
+
};
|
|
250
|
+
const buildVSeedDSL = async ({ vbiDSL, queryDSL })=>{
|
|
251
|
+
const connectorId = vbiDSL.connectorId;
|
|
252
|
+
const connector = await getConnector(connectorId);
|
|
253
|
+
const schema = await connector.discoverSchema();
|
|
254
|
+
const queryResult = await connector.query({
|
|
255
|
+
queryDSL,
|
|
256
|
+
schema,
|
|
257
|
+
connectorId
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
chartType: vbiDSL.chartType,
|
|
261
|
+
dataset: queryResult.dataset,
|
|
262
|
+
theme: vbiDSL.theme,
|
|
263
|
+
locale: vbiDSL.locale
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
const getCollectionLength = (value)=>{
|
|
267
|
+
if (value instanceof external_yjs_namespaceObject.Array) return value.length;
|
|
268
|
+
if (Array.isArray(value)) return value.length;
|
|
269
|
+
return 0;
|
|
270
|
+
};
|
|
271
|
+
const isEmptyVBIDSL = (dsl)=>{
|
|
272
|
+
const dimensionsLength = getCollectionLength(dsl.get('dimensions'));
|
|
273
|
+
const measuresLength = getCollectionLength(dsl.get('measures'));
|
|
274
|
+
return 0 === dimensionsLength && 0 === measuresLength;
|
|
275
|
+
};
|
|
276
|
+
const getBuilderSchema = async (dsl)=>{
|
|
277
|
+
const connectorId = dsl.get('connectorId');
|
|
278
|
+
const connector = await getConnector(connectorId);
|
|
279
|
+
return connector.discoverSchema();
|
|
280
|
+
};
|
|
48
281
|
class MeasureNodeBuilder {
|
|
49
282
|
yMap;
|
|
50
283
|
constructor(yMap){
|
|
51
284
|
this.yMap = yMap;
|
|
52
285
|
}
|
|
286
|
+
getId() {
|
|
287
|
+
return this.yMap.get('id');
|
|
288
|
+
}
|
|
53
289
|
getField() {
|
|
54
290
|
return this.yMap.get('field');
|
|
55
291
|
}
|
|
@@ -69,13 +305,48 @@ class MeasureNodeBuilder {
|
|
|
69
305
|
return this.yMap.toJSON();
|
|
70
306
|
}
|
|
71
307
|
}
|
|
308
|
+
const vseed_namespaceObject = require("@visactor/vseed");
|
|
309
|
+
const external_uuid_namespaceObject = require("uuid");
|
|
310
|
+
const id_id = {
|
|
311
|
+
uuid: ()=>(0, external_uuid_namespaceObject.v4)()
|
|
312
|
+
};
|
|
313
|
+
function isVBIFilter(clause) {
|
|
314
|
+
return 'field' in clause;
|
|
315
|
+
}
|
|
316
|
+
function isVBIWhereGroup(clause) {
|
|
317
|
+
return 'conditions' in clause;
|
|
318
|
+
}
|
|
319
|
+
function isVBIHavingFilter(clause) {
|
|
320
|
+
return 'field' in clause;
|
|
321
|
+
}
|
|
322
|
+
function isVBIHavingGroup(clause) {
|
|
323
|
+
return 'conditions' in clause;
|
|
324
|
+
}
|
|
325
|
+
const getOrCreateMeasures = (dsl)=>{
|
|
326
|
+
const measures = dsl.get('measures');
|
|
327
|
+
if (measures instanceof external_yjs_namespaceObject.Array) return measures;
|
|
328
|
+
const yMeasures = new external_yjs_namespaceObject.Array();
|
|
329
|
+
dsl.set('measures', yMeasures);
|
|
330
|
+
return yMeasures;
|
|
331
|
+
};
|
|
332
|
+
const normalizeMeasureNodeIds = (measures)=>{
|
|
333
|
+
measures.toArray().forEach((item)=>{
|
|
334
|
+
if (item instanceof external_yjs_namespaceObject.Map && 'string' == typeof item.get('field') && !item.get('id')) item.set('id', id_id.uuid());
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
const locateMeasureIndexById = (measures, measureId)=>measures.toArray().findIndex((item)=>item.get('id') === measureId);
|
|
72
338
|
class MeasuresBuilder {
|
|
73
339
|
dsl;
|
|
74
|
-
constructor(
|
|
340
|
+
constructor(doc, dsl){
|
|
75
341
|
this.dsl = dsl;
|
|
342
|
+
doc.transact(()=>{
|
|
343
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
344
|
+
normalizeMeasureNodeIds(measures);
|
|
345
|
+
});
|
|
76
346
|
}
|
|
77
347
|
add(field, callback) {
|
|
78
348
|
const measure = {
|
|
349
|
+
id: id_id.uuid(),
|
|
79
350
|
alias: field,
|
|
80
351
|
field,
|
|
81
352
|
encoding: 'yAxis',
|
|
@@ -85,45 +356,50 @@ class MeasuresBuilder {
|
|
|
85
356
|
};
|
|
86
357
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
87
358
|
for (const [key, value] of Object.entries(measure))yMap.set(key, value);
|
|
88
|
-
this.dsl
|
|
359
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
360
|
+
measures.push([
|
|
89
361
|
yMap
|
|
90
362
|
]);
|
|
91
363
|
const node = new MeasureNodeBuilder(yMap);
|
|
92
364
|
callback(node);
|
|
93
365
|
return this;
|
|
94
366
|
}
|
|
95
|
-
remove(
|
|
96
|
-
const measures = this.dsl
|
|
97
|
-
const index = measures
|
|
98
|
-
if (-1 !== index)
|
|
367
|
+
remove(id) {
|
|
368
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
369
|
+
const index = locateMeasureIndexById(measures, id);
|
|
370
|
+
if (-1 !== index) measures.delete(index, 1);
|
|
99
371
|
return this;
|
|
100
372
|
}
|
|
101
|
-
update(
|
|
102
|
-
const measures = this.dsl
|
|
103
|
-
const index = measures
|
|
104
|
-
if (-1 === index) throw new Error(`Measure with
|
|
373
|
+
update(id, callback) {
|
|
374
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
375
|
+
const index = locateMeasureIndexById(measures, id);
|
|
376
|
+
if (-1 === index) throw new Error(`Measure with id "${id}" not found`);
|
|
105
377
|
const measureYMap = measures.get(index);
|
|
106
378
|
const node = new MeasureNodeBuilder(measureYMap);
|
|
107
379
|
callback(node);
|
|
108
380
|
return this;
|
|
109
381
|
}
|
|
110
|
-
find(
|
|
111
|
-
const measures = this.dsl
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
382
|
+
find(predicate) {
|
|
383
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
384
|
+
const items = measures.toArray();
|
|
385
|
+
for(let index = 0; index < items.length; index++){
|
|
386
|
+
const node = new MeasureNodeBuilder(items[index]);
|
|
387
|
+
if (predicate(node, index)) return node;
|
|
388
|
+
}
|
|
115
389
|
}
|
|
116
390
|
findAll() {
|
|
117
|
-
const measures = this.dsl
|
|
391
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
118
392
|
return measures.toArray().map((yMap)=>new MeasureNodeBuilder(yMap));
|
|
119
393
|
}
|
|
120
394
|
toJSON() {
|
|
121
|
-
|
|
395
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
396
|
+
return measures.toJSON();
|
|
122
397
|
}
|
|
123
398
|
observe(callback) {
|
|
124
|
-
this.dsl
|
|
399
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
400
|
+
measures.observe(callback);
|
|
125
401
|
return ()=>{
|
|
126
|
-
|
|
402
|
+
measures.unobserve(callback);
|
|
127
403
|
};
|
|
128
404
|
}
|
|
129
405
|
static isMeasureNode(node) {
|
|
@@ -138,6 +414,9 @@ class DimensionNodeBuilder {
|
|
|
138
414
|
constructor(yMap){
|
|
139
415
|
this.yMap = yMap;
|
|
140
416
|
}
|
|
417
|
+
getId() {
|
|
418
|
+
return this.yMap.get('id');
|
|
419
|
+
}
|
|
141
420
|
getField() {
|
|
142
421
|
return this.yMap.get('field');
|
|
143
422
|
}
|
|
@@ -149,57 +428,80 @@ class DimensionNodeBuilder {
|
|
|
149
428
|
return this.yMap.toJSON();
|
|
150
429
|
}
|
|
151
430
|
}
|
|
431
|
+
const getOrCreateDimensions = (dsl)=>{
|
|
432
|
+
const dimensions = dsl.get('dimensions');
|
|
433
|
+
if (dimensions instanceof external_yjs_namespaceObject.Array) return dimensions;
|
|
434
|
+
const yDimensions = new external_yjs_namespaceObject.Array();
|
|
435
|
+
dsl.set('dimensions', yDimensions);
|
|
436
|
+
return yDimensions;
|
|
437
|
+
};
|
|
438
|
+
const normalizeDimensionNodeIds = (dimensions)=>{
|
|
439
|
+
dimensions.toArray().forEach((item)=>{
|
|
440
|
+
if (item instanceof external_yjs_namespaceObject.Map && 'string' == typeof item.get('field') && !item.get('id')) item.set('id', id_id.uuid());
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
const locateDimensionIndexById = (dimensions, dimensionId)=>dimensions.toArray().findIndex((item)=>item.get('id') === dimensionId);
|
|
152
444
|
class DimensionsBuilder {
|
|
153
445
|
dsl;
|
|
154
|
-
constructor(
|
|
446
|
+
constructor(doc, dsl){
|
|
155
447
|
this.dsl = dsl;
|
|
448
|
+
doc.transact(()=>{
|
|
449
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
450
|
+
normalizeDimensionNodeIds(dimensions);
|
|
451
|
+
});
|
|
156
452
|
}
|
|
157
453
|
add(field, callback) {
|
|
158
454
|
const dimension = {
|
|
455
|
+
id: id_id.uuid(),
|
|
159
456
|
alias: field,
|
|
160
457
|
field
|
|
161
458
|
};
|
|
162
459
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
163
460
|
for (const [key, value] of Object.entries(dimension))yMap.set(key, value);
|
|
164
|
-
this.dsl
|
|
461
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
462
|
+
dimensions.push([
|
|
165
463
|
yMap
|
|
166
464
|
]);
|
|
167
465
|
const node = new DimensionNodeBuilder(yMap);
|
|
168
466
|
callback(node);
|
|
169
467
|
return this;
|
|
170
468
|
}
|
|
171
|
-
remove(
|
|
172
|
-
const dimensions = this.dsl
|
|
173
|
-
const index = dimensions
|
|
174
|
-
if (-1 !== index)
|
|
469
|
+
remove(id) {
|
|
470
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
471
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
472
|
+
if (-1 !== index) dimensions.delete(index, 1);
|
|
175
473
|
return this;
|
|
176
474
|
}
|
|
177
|
-
update(
|
|
178
|
-
const dimensions = this.dsl
|
|
179
|
-
const index = dimensions
|
|
180
|
-
if (-1 === index) throw new Error(`Dimension with
|
|
475
|
+
update(id, callback) {
|
|
476
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
477
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
478
|
+
if (-1 === index) throw new Error(`Dimension with id "${id}" not found`);
|
|
181
479
|
const dimensionYMap = dimensions.get(index);
|
|
182
480
|
const node = new DimensionNodeBuilder(dimensionYMap);
|
|
183
481
|
callback(node);
|
|
184
482
|
return this;
|
|
185
483
|
}
|
|
186
|
-
find(
|
|
187
|
-
const dimensions = this.dsl
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
484
|
+
find(predicate) {
|
|
485
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
486
|
+
const items = dimensions.toArray();
|
|
487
|
+
for(let index = 0; index < items.length; index++){
|
|
488
|
+
const node = new DimensionNodeBuilder(items[index]);
|
|
489
|
+
if (predicate(node, index)) return node;
|
|
490
|
+
}
|
|
191
491
|
}
|
|
192
492
|
findAll() {
|
|
193
|
-
const dimensions = this.dsl
|
|
493
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
194
494
|
return dimensions.toArray().map((yMap)=>new DimensionNodeBuilder(yMap));
|
|
195
495
|
}
|
|
196
496
|
toJSON() {
|
|
197
|
-
|
|
497
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
498
|
+
return dimensions.toJSON();
|
|
198
499
|
}
|
|
199
500
|
observe(callback) {
|
|
200
|
-
this.dsl
|
|
501
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
502
|
+
dimensions.observe(callback);
|
|
201
503
|
return ()=>{
|
|
202
|
-
|
|
504
|
+
dimensions.unobserve(callback);
|
|
203
505
|
};
|
|
204
506
|
}
|
|
205
507
|
static isDimensionNode(node) {
|
|
@@ -209,7 +511,6 @@ class DimensionsBuilder {
|
|
|
209
511
|
return 'children' in node;
|
|
210
512
|
}
|
|
211
513
|
}
|
|
212
|
-
const vseed_namespaceObject = require("@visactor/vseed");
|
|
213
514
|
class ChartTypeBuilder {
|
|
214
515
|
dsl;
|
|
215
516
|
constructor(_doc, dsl){
|
|
@@ -259,22 +560,6 @@ class ChartTypeBuilder {
|
|
|
259
560
|
];
|
|
260
561
|
}
|
|
261
562
|
}
|
|
262
|
-
const external_uuid_namespaceObject = require("uuid");
|
|
263
|
-
const id_id = {
|
|
264
|
-
uuid: ()=>(0, external_uuid_namespaceObject.v4)()
|
|
265
|
-
};
|
|
266
|
-
function isVBIFilter(clause) {
|
|
267
|
-
return 'field' in clause;
|
|
268
|
-
}
|
|
269
|
-
function isVBIWhereGroup(clause) {
|
|
270
|
-
return 'conditions' in clause;
|
|
271
|
-
}
|
|
272
|
-
function isVBIHavingFilter(clause) {
|
|
273
|
-
return 'field' in clause;
|
|
274
|
-
}
|
|
275
|
-
function isVBIHavingGroup(clause) {
|
|
276
|
-
return 'conditions' in clause;
|
|
277
|
-
}
|
|
278
563
|
function createWhereGroup(op = 'and', groupId = 'root') {
|
|
279
564
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
280
565
|
yMap.set('id', groupId);
|
|
@@ -282,7 +567,7 @@ function createWhereGroup(op = 'and', groupId = 'root') {
|
|
|
282
567
|
yMap.set('conditions', new external_yjs_namespaceObject.Array());
|
|
283
568
|
return yMap;
|
|
284
569
|
}
|
|
285
|
-
function
|
|
570
|
+
function where_utils_isWhereGroup(yMap) {
|
|
286
571
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
287
572
|
}
|
|
288
573
|
function findEntry(collection, entryId) {
|
|
@@ -294,7 +579,7 @@ function findEntry(collection, entryId) {
|
|
|
294
579
|
index,
|
|
295
580
|
item
|
|
296
581
|
};
|
|
297
|
-
if (
|
|
582
|
+
if (where_utils_isWhereGroup(item)) {
|
|
298
583
|
const nestedCollection = item.get('conditions');
|
|
299
584
|
const nestedMatch = findEntry(nestedCollection, entryId);
|
|
300
585
|
if (nestedMatch) return nestedMatch;
|
|
@@ -456,13 +741,21 @@ class WhereFilterBuilder {
|
|
|
456
741
|
}
|
|
457
742
|
return this;
|
|
458
743
|
}
|
|
459
|
-
find(
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
744
|
+
find(predicate) {
|
|
745
|
+
const traverse = (collection)=>{
|
|
746
|
+
const items = collection.toArray();
|
|
747
|
+
for(let index = 0; index < items.length; index++){
|
|
748
|
+
const yMap = items[index];
|
|
749
|
+
const entry = WhereFilterBuilder.isGroup(yMap) ? new WhereGroupBuilder(yMap) : new WhereFilterNodeBuilder(yMap);
|
|
750
|
+
if (predicate(entry, index)) return entry;
|
|
751
|
+
if (WhereFilterBuilder.isGroup(yMap)) {
|
|
752
|
+
const nestedCollection = yMap.get('conditions');
|
|
753
|
+
const nestedMatch = traverse(nestedCollection);
|
|
754
|
+
if (nestedMatch) return nestedMatch;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
return traverse(this.getConditions());
|
|
466
759
|
}
|
|
467
760
|
clear() {
|
|
468
761
|
const conditions = this.getConditions();
|
|
@@ -479,7 +772,7 @@ class WhereFilterBuilder {
|
|
|
479
772
|
};
|
|
480
773
|
}
|
|
481
774
|
static isGroup(yMap) {
|
|
482
|
-
return
|
|
775
|
+
return where_utils_isWhereGroup(yMap);
|
|
483
776
|
}
|
|
484
777
|
static isNode(yMap) {
|
|
485
778
|
return void 0 !== yMap.get('field');
|
|
@@ -492,7 +785,7 @@ function createHavingGroup(op = 'and', groupId = 'root') {
|
|
|
492
785
|
yMap.set('conditions', new external_yjs_namespaceObject.Array());
|
|
493
786
|
return yMap;
|
|
494
787
|
}
|
|
495
|
-
function
|
|
788
|
+
function having_utils_isHavingGroup(yMap) {
|
|
496
789
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
497
790
|
}
|
|
498
791
|
function having_utils_findEntry(collection, entryId) {
|
|
@@ -504,7 +797,7 @@ function having_utils_findEntry(collection, entryId) {
|
|
|
504
797
|
index,
|
|
505
798
|
item
|
|
506
799
|
};
|
|
507
|
-
if (
|
|
800
|
+
if (having_utils_isHavingGroup(item)) {
|
|
508
801
|
const nestedCollection = item.get('conditions');
|
|
509
802
|
const nestedMatch = having_utils_findEntry(nestedCollection, entryId);
|
|
510
803
|
if (nestedMatch) return nestedMatch;
|
|
@@ -662,13 +955,21 @@ class HavingFilterBuilder {
|
|
|
662
955
|
}
|
|
663
956
|
return this;
|
|
664
957
|
}
|
|
665
|
-
find(
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
958
|
+
find(predicate) {
|
|
959
|
+
const traverse = (collection)=>{
|
|
960
|
+
const items = collection.toArray();
|
|
961
|
+
for(let index = 0; index < items.length; index++){
|
|
962
|
+
const yMap = items[index];
|
|
963
|
+
const entry = HavingFilterBuilder.isGroup(yMap) ? new HavingGroupBuilder(yMap) : new HavingFilterNodeBuilder(yMap);
|
|
964
|
+
if (predicate(entry, index)) return entry;
|
|
965
|
+
if (HavingFilterBuilder.isGroup(yMap)) {
|
|
966
|
+
const nestedCollection = yMap.get('conditions');
|
|
967
|
+
const nestedMatch = traverse(nestedCollection);
|
|
968
|
+
if (nestedMatch) return nestedMatch;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
return traverse(this.getConditions());
|
|
672
973
|
}
|
|
673
974
|
clear() {
|
|
674
975
|
const conditions = this.getConditions();
|
|
@@ -685,7 +986,7 @@ class HavingFilterBuilder {
|
|
|
685
986
|
};
|
|
686
987
|
}
|
|
687
988
|
static isGroup(yMap) {
|
|
688
|
-
return
|
|
989
|
+
return having_utils_isHavingGroup(yMap);
|
|
689
990
|
}
|
|
690
991
|
static isNode(yMap) {
|
|
691
992
|
return void 0 !== yMap.get('field');
|
|
@@ -784,203 +1085,20 @@ class UndoManager {
|
|
|
784
1085
|
this.manager.clear(clearUndoStack, clearRedoStack);
|
|
785
1086
|
}
|
|
786
1087
|
}
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
alias: measure.alias,
|
|
799
|
-
aggr: measure.aggregate
|
|
800
|
-
}));
|
|
801
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
802
|
-
const dimensionSelects = dimensionNodes.map((dimension)=>({
|
|
803
|
-
field: dimension.field,
|
|
804
|
-
alias: dimension.alias
|
|
805
|
-
}));
|
|
806
|
-
result.select = measureSelects.concat(dimensionSelects);
|
|
807
|
-
return result;
|
|
808
|
-
};
|
|
809
|
-
const buildGroupBy = (queryDSL, context)=>{
|
|
810
|
-
const result = {
|
|
811
|
-
...queryDSL
|
|
812
|
-
};
|
|
813
|
-
const { vbiDSL } = context;
|
|
814
|
-
const dimensions = vbiDSL.dimensions;
|
|
815
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
816
|
-
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
817
|
-
return result;
|
|
818
|
-
};
|
|
819
|
-
const buildWhere = (queryDSL, context)=>{
|
|
820
|
-
const { vbiDSL } = context;
|
|
821
|
-
const whereFilter = vbiDSL.whereFilter;
|
|
822
|
-
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
823
|
-
const result = {
|
|
824
|
-
...queryDSL
|
|
825
|
-
};
|
|
826
|
-
result.where = mapGroupToCondition(whereFilter);
|
|
827
|
-
return result;
|
|
828
|
-
};
|
|
829
|
-
function buildWhere_isWhereGroup(clause) {
|
|
830
|
-
return 'op' in clause && 'conditions' in clause;
|
|
831
|
-
}
|
|
832
|
-
function mapClauseToCondition(clause) {
|
|
833
|
-
if (buildWhere_isWhereGroup(clause)) return [
|
|
834
|
-
mapGroupToCondition(clause)
|
|
835
|
-
];
|
|
836
|
-
return mapFilterToCondition(clause);
|
|
837
|
-
}
|
|
838
|
-
function mapGroupToCondition(group) {
|
|
839
|
-
return {
|
|
840
|
-
op: group.op,
|
|
841
|
-
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
function mapFilterToCondition(filter) {
|
|
845
|
-
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
846
|
-
return handleSimpleFilter(filter);
|
|
847
|
-
}
|
|
848
|
-
function handleBetweenFilter(filter) {
|
|
849
|
-
const value = normalizeBetweenValue(filter.value);
|
|
850
|
-
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
851
|
-
field: filter.field,
|
|
852
|
-
op: '<' === value.leftOp ? '>' : '>=',
|
|
853
|
-
value: value.min
|
|
854
|
-
} : void 0;
|
|
855
|
-
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
856
|
-
field: filter.field,
|
|
857
|
-
op: '<' === value.rightOp ? '<' : '<=',
|
|
858
|
-
value: value.max
|
|
859
|
-
} : void 0;
|
|
860
|
-
if ('not between' === filter.op) {
|
|
861
|
-
const outsideConditions = [
|
|
862
|
-
lowerCondition && invertLowerBound(lowerCondition),
|
|
863
|
-
upperCondition && invertUpperBound(upperCondition)
|
|
864
|
-
].filter(Boolean);
|
|
865
|
-
if (outsideConditions.length <= 1) return outsideConditions;
|
|
866
|
-
return [
|
|
867
|
-
{
|
|
868
|
-
op: 'or',
|
|
869
|
-
conditions: outsideConditions
|
|
870
|
-
}
|
|
871
|
-
];
|
|
872
|
-
}
|
|
873
|
-
return [
|
|
874
|
-
lowerCondition,
|
|
875
|
-
upperCondition
|
|
876
|
-
].filter(Boolean);
|
|
877
|
-
}
|
|
878
|
-
function normalizeBetweenValue(value) {
|
|
879
|
-
if (Array.isArray(value)) return {
|
|
880
|
-
min: value[0],
|
|
881
|
-
max: value[1],
|
|
882
|
-
leftOp: '<=',
|
|
883
|
-
rightOp: '<='
|
|
884
|
-
};
|
|
885
|
-
if ('object' == typeof value && null !== value) return value;
|
|
886
|
-
return {};
|
|
887
|
-
}
|
|
888
|
-
function invertLowerBound(condition) {
|
|
889
|
-
return {
|
|
890
|
-
field: condition.field,
|
|
891
|
-
op: '>' === condition.op ? '<=' : '<',
|
|
892
|
-
value: condition.value
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
function invertUpperBound(condition) {
|
|
896
|
-
return {
|
|
897
|
-
field: condition.field,
|
|
898
|
-
op: '<' === condition.op ? '>=' : '>',
|
|
899
|
-
value: condition.value
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
function handleSimpleFilter(filter) {
|
|
903
|
-
let mappedOp = filter.op ?? '=';
|
|
904
|
-
const value = filter.value;
|
|
905
|
-
if (Array.isArray(value)) {
|
|
906
|
-
if ('=' === mappedOp) mappedOp = 'in';
|
|
907
|
-
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
908
|
-
}
|
|
909
|
-
return [
|
|
910
|
-
{
|
|
911
|
-
field: filter.field,
|
|
912
|
-
op: mappedOp,
|
|
913
|
-
value
|
|
914
|
-
}
|
|
915
|
-
];
|
|
916
|
-
}
|
|
917
|
-
const buildHaving = (queryDSL, context)=>{
|
|
918
|
-
const { vbiDSL } = context;
|
|
919
|
-
const havingFilter = vbiDSL.havingFilter;
|
|
920
|
-
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
921
|
-
const result = {
|
|
922
|
-
...queryDSL
|
|
923
|
-
};
|
|
924
|
-
result.having = {
|
|
925
|
-
op: havingFilter.op,
|
|
926
|
-
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
927
|
-
};
|
|
928
|
-
return result;
|
|
929
|
-
};
|
|
930
|
-
function buildHaving_isHavingGroup(clause) {
|
|
931
|
-
return 'op' in clause && 'conditions' in clause;
|
|
932
|
-
}
|
|
933
|
-
function buildHaving_mapClauseToCondition(clause) {
|
|
934
|
-
if (buildHaving_isHavingGroup(clause)) return [
|
|
935
|
-
buildHaving_mapGroupToCondition(clause)
|
|
936
|
-
];
|
|
937
|
-
return buildHaving_mapFilterToCondition(clause);
|
|
938
|
-
}
|
|
939
|
-
function buildHaving_mapGroupToCondition(group) {
|
|
940
|
-
return {
|
|
941
|
-
op: group.op,
|
|
942
|
-
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
943
|
-
};
|
|
944
|
-
}
|
|
945
|
-
function buildHaving_mapFilterToCondition(filter) {
|
|
946
|
-
const mappedOp = filter.op ?? '=';
|
|
947
|
-
return [
|
|
948
|
-
{
|
|
949
|
-
field: filter.field,
|
|
950
|
-
op: mappedOp,
|
|
951
|
-
value: filter.value
|
|
952
|
-
}
|
|
953
|
-
];
|
|
954
|
-
}
|
|
955
|
-
const buildLimit = (queryDSL, context)=>{
|
|
956
|
-
const result = {
|
|
957
|
-
...queryDSL
|
|
958
|
-
};
|
|
959
|
-
const limit = context.vbiDSL.limit ?? 1000;
|
|
960
|
-
result.limit = limit;
|
|
961
|
-
return result;
|
|
962
|
-
};
|
|
963
|
-
const buildVQuery = (vbiDSL, builder)=>{
|
|
964
|
-
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
965
|
-
vbiDSL,
|
|
966
|
-
builder
|
|
967
|
-
});
|
|
968
|
-
return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
969
|
-
};
|
|
970
|
-
const connectorMap = new Map();
|
|
971
|
-
const registerConnector = (id, connector)=>{
|
|
972
|
-
connectorMap.set(id, connector);
|
|
973
|
-
};
|
|
974
|
-
const getConnector = async (id)=>{
|
|
975
|
-
const connector = connectorMap.get(id);
|
|
976
|
-
if (!connector) throw new Error(`connector ${id} not registered`);
|
|
977
|
-
if ('function' == typeof connector) return connector();
|
|
978
|
-
return connector;
|
|
979
|
-
};
|
|
1088
|
+
const createBuilderFeatures = (doc, dsl)=>({
|
|
1089
|
+
undoManager: new UndoManager(dsl),
|
|
1090
|
+
chartType: new ChartTypeBuilder(doc, dsl),
|
|
1091
|
+
measures: new MeasuresBuilder(doc, dsl),
|
|
1092
|
+
dimensions: new DimensionsBuilder(doc, dsl),
|
|
1093
|
+
havingFilter: new HavingFilterBuilder(doc, dsl),
|
|
1094
|
+
whereFilter: new WhereFilterBuilder(doc, dsl),
|
|
1095
|
+
theme: new ThemeBuilder(doc, dsl),
|
|
1096
|
+
locale: new LocaleBuilder(doc, dsl),
|
|
1097
|
+
limit: new LimitBuilder(doc, dsl)
|
|
1098
|
+
});
|
|
980
1099
|
class VBIBuilder {
|
|
981
1100
|
doc;
|
|
982
1101
|
dsl;
|
|
983
|
-
undoManager;
|
|
984
1102
|
chartType;
|
|
985
1103
|
measures;
|
|
986
1104
|
dimensions;
|
|
@@ -989,162 +1107,180 @@ class VBIBuilder {
|
|
|
989
1107
|
theme;
|
|
990
1108
|
locale;
|
|
991
1109
|
limit;
|
|
1110
|
+
undoManager;
|
|
992
1111
|
constructor(doc){
|
|
993
1112
|
this.doc = doc;
|
|
994
1113
|
this.dsl = doc.getMap('dsl');
|
|
995
|
-
|
|
996
|
-
this.
|
|
997
|
-
this.
|
|
998
|
-
this.
|
|
999
|
-
this.
|
|
1000
|
-
this.
|
|
1001
|
-
this.
|
|
1002
|
-
this.
|
|
1003
|
-
this.
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
encodeStateAsUpdate(targetStateVector) {
|
|
1009
|
-
return external_yjs_namespaceObject.encodeStateAsUpdate(this.doc, targetStateVector);
|
|
1010
|
-
}
|
|
1114
|
+
const features = createBuilderFeatures(doc, this.dsl);
|
|
1115
|
+
this.undoManager = features.undoManager;
|
|
1116
|
+
this.chartType = features.chartType;
|
|
1117
|
+
this.measures = features.measures;
|
|
1118
|
+
this.dimensions = features.dimensions;
|
|
1119
|
+
this.havingFilter = features.havingFilter;
|
|
1120
|
+
this.whereFilter = features.whereFilter;
|
|
1121
|
+
this.theme = features.theme;
|
|
1122
|
+
this.locale = features.locale;
|
|
1123
|
+
this.limit = features.limit;
|
|
1124
|
+
}
|
|
1125
|
+
applyUpdate = (update, transactionOrigin)=>applyUpdateToDoc(this.doc, update, transactionOrigin);
|
|
1126
|
+
encodeStateAsUpdate = (targetStateVector)=>encodeDocStateAsUpdate(this.doc, targetStateVector);
|
|
1011
1127
|
buildVSeed = async ()=>{
|
|
1012
1128
|
const vbiDSL = this.build();
|
|
1013
|
-
const connectorId = vbiDSL.connectorId;
|
|
1014
|
-
const connector = await getConnector(vbiDSL.connectorId);
|
|
1015
1129
|
const queryDSL = this.buildVQuery();
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
queryDSL
|
|
1019
|
-
schema,
|
|
1020
|
-
connectorId
|
|
1130
|
+
return buildVSeedDSL({
|
|
1131
|
+
vbiDSL,
|
|
1132
|
+
queryDSL
|
|
1021
1133
|
});
|
|
1022
|
-
return {
|
|
1023
|
-
chartType: vbiDSL.chartType,
|
|
1024
|
-
dataset: queryResult.dataset,
|
|
1025
|
-
theme: vbiDSL.theme,
|
|
1026
|
-
locale: vbiDSL.locale
|
|
1027
|
-
};
|
|
1028
|
-
};
|
|
1029
|
-
buildVQuery = ()=>{
|
|
1030
|
-
const vbiDSL = this.build();
|
|
1031
|
-
return buildVQuery(vbiDSL, this);
|
|
1032
|
-
};
|
|
1033
|
-
build = ()=>this.dsl.toJSON();
|
|
1034
|
-
getSchema = async ()=>{
|
|
1035
|
-
const connectorId = this.dsl.get('connectorId');
|
|
1036
|
-
const con = await getConnector(connectorId);
|
|
1037
|
-
const result = await con.discoverSchema();
|
|
1038
|
-
return result;
|
|
1039
1134
|
};
|
|
1135
|
+
buildVQuery = ()=>buildVQueryDSL(this.dsl, this);
|
|
1136
|
+
build = ()=>buildVBIDSL(this.dsl);
|
|
1137
|
+
isEmpty = ()=>isEmptyVBIDSL(this.dsl);
|
|
1138
|
+
getSchema = async ()=>getBuilderSchema(this.dsl);
|
|
1040
1139
|
}
|
|
1140
|
+
const shouldEnsureIdForObject = (obj, ensureId)=>{
|
|
1141
|
+
if (true === ensureId) return true;
|
|
1142
|
+
if ('field' === ensureId) return 'string' == typeof obj.field;
|
|
1143
|
+
return false;
|
|
1144
|
+
};
|
|
1145
|
+
const toYMap = (obj, ensureId = false)=>{
|
|
1146
|
+
const yMap = new external_yjs_namespaceObject.Map();
|
|
1147
|
+
if (shouldEnsureIdForObject(obj, ensureId) && !obj.id) yMap.set('id', id_id.uuid());
|
|
1148
|
+
for (const [key, value] of Object.entries(obj)){
|
|
1149
|
+
if (('conditions' === key || 'children' === key) && Array.isArray(value)) {
|
|
1150
|
+
const yArr = new external_yjs_namespaceObject.Array();
|
|
1151
|
+
for (const child of value){
|
|
1152
|
+
if (child instanceof external_yjs_namespaceObject.Map) {
|
|
1153
|
+
yArr.push([
|
|
1154
|
+
child
|
|
1155
|
+
]);
|
|
1156
|
+
continue;
|
|
1157
|
+
}
|
|
1158
|
+
if ('object' == typeof child && null !== child) {
|
|
1159
|
+
yArr.push([
|
|
1160
|
+
toYMap(child, ensureId)
|
|
1161
|
+
]);
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
yArr.push([
|
|
1165
|
+
child
|
|
1166
|
+
]);
|
|
1167
|
+
}
|
|
1168
|
+
yMap.set(key, yArr);
|
|
1169
|
+
continue;
|
|
1170
|
+
}
|
|
1171
|
+
yMap.set(key, value);
|
|
1172
|
+
}
|
|
1173
|
+
return yMap;
|
|
1174
|
+
};
|
|
1175
|
+
const ensureYArray = (arr, ensureId = false)=>{
|
|
1176
|
+
if (!arr) return new external_yjs_namespaceObject.Array();
|
|
1177
|
+
if (arr instanceof external_yjs_namespaceObject.Array) return arr;
|
|
1178
|
+
const yArr = new external_yjs_namespaceObject.Array();
|
|
1179
|
+
for (const item of arr){
|
|
1180
|
+
if (item instanceof external_yjs_namespaceObject.Map) {
|
|
1181
|
+
yArr.push([
|
|
1182
|
+
item
|
|
1183
|
+
]);
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1186
|
+
if ('object' == typeof item && null !== item) {
|
|
1187
|
+
yArr.push([
|
|
1188
|
+
toYMap(item, ensureId)
|
|
1189
|
+
]);
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
yArr.push([
|
|
1193
|
+
item
|
|
1194
|
+
]);
|
|
1195
|
+
}
|
|
1196
|
+
return yArr;
|
|
1197
|
+
};
|
|
1198
|
+
const getDefaultWhereFilter = ()=>({
|
|
1199
|
+
id: 'root',
|
|
1200
|
+
op: 'and',
|
|
1201
|
+
conditions: []
|
|
1202
|
+
});
|
|
1203
|
+
const isFilterGroupInput = (value)=>'object' == typeof value && null !== value;
|
|
1204
|
+
const ensureWhereGroup = (whereFilter)=>{
|
|
1205
|
+
const sourceWhereFilter = whereFilter instanceof external_yjs_namespaceObject.Map || isFilterGroupInput(whereFilter) ? whereFilter : getDefaultWhereFilter();
|
|
1206
|
+
const whereGroup = sourceWhereFilter instanceof external_yjs_namespaceObject.Map ? sourceWhereFilter : createWhereGroup();
|
|
1207
|
+
if (sourceWhereFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1208
|
+
if (!(whereGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) whereGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1209
|
+
if (!whereGroup.get('id')) whereGroup.set('id', 'root');
|
|
1210
|
+
if (!whereGroup.get('op')) whereGroup.set('op', 'and');
|
|
1211
|
+
return whereGroup;
|
|
1212
|
+
}
|
|
1213
|
+
whereGroup.set('id', sourceWhereFilter.id ?? 'root');
|
|
1214
|
+
whereGroup.set('op', sourceWhereFilter.op ?? 'and');
|
|
1215
|
+
whereGroup.set('conditions', ensureYArray(sourceWhereFilter.conditions, true));
|
|
1216
|
+
return whereGroup;
|
|
1217
|
+
};
|
|
1218
|
+
const getDefaultHavingFilter = ()=>({
|
|
1219
|
+
id: 'root',
|
|
1220
|
+
op: 'and',
|
|
1221
|
+
conditions: []
|
|
1222
|
+
});
|
|
1223
|
+
const ensure_having_group_isFilterGroupInput = (value)=>'object' == typeof value && null !== value;
|
|
1224
|
+
const ensureHavingGroup = (havingFilter)=>{
|
|
1225
|
+
const sourceHavingFilter = havingFilter instanceof external_yjs_namespaceObject.Map || ensure_having_group_isFilterGroupInput(havingFilter) ? havingFilter : getDefaultHavingFilter();
|
|
1226
|
+
const havingGroup = sourceHavingFilter instanceof external_yjs_namespaceObject.Map ? sourceHavingFilter : createHavingGroup();
|
|
1227
|
+
if (sourceHavingFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1228
|
+
if (!(havingGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) havingGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1229
|
+
if (!havingGroup.get('id')) havingGroup.set('id', 'root');
|
|
1230
|
+
if (!havingGroup.get('op')) havingGroup.set('op', 'and');
|
|
1231
|
+
return havingGroup;
|
|
1232
|
+
}
|
|
1233
|
+
havingGroup.set('id', sourceHavingFilter.id ?? 'root');
|
|
1234
|
+
havingGroup.set('op', sourceHavingFilter.op ?? 'and');
|
|
1235
|
+
havingGroup.set('conditions', ensureYArray(sourceHavingFilter.conditions, true));
|
|
1236
|
+
return havingGroup;
|
|
1237
|
+
};
|
|
1238
|
+
const setBaseDSLFields = (dsl, vbi)=>{
|
|
1239
|
+
if (vbi.connectorId) dsl.set('connectorId', vbi.connectorId);
|
|
1240
|
+
if (vbi.chartType) dsl.set('chartType', vbi.chartType);
|
|
1241
|
+
if (vbi.theme) dsl.set('theme', vbi.theme);
|
|
1242
|
+
if (vbi.limit) dsl.set('limit', vbi.limit);
|
|
1243
|
+
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
1244
|
+
if (void 0 !== vbi.version) dsl.set('version', vbi.version);
|
|
1245
|
+
};
|
|
1246
|
+
const fromVBIDSLInput = (vbi)=>{
|
|
1247
|
+
const doc = new external_yjs_namespaceObject.Doc();
|
|
1248
|
+
const dsl = doc.getMap('dsl');
|
|
1249
|
+
doc.transact(()=>{
|
|
1250
|
+
setBaseDSLFields(dsl, vbi);
|
|
1251
|
+
dsl.set('whereFilter', ensureWhereGroup(vbi.whereFilter));
|
|
1252
|
+
dsl.set('havingFilter', ensureHavingGroup(vbi.havingFilter));
|
|
1253
|
+
dsl.set('measures', ensureYArray(vbi.measures, 'field'));
|
|
1254
|
+
dsl.set('dimensions', ensureYArray(vbi.dimensions, 'field'));
|
|
1255
|
+
});
|
|
1256
|
+
return new VBIBuilder(doc);
|
|
1257
|
+
};
|
|
1258
|
+
const generateEmptyDSL = (connectorId)=>({
|
|
1259
|
+
connectorId,
|
|
1260
|
+
chartType: 'table',
|
|
1261
|
+
measures: [],
|
|
1262
|
+
dimensions: [],
|
|
1263
|
+
whereFilter: {
|
|
1264
|
+
id: 'root',
|
|
1265
|
+
op: 'and',
|
|
1266
|
+
conditions: []
|
|
1267
|
+
},
|
|
1268
|
+
havingFilter: {
|
|
1269
|
+
id: 'root',
|
|
1270
|
+
op: 'and',
|
|
1271
|
+
conditions: []
|
|
1272
|
+
},
|
|
1273
|
+
theme: 'light',
|
|
1274
|
+
locale: 'zh-CN',
|
|
1275
|
+
version: 0
|
|
1276
|
+
});
|
|
1041
1277
|
const createVBI = ()=>({
|
|
1042
1278
|
connectorMap: connectorMap,
|
|
1043
1279
|
registerConnector: registerConnector,
|
|
1044
1280
|
getConnector: getConnector,
|
|
1045
|
-
generateEmptyDSL:
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
measures: [],
|
|
1049
|
-
dimensions: [],
|
|
1050
|
-
whereFilter: {
|
|
1051
|
-
id: 'root',
|
|
1052
|
-
op: 'and',
|
|
1053
|
-
conditions: []
|
|
1054
|
-
},
|
|
1055
|
-
havingFilter: {
|
|
1056
|
-
id: 'root',
|
|
1057
|
-
op: 'and',
|
|
1058
|
-
conditions: []
|
|
1059
|
-
},
|
|
1060
|
-
theme: 'light',
|
|
1061
|
-
locale: 'zh-CN',
|
|
1062
|
-
version: 0
|
|
1063
|
-
}),
|
|
1064
|
-
from: (vbi)=>{
|
|
1065
|
-
const doc = new external_yjs_namespaceObject.Doc();
|
|
1066
|
-
const dsl = doc.getMap('dsl');
|
|
1067
|
-
doc.transact(()=>{
|
|
1068
|
-
if (vbi.connectorId) dsl.set('connectorId', vbi.connectorId);
|
|
1069
|
-
if (vbi.chartType) dsl.set('chartType', vbi.chartType);
|
|
1070
|
-
if (vbi.theme) dsl.set('theme', vbi.theme);
|
|
1071
|
-
if (vbi.limit) dsl.set('limit', vbi.limit);
|
|
1072
|
-
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
1073
|
-
if (void 0 !== vbi.version) dsl.set('version', vbi.version);
|
|
1074
|
-
const toYMap = (obj, ensureId = false)=>{
|
|
1075
|
-
const yMap = new external_yjs_namespaceObject.Map();
|
|
1076
|
-
if (ensureId && !obj.id) yMap.set('id', id_id.uuid());
|
|
1077
|
-
for (const [key, value] of Object.entries(obj))if ('conditions' === key && Array.isArray(value)) {
|
|
1078
|
-
const yArr = new external_yjs_namespaceObject.Array();
|
|
1079
|
-
value.forEach((child)=>{
|
|
1080
|
-
if (child instanceof external_yjs_namespaceObject.Map) yArr.push([
|
|
1081
|
-
child
|
|
1082
|
-
]);
|
|
1083
|
-
else if ('object' == typeof child && null !== child) yArr.push([
|
|
1084
|
-
toYMap(child, true)
|
|
1085
|
-
]);
|
|
1086
|
-
else yArr.push([
|
|
1087
|
-
child
|
|
1088
|
-
]);
|
|
1089
|
-
});
|
|
1090
|
-
yMap.set(key, yArr);
|
|
1091
|
-
} else yMap.set(key, value);
|
|
1092
|
-
return yMap;
|
|
1093
|
-
};
|
|
1094
|
-
const ensureYArray = (arr, ensureId = false)=>{
|
|
1095
|
-
if (!arr) return new external_yjs_namespaceObject.Array();
|
|
1096
|
-
if (arr instanceof external_yjs_namespaceObject.Array) return arr;
|
|
1097
|
-
const yArr = new external_yjs_namespaceObject.Array();
|
|
1098
|
-
arr.forEach((item)=>{
|
|
1099
|
-
if (item instanceof external_yjs_namespaceObject.Map) yArr.push([
|
|
1100
|
-
item
|
|
1101
|
-
]);
|
|
1102
|
-
else if ('object' == typeof item && null !== item) yArr.push([
|
|
1103
|
-
toYMap(item, ensureId)
|
|
1104
|
-
]);
|
|
1105
|
-
else yArr.push([
|
|
1106
|
-
item
|
|
1107
|
-
]);
|
|
1108
|
-
});
|
|
1109
|
-
return yArr;
|
|
1110
|
-
};
|
|
1111
|
-
const whereFilter = vbi.whereFilter ?? {
|
|
1112
|
-
id: 'root',
|
|
1113
|
-
op: 'and',
|
|
1114
|
-
conditions: []
|
|
1115
|
-
};
|
|
1116
|
-
const whereGroup = whereFilter instanceof external_yjs_namespaceObject.Map ? whereFilter : createWhereGroup();
|
|
1117
|
-
if (whereFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1118
|
-
if (!(whereGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) whereGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1119
|
-
if (!whereGroup.get('id')) whereGroup.set('id', 'root');
|
|
1120
|
-
if (!whereGroup.get('op')) whereGroup.set('op', 'and');
|
|
1121
|
-
} else {
|
|
1122
|
-
whereGroup.set('id', whereFilter.id ?? 'root');
|
|
1123
|
-
whereGroup.set('op', whereFilter.op ?? 'and');
|
|
1124
|
-
whereGroup.set('conditions', ensureYArray(whereFilter.conditions, true));
|
|
1125
|
-
}
|
|
1126
|
-
dsl.set('whereFilter', whereGroup);
|
|
1127
|
-
const havingFilter = vbi.havingFilter ?? {
|
|
1128
|
-
id: 'root',
|
|
1129
|
-
op: 'and',
|
|
1130
|
-
conditions: []
|
|
1131
|
-
};
|
|
1132
|
-
const havingGroup = havingFilter instanceof external_yjs_namespaceObject.Map ? havingFilter : createHavingGroup();
|
|
1133
|
-
if (havingFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1134
|
-
if (!(havingGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) havingGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1135
|
-
if (!havingGroup.get('id')) havingGroup.set('id', 'root');
|
|
1136
|
-
if (!havingGroup.get('op')) havingGroup.set('op', 'and');
|
|
1137
|
-
} else {
|
|
1138
|
-
havingGroup.set('id', havingFilter.id ?? 'root');
|
|
1139
|
-
havingGroup.set('op', havingFilter.op ?? 'and');
|
|
1140
|
-
havingGroup.set('conditions', ensureYArray(havingFilter.conditions, true));
|
|
1141
|
-
}
|
|
1142
|
-
dsl.set('havingFilter', havingGroup);
|
|
1143
|
-
dsl.set('measures', ensureYArray(vbi.measures));
|
|
1144
|
-
dsl.set('dimensions', ensureYArray(vbi.dimensions));
|
|
1145
|
-
});
|
|
1146
|
-
return new VBIBuilder(doc);
|
|
1147
|
-
}
|
|
1281
|
+
generateEmptyDSL: generateEmptyDSL,
|
|
1282
|
+
from: fromVBIDSLInput,
|
|
1283
|
+
create: fromVBIDSLInput
|
|
1148
1284
|
});
|
|
1149
1285
|
const VBI = createVBI();
|
|
1150
1286
|
exports.ChartTypeBuilder = __webpack_exports__.ChartTypeBuilder;
|