feat: swagger
This commit is contained in:
333
backend/package-lock.json
generated
333
backend/package-lock.json
generated
@@ -10,9 +10,74 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^5.2.1"
|
"express": "^5.2.1",
|
||||||
|
"swagger-jsdoc": "^6.2.8",
|
||||||
|
"swagger-ui-express": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@apidevtools/json-schema-ref-parser": {
|
||||||
|
"version": "9.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz",
|
||||||
|
"integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jsdevtools/ono": "^7.1.3",
|
||||||
|
"@types/json-schema": "^7.0.6",
|
||||||
|
"call-me-maybe": "^1.0.1",
|
||||||
|
"js-yaml": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@apidevtools/openapi-schemas": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@apidevtools/swagger-methods": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@apidevtools/swagger-parser": {
|
||||||
|
"version": "10.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||||
|
"integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@apidevtools/json-schema-ref-parser": "^9.0.6",
|
||||||
|
"@apidevtools/openapi-schemas": "^2.0.4",
|
||||||
|
"@apidevtools/swagger-methods": "^3.0.2",
|
||||||
|
"@jsdevtools/ono": "^7.1.3",
|
||||||
|
"call-me-maybe": "^1.0.1",
|
||||||
|
"z-schema": "^5.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"openapi-types": ">=7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jsdevtools/ono": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@scarf/scarf": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/@types/json-schema": {
|
||||||
|
"version": "7.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
|
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
||||||
@@ -26,6 +91,18 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
|
"license": "Python-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/body-parser": {
|
"node_modules/body-parser": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
|
||||||
@@ -50,6 +127,16 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@@ -88,6 +175,27 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/call-me-maybe": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"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/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/content-disposition": {
|
"node_modules/content-disposition": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
|
||||||
@@ -167,6 +275,18 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/doctrine": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"esutils": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dunder-proto": {
|
"node_modules/dunder-proto": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
@@ -232,6 +352,15 @@
|
|||||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/esutils": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/etag": {
|
"node_modules/etag": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
@@ -323,6 +452,12 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -369,6 +504,27 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/glob": {
|
||||||
|
"version": "7.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||||
|
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||||
|
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
@@ -441,6 +597,17 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||||
|
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
@@ -462,6 +629,38 @@
|
|||||||
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash.get": {
|
||||||
|
"version": "4.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||||
|
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
|
||||||
|
"deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isequal": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
|
||||||
|
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.mergewith": {
|
||||||
|
"version": "4.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
|
||||||
|
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/math-intrinsics": {
|
"node_modules/math-intrinsics": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
@@ -517,6 +716,18 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -574,6 +785,13 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openapi-types": {
|
||||||
|
"version": "12.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
|
||||||
|
"integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/parseurl": {
|
"node_modules/parseurl": {
|
||||||
"version": "1.3.3",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
@@ -583,6 +801,15 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/path-to-regexp": {
|
"node_modules/path-to-regexp": {
|
||||||
"version": "8.3.0",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
|
||||||
@@ -799,6 +1026,62 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/swagger-jsdoc": {
|
||||||
|
"version": "6.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz",
|
||||||
|
"integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "6.2.0",
|
||||||
|
"doctrine": "3.0.0",
|
||||||
|
"glob": "7.1.6",
|
||||||
|
"lodash.mergewith": "^4.6.2",
|
||||||
|
"swagger-parser": "^10.0.3",
|
||||||
|
"yaml": "2.0.0-1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"swagger-jsdoc": "bin/swagger-jsdoc.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/swagger-parser": {
|
||||||
|
"version": "10.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz",
|
||||||
|
"integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@apidevtools/swagger-parser": "10.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/swagger-ui-dist": {
|
||||||
|
"version": "5.31.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.31.0.tgz",
|
||||||
|
"integrity": "sha512-zSUTIck02fSga6rc0RZP3b7J7wgHXwLea8ZjgLA3Vgnb8QeOl3Wou2/j5QkzSGeoz6HusP/coYuJl33aQxQZpg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@scarf/scarf": "=1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/swagger-ui-express": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"swagger-ui-dist": ">=5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= v0.10.32"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": ">=4.0.0 || >=5.0.0-beta"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/toidentifier": {
|
"node_modules/toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
@@ -831,6 +1114,15 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/validator": {
|
||||||
|
"version": "13.15.26",
|
||||||
|
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
|
||||||
|
"integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vary": {
|
"node_modules/vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
@@ -845,6 +1137,45 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/yaml": {
|
||||||
|
"version": "2.0.0-1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz",
|
||||||
|
"integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/z-schema": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"lodash.isequal": "^4.5.0",
|
||||||
|
"validator": "^13.7.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"z-schema": "bin/z-schema"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^5.2.1"
|
"express": "^5.2.1",
|
||||||
|
"swagger-jsdoc": "^6.2.8",
|
||||||
|
"swagger-ui-express": "^5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { json } from 'express';
|
import { json } from 'express';
|
||||||
// cors - middleware для разрешения кросс-доменных запросов
|
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
// Эти модули нужны для работы с путями файлов
|
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
|
|
||||||
// Получаем текущий путь к файлу (специально для модулей ES6)
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
// Получаем директорию текущего файла
|
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
// Создаем экземпляр приложения Express
|
// Создаем экземпляр приложения Express
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// Подключаем middleware (промежуточное программное обеспечение)
|
// Подключаем наши middleware (промежуточные обработчики маршрутов)
|
||||||
// CORS разрешает запросы с других доменов
|
|
||||||
|
// middlware CORS разрешает запросы с других доменов. Без этого браузер
|
||||||
|
// запретит фронтенду общаться с бекендом!
|
||||||
app.use(cors({
|
app.use(cors({
|
||||||
origin: 'http://localhost:8080', // разрешаем только с этого домена
|
origin: 'http://localhost:8080', // разрешаем только с этого домена
|
||||||
methods: ['GET', 'POST', 'PUT', 'DELETE'], // разрешаем только эти методы
|
methods: ['GET', 'POST', 'PUT', 'DELETE'], // разрешаем только эти методы
|
||||||
@@ -247,7 +245,8 @@ app.get('/', function(_, response) {
|
|||||||
getOneNote: 'GET /notes/:id',
|
getOneNote: 'GET /notes/:id',
|
||||||
createNote: 'POST /notes',
|
createNote: 'POST /notes',
|
||||||
updateNote: 'PUT /notes/:id',
|
updateNote: 'PUT /notes/:id',
|
||||||
deleteNote: 'DELETE /notes/:id'
|
deleteNote: 'DELETE /notes/:id',
|
||||||
|
docs: 'GET /docs'
|
||||||
},
|
},
|
||||||
instructions: 'Используйте Postman или curl для тестирования API'
|
instructions: 'Используйте Postman или curl для тестирования API'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,20 +1,16 @@
|
|||||||
// Импортируем настроенное приложение Express из app.js
|
// Импортируем настроенное приложение Express из app.js
|
||||||
import app from './app.js';
|
import app from './app.js';
|
||||||
|
import setupSwagger from './swagger.js'; // Импортируем настройку Swagger
|
||||||
|
|
||||||
// Определяем порт для сервера
|
// Определяем порт для сервера
|
||||||
// process.env.PORT - берет порт из переменных окружения (если есть)
|
// process.env.PORT - берет порт из переменных окружения (если есть)
|
||||||
// || 3000 - если переменной нет, используем порт 3000
|
// || 3000 - если переменной нет, используем порт 3000
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
setupSwagger(app);
|
||||||
|
|
||||||
// Запускаем сервер на указанном порту
|
// Запускаем сервер на указанном порту
|
||||||
app.listen(PORT, function() {
|
app.listen(PORT, function() {
|
||||||
// Эта функция выполнится при успешном запуске сервера
|
// Эта функция выполнится при успешном запуске сервера
|
||||||
console.log(`Backend server running on port ${PORT}`);
|
console.log(`Backend server running on port ${PORT}`);
|
||||||
console.log(`Вы можете открыть в браузере: http://localhost:${PORT}`);
|
console.log(`Вы можете открыть в браузере: http://localhost:${PORT}`);
|
||||||
console.log('Для тестирования API используйте:');
|
|
||||||
console.log('1. GET http://localhost:3000/notes - получить все заметки');
|
|
||||||
console.log('2. GET http://localhost:3000/notes/1 - получить заметку с ID=1');
|
|
||||||
console.log('3. POST http://localhost:3000/notes - создать новую заметку');
|
|
||||||
console.log('4. PUT http://localhost:3000/notes/1 - обновить заметку с ID=1');
|
|
||||||
console.log('5. DELETE http://localhost:3000/notes/1 - удалить заметку с ID=1');
|
|
||||||
});
|
});
|
||||||
|
|||||||
580
backend/src/swagger.js
Normal file
580
backend/src/swagger.js
Normal file
@@ -0,0 +1,580 @@
|
|||||||
|
import swaggerJsdoc from 'swagger-jsdoc';
|
||||||
|
import swaggerUi from 'swagger-ui-express';
|
||||||
|
|
||||||
|
// Определение схем OpenAPI
|
||||||
|
const swaggerDefinition = {
|
||||||
|
openapi: '3.0.0',
|
||||||
|
info: {
|
||||||
|
title: 'API для управления заметками',
|
||||||
|
version: '1.0.0',
|
||||||
|
description: 'Простое REST API для создания, чтения, обновления и удаления заметок',
|
||||||
|
contact: {
|
||||||
|
name: 'Разработчик API',
|
||||||
|
email: 'dev@example.com'
|
||||||
|
},
|
||||||
|
license: {
|
||||||
|
name: 'MIT',
|
||||||
|
url: 'https://opensource.org/licenses/MIT'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
servers: [
|
||||||
|
{
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
description: 'Локальный сервер разработки'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: 'https://api.example.com',
|
||||||
|
description: 'Продакшен сервер'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
name: 'Заметки',
|
||||||
|
description: 'Операции с заметками'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Системные',
|
||||||
|
description: 'Системные endpoints'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
components: {
|
||||||
|
schemas: {
|
||||||
|
Note: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['title', 'text', 'author'],
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: 'integer',
|
||||||
|
example: 1,
|
||||||
|
description: 'Уникальный идентификатор заметки'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Моя первая заметка',
|
||||||
|
description: 'Заголовок заметки',
|
||||||
|
minLength: 1,
|
||||||
|
maxLength: 100
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Это содержимое моей заметки...',
|
||||||
|
description: 'Текст заметки',
|
||||||
|
minLength: 1
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Иван Иванов',
|
||||||
|
description: 'Автор заметки',
|
||||||
|
minLength: 1,
|
||||||
|
maxLength: 50
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
example: '2023-10-01T12:00:00.000Z',
|
||||||
|
description: 'Дата и время создания'
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date-time',
|
||||||
|
example: '2023-10-02T14:30:00.000Z',
|
||||||
|
description: 'Дата и время последнего обновления'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
NoteInput: {
|
||||||
|
type: 'object',
|
||||||
|
required: ['title', 'text', 'author'],
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Моя первая заметка',
|
||||||
|
description: 'Заголовок заметки'
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Это содержимое мой заметки...',
|
||||||
|
description: 'Текст заметки'
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Иван Иванов',
|
||||||
|
description: 'Автор заметки'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
NoteUpdate: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Обновленный заголовок',
|
||||||
|
description: 'Новый заголовок заметки'
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Обновленный текст заметки...',
|
||||||
|
description: 'Новый текст заметки'
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Петр Петров',
|
||||||
|
description: 'Новый автор заметки'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SuccessResponse: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
success: {
|
||||||
|
type: 'boolean',
|
||||||
|
example: true
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Операция выполнена успешно'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
oneOf: [
|
||||||
|
{ $ref: '#/components/schemas/Note' },
|
||||||
|
{ type: 'array', items: { $ref: '#/components/schemas/Note' } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
type: 'integer',
|
||||||
|
example: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ErrorResponse: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
success: {
|
||||||
|
type: 'boolean',
|
||||||
|
example: false
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'Произошла ошибка'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
securitySchemes: {
|
||||||
|
BearerAuth: {
|
||||||
|
type: 'http',
|
||||||
|
scheme: 'bearer',
|
||||||
|
bearerFormat: 'JWT'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
paths: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Опции для swagger-jsdoc
|
||||||
|
const options = {
|
||||||
|
swaggerDefinition,
|
||||||
|
apis: [], // Пути к файлам с JSDoc комментариями (если будут использоваться)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Генерируем спецификацию
|
||||||
|
const swaggerSpec = swaggerJsdoc(options);
|
||||||
|
|
||||||
|
// Расширяем спецификацию описанием endpoints
|
||||||
|
swaggerSpec.paths = {
|
||||||
|
'/': {
|
||||||
|
get: {
|
||||||
|
tags: ['Системные'],
|
||||||
|
summary: 'Проверка работы сервера',
|
||||||
|
description: 'Возвращает приветственное сообщение и список доступных endpoints',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Сервер работает',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
message: { type: 'string' },
|
||||||
|
endpoints: { type: 'object' },
|
||||||
|
instructions: { type: 'string' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
message: 'Добро пожаловать в API для заметок!',
|
||||||
|
endpoints: {
|
||||||
|
getAllNotes: 'GET /notes',
|
||||||
|
getOneNote: 'GET /notes/:id',
|
||||||
|
createNote: 'POST /notes',
|
||||||
|
updateNote: 'PUT /notes/:id',
|
||||||
|
deleteNote: 'DELETE /notes/:id'
|
||||||
|
},
|
||||||
|
instructions: 'Используйте Postman или curl для тестирования API'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'/notes': {
|
||||||
|
get: {
|
||||||
|
tags: ['Заметки'],
|
||||||
|
summary: 'Получить все заметки',
|
||||||
|
description: 'Возвращает список всех заметок с пагинацией',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'page',
|
||||||
|
in: 'query',
|
||||||
|
description: 'Номер страницы',
|
||||||
|
required: false,
|
||||||
|
schema: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'limit',
|
||||||
|
in: 'query',
|
||||||
|
description: 'Количество заметок на странице',
|
||||||
|
required: false,
|
||||||
|
schema: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 100,
|
||||||
|
default: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Список заметок успешно получен',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/SuccessResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: true,
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'Первая заметка',
|
||||||
|
text: 'Содержимое первой заметки',
|
||||||
|
author: 'Иван Иванов',
|
||||||
|
createdAt: '2023-10-01T12:00:00.000Z',
|
||||||
|
updatedAt: '2023-10-01T12:00:00.000Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'Вторая заметка',
|
||||||
|
text: 'Содержимое второй заметки',
|
||||||
|
author: 'Петр Петров',
|
||||||
|
createdAt: '2023-10-02T14:30:00.000Z',
|
||||||
|
updatedAt: '2023-10-02T14:30:00.000Z'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
count: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
description: 'Внутренняя ошибка сервера',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: false,
|
||||||
|
message: 'Произошла внутренняя ошибка сервера'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
post: {
|
||||||
|
tags: ['Заметки'],
|
||||||
|
summary: 'Создать новую заметку',
|
||||||
|
description: 'Создает новую заметку с указанными данными',
|
||||||
|
requestBody: {
|
||||||
|
required: true,
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/NoteInput'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
title: 'Новая заметка',
|
||||||
|
text: 'Содержимое новой заметки...',
|
||||||
|
author: 'Иван Иванов'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
201: {
|
||||||
|
description: 'Заметка успешно создана',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/SuccessResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: true,
|
||||||
|
message: 'Заметка успешно создана',
|
||||||
|
data: {
|
||||||
|
id: 3,
|
||||||
|
title: 'Новая заметка',
|
||||||
|
text: 'Содержимое новой заметки...',
|
||||||
|
author: 'Иван Иванов',
|
||||||
|
createdAt: '2023-10-03T10:15:00.000Z',
|
||||||
|
updatedAt: '2023-10-03T10:15:00.000Z'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
description: 'Неверные данные запроса',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: false,
|
||||||
|
message: 'Пожалуйста, заполните все поля: title, text, author'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
description: 'Внутренняя ошибка сервера'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'/notes/{id}': {
|
||||||
|
get: {
|
||||||
|
tags: ['Заметки'],
|
||||||
|
summary: 'Получить заметку по ID',
|
||||||
|
description: 'Возвращает заметку по указанному идентификатору',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
in: 'path',
|
||||||
|
description: 'ID заметки',
|
||||||
|
required: true,
|
||||||
|
schema: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Заметка успешно найдена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/SuccessResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
title: 'Первая заметка',
|
||||||
|
text: 'Содержимое первой заметки',
|
||||||
|
author: 'Иван Иванов',
|
||||||
|
createdAt: '2023-10-01T12:00:00.000Z',
|
||||||
|
updatedAt: '2023-10-01T12:00:00.000Z'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
404: {
|
||||||
|
description: 'Заметка не найдена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: false,
|
||||||
|
message: 'Заметка с таким ID не найдена'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
description: 'Неверный формат ID'
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
description: 'Внутренняя ошибка сервера'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
put: {
|
||||||
|
tags: ['Заметки'],
|
||||||
|
summary: 'Обновить заметку',
|
||||||
|
description: 'Обновляет существующую заметку по указанному ID',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
in: 'path',
|
||||||
|
description: 'ID заметки для обновления',
|
||||||
|
required: true,
|
||||||
|
schema: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
requestBody: {
|
||||||
|
required: true,
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/NoteUpdate'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
title: 'Обновленный заголовок',
|
||||||
|
text: 'Обновленное содержимое заметки...',
|
||||||
|
author: 'Петр Петров'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Заметка успешно обновлена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/SuccessResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: true,
|
||||||
|
message: 'Заметка успешно обновлена',
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
title: 'Обновленный заголовок',
|
||||||
|
text: 'Обновленное содержимое заметки...',
|
||||||
|
author: 'Петр Петров',
|
||||||
|
createdAt: '2023-10-01T12:00:00.000Z',
|
||||||
|
updatedAt: '2023-10-03T15:45:00.000Z'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
description: 'Неверные данные запроса',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
404: {
|
||||||
|
description: 'Заметка не найдена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: false,
|
||||||
|
message: 'Заметка с таким ID не найдена'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
description: 'Внутренняя ошибка сервера'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
tags: ['Заметки'],
|
||||||
|
summary: 'Удалить заметку',
|
||||||
|
description: 'Удаляет заметку по указанному ID',
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
in: 'path',
|
||||||
|
description: 'ID заметки для удаления',
|
||||||
|
required: true,
|
||||||
|
schema: {
|
||||||
|
type: 'integer',
|
||||||
|
minimum: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'Заметка успешно удалена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/SuccessResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: true,
|
||||||
|
message: 'Заметка успешно удалена',
|
||||||
|
data: {
|
||||||
|
id: 1,
|
||||||
|
title: 'Первая заметка',
|
||||||
|
text: 'Содержимое первой заметки',
|
||||||
|
author: 'Иван Иванов',
|
||||||
|
createdAt: '2023-10-01T12:00:00.000Z',
|
||||||
|
updatedAt: '2023-10-01T12:00:00.000Z'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
404: {
|
||||||
|
description: 'Заметка не найдена',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: {
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
},
|
||||||
|
example: {
|
||||||
|
success: false,
|
||||||
|
message: 'Заметка с таким ID не найдена'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500: {
|
||||||
|
description: 'Внутренняя ошибка сервера'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Функция для настройки Swagger UI
|
||||||
|
const setupSwagger = (app) => {
|
||||||
|
app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
|
||||||
|
|
||||||
|
// Дополнительный endpoint для получения сырой спецификации JSON
|
||||||
|
app.get('/docs.json', (_, res) => {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
res.send(swaggerSpec);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('📚 Swagger документация доступна по адресу: http://localhost:3000/docs');
|
||||||
|
console.log('📄 Swagger спецификация доступна по адресу: http://localhost:3000/docs.json');
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setupSwagger;
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"backendUrl": "http://localhost:3000",
|
|
||||||
"apiPrefix": "",
|
|
||||||
"version": "1.0.0"
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,9 @@ const __dirname = dirname(__filename);
|
|||||||
// файлу в public, то буден выдан данный файл
|
// файлу в public, то буден выдан данный файл
|
||||||
app.use(express.static(join(__dirname, 'public')));
|
app.use(express.static(join(__dirname, 'public')));
|
||||||
|
|
||||||
// Конфигурационный endpoint
|
// Маршрут с конфигурацией.
|
||||||
|
// Здесь javascript фронтенда может узнать, по какому адресу
|
||||||
|
// можно найти API бекенда
|
||||||
app.get('/config.json', (_, res) => {
|
app.get('/config.json', (_, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
backendUrl: BACKEND_URL,
|
backendUrl: BACKEND_URL,
|
||||||
|
|||||||
Reference in New Issue
Block a user