Valeriy Kuzmin, Moonfare, Berlin, 2022
Plan
Problem π§ͺ
Swagger / OpenAPI
/**
* @swagger
*
* /v3/documents/:documentId/download:
* get:
* description: <truncated>
* consumes:
* - application/json
* produces:
* - application/octet-stream
* parameters:
* - in: path
* name: documentId
* required: true
* type: string
* responses:
* "200":
* description: ok
*
* */
Goals π―
Solution overview
DTOs
docs/**/*.yaml
@swagger comments
*.swagger.yaml
*.swagger.yaml
*.swagger.yaml
mf_spec.yaml
Controllers
Swaggershift
Implementation details
Pipeline
derive-comments
derive-comments
derive-comments
dto-to-comments
derive-comments
aux.json
derive-comments
swagger.yaml
derive-comments
ast-tools cache
derive-comments
comments + lint
Controller anatomy
@Routing.ApiController(ROUTE_PREFIX_V1, '/root-url/root-2')
class Controller {
...
}
Method anatomy
@Routing.Get('/:id/some-string/:some-other-id(\\d+)')
@Routing.HttpCode(HTTP.OK)
@Routing.Authorized([Roles.DOCUMENT_ADMIN])
@Routing.ContentType('application/json')
public async paramsAndQueryMethod(@Routing.Param('id') _categoryId: number): Promise<{}> {
...
}
Parameter anatomy - query & path
@Routing.Get('/referrals/list/:id')
public async doesNotEatDecorators(
@Routing.Param('id') id: number,
@Routing.QueryParam('hint') hint: number,
@Routing.QueryParam('hint2') hint2: boolean,
@Routing.QueryParam('order') order: 'ASC' | 'DESC' = 'DESC',
@Routing.QueryParam('perPage') perPage = DEFAULT_RESULTS_PER_PAGE,
) {
...
}
Parameter anatomy - body & bodyParam
@Routing.Post('/')
@Routing.HttpCode(HTTP.OK)
public async fullBodyMethod(
@Routing.Body() _body: SomeDTO
): Promise<void> {
...
}
@Routing.Put('/')
@Routing.HttpCode(HTTP.OK)
public async virtualBodyMethod(
@Routing.BodyParam('dtoAsBodyField') _body: SomeDTO
): Promise<void> {
...
}
Type mapping - params & DTOs
export interface MyInterfaceDTO {
count: number,
name: string,
flag: boolean,
strangeStuff: Partial<MyTypeDTO>,
}
export type MyTypeDTO = {
count: number,
name: string,
flag: boolean,
extra: SomeOtherType,
parts: Array<string>,
};
Testing
// __testfixtures__/name.input.ts
SomeCode
// __testfixtures__/name.output.ts
SomeTransformedCode
// __testfixtures__/name.side-effect.ts
Stuff that is written into files
// .spec
runAsyncTestWithSideEffects(name)
// βοΈ it is possible to pass options to transforms!
unit-tests:ast-tools
Augmentation & tricks
Limitations & further plans π₯
Questions?