11import {
22 AnyOfType ,
3+ AnyType ,
34 ArrayType ,
45 NumberType ,
56 ObjectType ,
67 ReferenceType ,
78} from "../builders/index.js" ;
9+ import { databaseIsEnabled } from "../database/generator.js" ;
10+ import { fileWriteRaw } from "../file/write.js" ;
11+ import { TypescriptImportCollector } from "../target/typescript.js" ;
12+ import { typesTypescriptResolveFile } from "../types/typescript.js" ;
813import { upperCaseFirst } from "../utils.js" ;
914import {
1015 modelRelationGetInformation ,
@@ -79,6 +84,13 @@ export function modelQueryBuilderTypes(generateContext) {
7984 */
8085export function modelQueryResultTypes ( generateContext ) {
8186 for ( const model of structureModels ( generateContext ) ) {
87+ const expansionType = new ObjectType (
88+ "queryExpansion" ,
89+ model . group + upperCaseFirst ( model . name ) ,
90+ )
91+ . keys ( { } )
92+ . build ( ) ;
93+
8294 const type = new ObjectType (
8395 "queryResult" ,
8496 model . group + upperCaseFirst ( model . name ) ,
@@ -99,6 +111,7 @@ export function modelQueryResultTypes(generateContext) {
99111 type . keys [ relationInfo . keyNameOwn ] ,
100112 [ "isOptional" ] ,
101113 ) ;
114+
102115 const joinedType = new ReferenceType (
103116 "queryResult" ,
104117 `${ relationInfo . modelInverse . group } ${ upperCaseFirst (
@@ -110,9 +123,19 @@ export function modelQueryResultTypes(generateContext) {
110123 if ( isOptional ) {
111124 anyOfType . optional ( ) ;
112125 }
113- type . keys [ relationInfo . keyNameOwn ] = anyOfType . build ( ) ;
114126
127+ type . keys [ relationInfo . keyNameOwn ] = anyOfType . build ( ) ;
115128 type . keys [ relationInfo . keyNameOwn ] . values = [ existingType , joinedType ] ;
129+
130+ const joinedExpansionType = getQueryDefinitionReference (
131+ relationInfo . modelInverse . group ,
132+ relationInfo . modelInverse . name ,
133+ ) ;
134+ if ( isOptional ) {
135+ joinedExpansionType . optional ( ) ;
136+ }
137+
138+ expansionType . keys [ relationInfo . keyNameOwn ] = joinedExpansionType . build ( ) ;
116139 }
117140
118141 for ( const relation of modelRelationGetInverse ( model ) ) {
@@ -136,10 +159,97 @@ export function modelQueryResultTypes(generateContext) {
136159 type . keys [ relationInfo . virtualKeyNameInverse ] = joinedType
137160 . optional ( )
138161 . build ( ) ;
162+
163+ const joinedExpansionType =
164+ relation . subType === "oneToMany" ?
165+ new ArrayType ( ) . values (
166+ getQueryDefinitionReference (
167+ relationInfo . modelOwn . group ,
168+ relationInfo . modelOwn . name ,
169+ ) ,
170+ )
171+ : getQueryDefinitionReference (
172+ relationInfo . modelOwn . group ,
173+ relationInfo . modelOwn . name ,
174+ ) ;
175+
176+ expansionType . keys [ relationInfo . virtualKeyNameInverse ] =
177+ joinedExpansionType . optional ( ) . build ( ) ;
139178 }
140179
141180 structureAddType ( generateContext . structure , type , {
142181 skipReferenceExtraction : true ,
143182 } ) ;
183+ structureAddType ( generateContext . structure , expansionType , {
184+ skipReferenceExtraction : true ,
185+ } ) ;
186+ }
187+ }
188+
189+ function getQueryDefinitionReference ( group , name ) {
190+ const resolvedName = `${ upperCaseFirst ( group ) } ${ upperCaseFirst ( name ) } ` ;
191+
192+ const implementation = {
193+ validatorInputType : `QueryDefinition${ resolvedName } ` ,
194+ validatorOutputType : `QueryDefinition${ resolvedName } ` ,
195+ } ;
196+ return new AnyType ( ) . implementations ( {
197+ js : implementation ,
198+ ts : implementation ,
199+ jsPostgres : implementation ,
200+ tsPostgres : implementation ,
201+ } ) ;
202+ }
203+
204+ /**
205+ * Add raw types related to models and query builders
206+ *
207+ * @param {import("../generate.js").GenerateContext } generateContext
208+ * @returns {void }
209+ */
210+ export function modelQueryRawTypes ( generateContext ) {
211+ if ( ! databaseIsEnabled ( generateContext ) ) {
212+ return ;
213+ }
214+
215+ const file = typesTypescriptResolveFile ( generateContext ) ;
216+
217+ if ( generateContext . options . targetLanguage === "ts" ) {
218+ const typeImports = TypescriptImportCollector . getImportCollector (
219+ file ,
220+ true ,
221+ ) ;
222+ typeImports . destructure ( "@compas/store" , "QueryBuilderResolver" ) ;
223+ typeImports . destructure ( "@compas/store" , "QueryBuilderDefinition" ) ;
224+ typeImports . destructure ( "@compas/store" , "ResolveOptionalJoins" ) ;
225+ }
226+
227+ const exportPrefix =
228+ generateContext . options . generators . types ?. declareGlobalTypes ?
229+ ""
230+ : "export" ;
231+
232+ for ( const model of structureModels ( generateContext ) ) {
233+ const name = `${ upperCaseFirst ( model . group ) } ${ upperCaseFirst ( model . name ) } ` ;
234+
235+ if ( generateContext . options . targetLanguage === "ts" ) {
236+ fileWriteRaw (
237+ file ,
238+ `${ exportPrefix } type QueryDefinition${ name } = QueryBuilderDefinition<${ name } , QueryExpansion${ name } >;\n` ,
239+ ) ;
240+ fileWriteRaw (
241+ file ,
242+ `${ exportPrefix } type ${ name } QueryResolver<QueryBuilder extends ${ name } QueryBuilderInput, const OptionalJoins extends ResolveOptionalJoins<QueryExpansion${ name } > = never> = QueryBuilderResolver<QueryDefinition${ name } , QueryBuilder, OptionalJoins>;\n\n` ,
243+ ) ;
244+ } else if ( generateContext . options . targetLanguage === "js" ) {
245+ fileWriteRaw (
246+ file ,
247+ `${ exportPrefix } type QueryDefinition${ name } = import("@compas/store").QueryBuilderDefinition<${ name } , QueryExpansion${ name } >;\n` ,
248+ ) ;
249+ fileWriteRaw (
250+ file ,
251+ `${ exportPrefix } type ${ name } QueryResolver<QueryBuilder extends ${ name } QueryBuilderInput, const OptionalJoins extends import("@compas/store").ResolveOptionalJoins<QueryExpansion${ name } > = never> = import("@compas/store").QueryBuilderResolver<QueryDefinition${ name } , QueryBuilder, OptionalJoins>;\n\n` ,
252+ ) ;
253+ }
144254 }
145255}
0 commit comments