Skip to content

Commit

Permalink
feat: integrate swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
Kpoke committed Feb 10, 2023
1 parent 107cd51 commit aecab95
Show file tree
Hide file tree
Showing 12 changed files with 1,022 additions and 14 deletions.
Binary file added assets/greenstand.webp
Binary file not shown.
56 changes: 56 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@
"express-async-handler": "^1.1.4",
"express-validator": "^6.4.0",
"joi": "^17.2.1",
"joi-to-swagger": "^6.2.0",
"knex": "^0.95.11",
"loglevel": "^1.8.0",
"multer": "^1.4.5-lts.1",
"pg": "^8.7.0",
"rascal": "^13.0.0",
"swagger-ui-express": "^4.6.0",
"uuid": "^8.2.0"
},
"devDependencies": {
Expand Down
26 changes: 21 additions & 5 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
const express = require('express');
const swaggerUi = require('swagger-ui-express');
const log = require('loglevel');
const cors = require('cors');
const { join } = require('path');

// const Sentry = require('@sentry/node');
const cors = require('cors');
const log = require('loglevel');
const { EventHandlerService } = require('./services/EventHandlerService');
const { errorHandler, handlerWrapper } = require('./utils/utils');
const swaggerDocument = require('./handlers/swaggerDoc');
const HttpError = require('./utils/HttpError');
const { errorHandler } = require('./utils/utils');
const helper = require('./utils/utils');
const router = require('./routes');

const app = express();
Expand All @@ -22,7 +24,7 @@ if (process.env.NODE_ENV === 'development') {
* Check request
*/
app.use(
helper.handlerWrapper(async (req, _res, next) => {
handlerWrapper(async (req, _res, next) => {
if (req.path === '/grower_accounts/image' && req.method === 'POST') {
if (!req.headers['content-type'].includes('multipart/form-data')) {
throw new HttpError(
Expand All @@ -48,6 +50,20 @@ app.use(
}),
);

const options = {
customCss: `
.topbar-wrapper img {
content:url('../assets/greenstand.webp');
width:80px;
height:auto;
}
`,
explorer: true,
};

app.use('/assets', express.static(join(__dirname, '..', '/assets')));

app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, options));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

Expand Down
239 changes: 239 additions & 0 deletions server/handlers/captureHandler/docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
const j2s = require('joi-to-swagger');
const {
captureGetQuerySchema: getJoiSchema,
captureTagPatchSchema: captureTagsJoiPatchSchema,
captureTagsPostSchema: captureTagsJoiPostSchema,
capturePatchSchema: patchJoiSchema,
capturePostSchema: postJoiSchema,
} = require('./schemas');

const { swagger: capturePostSchema } = j2s(postJoiSchema);
const { swagger: captureGetSchema } = j2s(getJoiSchema);
const { swagger: capturePatchSchema } = j2s(patchJoiSchema);
const { swagger: captureTagsPostSchema } = j2s(captureTagsJoiPostSchema);
const { swagger: captureTagPatchSchema } = j2s(captureTagsJoiPatchSchema);

const singleCaptureResponse = {
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/Capture',
},
},
},
};

const singleCaptureTagResponse = {
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/CaptureTag',
},
},
},
};

const captureSwagger = {
'/captures': {
get: {
tags: ['captures'],
summary: 'get all captures',
parameters: [
{
schema: {
...captureGetSchema,
},
in: 'query',
name: 'query',
description: 'Allowed query parameters',
},
],
responses: {
200: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
tags: {
type: 'array',
items: {
$ref: '#/components/schemas/Capture',
},
},
},
},
},
},
},
},
},
post: {
tags: ['captures'],
summary: 'create a new capture',
requestBody: {
content: {
'application/json': {
schema: { ...capturePostSchema },
},
},
},
responses: {
201: singleCaptureResponse,
200: singleCaptureResponse,
},
},
},
'/captures/{capture_id}': {
get: {
tags: ['captures'],
summary: 'get a single capture',
parameters: [
{
schema: { type: 'string', format: 'uuid' },
in: 'path',
required: true,
name: 'capture_id',
description: 'id of capture to return',
},
],
responses: {
200: singleCaptureResponse,
},
},
patch: {
tags: ['captures'],
summary: 'update a capture',
requestBody: {
content: {
'application/json': {
schema: {
...capturePatchSchema,
},
},
},
},
responses: {
200: singleCaptureResponse,
},
},
},
'/captures/{capture_id}/tags': {
get: {
tags: ['capture tags'],
summary: 'get all tags for a single capture',
responses: {
200: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
tags: {
type: 'array',
items: {
$ref: '#/components/schemas/CaptureTag',
},
},
},
},
},
},
},
},
},
post: {
tags: ['capture tags'],
summary: 'add tags to a capture',
requestBody: {
content: {
'application/json': {
schema: { ...captureTagsPostSchema },
},
},
},
responses: { 204: {} },
},
},
'/captures/{capture_id}/tags/{tag_id}': {
get: {
tags: ['capture tags'],
summary: 'get a single tag for a single capture',
parameters: [
{
schema: { type: 'string', format: 'uuid' },
in: 'path',
required: true,
name: 'capture_id',
description: 'id of capture to return',
},
{
schema: { type: 'string', format: 'uuid' },
in: 'path',
required: true,
name: 'tag_id',
description: 'id of tag to return',
},
],
responses: {
200: singleCaptureTagResponse,
},
},
patch: {
tags: ['capture tags'],
summary: 'update a capture tag relationship',
requestBody: {
content: {
'application/json': {
schema: {
...captureTagPatchSchema,
},
},
},
},
responses: {
200: singleCaptureTagResponse,
},
},
},
};

const captureComponent = {
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
reference_id: { type: 'number' },
tree_id: { type: 'string', format: 'uuid' },
image_url: { type: 'string' },
lat: { type: 'number' },
lon: { type: 'number' },
created_at: { type: 'string', format: 'date-time' },
status: { type: 'string' },
captured_at: { type: 'string', format: 'date-time' },
planting_organization_id: { type: 'string', format: 'uuid' },
tag_array: { type: 'array', items: { type: 'string' } },
grower_account_id: { type: 'string', format: 'uuid' },
morphology: { type: 'string' },
age: { type: 'number' },
note: { type: 'string' },
attributes: { type: 'object' },
species_id: { type: 'string', format: 'uuid' },
session_id: { type: 'string', format: 'uuid' },
device_configuration_id: { type: 'string', format: 'uuid' },
},
};

const captureTagComponent = {
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
capture_id: { type: 'string', format: 'uuid' },
tag_id: { type: 'string', format: 'uuid' },
tag_name: { type: 'string' },
status: { type: 'string' },
created_at: { type: 'string', format: 'date-time' },
updated_at: { type: 'string', format: 'date-time' },
},
};

module.exports = { captureSwagger, captureComponent, captureTagComponent };
Loading

0 comments on commit aecab95

Please # to comment.