@@ -23,6 +23,33 @@ function buildCollectionFixture(actionSchema: Record<string, unknown>) {
2323 } as any ;
2424}
2525
26+ function buildColumn ( operators : string [ ] = [ 'Equal' ] ) {
27+ return { type : 'Column' , filterOperators : new Set ( operators ) } ;
28+ }
29+
30+ function buildRelation ( foreignCollection : string ) {
31+ return { type : 'ManyToOne' , foreignCollection, foreignKey : `${ foreignCollection } Id` } ;
32+ }
33+
34+ function buildSchemaCollection ( name : string , fields : Record < string , unknown > ) {
35+ return {
36+ name,
37+ schema : {
38+ fields,
39+ actions : { } ,
40+ aggregationCapabilities : {
41+ supportedDateOperations : new Set < string > ( ) ,
42+ supportGroups : false ,
43+ } ,
44+ countable : false ,
45+ searchable : false ,
46+ charts : [ ] ,
47+ segments : [ ] ,
48+ } ,
49+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50+ } as any ;
51+ }
52+
2653describe ( 'RpcAgent.buildCollection' , ( ) => {
2754 it ( 'serialises generateFile as is_generate_file so Ruby main agents read it natively' , ( ) => {
2855 const agent = createAgent ( ) ;
@@ -42,3 +69,79 @@ describe('RpcAgent.buildCollection', () => {
4269 } ) ;
4370 } ) ;
4471} ) ;
72+
73+ describe ( 'RpcAgent.buildSchema' , ( ) => {
74+ function createAgentWithRpcCollections ( rpcCollections : string [ ] ) : RpcAgent {
75+ const agent = createAgent ( ) ;
76+ ( agent as unknown as { rpcCollections : string [ ] } ) . rpcCollections = rpcCollections ;
77+
78+ return agent ;
79+ }
80+
81+ function buildDataSource ( collections : unknown [ ] ) {
82+ return {
83+ collections,
84+ schema : { charts : [ ] } ,
85+ nativeQueryConnections : { } ,
86+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87+ } as any ;
88+ }
89+
90+ // Non-regression: a NON-RPC collection holding a relation toward an RPC collection
91+ // must be exposed in `rpc_relations`. The cross relation used to be computed in
92+ // buildCollection then dropped because the registration lived inside the RPC branch only.
93+ it ( 'exposes cross relations from a non-RPC collection pointing to an RPC collection' , ( ) => {
94+ const agent = createAgentWithRpcCollections ( [ 'Books' ] ) ;
95+
96+ // Authors is a main (non-RPC) collection referencing the RPC collection Books.
97+ const authors = buildSchemaCollection ( 'Authors' , {
98+ id : buildColumn ( ) ,
99+ myBook : buildRelation ( 'Books' ) ,
100+ } ) ;
101+ const books = buildSchemaCollection ( 'Books' , { id : buildColumn ( ) } ) ;
102+
103+ const schema = agent . buildSchema ( buildDataSource ( [ authors , books ] ) ) ;
104+
105+ expect ( schema . rpc_relations . Authors ) . toBeDefined ( ) ;
106+ expect ( schema . rpc_relations . Authors . myBook ) . toMatchObject ( {
107+ type : 'ManyToOne' ,
108+ foreign_collection : 'Books' ,
109+ } ) ;
110+
111+ // The cross relation is stripped from the exposed collection fields.
112+ const exposedAuthors = schema . collections . find ( c => c . name === 'Authors' ) ;
113+ expect ( exposedAuthors . fields ) . toHaveProperty ( 'id' ) ;
114+ expect ( exposedAuthors . fields ) . not . toHaveProperty ( 'myBook' ) ;
115+ } ) ;
116+
117+ it ( 'keeps exposing relations from an RPC collection toward non-RPC collections' , ( ) => {
118+ const agent = createAgentWithRpcCollections ( [ 'Books' ] ) ;
119+
120+ const books = buildSchemaCollection ( 'Books' , {
121+ id : buildColumn ( ) ,
122+ author : buildRelation ( 'Authors' ) ,
123+ } ) ;
124+ const authors = buildSchemaCollection ( 'Authors' , { id : buildColumn ( ) } ) ;
125+
126+ const schema = agent . buildSchema ( buildDataSource ( [ books , authors ] ) ) ;
127+
128+ expect ( schema . rpc_relations . Books ) . toBeDefined ( ) ;
129+ expect ( schema . rpc_relations . Books . author ) . toMatchObject ( {
130+ type : 'ManyToOne' ,
131+ foreign_collection : 'Authors' ,
132+ } ) ;
133+ // The RPC collection itself is not added to the exposed `collections` array.
134+ expect ( schema . collections . find ( c => c . name === 'Books' ) ) . toBeUndefined ( ) ;
135+ } ) ;
136+
137+ it ( 'omits collections without cross relations from rpc_relations' , ( ) => {
138+ const agent = createAgentWithRpcCollections ( [ 'Books' ] ) ;
139+
140+ const books = buildSchemaCollection ( 'Books' , { id : buildColumn ( ) } ) ;
141+ const authors = buildSchemaCollection ( 'Authors' , { id : buildColumn ( ) } ) ;
142+
143+ const schema = agent . buildSchema ( buildDataSource ( [ books , authors ] ) ) ;
144+
145+ expect ( schema . rpc_relations ) . toEqual ( { } ) ;
146+ } ) ;
147+ } ) ;
0 commit comments