@@ -35,6 +35,12 @@ interface CubeDefinition {
3535 includedMembers ?: any [ ] ;
3636}
3737
38+ interface CubeDefinitionExtended extends CubeDefinition {
39+ allDefinitions : ( type : string ) => Record < string , any > ;
40+ rawFolders : ( ) => any [ ] ;
41+ rawCubes : ( ) => any [ ] ;
42+ }
43+
3844interface SplitViews {
3945 [ key : string ] : any ;
4046}
@@ -102,7 +108,7 @@ export class CubeSymbols {
102108 }
103109 }
104110
105- public getCubeDefinition ( cubeName : string ) {
111+ public getCubeDefinition ( cubeName : string ) : CubeDefinitionExtended {
106112 if ( ! this . builtCubes [ cubeName ] ) {
107113 const cubeDefinition = this . cubeDefinitions [ cubeName ] ;
108114 this . builtCubes [ cubeName ] = this . createCube ( cubeDefinition ) ;
@@ -111,7 +117,7 @@ export class CubeSymbols {
111117 return this . builtCubes [ cubeName ] ;
112118 }
113119
114- public createCube ( cubeDefinition : CubeDefinition ) {
120+ public createCube ( cubeDefinition : CubeDefinition ) : CubeDefinitionExtended {
115121 let preAggregations : any ;
116122 let joins : any ;
117123 let measures : any ;
@@ -120,6 +126,7 @@ export class CubeSymbols {
120126 let hierarchies : any ;
121127 let accessPolicy : any ;
122128 let folders : any ;
129+ let cubes : any ;
123130
124131 const cubeObject = Object . assign ( {
125132 allDefinitions ( type : string ) {
@@ -149,6 +156,22 @@ export class CubeSymbols {
149156 return folders ;
150157 } ,
151158
159+ // `Cubes` of a view are not a part of Cube Symbols,
160+ // but views can extend other views, so we need the ability to access parent view's cubes.
161+ rawCubes ( ) {
162+ if ( ! cubes ) {
163+ if ( cubeDefinition . extends ) {
164+ cubes = [
165+ ...super . rawCubes ( ) ,
166+ ...( cubeDefinition . cubes || [ ] )
167+ ] ;
168+ } else {
169+ cubes = [ ...( cubeDefinition . cubes || [ ] ) ] ;
170+ }
171+ }
172+ return cubes ;
173+ } ,
174+
152175 get preAggregations ( ) {
153176 // For preAggregations order is important, and destructing parents cube pre-aggs first will lead to
154177 // unexpected results, so we can not use common approach with allDefinitions('preAggregations') here.
@@ -240,7 +263,7 @@ export class CubeSymbols {
240263 if ( cubeDefinition . extends ) {
241264 const superCube = this . resolveSymbolsCall ( cubeDefinition . extends , ( name : string ) => this . cubeReferenceProxy ( name ) ) ;
242265 // eslint-disable-next-line no-underscore-dangle
243- const parentCube = superCube . __cubeName ? this . getCubeDefinition ( superCube . __cubeName ) : superCube ;
266+ const parentCube = superCube . __cubeName ? this . getCubeDefinition ( superCube . __cubeName ) : superCube as unknown as CubeDefinition ;
244267 Object . setPrototypeOf ( cubeObject , parentCube ) ;
245268
246269 // We have 2 different properties that are mutually exclusive: `sqlTable` & `sql`
@@ -303,7 +326,7 @@ export class CubeSymbols {
303326 } ;
304327 }
305328
306- private camelCaseTypes ( obj : Object ) {
329+ private camelCaseTypes ( obj : Object | undefined ) {
307330 if ( ! obj ) {
308331 return ;
309332 }
@@ -362,8 +385,9 @@ export class CubeSymbols {
362385 }
363386 }
364387
365- protected prepareIncludes ( cube : CubeDefinition , errorReporter : ErrorReporter , splitViews : SplitViews ) {
366- if ( ! cube . cubes ) {
388+ protected prepareIncludes ( cube : CubeDefinitionExtended , errorReporter : ErrorReporter , splitViews : SplitViews ) {
389+ const includedCubes = cube . rawCubes ( ) ;
390+ if ( ! includedCubes . length ) {
367391 return ;
368392 }
369393
@@ -378,32 +402,31 @@ export class CubeSymbols {
378402
379403 for ( const type of types ) {
380404 let cubeIncludes : any [ ] = [ ] ;
381- if ( cube . cubes ) {
382- // If the hierarchy is included all members from it should be included as well
383- // Extend `includes` with members from hierarchies that should be auto-included
384- const cubes = type === 'dimensions' ? cube . cubes . map ( ( it ) => {
385- // TODO recheck `it.joinPath` typing
386- const fullPath = this . evaluateReferences ( null , it . joinPath as ( ) => ToString , { collectJoinHints : true } ) ;
387- const split = fullPath . split ( '.' ) ;
388- const cubeRef = split [ split . length - 1 ] ;
389-
390- if ( it . includes === '*' ) {
391- return it ;
392- }
393405
394- const currentCubeAutoIncludeMembers = Array . from ( autoIncludeMembers )
395- . filter ( ( path ) => path . startsWith ( `${ cubeRef } .` ) )
396- . map ( ( path ) => path . split ( '.' ) [ 1 ] )
397- . filter ( memberName => ! it . includes . find ( ( include ) => ( include . name || include ) === memberName ) ) ;
406+ // If the hierarchy is included all members from it should be included as well
407+ // Extend `includes` with members from hierarchies that should be auto-included
408+ const cubes = type === 'dimensions' ? includedCubes . map ( ( it ) => {
409+ // TODO recheck `it.joinPath` typing
410+ const fullPath = this . evaluateReferences ( null , it . joinPath as ( ) => ToString , { collectJoinHints : true } ) ;
411+ const split = fullPath . split ( '.' ) ;
412+ const cubeRef = split [ split . length - 1 ] ;
398413
399- return {
400- ...it ,
401- includes : ( it . includes || [ ] ) . concat ( currentCubeAutoIncludeMembers ) ,
402- } ;
403- } ) : cube . cubes ;
414+ if ( it . includes === '*' ) {
415+ return it ;
416+ }
404417
405- cubeIncludes = this . membersFromCubes ( cube , cubes , type , errorReporter , splitViews , memberSets ) || [ ] ;
406- }
418+ const currentCubeAutoIncludeMembers = Array . from ( autoIncludeMembers )
419+ . filter ( ( path ) => path . startsWith ( `${ cubeRef } .` ) )
420+ . map ( ( path ) => path . split ( '.' ) [ 1 ] )
421+ . filter ( memberName => ! it . includes . find ( ( include ) => ( include . name || include ) === memberName ) ) ;
422+
423+ return {
424+ ...it ,
425+ includes : ( it . includes || [ ] ) . concat ( currentCubeAutoIncludeMembers ) ,
426+ } ;
427+ } ) : includedCubes ;
428+
429+ cubeIncludes = this . membersFromCubes ( cube , cubes , type , errorReporter , splitViews , memberSets ) || [ ] ;
407430
408431 if ( type === 'hierarchies' ) {
409432 for ( const member of cubeIncludes ) {
@@ -424,15 +447,15 @@ export class CubeSymbols {
424447 const includeMembers = this . generateIncludeMembers ( cubeIncludes , cube . name , type ) ;
425448 this . applyIncludeMembers ( includeMembers , cube , type , errorReporter ) ;
426449
427- cube . includedMembers = [ ...( cube . includedMembers || [ ] ) , ...Array . from ( new Set ( cubeIncludes . map ( ( it : any ) => {
450+ cube . includedMembers = R . uniqWith ( R . equals , [ ...( cube . includedMembers || [ ] ) , ...Array . from ( new Set ( cubeIncludes . map ( ( it : any ) => {
428451 const split = it . member . split ( '.' ) ;
429452 const memberPath = this . pathFromArray ( [ split [ split . length - 2 ] , split [ split . length - 1 ] ] ) ;
430453 return {
431454 type,
432455 memberPath,
433456 name : it . name
434457 } ;
435- } ) ) ) ] ;
458+ } ) ) ) ] ) ;
436459 }
437460
438461 [ ...memberSets . allMembers ] . filter ( it => ! memberSets . resolvedMembers . has ( it ) ) . forEach ( it => {
@@ -451,7 +474,7 @@ export class CubeSymbols {
451474 }
452475
453476 protected membersFromCubes ( parentCube : CubeDefinition , cubes : any [ ] , type : string , errorReporter : ErrorReporter , splitViews : SplitViews , memberSets : any ) {
454- return R . unnest ( cubes . map ( cubeInclude => {
477+ return R . uniqWith ( R . equals , R . unnest ( cubes . map ( cubeInclude => {
455478 // TODO recheck `cubeInclude.joinPath` typing
456479 const fullPath = this . evaluateReferences ( null , cubeInclude . joinPath as ( ) => ToString , { collectJoinHints : true } ) ;
457480 const split = fullPath . split ( '.' ) ;
@@ -531,7 +554,7 @@ export class CubeSymbols {
531554 } else {
532555 return finalIncludes ;
533556 }
534- } ) ) ;
557+ } ) ) ) ;
535558 }
536559
537560 protected diffByMember ( includes : any [ ] , excludes : any [ ] ) {
0 commit comments