diff --git a/package-lock.json b/package-lock.json index bce6a86..774faec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,13 @@ "name": "openapigen", "version": "1.0.0", "license": "ISC", + "dependencies": { + "uuid": "^11.1.0" + }, "devDependencies": { "@accordproject/concerto-cli": "^3.4.0", "@ibm-cloud/openapi-ruleset": "^0.44.3", + "@types/uuid": "^10.0.0", "ibm-openapi-validator": "^0.96.4", "openapi-typescript": "^6.1.0", "reslate": "^3.0.0-5", @@ -215,6 +219,16 @@ "npm": ">=6" } }, + "node_modules/@accordproject/concerto-core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@accordproject/concerto-cto": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@accordproject/concerto-cto/-/concerto-cto-3.4.0.tgz", @@ -1107,6 +1121,13 @@ "integrity": "sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg==", "dev": true }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true, + "license": "MIT" + }, "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", @@ -8283,12 +8304,16 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/valid-url": { diff --git a/package.json b/package.json index 76ce187..86766ef 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,14 @@ "devDependencies": { "@accordproject/concerto-cli": "^3.4.0", "@ibm-cloud/openapi-ruleset": "^0.44.3", + "@types/uuid": "^10.0.0", "ibm-openapi-validator": "^0.96.4", "openapi-typescript": "^6.1.0", "reslate": "^3.0.0-5", "swagger-combine": "^1.4.0", "widdershins": "^4.0.1" + }, + "dependencies": { + "uuid": "^11.1.0" } } diff --git a/server/index.ts b/server/index.ts index e400e69..0b5539c 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,48 +1,94 @@ -import 'source-map-support/register'; -import OpenAPIBackend, { Request } from 'openapi-backend'; -import Express from 'express'; -import morgan from 'morgan' -import path from 'path'; +import "source-map-support/register"; +import OpenAPIBackend, { Request } from "openapi-backend"; +import Express from "express"; +import morgan from "morgan"; +import path from "path"; +import { v4 as uuidv4 } from "uuid"; -import { Request as ExpressReq, Response as ExpressRes } from 'express'; +import { Request as ExpressReq, Response as ExpressRes } from "express"; const app = Express(); app.use(Express.json()); -const openApiPath = path.join(__dirname, '..', '..', 'openapi.json'); +const openApiPath = path.join(__dirname, "..", "..", "openapi.json"); console.log(openApiPath); +const templates: Record = {}; + // define api const api = new OpenAPIBackend({ - quick: true, // disabled validation of OpenAPI on load - definition: openApiPath, - handlers: { - listTemplates: async (c, req: Express.Request, res: Express.Response) => - res.status(200).json([]), - createTemplate: async (c, req: Express.Request, res: Express.Response) => - res.status(200).json({}), - getTemplate: async (c, req: Express.Request, res: Express.Response) => - res.status(200).json({}), - replaceTemplate: async (c, req: Express.Request, res: Express.Response) => - res.status(200).json({}), - deleteTemplate: async (c, req: Express.Request, res: Express.Response) => - res.status(200).json({}), - validationFail: async (c, req: ExpressReq, res: ExpressRes) => res.status(400).json({ err: c.validation.errors }), - notFound: async (c, req: ExpressReq, res: ExpressRes) => res.status(404).json({ err: 'not found' }), - notImplemented: async (c, req: ExpressReq, res: ExpressRes) => { - const { status, mock } = c.api.mockResponseForOperation(c.operation.operationId); - return res.status(status).json(mock); - }, + quick: true, // disabled validation of OpenAPI on load + definition: openApiPath, + handlers: { + createTemplate: async (c, req: Express.Request, res: Express.Response) => { + const { $class, name, ...otherData } = req.body; + + if (!$class) { + return res + .status(400) + .json({ error: "Missing required property: $class" }); + } + + const id = uuidv4(); + + const newTemplate = { id, $class, name, ...otherData }; + templates[id] = newTemplate; + + return res + .status(201) + .header("Location", `/templates/${id}`) + .json({ id }); + }, + + getTemplate: async (c, req: Express.Request, res: Express.Response) => { + const { id } = req.params; + + const template = templates[id]; + + if (!template) { + return res.status(404).json({ error: "Template not found" }); + } + + res.json(template); + }, + + listTemplates: async (c, req: Express.Request, res: Express.Response) => + res.status(200).json(Object.values(templates)), + + deleteTemplate: async (c, req: Express.Request, res: Express.Response) => { + const { id } = req.params; + + if (!templates[id]) { + return res.status(404).json({ error: "Template not found" }); + } + + delete templates[id]; + res.status(204).send(); + }, + + replaceTemplate: async (c, req: Express.Request, res: Express.Response) => + res.status(200).json({}), + + validationFail: async (c, req: ExpressReq, res: ExpressRes) => + res.status(400).json({ err: c.validation.errors }), + notFound: async (c, req: ExpressReq, res: ExpressRes) => + res.status(404).json({ err: "not found" }), + notImplemented: async (c, req: ExpressReq, res: ExpressRes) => { + const { status, mock } = c.api.mockResponseForOperation( + c.operation.operationId + ); + return res.status(status).json(mock); }, + }, }); api.init(); // logging -app.use(morgan('combined')); +app.use(morgan("combined")); // use as express middleware app.use((req, res) => api.handleRequest(req as Request, req, res)); // start server -app.listen(9000, () => console.info('api listening at http://localhost:9000')); \ No newline at end of file +app.listen(9000, () => console.info("api listening at http://localhost:9000"));