Skip to content

Commit e5a8bfa

Browse files
authored
refactor(schema-compiler): CubeValidator - migrate to TypeScript (#7489)
1 parent f211e16 commit e5a8bfa

File tree

3 files changed

+56
-64
lines changed

3 files changed

+56
-64
lines changed

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

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
const Joi = require('joi');
2-
const cronParser = require('cron-parser');
1+
import Joi from 'joi';
2+
import cronParser from 'cron-parser';
3+
4+
import type { CubeSymbols } from './CubeSymbols';
5+
import type { ErrorReporter } from './ErrorReporter';
36

47
/* *****************************
58
* ATTENTION:
@@ -29,11 +32,21 @@ const identifierRegex = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
2932

3033
const identifier = Joi.string().regex(identifierRegex, 'identifier');
3134

35+
function formatStatePath(state: Joi.State): string {
36+
if (state.path) {
37+
// TODO: Remove cast after upgrade of Joi. It show it as string, while it's array
38+
const path = state.path as any as string[];
39+
return path.join('.');
40+
}
41+
42+
return '<unknown path>';
43+
}
44+
3245
const regexTimeInterval = Joi.string().custom((value, helper) => {
3346
if (value.match(/^(-?\d+) (minute|hour|day|week|month|quarter|year)$/)) {
3447
return value;
3548
} else {
36-
return helper.message({ custom: `(${helper.state.path.join('.')} = ${value}) does not match regexp: /^(-?\\d+) (minute|hour|day|week|month|quarter|year)$/` });
49+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) does not match regexp: /^(-?\\d+) (minute|hour|day|week|month|quarter|year)$/` });
3750
}
3851
});
3952

@@ -47,16 +60,16 @@ const everyInterval = Joi.string().custom((value, helper) => {
4760
if (value.match(/^(\d+) (second|minute|hour|day|week)s?$/)) {
4861
return value;
4962
} else {
50-
return helper.message({ custom: `(${helper.state.path.join('.')} = ${value}) does not match regexp: /^(\\d+) (second|minute|hour|day|week)s?$/` });
63+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) does not match regexp: /^(\\d+) (second|minute|hour|day|week)s?$/` });
5164
}
5265
});
5366

5467
const everyCronInterval = Joi.string().custom((value, helper) => {
5568
try {
5669
cronParser.parseExpression(value);
5770
return value;
58-
} catch (e) {
59-
return helper.message({ custom: `(${helper.state.path.join('.')} = ${value}) CronParser: ${e.toString()}` });
71+
} catch (e: any) {
72+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) CronParser: ${e.toString()}` });
6073
}
6174
});
6275

@@ -65,7 +78,7 @@ const everyCronTimeZone = Joi.string().custom((value, helper) => {
6578
cronParser.parseExpression('0 * * * *', { currentDate: '2020-01-01 00:00:01', tz: value });
6679
return value;
6780
} catch (e) {
68-
return helper.message({ custom: `(${helper.state.path.join('.')} = ${value}) unknown timezone. Take a look here https://cube.dev/docs/schema/reference/cube#supported-timezones to get available time zones` });
81+
return helper.message({ custom: `(${formatStatePath(helper.state)} = ${value}) unknown timezone. Take a look here https://cube.dev/docs/schema/reference/cube#supported-timezones to get available time zones` });
6982
}
7083
});
7184

@@ -613,25 +626,27 @@ function collectFunctionFieldsPatterns(patterns, path, o) {
613626
}
614627
}
615628

616-
export function functionFieldsPatterns() {
617-
const functionPatterns = new Set();
629+
export function functionFieldsPatterns(): string[] {
630+
const functionPatterns = new Set<string>();
618631
collectFunctionFieldsPatterns(functionPatterns, '', { ...cubeSchema, ...viewSchema });
619632
return Array.from(functionPatterns);
620633
}
621634

622635
export class CubeValidator {
623-
constructor(cubeSymbols) {
624-
this.cubeSymbols = cubeSymbols;
625-
this.validCubes = {};
636+
protected readonly validCubes: Map<string, boolean> = new Map();
637+
638+
public constructor(
639+
protected readonly cubeSymbols: CubeSymbols
640+
) {
626641
}
627642

628-
compile(cubes, errorReporter) {
643+
public compile(cubes, errorReporter: ErrorReporter) {
629644
return this.cubeSymbols.cubeList.map(
630645
(v) => this.validate(this.cubeSymbols.getCubeDefinition(v.name), errorReporter.inContext(`${v.name} cube`))
631646
);
632647
}
633648

634-
validate(cube, errorReporter) {
649+
public validate(cube, errorReporter: ErrorReporter) {
635650
const result = cube.isView ? viewSchema.validate(cube) : cubeSchema.validate(cube);
636651

637652
if (result.error != null) {
@@ -643,7 +658,7 @@ export class CubeValidator {
643658
return result;
644659
}
645660

646-
isCubeValid(cube) {
661+
public isCubeValid(cube) {
647662
return this.validCubes[cube.name] || cube.isSplitView;
648663
}
649664
}

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

Lines changed: 0 additions & 17 deletions
This file was deleted.

packages/cubejs-schema-compiler/test/unit/cube-validator.test.ts

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import { CubeValidator, functionFieldsPatterns } from '../../src/compiler/CubeValidator';
22
import { CubeSymbols } from '../../src/compiler/CubeSymbols';
3+
import { ErrorReporter } from '../../src/compiler/ErrorReporter';
34

45
describe('Cube Validation', () => {
6+
class ConsoleErrorReporter extends ErrorReporter {
7+
public error(message, e) {
8+
console.log(message);
9+
}
10+
}
11+
512
it('transpiledFieldsPatterns', async () => {
613
const transpiledFieldsPatterns = functionFieldsPatterns()
714
.filter((p) => p.indexOf('extends') < 0 && p.indexOf('allDefinitions') < 0)
@@ -61,12 +68,7 @@ describe('Cube Validation', () => {
6168
fileName: 'fileName',
6269
};
6370

64-
const validationResult = cubeValidator.validate(cube, {
65-
error: (message, e) => {
66-
console.log(message);
67-
}
68-
});
69-
71+
const validationResult = cubeValidator.validate(cube, new ConsoleErrorReporter());
7072
expect(validationResult.error).toBeFalsy();
7173
});
7274

@@ -78,11 +80,7 @@ describe('Cube Validation', () => {
7880
fileName: 'fileName',
7981
};
8082

81-
const validationResult = cubeValidator.validate(cube, {
82-
error: (message, e) => {
83-
console.log(message);
84-
}
85-
});
83+
const validationResult = cubeValidator.validate(cube, new ConsoleErrorReporter());
8684

8785
expect(validationResult.error).toBeFalsy();
8886
});
@@ -95,12 +93,7 @@ describe('Cube Validation', () => {
9593
fileName: 'fileName',
9694
};
9795

98-
const validationResult = cubeValidator.validate(cube, {
99-
error: (message, e) => {
100-
console.log(message);
101-
}
102-
});
103-
96+
const validationResult = cubeValidator.validate(cube, new ConsoleErrorReporter());
10497
expect(validationResult.error).toBeFalsy();
10598
});
10699

@@ -118,7 +111,7 @@ describe('Cube Validation', () => {
118111
console.log(message);
119112
expect(message).toContain('You must use either sql or sqlTable within a model, but not both');
120113
}
121-
});
114+
} as any);
122115

123116
expect(validationResult.error).toBeTruthy();
124117
});
@@ -136,7 +129,7 @@ describe('Cube Validation', () => {
136129
error: (message, e) => {
137130
console.log(message);
138131
}
139-
});
132+
} as any);
140133

141134
expect(validationResult.error).toBeFalsy();
142135
});
@@ -155,10 +148,11 @@ describe('Cube Validation', () => {
155148
const validationResult = cubeValidator.validate(cube, {
156149
error: (message, e) => {
157150
console.log(message);
151+
expect(message).toContain('(refreshKey.every = 12h)');
158152
expect(message).toContain('does not match regexp');
159153
expect(message).toContain('CronParser');
160154
}
161-
});
155+
} as any);
162156

163157
expect(validationResult.error).toBeTruthy();
164158
});
@@ -180,7 +174,7 @@ describe('Cube Validation', () => {
180174
console.log(message);
181175
expect(message).toContain('unknown timezone');
182176
}
183-
});
177+
} as any);
184178

185179
expect(validationResult.error).toBeTruthy();
186180
});
@@ -203,7 +197,7 @@ describe('Cube Validation', () => {
203197
console.log(message);
204198
expect(message).toContain('must be one of [count, number,');
205199
}
206-
});
200+
} as any);
207201

208202
expect(validationResult.error).toBeTruthy();
209203
});
@@ -227,7 +221,7 @@ describe('Cube Validation', () => {
227221
console.log(message);
228222
expect(message).toContain('timeDimension) is required');
229223
}
230-
});
224+
} as any);
231225

232226
expect(validationResult.error).toBeTruthy();
233227
});
@@ -251,7 +245,7 @@ describe('Cube Validation', () => {
251245
expect(message).toContain('granularity) is required');
252246
expect(message).toContain('rollups) is required');
253247
}
254-
});
248+
} as any);
255249

256250
expect(validationResult.error).toBeTruthy();
257251
});
@@ -285,7 +279,7 @@ describe('Cube Validation', () => {
285279
console.log(message);
286280
expect(message).toContain('granularity) is required');
287281
}
288-
});
282+
} as any);
289283

290284
expect(validationResult.error).toBeTruthy();
291285
});
@@ -310,7 +304,7 @@ describe('Cube Validation', () => {
310304
console.log(message);
311305
expect(message).toContain('(preAggregations.eventsByType.scheduledRefresh = true) must be [false]');
312306
}
313-
});
307+
} as any);
314308

315309
expect(validationResult.error).toBeTruthy();
316310
});
@@ -339,7 +333,7 @@ describe('Cube Validation', () => {
339333
expect(message).toContain('number.sql) is required');
340334
expect(message).toContain('number.columns) is required');
341335
}
342-
});
336+
} as any);
343337

344338
expect(validationResult.error).toBeTruthy();
345339
});
@@ -374,7 +368,7 @@ describe('Cube Validation', () => {
374368
expect(message).toContain('must be one of');
375369
expect(message).not.toContain('rollup) must be');
376370
}
377-
});
371+
} as any);
378372

379373
expect(validationResult.error).toBeTruthy();
380374
});
@@ -397,7 +391,7 @@ describe('Cube Validation', () => {
397391
console.log(message);
398392
expect(message).toContain('must be');
399393
}
400-
});
394+
} as any);
401395

402396
expect(validationResult.error).toBeTruthy();
403397
});
@@ -421,7 +415,7 @@ describe('Cube Validation', () => {
421415
console.log(message);
422416
expect(message).toContain('are deprecated, please, use');
423417
}
424-
});
418+
} as any);
425419

426420
expect(validationResult.error).toBeTruthy();
427421
});
@@ -445,7 +439,7 @@ describe('Cube Validation', () => {
445439
// this callback should not be invoked
446440
expect(true).toBeFalsy();
447441
}
448-
});
442+
} as any);
449443

450444
expect(validationResult.error).toBeFalsy();
451445
});
@@ -512,7 +506,7 @@ describe('Cube Validation', () => {
512506
error: (message, _e) => {
513507
console.log(message);
514508
}
515-
});
509+
} as any);
516510

517511
expect(validationResult.error).toBeFalsy();
518512
});

0 commit comments

Comments
 (0)