Skip to content
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ CLI to help you set up a Node.js TypeScript project. The setup includes:

## Usage

Run directly from GitHub repo via npx:
Run directly from npm via npx:

```
Usage: npm exec --ignore-scripts -- github:AckeeCZ/create-node-app [OPTIONS]
Usage: npx @ackee/create-node-app [OPTIONS]

Options:
-d, --dir Destination directory [string] [default: "./node-app"]
Expand Down
2 changes: 1 addition & 1 deletion src/Bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class Bootstrap {
}

cli = cli
.version('1.0.0')
.version()
.help()
.check(argv => {
for (const [key, val] of Object.entries(argv)) {
Expand Down
7 changes: 7 additions & 0 deletions starter/api/rest/src/view/cli/openapi/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,16 @@ export const run = async (argv: any): Promise<void> => {
const pathSpec = spec.paths[path]
Object.keys(pathSpec).forEach(method => {
if (pathSpec[method]?.operationId) {
const operationResponses = pathSpec[method].responses ?? {}
const responseCodes = Object.keys(operationResponses)
const successStatus = responseCodes.find(s => s.startsWith('2'))
?? responseCodes.find(s => s.startsWith('3'))
?? '200';

acc[pathSpec[method].operationId] = {
method,
path,
successStatus: parseInt(successStatus, 10),
}
}
})
Expand Down
31 changes: 25 additions & 6 deletions starter/api/rest/src/view/rest/util/openapi.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,25 @@ export type ApiHandler<TRes> = (
) => TRes | Promise<TRes>

const asyncHandler =
<TRes>(fn: ApiHandler<TRes>): express.Handler =>
<TRes>(fn: ApiHandler<TRes>, operationId?: OperationIds): express.Handler =>
async (req, res, next) => {
try {
if (operationId) {
const metadata = operationPaths[operationId]
if (metadata?.successStatus) {
res.status(metadata.successStatus)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: This will overwrite the status user set right?

Imagine having two possible success statuses for operation (200 and 2xx or 200 and 3xx) for example based on Accept header of the client request. If the dev sets the status before the async handler is called, this will overwrite it to 200.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I moved the status code assignment before we execute the operation handler, so anything set by user will overwrite it.

}
}

const result = await fn(req.context, req, res)
res.json(result)

if (!res.headersSent) {
if (result != undefined) {
res.json(result)
} else {
res.end()
}
}
} catch (error: unknown) {
next(error)
}
Expand Down Expand Up @@ -158,7 +172,7 @@ type MimeContentValue<
type OpenApiContentTypes<OpenApiContent extends Record<number, any>> = {
[K in keyof OpenApiContent]: OpenApiContent[K] extends Content
? MimeContentValue<ApiMimeTypes, OpenApiContent[K]>
: never
: void
}[keyof OpenApiContent]

export type OperationParams<OperationId extends OperationIds> =
Expand Down Expand Up @@ -200,8 +214,9 @@ export type RestApiController<
}

const handleOperationAsync = <OperationId extends OperationIds>(
fn: OperationHandler<OperationId>
): OpenApiHandler<OperationId> => asyncHandler(fn as any) as any
fn: OperationHandler<OperationId>,
operationId: OperationId
): OpenApiHandler<OperationId> => asyncHandler(fn as any, operationId) as any

const createRestController = <SubsetOperationIds extends OperationIds>(
def: RouteHandlers<SubsetOperationIds>
Expand All @@ -211,7 +226,8 @@ const createRestController = <SubsetOperationIds extends OperationIds>(
return ctrl
}
ctrl[operationId as SubsetOperationIds] = handleOperationAsync(
handler as any
handler as any,
operationId as SubsetOperationIds
) as any
return ctrl
}, {} as RestApiController<SubsetOperationIds>)
Expand Down Expand Up @@ -245,6 +261,9 @@ export const openApiRouter = (
case 'post':
router.post(route, handler)
break
case 'PUT':
router.put(route, handler)
break
case 'patch':
router.patch(route, handler)
break
Expand Down