1- import type { Model } from '@zenstackhq/language/ast' ;
1+ import { Model , Enum , DataModel } from '@zenstackhq/language/ast' ;
22import { ZModelCodeGenerator } from '@zenstackhq/sdk' ;
33import fs from 'node:fs' ;
44import path from 'node:path' ;
@@ -11,7 +11,7 @@ import {
1111} from './action-utils' ;
1212import { syncEnums , syncRelation , syncTable , type Relation } from './pull' ;
1313import { providers } from './pull/provider' ;
14- import { getDatasource } from './pull/utils' ;
14+ import { getDatasource , getDbName } from './pull/utils' ;
1515import { config } from '@dotenvx/dotenvx' ;
1616
1717type PushOptions = {
@@ -116,18 +116,93 @@ async function runPull(options: PullOptions) {
116116 syncRelation ( { model : newModel , relation, services, options } ) ;
117117 }
118118
119- //TODO: diff models and apply changes only
119+ const cwd = new URL ( `file://${ process . cwd ( ) } ` ) . pathname ;
120+ const docs = services . shared . workspace . LangiumDocuments . all
121+ . filter ( ( { uri } ) => uri . path . toLowerCase ( ) . startsWith ( cwd . toLowerCase ( ) ) )
122+ . toArray ( ) ;
123+ const docsSet = new Set ( docs . map ( ( d ) => d . uri . toString ( ) ) ) ;
124+ console . log ( docsSet ) ;
125+ newModel . declarations
126+ . filter ( ( d ) => [ DataModel , Enum ] . includes ( d . $type ) )
127+ . forEach ( ( _declaration ) => {
128+ const declaration = _declaration as DataModel | Enum ;
129+ const declarations = services . shared . workspace . IndexManager . allElements ( declaration . $type , docsSet ) ;
130+ const originalModel = declarations . find ( ( d ) => getDbName ( d . node as any ) === getDbName ( declaration ) )
131+ ?. node as DataModel | Enum | undefined ;
132+ if ( ! originalModel ) {
133+ model . declarations . push ( declaration ) ;
134+ ( declaration as any ) . $container = model ;
135+ return ;
136+ }
137+
138+ declaration . fields . forEach ( ( f ) => {
139+ const originalField = originalModel . fields . find ( ( d ) => getDbName ( d ) === getDbName ( f ) ) ;
140+
141+ if ( ! originalField ) {
142+ console . log ( `Added field ${ f . name } to ${ originalModel . name } ` ) ;
143+ ( f as any ) . $container = originalModel ;
144+ originalModel . fields . push ( f as any ) ;
145+ return ;
146+ }
147+ //TODO: update field
148+ } ) ;
149+ originalModel . fields
150+ . filter ( ( f ) => ! declaration . fields . find ( ( d ) => getDbName ( d ) === getDbName ( f ) ) )
151+ . forEach ( ( f ) => {
152+ const model = f . $container ;
153+ const index = model . fields . findIndex ( ( d ) => d === f ) ;
154+ model . fields . splice ( index , 1 ) ;
155+ console . log ( `Delete field ${ f . name } ` ) ;
156+ } ) ;
157+ } ) ;
158+
159+ services . shared . workspace . IndexManager . allElements ( 'DataModel' , docsSet )
160+ . filter (
161+ ( declaration ) =>
162+ ! newModel . declarations . find ( ( d ) => getDbName ( d ) === getDbName ( declaration . node as any ) ) ,
163+ )
164+ . forEach ( ( decl ) => {
165+ const model = decl . node ! . $container as Model ;
166+ const index = model . declarations . findIndex ( ( d ) => d === decl . node ) ;
167+ model . declarations . splice ( index , 1 ) ;
168+ console . log ( `Delete model ${ decl . name } ` ) ;
169+ } ) ;
170+ services . shared . workspace . IndexManager . allElements ( 'Enum' , docsSet )
171+ . filter (
172+ ( declaration ) =>
173+ ! newModel . declarations . find ( ( d ) => getDbName ( d ) === getDbName ( declaration . node as any ) ) ,
174+ )
175+ . forEach ( ( decl ) => {
176+ const model = decl . node ! . $container as Model ;
177+ const index = model . declarations . findIndex ( ( d ) => d === decl . node ) ;
178+ model . declarations . splice ( index , 1 ) ;
179+ console . log ( `Delete enum ${ decl . name } ` ) ;
180+ } ) ;
181+
182+ if ( options . out && ! fs . lstatSync ( options . out ) . isFile ( ) ) {
183+ throw new Error ( `Output path ${ options . out } is not a file` ) ;
184+ }
120185
121- const generator = new ZModelCodeGenerator ( ) ;
186+ const generator = new ZModelCodeGenerator ( {
187+ //TODO: make configurable
188+ quote : 'double' ,
189+ } ) ;
122190
123- const zmodelSchema = generator . generate ( newModel ) ;
191+ if ( options . out ) {
192+ const zmodelSchema = generator . generate ( newModel ) ;
124193
125- console . log ( options . out ? `Writing to ${ options . out } ` : schemaFile ) ;
194+ console . log ( `Writing to ${ options . out } ` ) ;
126195
127- const outPath = options . out ? path . resolve ( options . out ) : schemaFile ;
128- console . log ( outPath ) ;
196+ const outPath = options . out ? path . resolve ( options . out ) : schemaFile ;
129197
130- fs . writeFileSync ( outPath , zmodelSchema ) ;
198+ fs . writeFileSync ( outPath , zmodelSchema ) ;
199+ } else {
200+ docs . forEach ( ( { uri, parseResult : { value : model } } ) => {
201+ const zmodelSchema = generator . generate ( model ) ;
202+ console . log ( `Writing to ${ uri . path } ` ) ;
203+ fs . writeFileSync ( uri . fsPath , zmodelSchema ) ;
204+ } ) ;
205+ }
131206 } catch ( error ) {
132207 console . log ( error ) ;
133208 throw error ;
0 commit comments