@@ -52,9 +52,14 @@ import {
5252} from './model-utils' ;
5353
5454export class TsSchemaGenerator {
55+ private usedExpressionUtils = false ;
56+
5557 async generate ( model : Model , outputDir : string ) {
5658 fs . mkdirSync ( outputDir , { recursive : true } ) ;
5759
60+ // Reset the flag for each generation
61+ this . usedExpressionUtils = false ;
62+
5863 // the schema itself
5964 this . generateSchema ( model , outputDir ) ;
6065
@@ -82,6 +87,10 @@ export class TsSchemaGenerator {
8287 ( d ) => isDataModel ( d ) && d . fields . some ( ( f ) => hasAttribute ( f , '@computed' ) ) ,
8388 ) ;
8489
90+ // Generate schema content first to determine if ExpressionUtils is needed
91+ const schemaObject = this . createSchemaObject ( model ) ;
92+
93+ // Now generate the import declaration with the correct imports
8594 const runtimeImportDecl = ts . factory . createImportDeclaration (
8695 undefined ,
8796 ts . factory . createImportClause (
@@ -98,7 +107,15 @@ export class TsSchemaGenerator {
98107 ) ,
99108 ]
100109 : [ ] ) ,
101- ts . factory . createImportSpecifier ( false , undefined , ts . factory . createIdentifier ( 'ExpressionUtils' ) ) ,
110+ ...( this . usedExpressionUtils
111+ ? [
112+ ts . factory . createImportSpecifier (
113+ false ,
114+ undefined ,
115+ ts . factory . createIdentifier ( 'ExpressionUtils' ) ,
116+ ) ,
117+ ]
118+ : [ ] ) ,
102119 ] ) ,
103120 ) ,
104121 ts . factory . createStringLiteral ( '@zenstackhq/runtime/schema' ) ,
@@ -114,10 +131,7 @@ export class TsSchemaGenerator {
114131 undefined ,
115132 undefined ,
116133 ts . factory . createSatisfiesExpression (
117- ts . factory . createAsExpression (
118- this . createSchemaObject ( model ) ,
119- ts . factory . createTypeReferenceNode ( 'const' ) ,
120- ) ,
134+ ts . factory . createAsExpression ( schemaObject , ts . factory . createTypeReferenceNode ( 'const' ) ) ,
121135 ts . factory . createTypeReferenceNode ( 'SchemaDef' ) ,
122136 ) ,
123137 ) ,
@@ -137,6 +151,15 @@ export class TsSchemaGenerator {
137151 statements . push ( typeDeclaration ) ;
138152 }
139153
154+ private createExpressionUtilsCall ( method : string , args ?: ts . Expression [ ] ) : ts . CallExpression {
155+ this . usedExpressionUtils = true ;
156+ return ts . factory . createCallExpression (
157+ ts . factory . createPropertyAccessExpression ( ts . factory . createIdentifier ( 'ExpressionUtils' ) , method ) ,
158+ undefined ,
159+ args || [ ] ,
160+ ) ;
161+ }
162+
140163 private createSchemaObject ( model : Model ) {
141164 const properties : ts . PropertyAssignment [ ] = [
142165 // provider
@@ -477,40 +500,28 @@ export class TsSchemaGenerator {
477500 ts . factory . createPropertyAssignment (
478501 'default' ,
479502
480- ts . factory . createCallExpression (
481- ts . factory . createIdentifier ( 'ExpressionUtils.call' ) ,
482- undefined ,
483- [
484- ts . factory . createStringLiteral ( defaultValue . call ) ,
485- ...( defaultValue . args . length > 0
486- ? [
487- ts . factory . createArrayLiteralExpression (
488- defaultValue . args . map ( ( arg ) => this . createLiteralNode ( arg ) ) ,
489- ) ,
490- ]
491- : [ ] ) ,
492- ] ,
493- ) ,
503+ this . createExpressionUtilsCall ( 'call' , [
504+ ts . factory . createStringLiteral ( defaultValue . call ) ,
505+ ...( defaultValue . args . length > 0
506+ ? [
507+ ts . factory . createArrayLiteralExpression (
508+ defaultValue . args . map ( ( arg ) => this . createLiteralNode ( arg ) ) ,
509+ ) ,
510+ ]
511+ : [ ] ) ,
512+ ] ) ,
494513 ) ,
495514 ) ;
496515 } else if ( 'authMember' in defaultValue ) {
497516 objectFields . push (
498517 ts . factory . createPropertyAssignment (
499518 'default' ,
500- ts . factory . createCallExpression (
501- ts . factory . createIdentifier ( 'ExpressionUtils.member' ) ,
502- undefined ,
503- [
504- ts . factory . createCallExpression (
505- ts . factory . createIdentifier ( 'ExpressionUtils.call' ) ,
506- undefined ,
507- [ ts . factory . createStringLiteral ( 'auth' ) ] ,
508- ) ,
509- ts . factory . createArrayLiteralExpression (
510- defaultValue . authMember . map ( ( m ) => ts . factory . createStringLiteral ( m ) ) ,
511- ) ,
512- ] ,
513- ) ,
519+ this . createExpressionUtilsCall ( 'member' , [
520+ this . createExpressionUtilsCall ( 'call' , [ ts . factory . createStringLiteral ( 'auth' ) ] ) ,
521+ ts . factory . createArrayLiteralExpression (
522+ defaultValue . authMember . map ( ( m ) => ts . factory . createStringLiteral ( m ) ) ,
523+ ) ,
524+ ] ) ,
514525 ) ,
515526 ) ;
516527 } else {
@@ -1015,7 +1026,7 @@ export class TsSchemaGenerator {
10151026 }
10161027
10171028 private createThisExpression ( ) {
1018- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. _this') , undefined , [ ] ) ;
1029+ return this . createExpressionUtilsCall ( ' _this') ;
10191030 }
10201031
10211032 private createMemberExpression ( expr : MemberAccessExpr ) {
@@ -1034,39 +1045,37 @@ export class TsSchemaGenerator {
10341045 ts . factory . createArrayLiteralExpression ( members . map ( ( m ) => ts . factory . createStringLiteral ( m ) ) ) ,
10351046 ] ;
10361047
1037- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. member') , undefined , args ) ;
1048+ return this . createExpressionUtilsCall ( ' member', args ) ;
10381049 }
10391050
10401051 private createNullExpression ( ) {
1041- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. _null') , undefined , [ ] ) ;
1052+ return this . createExpressionUtilsCall ( ' _null') ;
10421053 }
10431054
10441055 private createBinaryExpression ( expr : BinaryExpr ) {
1045- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. binary') , undefined , [
1056+ return this . createExpressionUtilsCall ( ' binary', [
10461057 this . createExpression ( expr . left ) ,
10471058 this . createLiteralNode ( expr . operator ) ,
10481059 this . createExpression ( expr . right ) ,
10491060 ] ) ;
10501061 }
10511062
10521063 private createUnaryExpression ( expr : UnaryExpr ) {
1053- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. unary') , undefined , [
1064+ return this . createExpressionUtilsCall ( ' unary', [
10541065 this . createLiteralNode ( expr . operator ) ,
10551066 this . createExpression ( expr . operand ) ,
10561067 ] ) ;
10571068 }
10581069
10591070 private createArrayExpression ( expr : ArrayExpr ) : any {
1060- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. array') , undefined , [
1071+ return this . createExpressionUtilsCall ( ' array', [
10611072 ts . factory . createArrayLiteralExpression ( expr . items . map ( ( item ) => this . createExpression ( item ) ) ) ,
10621073 ] ) ;
10631074 }
10641075
10651076 private createRefExpression ( expr : ReferenceExpr ) : any {
10661077 if ( isDataField ( expr . target . ref ) ) {
1067- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils.field' ) , undefined , [
1068- this . createLiteralNode ( expr . target . $refText ) ,
1069- ] ) ;
1078+ return this . createExpressionUtilsCall ( 'field' , [ this . createLiteralNode ( expr . target . $refText ) ] ) ;
10701079 } else if ( isEnumField ( expr . target . ref ) ) {
10711080 return this . createLiteralExpression ( 'StringLiteral' , expr . target . $refText ) ;
10721081 } else {
@@ -1075,7 +1084,7 @@ export class TsSchemaGenerator {
10751084 }
10761085
10771086 private createCallExpression ( expr : InvocationExpr ) {
1078- return ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils. call') , undefined , [
1087+ return this . createExpressionUtilsCall ( ' call', [
10791088 ts . factory . createStringLiteral ( expr . function . $refText ) ,
10801089 ...( expr . args . length > 0
10811090 ? [ ts . factory . createArrayLiteralExpression ( expr . args . map ( ( arg ) => this . createExpression ( arg . value ) ) ) ]
@@ -1085,21 +1094,11 @@ export class TsSchemaGenerator {
10851094
10861095 private createLiteralExpression ( type : string , value : string | boolean ) {
10871096 return match ( type )
1088- . with ( 'BooleanLiteral' , ( ) =>
1089- ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils.literal' ) , undefined , [
1090- this . createLiteralNode ( value ) ,
1091- ] ) ,
1092- )
1097+ . with ( 'BooleanLiteral' , ( ) => this . createExpressionUtilsCall ( 'literal' , [ this . createLiteralNode ( value ) ] ) )
10931098 . with ( 'NumberLiteral' , ( ) =>
1094- ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils.literal' ) , undefined , [
1095- ts . factory . createIdentifier ( value as string ) ,
1096- ] ) ,
1097- )
1098- . with ( 'StringLiteral' , ( ) =>
1099- ts . factory . createCallExpression ( ts . factory . createIdentifier ( 'ExpressionUtils.literal' ) , undefined , [
1100- this . createLiteralNode ( value ) ,
1101- ] ) ,
1099+ this . createExpressionUtilsCall ( 'literal' , [ ts . factory . createIdentifier ( value as string ) ] ) ,
11021100 )
1101+ . with ( 'StringLiteral' , ( ) => this . createExpressionUtilsCall ( 'literal' , [ this . createLiteralNode ( value ) ] ) )
11031102 . otherwise ( ( ) => {
11041103 throw new Error ( `Unsupported literal type: ${ type } ` ) ;
11051104 } ) ;
0 commit comments