import isEmpty from "lodash.isempty" ; import { Schema , DataSource , DataSourceURLEnv , Model , ObjectField , ScalarField , FieldKind , BaseField , Generator , CallExpression , ScalarFieldDefault , Enum , } from "./types" ; import { formatSchema } from "@prisma/sdk" ; type Relation = { name ? : string | null ; fields ? : string [ ] ; references ? : string [ ] ; } ; param schema returns export async function print ( schema ) { const statements = [ ] ; if ( schema . dataSource ) { statements . push ( printDataSource ( schema . dataSource ) ) ; } if ( schema . generators . length ) { statements . push ( ... schema . generators . map ( printGenerator ) ) ; } statements . push ( ... schema . models . map ( printModel ) ) ; statements . push ( ... schema . enums . map ( printEnum ) ) ; const schemaText = statements . join ( "\n" ) ; return formatSchema ( { schema : schemaText } ) ; } param schema returns export function printDataSource ( dataSource ) { const url = printDataSourceURL ( dataSource . url ) ; return `datasource ${ dataSource . name } {
  provider = "${ dataSource . provider }"
  url      = ${ url }
}` ; } function printDataSourceURL ( url ) { return url instanceof DataSourceURLEnv ? `env("${ url . name }")` : `"${ url }"` ; } export function printGenerator ( generator ) { const fields = [ `provider = "${ generator . provider }"` ] ; if ( generator . output ) { fields . push ( `output = "${ generator . output }"` ) ; } if ( generator . binaryTargets . length ) { fields . push ( `binaryTargets = ${ JSON . stringify ( generator . binaryTargets ) }` ) ; } return `generator ${ generator . name } {
  ${ fields . join ( "\n  " ) }
}` ; } param documentation returns export function printDocumentation ( documentation ) { return `/// ${ documentation }` ; } param documentation param code returns function withDocumentation ( documentation , code ) { if ( documentation ) { return [ printDocumentation ( documentation ) , code ] . join ( "\n" ) ; } return code ; } param enum_ returns export function printEnum ( enum_ ) { const valuesText = enum_ . values . join ( "\n" ) ; return withDocumentation ( enum_ . documentation , `enum ${ enum_ . name } {\n${ valuesText }\n}` ) ; } param model returns export function printModel ( model ) { const fieldTexts = model . fields . map ( printField ) . join ( "\n" ) ; return withDocumentation ( model . documentation , `model ${ model . name } {\n${ fieldTexts }\n}` ) ; } param field returns export function printField ( field ) { return withDocumentation ( field . documentation , field . kind === FieldKind . Scalar ? printScalarField ( field ) : printObjectField ( field ) ) ; } function printScalarField ( field ) { const modifiersText = printFieldModifiers ( field ) ; const attributes = [ ] ; if ( field . isId ) { attributes . push ( "@id" ) ; } if ( field . isUnique ) { attributes . push ( "@unique" ) ; } if ( field . isUpdatedAt ) { attributes . push ( "@updatedAt" ) ; } if ( field . default ) { attributes . push ( `@default(${ printScalarDefault ( field . default ) })` ) ; } const typeText = `${ field . type }${ modifiersText }` ; const attributesText = attributes . join ( " " ) ; return [ field . name , typeText , attributesText ] . filter ( Boolean ) . join ( " " ) ; } function printScalarDefault ( value ) { if ( typeof value === "string" ) { return value ; } if ( typeof value === "boolean" ) { return String ( value ) ; } if ( typeof value === "number" ) { return String ( value ) ; } if ( value instanceof CallExpression ) { return `${ value . callee }()` ; } throw new Error ( `Invalid value: ${ value }` ) ; } function printObjectField ( field ) { const relation = { } ; if ( field . relationName ) { relation . name = field . relationName ; } if ( field . relationToFields . length ) { relation . fields = field . relationToFields ; } if ( field . relationToReferences . length ) { relation . references = field . relationToReferences ; } const attributes = [ ] ; if ( ! isEmpty ( relation ) ) { attributes . push ( printRelation ( relation ) ) ; } const typeText = `${ field . type }${ printFieldModifiers ( field ) }` ; const attributesText = attributes . join ( " " ) ; return [ field . name , typeText , attributesText ] . filter ( Boolean ) . join ( " " ) ; } function printFieldModifiers ( field ) { const modifiers = [ ] ; if ( field . isList ) { modifiers . push ( "[]" ) ; } if ( ! field . isRequired ) { modifiers . push ( "?" ) ; } return modifiers . join ( "" ) ; } function printRelation ( relation ) { const nameText = relation . name ? `name: "${ relation . name }"` : "" ; const fieldsText = relation . fields ? `fields: [${ relation . fields }]` : "" ; const referencesText = relation . references ? `references: [${ relation . references }]` : "" ; return `@relation(${ [ nameText , fieldsText , referencesText ] . filter ( Boolean ) . join ( ", " ) })` ; }