Skip to content

Commit 381630e

Browse files
committed
refactor(schema-compiler): More types in CubeSymbols
1 parent bb4c270 commit 381630e

File tree

2 files changed

+34
-17
lines changed

2 files changed

+34
-17
lines changed

packages/cubejs-schema-compiler/src/compiler/CubeEvaluator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export type DimensionDefinition = {
2828
};
2929

3030
export type TimeShiftDefinition = {
31-
timeDimension: Function,
31+
timeDimension: (...args: Array<unknown>) => { toString(): string },
3232
interval: string,
3333
type: 'next' | 'prior',
3434
};
@@ -48,9 +48,9 @@ export type MeasureDefinition = {
4848
primaryKey?: true,
4949
drillFilters?: any,
5050
multiStage?: boolean,
51-
groupBy?: Function,
52-
reduceBy?: Function,
53-
addGroupBy?: Function,
51+
groupBy?: (...args: Array<unknown>) => Array<{ toString(): string }>,
52+
reduceBy?: (...args: Array<unknown>) => Array<{ toString(): string }>,
53+
addGroupBy?: (...args: Array<unknown>) => Array<{ toString(): string }>,
5454
timeShift?: TimeShiftDefinition[],
5555
groupByReferences?: string[],
5656
reduceByReferences?: string[],

packages/cubejs-schema-compiler/src/compiler/CubeSymbols.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { ErrorReporter } from './ErrorReporter';
1111

1212
interface CubeDefinition {
1313
name: string;
14-
extends?: string;
14+
extends?: (...args: Array<unknown>) => { __cubeName: string };
1515
measures?: Record<string, any>;
1616
dimensions?: Record<string, any>;
1717
segments?: Record<string, any>;
@@ -292,7 +292,8 @@ export class CubeSymbols {
292292
// If the hierarchy is included all members from it should be included as well
293293
// Extend `includes` with members from hierarchies that should be auto-included
294294
const cubes = type === 'dimensions' ? cube.cubes.map((it) => {
295-
const fullPath = this.evaluateReferences(null, it.joinPath, { collectJoinHints: true });
295+
// TODO recheck `it.joinPath` typing
296+
const fullPath = this.evaluateReferences(null, it.joinPath as () => { toString(): string }, { collectJoinHints: true });
296297
const split = fullPath.split('.');
297298
const cubeRef = split[split.length - 1];
298299

@@ -332,7 +333,8 @@ export class CubeSymbols {
332333
const hierarchy = this.getResolvedMember(type, cubeName, hierarchyName);
333334

334335
if (hierarchy) {
335-
const levels = this.evaluateReferences(cubeName, this.getResolvedMember('hierarchies', cubeName, hierarchyName).levels, { originalSorting: true });
336+
// TODO recheck `this.getResolvedMember(...).levels` typing
337+
const levels = this.evaluateReferences(cubeName, this.getResolvedMember('hierarchies', cubeName, hierarchyName).levels as () => Array<{ toString(): string }>, { originalSorting: true });
336338

337339
levels.forEach((level) => autoIncludeMembers.add(level));
338340
}
@@ -370,7 +372,8 @@ export class CubeSymbols {
370372

371373
protected membersFromCubes(parentCube: CubeDefinition, cubes: any[], type: string, errorReporter: ErrorReporter, splitViews: SplitViews, memberSets: any) {
372374
return R.unnest(cubes.map(cubeInclude => {
373-
const fullPath = this.evaluateReferences(null, cubeInclude.joinPath, { collectJoinHints: true });
375+
// TODO recheck `cubeInclude.joinPath` typing
376+
const fullPath = this.evaluateReferences(null, cubeInclude.joinPath as () => { toString(): string }, { collectJoinHints: true });
374377
const split = fullPath.split('.');
375378
const cubeReference = split[split.length - 1];
376379
const cubeName = cubeInclude.alias || cubeReference;
@@ -453,7 +456,7 @@ export class CubeSymbols {
453456
return includes.filter(include => !excludesMap.has(include.member));
454457
}
455458

456-
protected membersFromIncludeExclude(referencesFn: any, cubeName: string, type: string) {
459+
protected membersFromIncludeExclude(referencesFn: (...args: Array<unknown>) => Array<{ toString(): string }>, cubeName: string, type: string) {
457460
const references = this.evaluateReferences(cubeName, referencesFn);
458461
return R.unnest(references.map((ref: string) => {
459462
const path = ref.split('.');
@@ -550,7 +553,11 @@ export class CubeSymbols {
550553
return res;
551554
}
552555

553-
protected evaluateReferences(cube, referencesFn, options: any = {}) {
556+
protected evaluateReferences<T extends { toString(): string } | Array<{ toString(): string }>>(
557+
cube: string | null,
558+
referencesFn: (...args: Array<unknown>) => T,
559+
options: { collectJoinHints?: boolean, originalSorting?: boolean } = {}):
560+
T extends Array<{ toString(): string }> ? Array<string> : T extends { toString(): string } ? string : string | Array<string> {
554561
const cubeEvaluator = this;
555562

556563
const fullPath = (joinHints, path) => {
@@ -561,7 +568,7 @@ export class CubeSymbols {
561568
}
562569
};
563570

564-
const arrayOrSingle = cubeEvaluator.resolveSymbolsCall(referencesFn, (name) => {
571+
const arrayOrSingle: T = cubeEvaluator.resolveSymbolsCall(referencesFn, (name) => {
565572
const referencedCube = cubeEvaluator.symbols[name] && name || cube;
566573
const resolvedSymbol =
567574
cubeEvaluator.resolveSymbol(
@@ -582,25 +589,35 @@ export class CubeSymbols {
582589
collectJoinHints: options.collectJoinHints,
583590
});
584591
if (!Array.isArray(arrayOrSingle)) {
585-
return arrayOrSingle.toString();
592+
// arrayOrSingle is of type `T`, and we just checked that it is not an array
593+
// Which means it `T` be an object with `toString`, and result must be `string`
594+
// For any branch of return type that can can contain just an object it's OK to return string
595+
return arrayOrSingle.toString() as any;
586596
}
587597

588-
const references = arrayOrSingle.map(p => p.toString());
589-
return options.originalSorting ? references : R.sortBy(R.identity, references);
598+
const references: Array<string> = arrayOrSingle.map(p => p.toString());
599+
// arrayOrSingle is of type `T`, and we just checked that it is an array
600+
// Which means that both `T` and result must be arrays
601+
// For any branch of return type that can contain array it's OK to return array
602+
return options.originalSorting ? references : R.sortBy(R.identity, references) as any;
590603
}
591604

592605
public pathFromArray(array) {
593606
return array.join('.');
594607
}
595608

596-
protected resolveSymbolsCall(func, nameResolver, context?: any) {
609+
protected resolveSymbolsCall<T>(
610+
func: (...args: Array<unknown>) => T | DynamicReference<T>,
611+
nameResolver: (id: string) => unknown,
612+
context?: unknown,
613+
): T {
597614
const oldContext = this.resolveSymbolsCallContext;
598615
this.resolveSymbolsCallContext = context;
599616
try {
600617
// eslint-disable-next-line prefer-spread
601-
let res = func.apply(null, this.funcArguments(func).map((id) => nameResolver(id.trim())));
618+
const res = func.apply(null, this.funcArguments(func).map((id) => nameResolver(id.trim())));
602619
if (res instanceof DynamicReference) {
603-
res = res.fn.apply(null, res.memberNames.map((id) => nameResolver(id.trim())));
620+
return res.fn.apply(null, res.memberNames.map((id) => nameResolver(id.trim())));
604621
}
605622
return res;
606623
} finally {

0 commit comments

Comments
 (0)