几周前,我终于有时间开始try NodeJS API构建,经过一些研究后,我决定使用Express + Sequelize + PostgreSQL + OpenAPI的组合. 此时我跳过了TypeScript, Select 了JS ES6+. 在阅读了OpenAPI Specification和我正在使用的npm包的官方文档(express-openapi)之后,我一直在从openapi 3.x到swagger 2.0来回切换,并将api—doc从JSON切换到yml,但最后我总是在同一点上遇到这个错误:
SyntaxError: Invalid regular expression: /^\/v2\/users\(?:([^\/]+?))\/?$/i: Unmatched ')'
at new RegExp (<anonymous>)
at pathtoRegexp (...\express-sequelize-openapi\node_modules\path-to-regexp\index.js:128:10)
at new Layer (...\express-sequelize-openapi\node_modules\express\lib\router\layer.js:45:17)
at Function.route (...\express-sequelize-openapi\node_modules\express\lib\router\index.js:505:15)
at app.<computed> [as get] (...\express-sequelize-openapi\node_modules\express\lib\application.js:498:30)
at Object.visitOperation (...\express-sequelize-openapi\node_modules\express-openapi\dist\index.js:131:33)
at ...\express-sequelize-openapi\node_modules\openapi-framework\dist\index.js:370:29
at Set.forEach (<anonymous>)
at ...\express-sequelize-openapi\node_modules\openapi-framework\dist\index.js:233:100
at Array.forEach (<anonymous>)
以下是我在当前版本的package. json中使用的一些依赖项:
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.19.1",
"express-openapi": "^12.1.3",
"helmet": "^7.1.0",
"pg": "^8.11.3",
"pg-hstore": "^2.3.4",
"sequelize": "^6.37.1",
"sequelize-cli": "^6.6.2",
"swagger-ui-express": "^5.0.0",
下面是app.js的内容:
import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import helmet from "helmet";
import path from "path";
import swaggerUi from "swagger-ui-express";
import { initialize as initializeOpenApi } from "express-openapi";
import { fileURLToPath } from "url";
import v1ApiDoc from "./doc/api-doc-v2.js";
// Defining the Express app
const app = express();
// Adding Helmet to enhance your Rest API's security
app.use(helmet());
// Using bodyParser to parse JSON bodies into JS objects
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Enabling CORS for all requests
app.use(cors());
const docsPath = "/openapi.json";
// OpenAPI UI
app.use("/api-documentation", swaggerUi.serve, swaggerUi.setup(v1ApiDoc));
export const startApp = async (port) => {
// OpenAPI routes
const openApiDoc = await initializeOpenApi({
apiDoc: v1ApiDoc,
app,
docsPath,
paths: "./api/routes/v2",
});
app.use(function (err, req, res, next) {
res.status(err.status).json(err);
});
// Starting the server
app.listen(port => {
console.log(`Listening on port ${port}`);
});
};
以下是我创建的当前api—doc v2:
const apiDoc = {
swagger: "2.0",
info: {
title: "Node Express API.",
version: "0.1.0",
},
basePath: "/v2",
paths: {},
tags: [
{
name: "Users",
},
],
definitions: {
GeneralSuccess: {
type: "object",
properties: {
success: {
type: "boolean",
},
data: {
type: "object",
},
},
},
GeneralError: {
type: "object",
properties: {
success: {
type: "boolean",
},
error: {
type: "object",
properties: {
message: {
type: "string",
},
error: {
type: "object",
},
},
},
},
},
User: {
required: ["id"],
type: "object",
properties: {
id: {
type: "string",
description: "User's unique identifier",
},
email: {
type: "string",
description: "User's email address",
},
password: {
type: "string",
description: "User's password",
},
firstName: {
type: "string",
description: "User's firstname",
},
lastName: {
type: "string",
description: "User's lastname",
},
},
},
},
responses: {
200: {
// Success
description: "Successful request.",
schema: {
$ref: "#/definitions/GeneralSuccess",
},
},
404: {
// Not Found
description: "Entity not found.",
schema: {
$ref: "#/definitions/GeneralError",
},
},
422: {
// Illegal Input
description: "Illegal input for operation.",
schema: {
$ref: "#/definitions/GeneralError",
},
},
500: {
// Internal Server Error
description: "An unexpected error occurred",
schema: {
$ref: "#/definitions/GeneralError",
},
},
default: {
description: "Unexpected error",
schema: {
$ref: "#/definitions/GeneralError",
},
},
},
};
export default apiDoc;
路由是在folder/routes/v2下指定的. 到目前为止,我有两个路由,users.js直接在干线下工作(get,post)和users/{id}. js每次都会触发相同的错误.在这一点上的内容是无关紧要的,因为我直接在v2下复制/粘贴相同的代码到不同的文件中,并且它工作正常.
所以我在这一点上得到的更多的是一个配置问题,一些愚蠢的细节我遗漏了,或者是一个包版本冲突.
我很感激我能得到的任何建议,让这个项目运行.
PS:我认为有一个次要问题是,我无法将任何端点加载到本地SwaggerUI api—documentation页面.