@@ -12,7 +12,19 @@ import {
1212 requireOption ,
1313 resolvePath ,
1414} from '@zenstackhq/sdk' ;
15- import { DataModel , DataModelField , DataModelFieldType , Enum , isDataModel , isEnum , Model } from '@zenstackhq/sdk/ast' ;
15+ import {
16+ DataModel ,
17+ DataModelField ,
18+ DataModelFieldType ,
19+ Enum ,
20+ isDataModel ,
21+ isEnum ,
22+ isTypeDef ,
23+ Model ,
24+ TypeDef ,
25+ TypeDefField ,
26+ TypeDefFieldType ,
27+ } from '@zenstackhq/sdk/ast' ;
1628import type { DMMF } from '@zenstackhq/sdk/prisma' ;
1729import fs from 'fs' ;
1830import { lowerCaseFirst } from 'lower-case-first' ;
@@ -79,6 +91,9 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
7991 security,
8092 } ;
8193
94+ // ensure output folder exists
95+ fs . mkdirSync ( path . dirname ( output ) , { recursive : true } ) ;
96+
8297 const ext = path . extname ( output ) ;
8398 if ( ext && ( ext . toLowerCase ( ) === '.yaml' || ext . toLowerCase ( ) === '.yml' ) ) {
8499 fs . writeFileSync ( output , YAML . stringify ( openapi ) ) ;
@@ -494,6 +509,8 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
494509 schema = this . ref ( fieldDecl . name ) ;
495510 } else if ( isDataModel ( fieldDecl ) ) {
496511 schema = { type : 'string' } ;
512+ } else if ( isTypeDef ( fieldDecl ) || field . type . type === 'Json' ) {
513+ schema = { type : 'string' , format : 'json' } ;
497514 } else {
498515 invariant ( field . type . type ) ;
499516 schema = this . fieldTypeToOpenAPISchema ( field . type ) ;
@@ -540,6 +557,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
540557 }
541558 }
542559
560+ // type defs
561+ for ( const typeDef of this . model . declarations . filter ( isTypeDef ) ) {
562+ schemas [ typeDef . name ] = this . generateTypeDefComponent ( typeDef ) ;
563+ }
564+
543565 return components ;
544566 }
545567
@@ -771,7 +793,7 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
771793 } ;
772794 }
773795
774- private generateEnumComponent ( _enum : Enum ) : OAPI . SchemaObject {
796+ private generateEnumComponent ( _enum : Enum ) {
775797 const schema : OAPI . SchemaObject = {
776798 type : 'string' ,
777799 description : `The "${ _enum . name } " Enum` ,
@@ -780,6 +802,18 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
780802 return schema ;
781803 }
782804
805+ private generateTypeDefComponent ( typeDef : TypeDef ) {
806+ const schema : OAPI . SchemaObject = {
807+ type : 'object' ,
808+ description : `The "${ typeDef . name } " TypeDef` ,
809+ properties : typeDef . fields . reduce ( ( acc , field ) => {
810+ acc [ field . name ] = this . generateField ( field ) ;
811+ return acc ;
812+ } , { } as Record < string , OAPI . SchemaObject > ) ,
813+ } ;
814+ return schema ;
815+ }
816+
783817 private generateDataModelComponents ( model : DataModel ) {
784818 const result : Record < string , OAPI . SchemaObject > = { } ;
785819 result [ `${ model . name } ` ] = this . generateModelEntity ( model , 'read' ) ;
@@ -945,14 +979,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
945979 return result ;
946980 }
947981
948- private generateField ( field : DataModelField ) {
982+ private generateField ( field : DataModelField | TypeDefField ) {
949983 return this . wrapArray (
950984 this . wrapNullable ( this . fieldTypeToOpenAPISchema ( field . type ) , field . type . optional ) ,
951985 field . type . array
952986 ) ;
953987 }
954988
955- private fieldTypeToOpenAPISchema ( type : DataModelFieldType ) : OAPI . ReferenceObject | OAPI . SchemaObject {
989+ private fieldTypeToOpenAPISchema (
990+ type : DataModelFieldType | TypeDefFieldType
991+ ) : OAPI . ReferenceObject | OAPI . SchemaObject {
956992 return match ( type . type )
957993 . with ( 'String' , ( ) => ( { type : 'string' } ) )
958994 . with ( P . union ( 'Int' , 'BigInt' ) , ( ) => ( { type : 'integer' } ) )
0 commit comments