11import type { ZModelServices } from '@zenstackhq/language'
22import type {
3+ ArrayExpr ,
34 Attribute ,
45 AttributeArg ,
56 DataField ,
@@ -9,18 +10,20 @@ import type {
910 Enum ,
1011 EnumField ,
1112 Model ,
13+ ReferenceExpr ,
14+ StringLiteral ,
1215 UnsupportedFieldType
1316} from '@zenstackhq/language/ast'
17+ import { getStringLiteral } from '@zenstackhq/language/utils'
1418import type { IntrospectedEnum , IntrospectedTable , IntrospectionProvider } from './provider'
15- import { getAttributeRef , getDbName } from './utils'
19+ import { getAttributeRef , getDbName , getEnumRef , getModelRef } from './utils'
1620
17- export function syncEnums ( dbEnums : IntrospectedEnum [ ] , model : Model ) {
21+ export function syncEnums ( { dbEnums, model , services } : { dbEnums : IntrospectedEnum [ ] , model : Model , services : ZModelServices } ) {
1822 for ( const dbEnum of dbEnums ) {
19- let schemaEnum = model . declarations . find (
20- ( d ) => d . $type === 'Enum' && getDbName ( d ) === dbEnum . enum_type
21- ) as Enum | undefined
23+ let schemaEnum = getEnumRef ( dbEnum . enum_type , services ) ;
2224
2325 if ( ! schemaEnum ) {
26+ console . log ( `Adding enum for type ${ dbEnum . enum_type } ` ) ;
2427 schemaEnum = {
2528 $type : 'Enum' as const ,
2629 $container : model ,
@@ -66,17 +69,29 @@ export function syncTable({
6669 model,
6770 provider,
6871 table,
72+ services
6973} : {
7074 table : IntrospectedTable
7175 model : Model
7276 provider : IntrospectionProvider
77+ services : ZModelServices
7378} ) {
79+ const idAttribute = getAttributeRef ( '@id' , services )
80+ const uniqueAttribute = getAttributeRef ( '@unique' , services )
81+ const relationAttribute = getAttributeRef ( '@relation' , services )
82+ const fieldMapAttribute = getAttributeRef ( '@map' , services )
83+ const tableMapAttribute = getAttributeRef ( '@@map' , services )
84+
85+ if ( ! idAttribute || ! uniqueAttribute || ! relationAttribute || ! fieldMapAttribute || ! tableMapAttribute ) {
86+ throw new Error ( 'Cannot find required attributes in the model.' )
87+ }
88+
7489 const relations : Relation [ ] = [ ]
75- let modelTable = model . declarations . find (
76- ( d ) => d . $type === 'DataModel' && getDbName ( d ) === table . name
77- ) as DataModel | undefined
90+ let modelTable = getModelRef ( table . name , services )
7891
7992 if ( ! modelTable ) {
93+ console . log ( `Adding model for table ${ table . name } ` ) ;
94+
8095 modelTable = {
8196 $type : 'DataModel' as const ,
8297 $container : model ,
@@ -96,7 +111,7 @@ export function syncTable({
96111 schema : table . schema ,
97112 table : table . name ,
98113 column : col . name ,
99- type : col . unique ? 'one' : 'many ',
114+ type : 'one' ,
100115 fk_name : col . foreign_key_name ! ,
101116 nullable : col . nullable ,
102117 references : {
@@ -115,85 +130,68 @@ export function syncTable({
115130 )
116131 if ( ! existingField ) {
117132 const builtinType = provider . getBuiltinType ( col . datatype )
118- const unsupported : UnsupportedFieldType = {
119- get $container ( ) {
120- return type
121- } ,
122- $type : 'UnsupportedFieldType' as const ,
123- value : {
124- get $container ( ) {
125- return unsupported
126- } ,
127- $type : 'StringLiteral' ,
128- value : col . datatype ,
129- } ,
130- }
131-
132- const type : DataFieldType = {
133- get $container ( ) {
134- return field
135- } ,
136- $type : 'DataFieldType' as const ,
137- type : builtinType . type === 'Unsupported' ? undefined : builtinType . type ,
138- array : builtinType . isArray ,
139- unsupported :
140- builtinType . type === 'Unsupported' ? unsupported : undefined ,
141- optional : col . nullable ,
142- reference : col . options . length
143- ? {
133+ const field : DataField = {
134+ $type : 'DataField' as const ,
135+ get type ( ) {
136+ return {
137+ $container : this ,
138+ $type : 'DataFieldType' as const ,
139+ type : builtinType . type === 'Unsupported' ? undefined : builtinType . type ,
140+ array : builtinType . isArray ,
141+ get unsupported ( ) {
142+ return builtinType . type === 'Unsupported' ? {
143+ $container : this ,
144+ $type : 'UnsupportedFieldType' as const ,
145+ get value ( ) {
146+ return {
147+ $container : this ,
148+ $type : 'StringLiteral' ,
149+ value : col . datatype ,
150+ } satisfies StringLiteral
151+ } ,
152+ } satisfies UnsupportedFieldType : undefined
153+ } ,
154+ optional : col . nullable ,
155+ reference : col . options . length
156+ ? {
144157 $refText : col . datatype ,
145158 ref : model . declarations . find (
146159 ( d ) => d . $type === 'Enum' && getDbName ( d ) === col . datatype
147- ) as Enum | undefined ,
148- }
149- : undefined ,
150- }
151-
152- const field : DataField = {
153- $type : 'DataField' as const ,
154- type,
160+ ) as Enum | undefined ,
161+ }
162+ : undefined ,
163+ } satisfies DataFieldType
164+ } ,
155165 $container : modelTable ! ,
156166 name : fieldName ,
157167 get attributes ( ) {
158168 if ( fieldPrefix !== '' ) return [ ]
159169
160- const attr : DataFieldAttribute = {
170+ return [ {
161171 $type : 'DataFieldAttribute' as const ,
162- get $container ( ) {
163- return field
164- } ,
172+ $container : this ,
165173 decl : {
166174 $refText : '@map' ,
167- ref : model . $document ?. references . find (
168- ( r ) =>
169- //@ts -ignore
170- r . ref . $type === 'Attribute' && r . ref . name === '@map'
171- ) ?. ref as Attribute ,
175+ ref : fieldMapAttribute ,
172176 } ,
173177 get args ( ) {
174- const arg : AttributeArg = {
178+ return [ {
175179 $type : 'AttributeArg' as const ,
176- get $container ( ) {
177- return attr
178- } ,
180+ $container : this ,
179181 name : 'name' ,
180182 $resolvedParam : {
181183 name : 'name' ,
182184 } ,
183185 get value ( ) {
184186 return {
185187 $type : 'StringLiteral' as const ,
186- $container : arg ,
188+ $container : this ,
187189 value : col . name ,
188190 }
189191 } ,
190- }
191-
192- return [ arg ]
192+ } ] satisfies AttributeArg [ ]
193193 } ,
194- }
195-
196- return [ attr ]
194+ } ] satisfies DataFieldAttribute [ ]
197195 } ,
198196 comments : [ ] ,
199197 }
@@ -205,10 +203,16 @@ export function syncTable({
205203 return relations
206204}
207205
208- export function syncRelation ( model : Model , relation : Relation , services : ZModelServices ) {
206+ export function syncRelation ( { model, relation , services } : { model : Model , relation : Relation , services : ZModelServices } ) {
209207 const idAttribute = getAttributeRef ( '@id' , services )
210208 const uniqueAttribute = getAttributeRef ( '@unique' , services )
211209 const relationAttribute = getAttributeRef ( '@relation' , services )
210+ const fieldMapAttribute = getAttributeRef ( '@map' , services )
211+ const tableMapAttribute = getAttributeRef ( '@@map' , services )
212+
213+ if ( ! idAttribute || ! uniqueAttribute || ! relationAttribute || ! fieldMapAttribute || ! tableMapAttribute ) {
214+ throw new Error ( 'Cannot find required attributes in the model.' )
215+ }
212216
213217 if ( ! idAttribute || ! uniqueAttribute || ! relationAttribute ) {
214218 throw new Error ( 'Cannot find required attributes in the model.' )
0 commit comments