The hand-maintained openapi.json has drifted significantly from the
actual API surface (PUT vs PATCH mismatches, missing query params,
stale endpoints, missing routes). This is a spike of the long-term
fix: derive the spec from the Zod validation schemas we already have.
Scope: monitors resource only. Other resources still come from the
static openapi.json — the new merger splices generated paths in and
drops the static ones the registry now owns. Migration can proceed
one resource per PR.
What this PR does:
- Adds @asteasolutions/zod-to-openapi (peerDep zod 4 satisfied).
- New src/openapi/ module:
- registry.ts — shared OpenAPIRegistry, bearerAuth scheme.
- schemas/common.ts — success/error envelope helpers.
- schemas/monitor.ts — Monitor / MonitorWithChecksList / etc.
- routes/monitor.ts — registers all 19 monitor routes against
the existing Zod validation schemas (no validation files modified).
- index.ts — getOpenApiSpec() merges generated monitor paths into
the static openapi.json and drops 2 stale entries.
- src/index.ts now calls getOpenApiSpec() instead of reading
openapi.json directly. The /api-docs Swagger UI is unchanged.
Drift fixes that fall out automatically once monitors are derived:
- PUT /monitors/{monitorId} -> PATCH (matches actual route)
- POST /monitors response 201 -> 200 (matches actual handler)
- GET /monitors/team/with-checks: 1 documented param -> 8 actual
(this is what #3354 fixed manually; now structural)
- /monitors/bulk and /monitors/test-email removed (no such routes)
- PATCH /monitors/notifications, POST /monitors/import/json, and
GET /monitors/{id}/geo-checks are now documented (were missing)
Verified by booting the merged spec in isolation: 16 monitor paths
emitted, all stale entries dropped, Monitor schema and bearerAuth
scheme registered.
Follow-ups (separate PRs):
- Migrate auth, statusPage, maintenanceWindow, notification, etc.
- Once all resources are migrated, delete the hand-edited
openapi.json and ship the generator output as the canonical doc.
- Optionally promote response shapes from passthrough() Monitor
to fully typed response Zod schemas.
104 lines
3.0 KiB
JSON
Executable File
104 lines
3.0 KiB
JSON
Executable File
{
|
|
"name": "server",
|
|
"version": "1.0.0",
|
|
"description": "",
|
|
"main": "index.js",
|
|
"type": "module",
|
|
"scripts": {
|
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
"test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --coverage --collectCoverageFrom='src/**/*.ts' test/unit",
|
|
"test:unit:services": "NODE_OPTIONS=--experimental-vm-modules jest --coverage --collectCoverageFrom='src/service/**/*.ts' test/unit/services test/unit/providers/network test/unit/providers/notifications",
|
|
"test:integration": "NODE_OPTIONS=--experimental-vm-modules jest --no-coverage test/integration",
|
|
"dev": "nodemon --exec tsx src/index.js",
|
|
"start": "node --watch ./dist/index.js",
|
|
"build": "tsc && tsc-alias && cp -r src/templates dist/templates",
|
|
"lint": "eslint .",
|
|
"lint-fix": "eslint --fix .",
|
|
"format": "prettier --write .",
|
|
"format-check": "prettier --check ."
|
|
},
|
|
"lint-staged": {
|
|
"**/*": "prettier --write"
|
|
},
|
|
"keywords": [],
|
|
"author": "",
|
|
"license": "ISC",
|
|
"engines": {
|
|
"node": ">=20"
|
|
},
|
|
"dependencies": {
|
|
"@grpc/grpc-js": "^1.14.3",
|
|
"@grpc/proto-loader": "^0.8.0",
|
|
"@pulsecron/pulse": "1.6.8",
|
|
"axios": "^1.7.2",
|
|
"bcryptjs": "3.0.2",
|
|
"cacheable-lookup": "7.0.0",
|
|
"compression": "1.8.1",
|
|
"cookie-parser": "^1.4.7",
|
|
"cors": "^2.8.5",
|
|
"dockerode": "4.0.6",
|
|
"dotenv": "^16.4.5",
|
|
"express": "^4.19.2",
|
|
"express-rate-limit": "8.3.2",
|
|
"gamedig": "5.2.0",
|
|
"got": "14.4.7",
|
|
"handlebars": "^4.7.8",
|
|
"helmet": "^8.0.0",
|
|
"ioredis": "^5.4.2",
|
|
"isomorphic-dompurify": "^2.26.0",
|
|
"jmespath": "^0.16.0",
|
|
"jsdom": "^26.1.0",
|
|
"jsonwebtoken": "9.0.2",
|
|
"mailersend": "^2.2.0",
|
|
"mjml": "^5.0.0-alpha.4",
|
|
"mongoose": "^8.3.3",
|
|
"multer": "^1.4.5-lts.1",
|
|
"nodemailer": "8.0.5",
|
|
"ping": "0.4.4",
|
|
"sharp": "0.33.5",
|
|
"ssl-checker": "2.0.10",
|
|
"super-simple-scheduler": "1.9.1",
|
|
"swagger-ui-express": "5.0.1",
|
|
"winston": "^3.13.0",
|
|
"ws": "^8.19.0",
|
|
"zod": "^4.3.6"
|
|
},
|
|
"devDependencies": {
|
|
"@asteasolutions/zod-to-openapi": "^8.5.0",
|
|
"@eslint/js": "^9.17.0",
|
|
"@types/compression": "1.8.1",
|
|
"@types/cookie-parser": "1.4.10",
|
|
"@types/cors": "2.8.19",
|
|
"@types/dockerode": "^4.0.0",
|
|
"@types/express": "5.0.3",
|
|
"@types/gamedig": "^5.0.3",
|
|
"@types/jest": "^30.0.0",
|
|
"@types/jmespath": "^0.15.2",
|
|
"@types/jsdom": "^27.0.0",
|
|
"@types/jsonwebtoken": "9.0.10",
|
|
"@types/mjml": "^4.7.4",
|
|
"@types/multer": "^2.0.0",
|
|
"@types/nodemailer": "7.0.1",
|
|
"@types/papaparse": "^5.5.2",
|
|
"@types/ping": "0.4.4",
|
|
"@types/swagger-ui-express": "4.1.8",
|
|
"@types/ws": "^8.18.1",
|
|
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
"@typescript-eslint/parser": "^8.56.1",
|
|
"eslint": "^9.17.0",
|
|
"eslint-plugin-mocha": "^10.5.0",
|
|
"esm": "3.2.25",
|
|
"globals": "^15.14.0",
|
|
"jest": "^30.2.0",
|
|
"lint-staged": "^16.2.7",
|
|
"nodemon": "^3.1.11",
|
|
"prettier": "^3.3.3",
|
|
"ts-jest": "^29.4.6",
|
|
"ts-node": "^10.9.2",
|
|
"tsc-alias": "1.8.16",
|
|
"tsx": "4.20.5",
|
|
"typescript": "5.9.2",
|
|
"typescript-eslint": "^8.56.1"
|
|
}
|
|
}
|