Commit c8515eeb authored by Kulpybaev Ilyas's avatar Kulpybaev Ilyas

Webinar-swagger

parent 84aa15f2
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"mysql2": "^3.9.4", "mysql2": "^3.9.4",
"reflect-metadata": "^0.2.1", "reflect-metadata": "^0.2.1",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typeorm": "^0.3.20", "typeorm": "^0.3.20",
...@@ -28,6 +30,8 @@ ...@@ -28,6 +30,8 @@
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/multer": "^1.4.11", "@types/multer": "^1.4.11",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.6",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.45.0", "eslint": "^8.45.0",
...@@ -47,6 +51,46 @@ ...@@ -47,6 +51,46 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"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==",
"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==",
"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=="
},
"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==",
"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/@cspotcode/source-map-support": { "node_modules/@cspotcode/source-map-support": {
"version": "0.8.1", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
...@@ -302,6 +346,11 @@ ...@@ -302,6 +346,11 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"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=="
},
"node_modules/@mapbox/node-pre-gyp": { "node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
...@@ -486,8 +535,7 @@ ...@@ -486,8 +535,7 @@
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
"dev": true
}, },
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.5", "version": "1.3.5",
...@@ -551,6 +599,22 @@ ...@@ -551,6 +599,22 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/swagger-jsdoc": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz",
"integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==",
"dev": true
},
"node_modules/@types/swagger-ui-express": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz",
"integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==",
"dev": true,
"dependencies": {
"@types/express": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/validator": { "node_modules/@types/validator": {
"version": "13.11.9", "version": "13.11.9",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz",
...@@ -915,8 +979,7 @@ ...@@ -915,8 +979,7 @@
"node_modules/argparse": { "node_modules/argparse": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
"dev": true
}, },
"node_modules/array-flatten": { "node_modules/array-flatten": {
"version": "1.1.1", "version": "1.1.1",
...@@ -1102,6 +1165,11 @@ ...@@ -1102,6 +1165,11 @@
"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=="
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
...@@ -1277,6 +1345,14 @@ ...@@ -1277,6 +1345,14 @@
"color-support": "bin.js" "color-support": "bin.js"
} }
}, },
"node_modules/commander": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz",
"integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==",
"engines": {
"node": ">= 6"
}
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
...@@ -1473,7 +1549,6 @@ ...@@ -1473,7 +1549,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"dependencies": { "dependencies": {
"esutils": "^2.0.2" "esutils": "^2.0.2"
}, },
...@@ -1760,7 +1835,6 @@ ...@@ -1760,7 +1835,6 @@
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
...@@ -2498,7 +2572,6 @@ ...@@ -2498,7 +2572,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
}, },
...@@ -2578,12 +2651,27 @@ ...@@ -2578,12 +2651,27 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"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=="
},
"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=="
},
"node_modules/lodash.merge": { "node_modules/lodash.merge": {
"version": "4.6.2", "version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "dev": true
}, },
"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=="
},
"node_modules/long": { "node_modules/long": {
"version": "5.2.3", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
...@@ -3031,6 +3119,12 @@ ...@@ -3031,6 +3119,12 @@
"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==",
"peer": true
},
"node_modules/optionator": { "node_modules/optionator": {
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
...@@ -3737,6 +3831,94 @@ ...@@ -3737,6 +3831,94 @@
"node": ">=8" "node": ">=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==",
"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-jsdoc/node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/swagger-jsdoc/node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"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/swagger-jsdoc/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"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==",
"dependencies": {
"@apidevtools/swagger-parser": "10.0.3"
},
"engines": {
"node": ">=10"
}
},
"node_modules/swagger-ui-dist": {
"version": "5.17.1",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.1.tgz",
"integrity": "sha512-6MNu1MYNALLFvcPpo2MJVJFIxz2rFkH+XoX+J72LBLdj4JLjVaP4lHmNHtJ/tXZUXHdsb2Iw9JhPlqspjkomQg=="
},
"node_modules/swagger-ui-express": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz",
"integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==",
"dependencies": {
"swagger-ui-dist": ">=5.0.0"
},
"engines": {
"node": ">= v0.10.32"
},
"peerDependencies": {
"express": ">=4.0.0 || >=5.0.0-beta"
}
},
"node_modules/synckit": { "node_modules/synckit": {
"version": "0.8.8", "version": "0.8.8",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
...@@ -4285,6 +4467,14 @@ ...@@ -4285,6 +4467,14 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}, },
"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==",
"engines": {
"node": ">= 6"
}
},
"node_modules/yargs": { "node_modules/yargs": {
"version": "17.7.2", "version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
...@@ -4329,6 +4519,34 @@ ...@@ -4329,6 +4519,34 @@
"funding": { "funding": {
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
},
"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==",
"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==",
"optional": true,
"engines": {
"node": "^12.20.0 || >=14"
}
} }
} }
} }
{ {
"name": "node_template", "name": "node_template",
"version": "1.0.0", "version": "2.1.5",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"mysql2": "^3.9.4", "mysql2": "^3.9.4",
"reflect-metadata": "^0.2.1", "reflect-metadata": "^0.2.1",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typeorm": "^0.3.20", "typeorm": "^0.3.20",
...@@ -32,6 +34,8 @@ ...@@ -32,6 +34,8 @@
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/multer": "^1.4.11", "@types/multer": "^1.4.11",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.6",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.45.0", "eslint": "^8.45.0",
......
...@@ -3,6 +3,8 @@ import { Application, RequestHandler } from 'express'; ...@@ -3,6 +3,8 @@ import { Application, RequestHandler } from 'express';
import { AppInit } from './interfaces/AppInit.interface'; import { AppInit } from './interfaces/AppInit.interface';
import { IRoute } from './interfaces/IRoute.interface'; import { IRoute } from './interfaces/IRoute.interface';
import { appDataSource } from '@/config/dataSource'; import { appDataSource } from '@/config/dataSource';
import swaggerUi from 'swagger-ui-express';
import { specs } from '@/config/swagger';
class App { class App {
public app: Application; public app: Application;
...@@ -28,6 +30,8 @@ class App { ...@@ -28,6 +30,8 @@ class App {
private initAssets() { private initAssets() {
this.app.use(express.json()); this.app.use(express.json());
this.app.use(express.static('public')); this.app.use(express.static('public'));
this.app.use('/api-docs', swaggerUi.serve);
this.app.get('/api-docs', swaggerUi.setup(specs));
} }
public async listen() { public async listen() {
await appDataSource.initialize(); await appDataSource.initialize();
......
import swaggerJsdoc from 'swagger-jsdoc';
import {version} from '../../package.json';
const options = {
swaggerDefinition: {
openapi: '3.0.0',
info: {
title: 'Shop-API',
version: version,
description: 'Shop REST API'
},
servers: [
{
url: 'http://localhost:8000'
}
],
components: {
schemas: {
ProductDto: {
type: 'object',
properties: {
title: {
type: 'string',
description: 'Название продукта'
},
description: {
type: 'string',
description: 'Описание продукта'
},
price: {
type: 'number',
description: 'Цена продукта'
},
image: {
type: 'file',
description: 'Картинка продукта',
format: 'binary'
},
categoryId: {
type: 'number',
description: 'ID категории продукта'
}
},
required: ['title', 'price', 'categoryId']
},
CategoryDto: {
type: 'object',
properties: {
title: {
type: 'string',
description: 'Название категории'
},
description: {
type: 'string',
description: 'Описание категории'
},
},
required: ['title']
},
StatusEnum: {
type: 'string',
enum: ['success', 'error', 'loading'],
description: 'Статус оплаты'
}
}
}
},
apis: ['src/controllers/*.ts']
};
export const specs = swaggerJsdoc(options);
\ No newline at end of file
...@@ -3,6 +3,8 @@ import { RequestHandler } from 'express'; ...@@ -3,6 +3,8 @@ import { RequestHandler } from 'express';
import { plainToInstance } from 'class-transformer'; import { plainToInstance } from 'class-transformer';
import { RegisterUserDto } from '@/dto/register-user.dto'; import { RegisterUserDto } from '@/dto/register-user.dto';
import { SignInUserDto } from '@/dto/sign-in-user.dto'; import { SignInUserDto } from '@/dto/sign-in-user.dto';
import { validate } from 'class-validator';
import { formatErrors } from '@/helpers/formatErrors';
export class AuthController { export class AuthController {
private service: AuthService; private service: AuthService;
...@@ -14,6 +16,7 @@ export class AuthController { ...@@ -14,6 +16,7 @@ export class AuthController {
signIn: RequestHandler = async (req, res): Promise<void> => { signIn: RequestHandler = async (req, res): Promise<void> => {
try { try {
const signInUserDto = plainToInstance(SignInUserDto, req.body); const signInUserDto = plainToInstance(SignInUserDto, req.body);
const user = await this.service.signIn(signInUserDto); const user = await this.service.signIn(signInUserDto);
res.send(user); res.send(user);
} catch (e) { } catch (e) {
...@@ -24,6 +27,15 @@ export class AuthController { ...@@ -24,6 +27,15 @@ export class AuthController {
register: RequestHandler = async (req, res): Promise<void> => { register: RequestHandler = async (req, res): Promise<void> => {
try { try {
const registerUserDto = plainToInstance(RegisterUserDto, req.body); const registerUserDto = plainToInstance(RegisterUserDto, req.body);
const errors = await validate(registerUserDto, {
whitelist: true,
validationError: { target: false, value: false },
});
if (errors.length > 0) {
res.status(400).send(formatErrors(errors));
return;
}
const user = await this.service.register(registerUserDto); const user = await this.service.register(registerUserDto);
res.send(user); res.send(user);
} catch (e) { } catch (e) {
......
...@@ -10,11 +10,43 @@ export class CategoryController { ...@@ -10,11 +10,43 @@ export class CategoryController {
this.service = new CategoryService(); this.service = new CategoryService();
} }
/**
* @swagger
* /categories:
* get:
* summary: Получить список категорий
* tags:
* - Categories
* responses:
* '200':
* description: Успешный запрос, получаем список категорий
* '500':
* description: Внутренняя ошибка сервера
*/
getCategories: RequestHandler = async (req, res): Promise<void> => { getCategories: RequestHandler = async (req, res): Promise<void> => {
const categories = await this.service.getCategories(); const categories = await this.service.getCategories();
res.send(categories); res.send(categories);
}; };
/**
* @swagger
* /categories:
* post:
* summary: Создать новую категорию
* tags:
* - Categories
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CategoryDto'
* responses:
* '200':
* description: Успешный запрос, получаем список категорий
* '500':
* description: Внутренняя ошибка сервера
*/
createCategory: RequestHandler = async (req, res): Promise<void> => { createCategory: RequestHandler = async (req, res): Promise<void> => {
const categoryDto = plainToInstance(CategoryDto, req.body); const categoryDto = plainToInstance(CategoryDto, req.body);
const category = await this.service.createCategory(categoryDto); const category = await this.service.createCategory(categoryDto);
......
...@@ -10,11 +10,44 @@ export class ProductController { ...@@ -10,11 +10,44 @@ export class ProductController {
this.service = new ProductService(); this.service = new ProductService();
} }
/**
* @swagger
* /products:
* get:
* summary: Получить список продуктов
* tags:
* - Products
* responses:
* '200':
* description: Успешный запрос, получаем список продуктов
* '500':
* description: Внутренняя ошибка сервера
*/
getProducts: RequestHandler = async (req, res): Promise<void> => { getProducts: RequestHandler = async (req, res): Promise<void> => {
const products = await this.service.getProducts(); const products = await this.service.getProducts();
res.send(products); res.send(products);
}; };
/**
* @swagger
* /products/{id}:
* get:
* summary: Получить один продукт
* tags:
* - Products
* parameters:
* - in: path
* name: id
* required: true
* description: ID продукта
* schema:
* type: integer
* responses:
* '200':
* description: Успешный запрос, получаем продукт
* '400':
* description: Неверный запрос, продукт с указанным ID не найден
*/
getProduct: RequestHandler = async (req, res): Promise<void> => { getProduct: RequestHandler = async (req, res): Promise<void> => {
try { try {
const product = await this.service.getProduct(Number(req.params.id)); const product = await this.service.getProduct(Number(req.params.id));
...@@ -24,6 +57,28 @@ export class ProductController { ...@@ -24,6 +57,28 @@ export class ProductController {
} }
}; };
/**
* @swagger
* /products:
* post:
* summary: Создать новый продукт
* tags:
* - Products
* requestBody:
* required: true
* content:
* multipart/form-data:
* schema:
* $ref: '#/components/schemas/ProductDto'
* responses:
* '200':
* description: Успешный запрос, создаем новый продукт
* '400':
* description: Ошибка в запросе, сообщение об ошибке
* '500':
* description: Внутренняя ошибка сервера
*/
createProduct: RequestHandler = async (req, res): Promise<void> => { createProduct: RequestHandler = async (req, res): Promise<void> => {
try { try {
const productDto = plainToInstance(ProductDto, req.body); const productDto = plainToInstance(ProductDto, req.body);
......
...@@ -15,4 +15,8 @@ export class ProductDto { ...@@ -15,4 +15,8 @@ export class ProductDto {
@IsOptional() @IsOptional()
image!: string; image!: string;
@IsNotEmpty({ message: 'Укажите категорию продукта' })
@IsNumberString({}, { message: 'Укажите корректную категорию' })
categoryId!: number;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment