import { AnyShape , BinaryShape , BoolShape , EnumShape , IntegerShape , isOptional , LiteralShape , Meta , NeverShape , NumberShape , Shape , ShapeGuards , ShapeVisitor , string , StringShape , TimestampShape , TypeShape , UnionShape } from '@punchcard/shape' ; import { ArrayShape , MapShape , SetShape } from '@punchcard/shape/lib/collection' ; import { FunctionArgs , FunctionShape } from '@punchcard/shape/lib/function' ; import { AnySchema , ArraySchema , BinarySchema , BoolSchema , EnumSchema , IntegerSchema , JsonSchema , MapSchema , NothingSchema , NumberSchema , ObjectSchema , SetSchema , StringSchema , TimestampSchema } from './json-schema' ; /**
 * Transforms a Shape into its corresponding JSON Schema representation.
 */ export class ToJsonSchemaVisitor implements ShapeVisitor < JsonSchema , undefined > { public enumShape ( shape , context ) { return { type : 'string' , enum : Object . values ( shape . Values ) } ; } public neverShape ( shape , context ) { throw new Error ( "JSON schema does not support never types" ) ; } public literalShape ( shape , context ) { throw new Error ( "Method not implemented." ) ; } public unionShape ( shape , context ) { const items = shape . Items . filter ( i => ! ShapeGuards . isNothingShape ( i ) ) ; if ( items . length === 1 ) { return items [ 0 ] . visit ( this , context ) ; } return { oneOf : shape . Items . map ( s => s . visit ( this , context ) ) } as any ; } public functionShape ( shape ) { throw new Error ( "JSON schema does not support function types" ) ; } public anyShape ( shape , context ) { return { type : { } } ; } public binaryShape ( shape , context ) { return { ... ( Meta . get ( shape , [ 'minLength' , 'maxLength' ] ) || { } ) , type : 'string' , format : 'base64' } as any ; } public boolShape ( shape ) { return { type : 'boolean' } ; } public stringShape ( shape ) { return { type : 'string' , ... ( Meta . get ( shape , [ 'minLength' , 'maxLength' , 'pattern' ] ) || { } ) } as any ; } public timestampShape ( shape ) { return { type : 'string' , format : 'date-time' } ; } public nothingShape ( ) { return { type : 'null' } ; } public numberShape ( shape ) { return { type : 'number' , ... ( Meta . get ( shape , [ 'minimum' , 'maximum' , 'exclusiveMinimum' , 'exclusiveMaximum' , 'multipleOf' ] ) || { } ) } as any ; } public integerShape ( shape ) { return { type : 'integer' , ... ( Meta . get ( shape , [ 'minimum' , 'maximum' , 'exclusiveMinimum' , 'exclusiveMaximum' , 'multipleOf' ] ) || { } ) } as any ; } public arrayShape ( shape ) { return { type : 'array' , uniqueItems : false , items : shape . Items . visit ( this ) } ; } public setShape ( shape ) { return { type : 'array' , uniqueItems : true , items : shape . Items . visit ( this ) } ; } public mapShape ( shape ) { return { type : 'object' , properties : { } , additionalProperties : shape . Items . visit ( this ) , allowAdditionalProperties : true , } ; } public recordShape ( shape ) { const required = ( Object . entries ( shape . Members ) as [ string , Shape ] [ ] ) . map ( ( [ name , member ] ) => { return isOptional ( member ) || ShapeGuards . isNothingShape ( member ) ? [ ] : [ name ] ; } ) . reduce ( ( a , b ) => a . concat ( b ) , [ ] ) ; const schema = { type : 'object' , properties : Object . entries ( shape . Members ) . map ( ( [ name , member ] ) => ( { [ name ] : ( member as any ) . visit ( this ) } ) ) . reduce ( ( a , b ) => ( { ... a , ... b } ) , { } ) } ; if ( required . length > 0 ) { schema . required = required ; } return schema ; } }