Skip to content

Commit f211e16

Browse files
authored
refactor(schema-compiler): CubeEvaluator - migrate to TypeScript (#7488)
1 parent ea1fa9c commit f211e16

File tree

6 files changed

+111
-80
lines changed

6 files changed

+111
-80
lines changed

packages/cubejs-schema-compiler/src/adapter/BaseDimension.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { BaseQuery } from './BaseQuery';
2+
import type { DimensionDefinition, SegmentDefinition } from '../compiler/CubeEvaluator';
23

34
export class BaseDimension {
45
public readonly expression: any;
@@ -68,21 +69,23 @@ export class BaseDimension {
6869
return this.query.cubeEvaluator.cubeFromPath(this.dimension);
6970
}
7071

71-
public dimensionDefinition() {
72+
public dimensionDefinition(): DimensionDefinition | SegmentDefinition {
7273
if (this.query.cubeEvaluator.isSegment(this.dimension)) {
7374
return this.query.cubeEvaluator.segmentByPath(this.dimension);
7475
}
76+
7577
return this.query.cubeEvaluator.dimensionByPath(this.dimension);
7678
}
7779

78-
public definition() {
80+
public definition(): DimensionDefinition | SegmentDefinition {
7981
if (this.expression) {
8082
return {
8183
sql: this.expression,
8284
// TODO use actual dimension type even though it isn't used right now
8385
type: 'number'
84-
};
86+
} as DimensionDefinition;
8587
}
88+
8689
return this.dimensionDefinition();
8790
}
8891

packages/cubejs-schema-compiler/src/adapter/BaseQuery.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ export class BaseQuery {
16621662

16631663
/**
16641664
* Returns a complete list of the dimensions, including time dimensions.
1665-
* @returns {Array<BaseDimension>}
1665+
* @returns {(BaseDimension|BaseTimeDimension)[]}
16661666
*/
16671667
dimensionsForSelect() {
16681668
return this.dimensions.concat(this.timeDimensions);

packages/cubejs-schema-compiler/src/compiler/ContextEvaluator.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import R from 'ramda';
22

33
export class ContextEvaluator {
4+
/**
5+
* @param {import('./CubeEvaluator').CubeEvaluator} cubeEvaluator
6+
*/
47
constructor(cubeEvaluator) {
58
this.cubeEvaluator = cubeEvaluator;
6-
79
this.contextDefinitions = {};
810
}
911

packages/cubejs-schema-compiler/src/compiler/CubeEvaluator.js renamed to packages/cubejs-schema-compiler/src/compiler/CubeEvaluator.ts

Lines changed: 90 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,49 @@ import R from 'ramda';
44
import { CubeSymbols } from './CubeSymbols';
55
import { UserError } from './UserError';
66
import { BaseQuery } from '../adapter';
7+
import type { CubeValidator } from './CubeValidator';
8+
import type { ErrorReporter } from './ErrorReporter';
9+
10+
export type SegmentDefinition = {
11+
type: string,
12+
sql: Function,
13+
primaryKey?: true,
14+
ownedByCube: boolean,
15+
fieldType?: string,
16+
};
17+
18+
export type DimensionDefinition = {
19+
type: string,
20+
sql: Function,
21+
primaryKey?: true,
22+
ownedByCube: boolean,
23+
fieldType?: string,
24+
};
25+
26+
export type MeasureDefinition = {
27+
type: string,
28+
sql: Function,
29+
ownedByCube: boolean,
30+
rollingWindow?: any
31+
filters?: any
32+
primaryKey?: true,
33+
drillFilters?: any
34+
};
735

836
export class CubeEvaluator extends CubeSymbols {
9-
constructor(cubeValidator) {
37+
public evaluatedCubes: Record<string, any> = {};
38+
39+
public primaryKeys: Record<string, any> = {};
40+
41+
public byFileName: Record<string, any> = {};
42+
43+
public constructor(
44+
protected readonly cubeValidator: CubeValidator
45+
) {
1046
super(true);
11-
this.cubeValidator = cubeValidator;
12-
/** @type {*} */
13-
this.evaluatedCubes = {};
14-
/** @type {*} */
15-
this.primaryKeys = {};
1647
}
1748

18-
compile(cubes, errorReporter) {
49+
public compile(cubes: any, errorReporter: ErrorReporter) {
1950
super.compile(cubes, errorReporter);
2051
const validCubes = this.cubeList.filter(cube => this.cubeValidator.isCubeValid(cube));
2152

@@ -26,33 +57,27 @@ export class CubeEvaluator extends CubeSymbols {
2657
this.primaryKeys = R.fromPairs(
2758
validCubes.map((v) => {
2859
const primaryKeyNamesToSymbols = R.compose(
29-
R.map((d) => d[0]),
30-
R.filter((d) => d[1].primaryKey),
60+
R.map((d: any) => d[0]),
61+
R.filter((d: any) => d[1].primaryKey),
3162
R.toPairs
3263
)(v.dimensions || {});
3364
return [v.name, primaryKeyNamesToSymbols];
3465
})
3566
);
3667
}
3768

38-
/**
39-
* @protected
40-
*/
41-
prepareCube(cube, errorReporter) {
69+
protected prepareCube(cube, errorReporter: ErrorReporter) {
4270
this.prepareJoins(cube, errorReporter);
4371
this.preparePreAggregations(cube, errorReporter);
4472
this.prepareMembers(cube.measures, cube, errorReporter);
4573
this.prepareMembers(cube.dimensions, cube, errorReporter);
4674
this.prepareMembers(cube.segments, cube, errorReporter);
4775
}
4876

49-
/**
50-
* @protected
51-
*/
52-
prepareJoins(cube, _errorReporter) {
77+
protected prepareJoins(cube: any, _errorReporter: ErrorReporter) {
5378
if (cube.joins) {
5479
// eslint-disable-next-line no-restricted-syntax
55-
for (const join of Object.values(cube.joins)) {
80+
for (const join of Object.values(cube.joins) as any[]) {
5681
// eslint-disable-next-line default-case
5782
switch (join.relationship) {
5883
case 'belongs_to':
@@ -75,13 +100,10 @@ export class CubeEvaluator extends CubeSymbols {
75100
}
76101
}
77102

78-
/**
79-
* @protected
80-
*/
81-
preparePreAggregations(cube, errorReporter) {
103+
protected preparePreAggregations(cube: any, errorReporter: ErrorReporter) {
82104
if (cube.preAggregations) {
83105
// eslint-disable-next-line no-restricted-syntax
84-
for (const preAggregation of Object.values(cube.preAggregations)) {
106+
for (const preAggregation of Object.values(cube.preAggregations) as any) {
85107
if (preAggregation.timeDimension) {
86108
preAggregation.timeDimensionReference = preAggregation.timeDimension;
87109
delete preAggregation.timeDimension;
@@ -110,7 +132,8 @@ export class CubeEvaluator extends CubeSymbols {
110132
if (preAggregation.buildRangeStart) {
111133
if (preAggregation.refreshRangeStart) {
112134
errorReporter.warning({
113-
message: 'You specified both buildRangeStart and refreshRangeStart, buildRangeStart will be used.'
135+
message: 'You specified both buildRangeStart and refreshRangeStart, buildRangeStart will be used.',
136+
loc: null,
114137
});
115138
}
116139

@@ -121,7 +144,8 @@ export class CubeEvaluator extends CubeSymbols {
121144
if (preAggregation.buildRangeEnd) {
122145
if (preAggregation.refreshRangeEnd) {
123146
errorReporter.warning({
124-
message: 'You specified both buildRangeEnd and refreshRangeEnd, buildRangeEnd will be used.'
147+
message: 'You specified both buildRangeEnd and refreshRangeEnd, buildRangeEnd will be used.',
148+
loc: null,
125149
});
126150
}
127151

@@ -132,10 +156,7 @@ export class CubeEvaluator extends CubeSymbols {
132156
}
133157
}
134158

135-
/**
136-
* @protected
137-
*/
138-
prepareMembers(members, cube, errorReporter) {
159+
protected prepareMembers(members: any, cube: any, errorReporter: ErrorReporter) {
139160
members = members || {};
140161

141162
for (const memberName of Object.keys(members)) {
@@ -173,23 +194,25 @@ export class CubeEvaluator extends CubeSymbols {
173194
}
174195
}
175196

176-
cubesByFileName(fileName) {
197+
public cubesByFileName(fileName) {
177198
return this.byFileName[fileName] || [];
178199
}
179200

180-
timeDimensionPathsForCube(cube) {
201+
public timeDimensionPathsForCube(cube: any) {
181202
return R.compose(
182203
R.map(nameToDefinition => `${cube}.${nameToDefinition[0]}`),
183204
R.toPairs,
184-
R.filter(d => d.type === 'time')
205+
// @ts-ignore
206+
R.filter((d: any) => d.type === 'time')
207+
// @ts-ignore
185208
)(this.evaluatedCubes[cube].dimensions || {});
186209
}
187210

188-
measuresForCube(cube) {
211+
public measuresForCube(cube) {
189212
return this.cubeFromPath(cube).measures || {};
190213
}
191214

192-
preAggregationsForCube(path) {
215+
public preAggregationsForCube(path: string) {
193216
return this.cubeFromPath(path).preAggregations || {};
194217
}
195218

@@ -203,7 +226,7 @@ export class CubeEvaluator extends CubeSymbols {
203226
* }} filter pre-aggregations selector
204227
* @returns {*}
205228
*/
206-
preAggregations(filter) {
229+
public preAggregations(filter) {
207230
const { scheduled, dataSources, cubes, preAggregationIds } = filter || {};
208231
const idFactory = ({ cube, preAggregationName }) => `${cube}.${preAggregationName}`;
209232

@@ -262,86 +285,78 @@ export class CubeEvaluator extends CubeSymbols {
262285
.reduce((a, b) => a.concat(b), []);
263286
}
264287

265-
scheduledPreAggregations() {
288+
public scheduledPreAggregations() {
266289
return this.preAggregations({ scheduled: true });
267290
}
268291

269-
cubeNames() {
292+
public cubeNames() {
270293
return Object.keys(this.evaluatedCubes);
271294
}
272295

273-
isMeasure(measurePath) {
296+
public isMeasure(measurePath: string): boolean {
274297
return this.isInstanceOfType('measures', measurePath);
275298
}
276299

277-
isDimension(path) {
300+
public isDimension(path: string): boolean {
278301
return this.isInstanceOfType('dimensions', path);
279302
}
280303

281-
isSegment(path) {
304+
public isSegment(path: string): boolean {
282305
return this.isInstanceOfType('segments', path);
283306
}
284307

285-
measureByPath(measurePath) {
308+
public measureByPath(measurePath: string): MeasureDefinition {
286309
return this.byPath('measures', measurePath);
287310
}
288311

289-
dimensionByPath(dimensionPath) {
312+
public dimensionByPath(dimensionPath: string): DimensionDefinition {
290313
return this.byPath('dimensions', dimensionPath);
291314
}
292315

293-
segmentByPath(segmentPath) {
316+
public segmentByPath(segmentPath: string): SegmentDefinition {
294317
return this.byPath('segments', segmentPath);
295318
}
296319

297-
cubeExists(cube) {
320+
public cubeExists(cube) {
298321
return !!this.evaluatedCubes[cube];
299322
}
300323

301-
cubeFromPath(path) {
324+
public cubeFromPath(path: string) {
302325
return this.evaluatedCubes[this.cubeNameFromPath(path)];
303326
}
304327

305-
cubeNameFromPath(path) {
328+
public cubeNameFromPath(path: string) {
306329
const cubeAndName = path.split('.');
307330
if (!this.evaluatedCubes[cubeAndName[0]]) {
308331
throw new UserError(`Cube '${cubeAndName[0]}' not found for path '${path}'`);
309332
}
310333
return cubeAndName[0];
311334
}
312335

313-
/**
314-
* @param {'measures'|'dimensions'|'segments'} type
315-
* @param {string} path
316-
* @returns boolean
317-
*/
318-
isInstanceOfType(type, path) {
336+
public isInstanceOfType(type: 'measures' | 'dimensions' | 'segments', path: string | string[]): boolean {
319337
const cubeAndName = Array.isArray(path) ? path : path.split('.');
320338
return this.evaluatedCubes[cubeAndName[0]] &&
321339
this.evaluatedCubes[cubeAndName[0]][type] &&
322340
this.evaluatedCubes[cubeAndName[0]][type][cubeAndName[1]];
323341
}
324342

325-
/**
326-
* @param {string} path
327-
* @returns {*}
328-
*/
329-
byPathAnyType(path) {
330-
const type = ['measures', 'dimensions', 'segments'].find(t => this.isInstanceOfType(t, path));
343+
public byPathAnyType(path: string[]) {
344+
if (this.isInstanceOfType('measures', path)) {
345+
return this.byPath('measures', path);
346+
}
331347

332-
if (!type) {
333-
throw new UserError(`Can't resolve member '${path.join('.')}'`);
348+
if (this.isInstanceOfType('dimensions', path)) {
349+
return this.byPath('dimensions', path);
334350
}
335351

336-
return this.byPath(type, path);
352+
if (this.isInstanceOfType('segments', path)) {
353+
return this.byPath('segments', path);
354+
}
355+
356+
throw new UserError(`Can't resolve member '${path.join('.')}'`);
337357
}
338358

339-
/**
340-
* @param {'measures'|'dimensions'|'segments'} type
341-
* @param {string} path
342-
* @returns {*}
343-
*/
344-
byPath(type, path) {
359+
public byPath(type: 'measures' | 'dimensions' | 'segments', path: string | string[]) {
345360
if (!type) {
346361
throw new Error(`Type can't be undefined for '${path}'`);
347362
}
@@ -366,23 +381,23 @@ export class CubeEvaluator extends CubeSymbols {
366381
return this.evaluatedCubes[cubeAndName[0]][type][cubeAndName[1]];
367382
}
368383

369-
parsePath(type, path) {
384+
public parsePath(type, path) {
370385
// Should throw UserError in case of parse error
371386
this.byPath(type, path);
372387
return path.split('.');
373388
}
374389

375-
parsePathAnyType(path) {
390+
protected parsePathAnyType(path) {
376391
// Should throw UserError in case of parse error
377392
this.byPathAnyType(path);
378393
return path.split('.');
379394
}
380395

381-
collectUsedCubeReferences(cube, sqlFn) {
396+
public collectUsedCubeReferences(cube: any, sqlFn: any) {
382397
const cubeEvaluator = this;
383398

384-
const cubeReferencesUsed = [];
385-
const pathReferencesUsed = [];
399+
const cubeReferencesUsed: string[] = [];
400+
const pathReferencesUsed: string[][] = [];
386401

387402
const evaluatedSql = cubeEvaluator.resolveSymbolsCall(sqlFn, (name) => {
388403
const referencedCube = cubeEvaluator.symbols[name] && name || cube;
@@ -400,8 +415,8 @@ export class CubeEvaluator extends CubeSymbols {
400415
return cubeEvaluator.pathFromArray(path);
401416
}, {
402417
// eslint-disable-next-line no-shadow
403-
sqlResolveFn: (symbol, cube, n) => {
404-
const path = [cube, n];
418+
sqlResolveFn: (_symbol: unknown, cubeName: string, memberName: string) => {
419+
const path = [cubeName, memberName];
405420
pathReferencesUsed.push(path);
406421
return cubeEvaluator.pathFromArray(path);
407422
},
@@ -411,7 +426,7 @@ export class CubeEvaluator extends CubeSymbols {
411426
return { cubeReferencesUsed, pathReferencesUsed, evaluatedSql };
412427
}
413428

414-
evaluatePreAggregationReferences(cube, aggregation) {
429+
protected evaluatePreAggregationReferences(cube, aggregation) {
415430
const timeDimensions = aggregation.timeDimensionReference ? [{
416431
dimension: this.evaluateReferences(cube, aggregation.timeDimensionReference),
417432
granularity: aggregation.granularity

0 commit comments

Comments
 (0)