configured openapi docs

main
Inga 🏳‍🌈 2 years ago
parent 023cd7b5c9
commit bfabff741d
  1. 5
      nest-cli.json
  2. 121
      package-lock.json
  3. 2
      package.json
  4. 7
      src/main.ts
  5. 24
      src/screenshots/screenshots.controller.ts
  6. 24
      src/screenshots/screenshots.dto.ts

@ -1,5 +1,8 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src"
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["@nestjs/swagger"]
}
}

121
package-lock.json generated

@ -14,6 +14,8 @@
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.0.0",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/swagger": "^6.0.1",
"class-validator": "^0.13.2",
"puppeteer": "^15.3.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
@ -1609,6 +1611,25 @@
}
}
},
"node_modules/@nestjs/mapped-types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.1.0.tgz",
"integrity": "sha512-+2kSly4P1QI+9eGt+/uGyPdEG1hVz7nbpqPHWZVYgoqz8eOHljpXPag+UCVRw9zo2XCu4sgNUIGe8Uk0+OvUQg==",
"peerDependencies": {
"@nestjs/common": "^7.0.8 || ^8.0.0 || ^9.0.0",
"class-transformer": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0",
"class-validator": "^0.11.1 || ^0.12.0 || ^0.13.0",
"reflect-metadata": "^0.1.12"
},
"peerDependenciesMeta": {
"class-transformer": {
"optional": true
},
"class-validator": {
"optional": true
}
}
},
"node_modules/@nestjs/platform-express": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.0.1.tgz",
@ -1645,6 +1666,29 @@
"typescript": "^4.3.5"
}
},
"node_modules/@nestjs/swagger": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-6.0.1.tgz",
"integrity": "sha512-rNpncETn+twpf3OPUtGO0MssEOd0cEqiklj2TZv+kAU9gmIWtC/p7Hf1hWbSp9C/l8vF1TnquK80oOaS2G0bAA==",
"dependencies": {
"@nestjs/mapped-types": "1.1.0",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"path-to-regexp": "3.2.0",
"swagger-ui-dist": "4.12.0"
},
"peerDependencies": {
"@fastify/static": "^6.0.0",
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0",
"reflect-metadata": "^0.1.12"
},
"peerDependenciesMeta": {
"@fastify/static": {
"optional": true
}
}
},
"node_modules/@nestjs/testing": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.0.1.tgz",
@ -2623,8 +2667,7 @@
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/array-flatten": {
"version": "1.1.1",
@ -3123,6 +3166,15 @@
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
"dev": true
},
"node_modules/class-validator": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
"dependencies": {
"libphonenumber-js": "^1.9.43",
"validator": "^13.7.0"
}
},
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@ -6063,7 +6115,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
},
@ -6162,6 +6213,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/libphonenumber-js": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.7.tgz",
"integrity": "sha512-jZXLCCWMe1b/HXkjiLeYt2JsytZMcqH26jLFIdzFDFF0xvSUWrYKyvPlyPG+XJzEyKUFbcZxLdWGMwQsWaHDxQ=="
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -7938,6 +7994,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/swagger-ui-dist": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.12.0.tgz",
"integrity": "sha512-B0Iy2ueXtbByE6OOyHTi3lFQkpPi/L7kFOKFeKTr44za7dJIELa9kzaca6GkndCgpK1QTjArnoXG+aUy0XQp1w=="
},
"node_modules/symbol-observable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
@ -8584,6 +8645,14 @@
"node": ">=10.12.0"
}
},
"node_modules/validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -10095,6 +10164,12 @@
"uuid": "8.3.2"
}
},
"@nestjs/mapped-types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-1.1.0.tgz",
"integrity": "sha512-+2kSly4P1QI+9eGt+/uGyPdEG1hVz7nbpqPHWZVYgoqz8eOHljpXPag+UCVRw9zo2XCu4sgNUIGe8Uk0+OvUQg==",
"requires": {}
},
"@nestjs/platform-express": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.0.1.tgz",
@ -10120,6 +10195,18 @@
"pluralize": "8.0.0"
}
},
"@nestjs/swagger": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-6.0.1.tgz",
"integrity": "sha512-rNpncETn+twpf3OPUtGO0MssEOd0cEqiklj2TZv+kAU9gmIWtC/p7Hf1hWbSp9C/l8vF1TnquK80oOaS2G0bAA==",
"requires": {
"@nestjs/mapped-types": "1.1.0",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"path-to-regexp": "3.2.0",
"swagger-ui-dist": "4.12.0"
}
},
"@nestjs/testing": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-9.0.1.tgz",
@ -10915,8 +11002,7 @@
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"array-flatten": {
"version": "1.1.1",
@ -11280,6 +11366,15 @@
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
"dev": true
},
"class-validator": {
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
"requires": {
"libphonenumber-js": "^1.9.43",
"validator": "^13.7.0"
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@ -13501,7 +13596,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"requires": {
"argparse": "^2.0.1"
}
@ -13574,6 +13668,11 @@
"type-check": "~0.4.0"
}
},
"libphonenumber-js": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.7.tgz",
"integrity": "sha512-jZXLCCWMe1b/HXkjiLeYt2JsytZMcqH26jLFIdzFDFF0xvSUWrYKyvPlyPG+XJzEyKUFbcZxLdWGMwQsWaHDxQ=="
},
"lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -14897,6 +14996,11 @@
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true
},
"swagger-ui-dist": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.12.0.tgz",
"integrity": "sha512-B0Iy2ueXtbByE6OOyHTi3lFQkpPi/L7kFOKFeKTr44za7dJIELa9kzaca6GkndCgpK1QTjArnoXG+aUy0XQp1w=="
},
"symbol-observable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
@ -15353,6 +15457,11 @@
"convert-source-map": "^1.6.0"
}
},
"validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

@ -26,6 +26,8 @@
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.0.0",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/swagger": "^6.0.1",
"class-validator": "^0.13.2",
"puppeteer": "^15.3.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",

@ -1,8 +1,15 @@
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder().build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
await app.listen(3000);
console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();

@ -1,26 +1,27 @@
import { InjectQueue } from '@nestjs/bull';
import { Body, Controller, Get, NotFoundException, Param, Post } from '@nestjs/common';
import { ApiResponse } from '@nestjs/swagger';
import { CreateJobRequestDto, GetJobResponseDto, JobStatusDto } from './screenshots.dto'
import { QUEUE_NAME, ScreenshotsQueue } from './shared';
type CreateScreenshotJobDto = {
pageUrl: URL,
imageType: 'jpeg' | 'png'
}
@Controller('screenshots')
export class ScreenshotsController {
constructor(@InjectQueue(QUEUE_NAME) private readonly screenshotsQueue: ScreenshotsQueue) {}
@Post()
async createScreenshotJob(@Body() createScreenshotJobDto: CreateScreenshotJobDto) {
const result = await this.screenshotsQueue.add(createScreenshotJobDto)
async createScreenshotJob(@Body() createScreenshotJobDto: CreateJobRequestDto): Promise<{ jobId: string }> {
const result = await this.screenshotsQueue.add({
pageUrl: new URL(createScreenshotJobDto.pageUrl),
imageType: createScreenshotJobDto.imageType,
})
return {
jobId: result.id.toString()
}
}
@Get(':id')
async getJob(@Param('id') id: string) {
@ApiResponse({ status: 404 })
async getJob(@Param('id') id: string): Promise<GetJobResponseDto> {
const jobInfo = await this.screenshotsQueue.getJob(id)
if (!jobInfo) {
@ -29,15 +30,16 @@ export class ScreenshotsController {
switch (await jobInfo.getState()) {
case 'completed':
return { status: 'completed' }
return { status: JobStatusDto.Completed }
case 'failed':
return { status: 'failed' }
return { status: JobStatusDto.Failed }
default:
return { status: 'queued' }
return { status: JobStatusDto.Queued }
}
}
@Get(':id/result')
@ApiResponse({ status: 404 })
async getScreenshot(@Param('id') id: string) {
const jobInfo = await this.screenshotsQueue.getJob(id)

@ -0,0 +1,24 @@
import { IsEnum, IsString, IsUrl } from "class-validator";
enum ImageTypeDto {
Jpeg = 'jpeg',
Png = 'png',
}
export enum JobStatusDto {
Completed = 'completed',
Failed = 'failed',
Queued = 'queued',
}
export class CreateJobRequestDto {
@IsUrl()
pageUrl!: string;
@IsEnum(ImageTypeDto)
imageType!: ImageTypeDto
}
export class GetJobResponseDto {
status!: JobStatusDto
}
Loading…
Cancel
Save