fix: revert swagger-jsdoc to 6.2.8 (7.0.0-rc.6 broke OpenAPI spec generation) + add OpenAPI spec tests
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled

swagger-jsdoc 7.0.0-rc.6 returns empty spec (0 paths), breaking /docs and /openapi.json.
Reverted to 6.2.8 which correctly generates all 10+ paths.
Added 2 regression tests to catch this in CI.
This commit is contained in:
DocFast CEO 2026-02-25 13:04:26 +00:00
parent 6fd707ab64
commit 288d6c7aab
3 changed files with 66 additions and 22 deletions

65
package-lock.json generated
View file

@ -19,7 +19,7 @@
"pino": "^10.3.1", "pino": "^10.3.1",
"puppeteer": "^24.0.0", "puppeteer": "^24.0.0",
"stripe": "^20.3.1", "stripe": "^20.3.1",
"swagger-jsdoc": "^7.0.0-rc.6", "swagger-jsdoc": "^6.2.8",
"swagger-ui-dist": "^5.31.0" "swagger-ui-dist": "^5.31.0"
}, },
"devDependencies": { "devDependencies": {
@ -63,9 +63,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@apidevtools/swagger-parser": { "node_modules/@apidevtools/swagger-parser": {
"version": "10.0.2", "version": "10.0.3",
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.2.tgz", "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
"integrity": "sha512-JFxcEyp8RlNHgBCE98nwuTkZT6eNFPc1aosWV6wPcQph72TSEEu1k3baJD4/x1qznU+JiDdz8F5pTwabZh+Dhg==", "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apidevtools/json-schema-ref-parser": "^9.0.6", "@apidevtools/json-schema-ref-parser": "^9.0.6",
@ -73,7 +73,7 @@
"@apidevtools/swagger-methods": "^3.0.2", "@apidevtools/swagger-methods": "^3.0.2",
"@jsdevtools/ono": "^7.1.3", "@jsdevtools/ono": "^7.1.3",
"call-me-maybe": "^1.0.1", "call-me-maybe": "^1.0.1",
"z-schema": "^4.2.3" "z-schema": "^5.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"openapi-types": ">=7" "openapi-types": ">=7"
@ -1713,7 +1713,7 @@
"version": "2.20.3", "version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"devOptional": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/compressible": { "node_modules/compressible": {
@ -4002,21 +4002,34 @@
} }
}, },
"node_modules/swagger-jsdoc": { "node_modules/swagger-jsdoc": {
"version": "7.0.0-rc.6", "version": "6.2.8",
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-7.0.0-rc.6.tgz", "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
"integrity": "sha512-LIvIPQxipRaOzIij+HrWOcCWTINE6OeJuqmXCfDkofVcstPVABHRkaAc3D7vrX9s7L0ccH0sH0amwHgN6+SXPg==", "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"commander": "6.2.0",
"doctrine": "3.0.0", "doctrine": "3.0.0",
"glob": "7.1.6", "glob": "7.1.6",
"lodash.mergewith": "4.6.2", "lodash.mergewith": "^4.6.2",
"swagger-parser": "10.0.2", "swagger-parser": "^10.0.3",
"yaml": "2.0.0-1" "yaml": "2.0.0-1"
}, },
"bin": {
"swagger-jsdoc": "bin/swagger-jsdoc.js"
},
"engines": { "engines": {
"node": ">=12.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/swagger-jsdoc/node_modules/commander": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/swagger-jsdoc/node_modules/yaml": { "node_modules/swagger-jsdoc/node_modules/yaml": {
"version": "2.0.0-1", "version": "2.0.0-1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
@ -4027,12 +4040,12 @@
} }
}, },
"node_modules/swagger-parser": { "node_modules/swagger-parser": {
"version": "10.0.2", "version": "10.0.3",
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.2.tgz", "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
"integrity": "sha512-9jHkHM+QXyLGFLk1DkXBwV+4HyNm0Za3b8/zk/+mjr8jgOSiqm3FOTHBSDsBjtn9scdL+8eWcHdupp2NLM8tDw==", "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "10.0.2" "@apidevtools/swagger-parser": "10.0.3"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@ -4644,23 +4657,33 @@
} }
}, },
"node_modules/z-schema": { "node_modules/z-schema": {
"version": "4.2.4", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.4.tgz", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
"integrity": "sha512-YvBeW5RGNeNzKOUJs3rTL4+9rpcvHXt5I051FJbOcitV8bl40pEfcG0Q+dWSwS0/BIYrMZ/9HHoqLllMkFhD0w==", "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"lodash.get": "^4.4.2", "lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"validator": "^13.6.0" "validator": "^13.7.0"
}, },
"bin": { "bin": {
"z-schema": "bin/z-schema" "z-schema": "bin/z-schema"
}, },
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=8.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"commander": "^2.7.1" "commander": "^9.4.1"
}
},
"node_modules/z-schema/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"license": "MIT",
"optional": true,
"engines": {
"node": "^12.20.0 || >=14"
} }
}, },
"node_modules/zod": { "node_modules/zod": {

View file

@ -23,7 +23,7 @@
"pino": "^10.3.1", "pino": "^10.3.1",
"puppeteer": "^24.0.0", "puppeteer": "^24.0.0",
"stripe": "^20.3.1", "stripe": "^20.3.1",
"swagger-jsdoc": "^7.0.0-rc.6", "swagger-jsdoc": "^6.2.8",
"swagger-ui-dist": "^5.31.0" "swagger-ui-dist": "^5.31.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -585,6 +585,27 @@ describe("Rate limit headers on PDF endpoints", () => {
}); });
}); });
describe("OpenAPI spec", () => {
it("returns a valid OpenAPI 3.0 spec with paths", async () => {
const res = await fetch(`${BASE}/openapi.json`);
expect(res.status).toBe(200);
const spec = await res.json();
expect(spec.openapi).toBe("3.0.3");
expect(spec.info).toBeDefined();
expect(spec.info.title).toBe("DocFast API");
expect(Object.keys(spec.paths).length).toBeGreaterThanOrEqual(8);
});
it("includes all major endpoint groups", async () => {
const res = await fetch(`${BASE}/openapi.json`);
const spec = await res.json();
const paths = Object.keys(spec.paths);
expect(paths).toContain("/v1/convert/html");
expect(paths).toContain("/v1/convert/markdown");
expect(paths).toContain("/health");
});
});
describe("404 handler", () => { describe("404 handler", () => {
it("returns proper JSON error format for API routes", async () => { it("returns proper JSON error format for API routes", async () => {
const res = await fetch(`${BASE}/v1/nonexistent-endpoint`); const res = await fetch(`${BASE}/v1/nonexistent-endpoint`);