import type * as tsc from "typescript" ; import { Pair } from "tstl/utility/Pair" ; import { Vector } from "tstl/container/Vector" ; import { IRoute } from "../structures/IRoute" ; export namespace FunctionGenerator { export function generate ( route ) { const query = route . parameters . find ( param => param . category === "query" ) ; const input = route . parameters . find ( param => param . category === "body" ) ; return [ head , body , tail ] . map ( closure => closure ( route , query , input ) ) . filter ( str => ! ! str ) . join ( "\n" ) ; } function body ( route , query , input ) { const parameters = filter_parameters ( route , query ) ; const fetchArguments = [ "connection" , `${ route . name }.ENCRYPTED` , `${ route . name }.METHOD` , `${ route . name }.path(${ parameters . map ( p => p . name ) . join ( ", " ) })` ] ; if ( input !== undefined ) fetchArguments . push ( input . name ) ; return "{\n" + "    return Fetcher.fetch\n" + "    (\n" + fetchArguments . map ( param => `        ${ param }` ) . join ( ",\n" ) + "\n" + "    );\n" + "}" ; } function filter_parameters ( route , query ) { const parameters = route . parameters . filter ( param => param . category === "param" ) ; if ( query ) parameters . push ( query ) ; return parameters ; } function head ( route , query , input ) { let comment = route . comments . map ( comment => `${ comment . kind === "linkText" ? " " : "" }${ comment . text }` ) . join ( "" ) ; if ( comment !== "" ) comment += "\n\n" ; const tagList = route . tags . filter ( tag => tag . text !== undefined ) ; if ( tagList . length !== 0 ) { const index = tagList . findIndex ( t => t . name === "param" ) ; if ( index !== - 1 ) { const capsule = Vector . wrap ( tagList ) ; capsule . insert ( capsule . nth ( index ) , { name : "param" , text : [ { kind : "parameterName" , text : "connection" } , { kind : "space" , text : " " } , { kind : "text" , text : "connection Information of the remote HTTP(s) server with headers (+encryption password)" } ] } ) ; } comment += tagList . map ( tag => `@${ tag . name } ${ tag . text ! . map ( elem => elem . text ) . join ( "" ) }` ) . join ( "\n" ) + "\n\n" ; } comment += `@nestia Generated by Nestia - https://github.com/samchon/nestia\n` ; comment += `@controller ${ route . symbol }\n` ; comment += `@path ${ route . method } ${ route . path }` ; const parameters = [ "connection: IConnection" , ... route . parameters . map ( param => { const type = ( param === query || param === input ) ? `Primitive<${ route . name }.${ param === query ? "Query" : "Input" }>` : param . type ; return `${ param . name }: ${ type }` ; } ) ] ; const output = route . output === "void" ? "void" : `${ route . name }.Output` ; return "" + "/**\n" + comment . split ( "\r\n" ) . join ( "\n" ) . split ( "\n" ) . map ( str => ` * ${ str }` ) . join ( "\n" ) + "\n" + " */\n" + `export function ${ route . name }\n` + `    (\n` + `${ parameters . map ( str => `        ${ str }` ) . join ( ",\n" ) }\n` + `    ): Promise<${ output }>` ; } function tail ( route , query , input ) { const types = [ ] ; if ( query !== undefined ) types . push ( new Pair ( "Query" , query . type ) ) ; if ( input !== undefined ) types . push ( new Pair ( "Input" , input . type ) ) ; if ( route . output !== "void" ) types . push ( new Pair ( "Output" , route . output ) ) ; const parameters = filter_parameters ( route , query ) ; let path = route . path ; for ( const param of parameters ) if ( param . category === "param" ) path = path . replace ( `:${ param . field }` , `\${${ param . name }}` ) ; path = ( query !== undefined ) ? `\`${ path }?\${new URLSearchParams(${ query . name } as any).toString()}\`` : `\`${ path }\`` ; return `export namespace ${ route . name }\n` + "{\n" + ( types . length !== 0 ? types . map ( tuple => `    export type ${ tuple . first } = Primitive<${ tuple . second }>;` ) . join ( "\n" ) + "\n" : "" ) + "\n" + `    export const METHOD = "${ route . method }" as const;\n` + `    export const PATH: string = "${ route . path }";\n` + `    export const ENCRYPTED: Fetcher.IEncrypted = {\n` + `        request: ${ input !== undefined && input . encrypted },\n` + `        response: ${ route . encrypted },\n` + `    };\n` + "\n" + `    export function path(${ parameters . map ( param => `${ param . name }: ${ param . type }` ) . join ( ", " ) }): string\n` + `    {\n` + `        return ${ path };\n` + `    }\n` + "}" ; } }