66 IROperation ,
77 IRParameter ,
88} from "../../core/openapi-types-normalized"
9- import { isDefined , titleCase } from "../../core/utils"
9+ import { titleCase } from "../../core/utils"
1010import { OpenapiGeneratorConfig } from "../../templates.types"
1111import { CompilationUnit , ICompilable } from "../common/compilation-units"
1212import { ImportBuilder } from "../common/import-builder"
@@ -74,7 +74,6 @@ export class ServerRouterBuilder implements ICompilable {
7474 . add (
7575 "startServer" ,
7676 "ServerConfig" ,
77- "Response" ,
7877 "KoaRuntimeResponse" ,
7978 "KoaRuntimeResponder" ,
8079 "StatusCode2xx" ,
@@ -84,13 +83,12 @@ export class ServerRouterBuilder implements ICompilable {
8483 "StatusCode" ,
8584 )
8685
86+ this . imports . from ( "next/server" ) . add ( "NextRequest" )
87+
8788 this . imports
8889 . from ( "@nahkies/typescript-koa-runtime/errors" )
8990 . add ( "KoaRuntimeError" , "RequestInputType" )
9091
91- this . imports . addModule ( "KoaRouter" , "@koa/router" )
92- this . imports . from ( "@koa/router" ) . add ( "RouterContext" )
93-
9492 if ( schemaBuilder instanceof ZodBuilder ) {
9593 imports
9694 . from ( "@nahkies/typescript-koa-runtime/zod" )
@@ -236,82 +234,63 @@ export class ServerRouterBuilder implements ICompilable {
236234 : " | undefined" )
237235 } >,
238236 respond: ${ titleCase ( operation . operationId ) + "Responder" } ,
239- ctx: RouterContext
240- ) => Promise<KoaRuntimeResponse<unknown> | ${ [
241- ...responseSchemas . specific . map (
242- ( it ) => `Response<${ it . statusType } , ${ it . type } >` ,
243- ) ,
244- responseSchemas . defaultResponse &&
245- `Response<StatusCode, ${ responseSchemas . defaultResponse . type } >` ,
246- ]
247- . filter ( isDefined )
248- . join ( " | " ) } >`,
237+ ctx: {request: NextRequest}
238+ ) => Promise<KoaRuntimeResponse<unknown>>` ,
249239 kind : "type" ,
250240 } ) ,
251241 ] ,
252242 } )
253243
254244 this . statements . push (
255- [
256- `const ${
257- operation . operationId
258- } ResponseValidator = responseValidationFactory([${ responseSchemas . specific . map (
259- ( it ) => `["${ it . statusString } ", ${ it . schema } ]` ,
260- ) }
261- ], ${ responseSchemas . defaultResponse ?. schema } )` ,
262- "" ,
263- `router.${ operation . method . toLowerCase ( ) } ('${
264- operation . operationId
265- } ','${ route ( operation . route ) } ',`,
266- `async (ctx, next) => {
267-
268- const input = {
245+ buildExport ( {
246+ name : operation . method . toUpperCase ( ) ,
247+ kind : "const" ,
248+ value : `async (request: NextRequest, {params}: {params: unknown}): Promise<Response> => {
249+ const input = {
269250 params: ${
270251 paramSchema
271- ? `parseRequestInput(${ operation . operationId } ParamSchema, ctx. params, RequestInputType.RouteParam)`
252+ ? `parseRequestInput(${ operation . operationId } ParamSchema, params, RequestInputType.RouteParam)`
272253 : "undefined"
273254 } ,
255+ // TODO: this swallows repeated parameters
274256 query: ${
275257 querySchema
276- ? `parseRequestInput(${ operation . operationId } QuerySchema, ctx.query , RequestInputType.QueryString)`
258+ ? `parseRequestInput(${ operation . operationId } QuerySchema, Object.fromEntries(request.nextUrl.searchParams.entries()) , RequestInputType.QueryString)`
277259 : "undefined"
278260 } ,
279261 body: ${
280262 bodyParamSchema
281- ? `parseRequestInput(${ operation . operationId } BodySchema, Reflect.get(ctx.request, "body" ), RequestInputType.RequestBody)`
263+ ? `parseRequestInput(${ operation . operationId } BodySchema, await request.json( ), RequestInputType.RequestBody)`
282264 : "undefined"
283- } ,
265+ }
284266 }
285267
286- const responder = {${ [
287- ...responseSchemas . specific . map ( ( it ) =>
288- it . isWildCard
289- ? `with${ it . statusType } (status: ${ it . statusType } ) {return new KoaRuntimeResponse<${ it . type } >(status) }`
290- : `with${ it . statusType } () {return new KoaRuntimeResponse<${ it . type } >(${ it . statusType } ) }` ,
291- ) ,
292- responseSchemas . defaultResponse &&
293- `withDefault(status: StatusCode) { return new KoaRuntimeResponse<${ responseSchemas . defaultResponse . type } >(status) }` ,
294- "withStatus(status: StatusCode) { return new KoaRuntimeResponse(status)}" ,
295- ]
296- . filter ( Boolean )
297- . join ( ",\n" ) } }
298-
299- const response = await implementation.${ operation . operationId } (input, responder, ctx)
300- .catch(err => { throw KoaRuntimeError.HandlerError(err) })
301-
302-
303- const {
268+ const responder = {${ [
269+ ...responseSchemas . specific . map ( ( it ) =>
270+ it . isWildCard
271+ ? `with${ it . statusType } (status: ${ it . statusType } ) {return new KoaRuntimeResponse<${ it . type } >(status) }`
272+ : `with${ it . statusType } () {return new KoaRuntimeResponse<${ it . type } >(${ it . statusType } ) }` ,
273+ ) ,
274+ responseSchemas . defaultResponse &&
275+ `withDefault(status: StatusCode) { return new KoaRuntimeResponse<${ responseSchemas . defaultResponse . type } >(status) }` ,
276+ "withStatus(status: StatusCode) { return new KoaRuntimeResponse(status)}" ,
277+ ]
278+ . filter ( Boolean )
279+ . join ( ",\n" ) } }
280+
281+ const {
304282 status,
305283 body,
306- } = response instanceof KoaRuntimeResponse ? response.unpack() : response
307-
308- ctx.body = ${ operation . operationId } ResponseValidator(status, body)
309- ctx.status = status
310- return next();
311- })` ,
312- ]
313- . filter ( isDefined )
314- . join ( "\n" ) ,
284+ } = await import('@/${ this . filename
285+ . replace ( "src/app" , "lib" )
286+ . replace ( ".ts" , "" ) } ')
287+ .then(it => it.GET(input, responder, { request }))
288+ .then(it => it.unpack())
289+ .catch(err => { throw KoaRuntimeError.HandlerError(err) })
290+
291+ return Response.json(body, {status})
292+ }` ,
293+ } ) ,
315294 )
316295 }
317296
@@ -323,24 +302,7 @@ ${this.existingRegions["header"] ?? ""}
323302//endregion safe-edit-region-header
324303${ this . operationTypes . flatMap ( ( it ) => it . statements ) . join ( "\n\n" ) }
325304
326- ${ buildExport ( {
327- name : "Implementation" ,
328- value : object (
329- this . operationTypes
330- . map ( ( it ) => it . operationId )
331- . map ( ( key ) => `${ key } : ${ titleCase ( key ) } ` )
332- . join ( "," ) ,
333- ) ,
334- kind : "type" ,
335- } ) }
336-
337- export function createRouter(implementation: Implementation): KoaRouter {
338- const router = new KoaRouter()
339-
340- ${ routes . join ( "\n\n" ) }
341-
342- return router
343- }
305+ ${ routes . join ( "\n\n" ) }
344306`
345307 return code
346308 }
@@ -390,14 +352,6 @@ export class ServerBuilder implements ICompilable {
390352 }
391353}
392354
393- function route ( route : string ) : string {
394- const placeholder = / { ( [ ^ { } ] + ) } / g
395-
396- return Array . from ( route . matchAll ( placeholder ) ) . reduce ( ( result , match ) => {
397- return result . replace ( match [ 0 ] , ":" + match [ 1 ] )
398- } , route )
399- }
400-
401355export async function generateTypescriptNextJS (
402356 config : OpenapiGeneratorConfig ,
403357) : Promise < void > {
@@ -470,7 +424,7 @@ function routeToNextJSFilepath(route: string): string {
470424 . split ( "/" )
471425 . map ( ( part ) => part . replaceAll ( "{" , "[" ) . replaceAll ( "}" , "]" ) )
472426
473- parts . push ( "route" )
427+ parts . push ( "route.ts " )
474428
475429 return path . join ( ...parts )
476430}
0 commit comments