@@ -19,6 +19,7 @@ import {
1919 InvocationExpr ,
2020 isArrayExpr ,
2121 isDataModel ,
22+ isDataSource ,
2223 isInvocationExpr ,
2324 isLiteralExpr ,
2425 isNullExpr ,
@@ -29,9 +30,14 @@ import {
2930 Model ,
3031 NumberLiteral ,
3132 StringLiteral ,
32- type AstNode ,
3333} from '@zenstackhq/language/ast' ;
34- import { getAllAttributes , getAllFields , isAuthInvocation , isDelegateModel } from '@zenstackhq/language/utils' ;
34+ import {
35+ getAllAttributes ,
36+ getAllFields ,
37+ getStringLiteral ,
38+ isAuthInvocation ,
39+ isDelegateModel ,
40+ } from '@zenstackhq/language/utils' ;
3541import { AstUtils } from 'langium' ;
3642import { match } from 'ts-pattern' ;
3743import { ModelUtils } from '..' ;
@@ -58,6 +64,9 @@ import {
5864// Here we use a conservative value that should work for most cases, and truncate names if needed
5965const IDENTIFIER_NAME_MAX_LENGTH = 50 - DELEGATE_AUX_RELATION_PREFIX . length ;
6066
67+ // Datasource fields that only exist in ZModel but not in Prisma schema
68+ const NON_PRISMA_DATASOURCE_FIELDS = [ 'defaultSchema' ] ;
69+
6170/**
6271 * Generates Prisma schema file
6372 */
@@ -101,10 +110,12 @@ export class PrismaSchemaGenerator {
101110 }
102111
103112 private generateDataSource ( prisma : PrismaModel , dataSource : DataSource ) {
104- const fields : SimpleField [ ] = dataSource . fields . map ( ( f ) => ( {
105- name : f . name ,
106- text : this . configExprToText ( f . value ) ,
107- } ) ) ;
113+ const fields : SimpleField [ ] = dataSource . fields
114+ . filter ( ( f ) => ! NON_PRISMA_DATASOURCE_FIELDS . includes ( f . name ) )
115+ . map ( ( f ) => ( {
116+ name : f . name ,
117+ text : this . configExprToText ( f . value ) ,
118+ } ) ) ;
108119 prisma . addDataSource ( dataSource . name , fields ) ;
109120 }
110121
@@ -171,13 +182,27 @@ export class PrismaSchemaGenerator {
171182 }
172183 }
173184
174- const allAttributes = getAllAttributes ( decl ) ;
175- for ( const attr of allAttributes . filter (
185+ const allAttributes = getAllAttributes ( decl ) . filter (
176186 ( attr ) => this . isPrismaAttribute ( attr ) && ! this . isInheritedMapAttribute ( attr , decl ) ,
177- ) ) {
187+ ) ;
188+
189+ for ( const attr of allAttributes ) {
178190 this . generateContainerAttribute ( model , attr ) ;
179191 }
180192
193+ if (
194+ this . datasourceHasSchemasSetting ( decl . $container ) &&
195+ ! allAttributes . some ( ( attr ) => attr . decl . ref ?. name === '@@schema' )
196+ ) {
197+ // if the datasource declared `schemas` and no @@schema attribute is defined, add a default one
198+ model . addAttribute ( '@@schema' , [
199+ new PrismaAttributeArg (
200+ undefined ,
201+ new PrismaAttributeArgValue ( 'String' , this . getDefaultPostgresSchemaName ( decl . $container ) ) ,
202+ ) ,
203+ ] ) ;
204+ }
205+
181206 // user defined comments pass-through
182207 decl . comments . forEach ( ( c ) => model . addComment ( c ) ) ;
183208
@@ -188,6 +213,20 @@ export class PrismaSchemaGenerator {
188213 this . generateDelegateRelationForConcrete ( model , decl ) ;
189214 }
190215
216+ private getDatasourceField ( zmodel : Model , fieldName : string ) {
217+ const dataSource = zmodel . declarations . find ( isDataSource ) ;
218+ return dataSource ?. fields . find ( ( f ) => f . name === fieldName ) ;
219+ }
220+
221+ private datasourceHasSchemasSetting ( zmodel : Model ) {
222+ return ! ! this . getDatasourceField ( zmodel , 'schemas' ) ;
223+ }
224+
225+ private getDefaultPostgresSchemaName ( zmodel : Model ) {
226+ const defaultSchemaField = this . getDatasourceField ( zmodel , 'defaultSchema' ) ;
227+ return getStringLiteral ( defaultSchemaField ?. value ) ?? 'public' ;
228+ }
229+
191230 private isInheritedMapAttribute ( attr : DataModelAttribute , contextModel : DataModel ) {
192231 if ( attr . $container === contextModel ) {
193232 return false ;
@@ -206,7 +245,7 @@ export class PrismaSchemaGenerator {
206245
207246 private getUnsupportedFieldType ( fieldType : DataFieldType ) {
208247 if ( fieldType . unsupported ) {
209- const value = this . getStringLiteral ( fieldType . unsupported . value ) ;
248+ const value = getStringLiteral ( fieldType . unsupported . value ) ;
210249 if ( value ) {
211250 return `Unsupported("${ value } ")` ;
212251 } else {
@@ -217,10 +256,6 @@ export class PrismaSchemaGenerator {
217256 }
218257 }
219258
220- private getStringLiteral ( node : AstNode | undefined ) : string | undefined {
221- return isStringLiteral ( node ) ? node . value : undefined ;
222- }
223-
224259 private generateModelField ( model : PrismaDataModel , field : DataField , contextModel : DataModel , addToFront = false ) {
225260 let fieldType : string | undefined ;
226261
0 commit comments