diff --git a/Server/index.ts b/Server/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/Server/package.json b/Server/package.json index 5cde57e..b7e1e1d 100644 --- a/Server/package.json +++ b/Server/package.json @@ -5,14 +5,15 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "nodemon index.ts" + "start": "ts-node src/index.ts" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", "@types/node": "^20.12.12", - "nodemon": "^3.1.0", "ts-node": "^10.9.2", "typescript": "^5.4.5" }, diff --git a/Server/pnpm-lock.yaml b/Server/pnpm-lock.yaml index 00e59e9..5fe8529 100644 --- a/Server/pnpm-lock.yaml +++ b/Server/pnpm-lock.yaml @@ -19,12 +19,15 @@ dependencies: version: 3.9.7 devDependencies: + '@types/cors': + specifier: ^2.8.17 + version: 2.8.17 + '@types/express': + specifier: ^4.17.21 + version: 4.17.21 '@types/node': specifier: ^20.12.12 version: 20.12.12 - nodemon: - specifier: ^3.1.0 - version: 3.1.0 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) @@ -77,12 +80,80 @@ packages: resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} dev: true + /@types/body-parser@1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.12.12 + dev: true + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 20.12.12 + dev: true + + /@types/cors@2.8.17: + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + dependencies: + '@types/node': 20.12.12 + dev: true + + /@types/express-serve-static-core@4.19.5: + resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} + dependencies: + '@types/node': 20.12.12 + '@types/qs': 6.9.15 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + dev: true + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.5 + '@types/qs': 6.9.15 + '@types/serve-static': 1.15.7 + dev: true + + /@types/http-errors@2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + dev: true + + /@types/mime@1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + dev: true + /@types/node@20.12.12: resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} dependencies: undici-types: 5.26.5 dev: true + /@types/qs@6.9.15: + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + dev: true + + /@types/range-parser@1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + dev: true + + /@types/send@0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 20.12.12 + dev: true + + /@types/serve-static@1.15.7: + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 20.12.12 + '@types/send': 0.17.4 + dev: true + /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -102,14 +173,6 @@ packages: hasBin: true dev: true - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -118,15 +181,6 @@ packages: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: false - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - /body-parser@1.20.2: resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -147,20 +201,6 @@ packages: - supports-color dev: false - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -177,30 +217,11 @@ packages: set-function-length: 1.2.2 dev: false - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} dev: false - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -245,7 +266,7 @@ packages: ms: 2.0.0 dev: false - /debug@4.3.4(supports-color@5.5.0): + /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -255,7 +276,7 @@ packages: optional: true dependencies: ms: 2.1.2 - supports-color: 5.5.0 + dev: false /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} @@ -355,13 +376,6 @@ packages: - supports-color dev: false - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - /finalhandler@1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} @@ -387,14 +401,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} dev: false @@ -416,23 +422,12 @@ packages: hasown: 2.0.2 dev: false - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.4 dev: false - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} dependencies: @@ -481,10 +476,6 @@ packages: safer-buffer: 2.1.2 dev: false - /ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - dev: true - /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: false @@ -495,7 +486,7 @@ packages: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4 denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -511,30 +502,6 @@ packages: engines: {node: '>= 0.10'} dev: false - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - /is-property@1.0.2: resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} dev: false @@ -597,18 +564,13 @@ packages: hasBin: true dev: false - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - /ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: false /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -640,28 +602,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /nodemon@3.1.0: - resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - chokidar: 3.6.0 - debug: 4.3.4(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 3.1.2 - pstree.remy: 1.1.8 - semver: 7.6.2 - simple-update-notifier: 2.0.0 - supports-color: 5.5.0 - touch: 3.1.1 - undefsafe: 2.0.5 - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -687,11 +627,6 @@ packages: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} dev: false - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -700,10 +635,6 @@ packages: ipaddr.js: 1.9.1 dev: false - /pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - dev: true - /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -726,13 +657,6 @@ packages: unpipe: 1.0.0 dev: false - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - /redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} @@ -753,12 +677,6 @@ packages: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: false - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: true - /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} @@ -822,13 +740,6 @@ packages: object-inspect: 1.13.1 dev: false - /simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - dependencies: - semver: 7.6.2 - dev: true - /sqlstring@2.3.3: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} @@ -843,29 +754,11 @@ packages: engines: {node: '>= 0.8'} dev: false - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} dev: false - /touch@3.1.1: - resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} - hasBin: true - dev: true - /ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -911,10 +804,6 @@ packages: hasBin: true dev: true - /undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - dev: true - /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true diff --git a/Server/src/APIs/GetBlogList.ts b/Server/src/APIs/GetBlogList.ts new file mode 100644 index 0000000..7f26f8a --- /dev/null +++ b/Server/src/APIs/GetBlogList.ts @@ -0,0 +1,22 @@ +import { API } from "../Plugs/API/API"; +import ServerStdResponse from "../ServerStdResponse"; +import MySQLConnection from '../Plugs/MySQLConnection' + +// 获取博客列表 +class GetBlogList extends API { + constructor() { + super('GET', '/blogList'); + } + private defaultAccessLevel = 6; + + public async onRequset(data: any, res: any) { + let blogListRes = await MySQLConnection.execute('SELECT uuid, title, description, publish_time from blog WHERE access_level > ? ORDER BY publish_time DESC',[this.defaultAccessLevel]); + if(!blogListRes){ + this.logger.error('查询时数据库发生错误'); + return res.json(ServerStdResponse.SERVER_ERROR); + } + return res.json({...ServerStdResponse.OK, data: blogListRes}); + } +} + +export default GetBlogList; \ No newline at end of file diff --git a/Server/src/APIs/GetResourceList.ts b/Server/src/APIs/GetResourceList.ts new file mode 100644 index 0000000..a51c82f --- /dev/null +++ b/Server/src/APIs/GetResourceList.ts @@ -0,0 +1,29 @@ +import { API } from "../Plugs/API/API"; +import ServerStdResponse from "../ServerStdResponse"; +import MySQLConnection from '../Plugs/MySQLConnection' + +// 获取资源列表 +class GetResourceList extends API { + constructor() { + super('GET', '/resourceList'); + } + private typeList = ['resource', 'download'] + + public async onRequset(data: any, res: any) { + let { type } = data; + if(!type){ + return res.json(ServerStdResponse.PARAMS_MISSING); + } + if(!this.typeList.includes(type)){ + return res.json(ServerStdResponse.INVALID_PARAMS); + } + let resourceListRes = await MySQLConnection.execute('SELECT * from resource WHERE type = ? ORDER BY recommand ASC',[type]); + if(!resourceListRes){ + this.logger.error('查询时数据库发生错误'); + return res.json(ServerStdResponse.SERVER_ERROR); + } + return res.json({...ServerStdResponse.OK, data: resourceListRes}); + } +} + +export default GetResourceList; \ No newline at end of file diff --git a/Server/src/APIs/GetTest.ts b/Server/src/APIs/GetTest.ts new file mode 100644 index 0000000..d8d3c1c --- /dev/null +++ b/Server/src/APIs/GetTest.ts @@ -0,0 +1,16 @@ +import { API } from "../Plugs/API/API"; +import ServerStdResponse from "../ServerStdResponse"; +import MySQLConnection from '../Plugs/MySQLConnection' + +// 测试接口 +class GetTest extends API { + constructor() { + super('GET', '/test'); + } + + public async onRequset(data: any, res: any) { + res.json(ServerStdResponse.OK); + } +} + +export default GetTest; \ No newline at end of file diff --git a/Server/src/Plugs/API/API.ts b/Server/src/Plugs/API/API.ts new file mode 100644 index 0000000..57400bf --- /dev/null +++ b/Server/src/Plugs/API/API.ts @@ -0,0 +1,16 @@ +import Logger from "../Logger"; + +abstract class API { + + protected logger: Logger; + public middlewareFunc: Function[] = []; + constructor(public method: string, public uri: string, ...func: any) { + this.logger = new Logger('API][' + method + '][' + uri); + this.middlewareFunc.push(...func); + } + + // to override + public abstract onRequset(data: any, res: any): void; +} + +export { API }; \ No newline at end of file diff --git a/Server/src/Plugs/API/APILoader.ts b/Server/src/Plugs/API/APILoader.ts new file mode 100644 index 0000000..bb6ceda --- /dev/null +++ b/Server/src/Plugs/API/APILoader.ts @@ -0,0 +1,53 @@ +import express, { NextFunction, Request, Response } from "express"; +import cors from "cors"; +import Logger from "../Logger"; +import { API } from "./API"; +import ServerStdResponse from "../../ServerStdResponse"; +class APILoader { + private app = express(); + private logger = new Logger('APILoader'); + constructor(private port?: number) { + this.logger.info('API服务加载中...'); + this.app.use(express.json({ limit: '50mb' })); + this.app.use(express.urlencoded({ extended: true })); + this.app.use(cors({ + origin: ['http://localhost:5173', 'http://note.ctbu.net.cn', 'http://124.223.5.195:23501'], + methods: ['GET', 'POST'], + allowedHeaders: ['Content-Type', 'Authorization', 'Access-Control-Allow-Origin', ''], + })); + } + + add(api: { new(): API }) { + const instance = new api(); + for (let func of instance.middlewareFunc) { + this.app[instance.method.toLowerCase() as keyof express.Application](instance.uri, (req: Request, res: Response, next: NextFunction) => { + func(req, res, next); + }); + this.logger.info(`[${instance.method}][${instance.uri}] 已启用中间件[${func.name}]`); + } + + this.app[instance.method.toLowerCase() as keyof express.Application](instance.uri, (req: Request, res: Response) => { + let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.ip; + this.logger.info(`[${instance.method}][${instance.uri}] 被请求[${(ip as string).replace('::ffff:', '')}]`); + const data = Object.assign({}, req.query, req.body); + instance.onRequset(data, res); + }); + this.logger.info(`[${instance.method}][${instance.uri}] 加载成功`); + } + + start(port?: number) { + if (this.port == undefined && port == undefined) + throw new Error('未指定API端口') + this.app.use((req: Request, res: Response) => { + this.logger.info(`[${req.method}][${req.url.split('?')[0]}] 该API不存在`); + res.json(ServerStdResponse.API_NOT_FOUND) + }) + this.app.listen(port || this.port, () => { + this.logger.info(`已全部加载完成,API服务开放在端口:${port || this.port}`); + }); + } +} + +export { + APILoader, +} \ No newline at end of file diff --git a/Server/src/Plugs/Logger.ts b/Server/src/Plugs/Logger.ts new file mode 100644 index 0000000..a5d59aa --- /dev/null +++ b/Server/src/Plugs/Logger.ts @@ -0,0 +1,40 @@ +class Logger { + constructor(private namespace: string) { + } + + private getTime(): string { + return new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); + } + + public info(info: string, ...args: any): void { + args = args.map((arg: any) => { + if (typeof arg === 'object') { + return JSON.stringify(arg); + } + return arg; + }) + console.log(`[${this.getTime()}][INFO][${this.namespace}]${info[0] == '[' ? '' : ' '}${info} ` + args.join(' ')); + } + + public warn(info: string, ...args: any): void { + args = args.map((arg: any) => { + if (typeof arg === 'object') { + return JSON.stringify(arg); + } + return arg; + }) + console.log(`[${this.getTime()}][WARN][${this.namespace}]${info[0] == '[' ? '' : ' '}${info} ` + args.join(' ')); + } + + public error(info: string, ...args: any): void { + args = args.map((arg: any) => { + if (typeof arg === 'object') { + return JSON.stringify(arg); + } + return arg; + }) + console.log(`[${this.getTime()}][ERROR][${this.namespace}]${info[0] == '[' ? '' : ' '}${info} ` + args.join(' ')); + } +} + +export default Logger; \ No newline at end of file diff --git a/Server/src/Plugs/Middleware/Auth.ts b/Server/src/Plugs/Middleware/Auth.ts new file mode 100644 index 0000000..4952485 --- /dev/null +++ b/Server/src/Plugs/Middleware/Auth.ts @@ -0,0 +1,17 @@ +import { Request, Response, NextFunction } from "express"; +import config from "../../config"; +import ServerStdResponse from "../../ServerStdResponse"; +import Logger from "../Logger"; +const logger = new Logger("Auth"); +const Auth = (req: Request, res: Response, next: NextFunction) => { + let token = req.headers.authorization; + if (token === config.authToken || token == config.adminToken) { + next(); + } else { + let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.ip; + logger.info(`API[${req.method}][${req.url.split('?')[0]}] 请求鉴权不通过[${token}][${ip}]`); + res.json(ServerStdResponse.AUTH_ERROR); + } +} + +export default Auth; \ No newline at end of file diff --git a/Server/src/Plugs/Middleware/AuthAdmin.ts b/Server/src/Plugs/Middleware/AuthAdmin.ts new file mode 100644 index 0000000..3c35847 --- /dev/null +++ b/Server/src/Plugs/Middleware/AuthAdmin.ts @@ -0,0 +1,17 @@ +import { Request, Response, NextFunction } from "express"; +import config from "../../config"; +import ServerStdResponse from "../../ServerStdResponse"; +import Logger from "../Logger"; +const logger = new Logger("AuthAdmin"); +const AuthAdmin = (req: Request, res: Response, next: NextFunction) => { + let token = req.headers.authorization; + if (token === config.adminToken) { + next(); + } else { + let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.ip; + logger.info(`API[${req.method}][${req.url.split('?')[0]}] 请求鉴权不通过[${token}][${ip}]`); + res.json(ServerStdResponse.AUTH_ERROR); + } +} + +export default AuthAdmin; \ No newline at end of file diff --git a/Server/src/Plugs/Middleware/Unbind.ts b/Server/src/Plugs/Middleware/Unbind.ts new file mode 100644 index 0000000..1ed8d03 --- /dev/null +++ b/Server/src/Plugs/Middleware/Unbind.ts @@ -0,0 +1,9 @@ +import { Request, Response, NextFunction } from "express"; +import Logger from "../Logger"; +const logger = new Logger("Unbind"); +const Unbind = (req: Request, res: Response, next: NextFunction) => { + let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.ip; + logger.info(`API[${req.method}][${req.url.split('?')[0]}] 请求了未绑定的接口[${ip}]`); +} + +export default Unbind; \ No newline at end of file diff --git a/Server/src/Plugs/MySQLConnection.ts b/Server/src/Plugs/MySQLConnection.ts new file mode 100644 index 0000000..1056954 --- /dev/null +++ b/Server/src/Plugs/MySQLConnection.ts @@ -0,0 +1,77 @@ +// MYSQL数据库连接池 +// 版本:v0.1 +import mysql from "mysql2/promise"; +import Logger from "./Logger"; +import config from "../config"; + +class MySQLConnectPool { + private pool: any; + private logger = new Logger('MySQLConnection'); + + constructor() { + this.pool = this.createConnectPool(); + this.logger.info("[MySQL] 数据库连接池已创建") + setTimeout(async () => { + let res = await this.testConnection(); + if (res) + this.logger.info("[MySQL] 数据库测试成功") + else + this.logger.error("[MySQL] 数据库测试失败") + }, 10); + } + + // 内部函数,无需手动调用 + createConnectPool() { + return mysql.createPool({ + host: config.mysql.host, + database: config.mysql.database, + user: config.mysql.user, + password: config.mysql.password, + waitForConnections: true, + connectionLimit: 10, + queueLimit: 0 + }) + } + + // 内部函数,无需手动调用 + async testConnection() { + try { + let res = await this.execute("SELECT 1 + 1 As result"); + if (res[0].result == 2) + return 1; + else + return 0; + } catch (error) { + this.logger.error(`[MySQL] 数据库测试发生了错误:` + error); + return 0; + } + + } + + // 执行SQL语句 + async execute(sql: string, values?: any[], database?: string) { + let connection: any; + try { + connection = await this.pool.getConnection(); + + // 如果指定了数据库,则更改当前连接的数据库 + if (database) { + await connection.changeUser({ database }); + } + + let [rows, fields] = await connection.execute(sql, values); + return rows; + } catch (error) { + this.logger.error("[MySQL] 数据库发生错误:" + error, '\n##', sql, '\n##', JSON.stringify(values)); + return undefined; + } finally { + if (database) + await connection.changeUser({ database: config.mysql.database });// 恢复默认数据库 + if (connection) + connection.release(); + } + } +} + +let MySQLConnection = new MySQLConnectPool(); +export default MySQLConnection; \ No newline at end of file diff --git a/Server/src/Server/Server.ts b/Server/src/Server/Server.ts new file mode 100644 index 0000000..cace755 --- /dev/null +++ b/Server/src/Server/Server.ts @@ -0,0 +1,31 @@ +import Logger from "../Plugs/Logger"; +import { APILoader } from "../Plugs/API/APILoader"; +import config from "../config"; + +import GetTest from "../APIs/GetTest"; +import GetResourceList from "../APIs/GetResourceList"; +import GetBlogList from "../APIs/GetBlogList"; + +class Server { + private logger = new Logger('Server'); + public static instance: Server; + private apiLoader = new APILoader(); + + constructor() { + Server.instance = this; + } + + public async start() { + // 加载前台API + this.apiLoader.add(GetTest); + this.apiLoader.add(GetResourceList); + this.apiLoader.add(GetBlogList); + + this.apiLoader.start(config.apiPort); + } +} + +let _Server = new Server(); +export { + _Server as server, +} \ No newline at end of file diff --git a/Server/src/ServerStdResponse.ts b/Server/src/ServerStdResponse.ts new file mode 100644 index 0000000..4dfe00d --- /dev/null +++ b/Server/src/ServerStdResponse.ts @@ -0,0 +1,52 @@ +const ServerStdResponse = { + OK: { + code: 0, + message: 'OK' + }, + PARAMS_MISSING: { + code: -1, + message: 'Parameters missing' + }, + INVALID_PARAMS: { + code: -2, + message: 'Invalid parameters' + }, + INVALID_TOKEN: { + code: -3, + message: 'Invalid token' + }, + SERVER_ERROR: { + code: -4, + message: 'Server error' + }, + API_NOT_FOUND: { + code: -5, + message: 'API not found' + }, + AUTH_ERROR: { + code: -6, + message: 'Authentication error' + }, + IDENTIFY_FAILED: { + code: -7, + message: 'Identify failed' + }, + GOODS: { + NOTFOUND: { + code: -4001, + message: 'Goods not found' + } + }, + ORDER: { + NOTFOUND: { + code: -5001, + message: 'Order not found' + }, + ALREADY_CANCEL: { + code: -5002, + message: 'Order already canceled' + } + } +} as const; + +export default ServerStdResponse; \ No newline at end of file diff --git a/Server/src/config.ts b/Server/src/config.ts new file mode 100644 index 0000000..04f4683 --- /dev/null +++ b/Server/src/config.ts @@ -0,0 +1,15 @@ +const config = { + mysql: { + host: 'localhost', + // host:'server.tonesc.cn', + database: 'tonecn', + user: 'root', + password: 'Shi15023847146' + // password: '245565' + }, + authToken: '17e50223f4a545ec9e36ebf08e2f71bb', + adminToken: '3a6f71412f9e48b9bbbd056aa7eb5467', + apiPort: 23500, +} as const; + +export default config; \ No newline at end of file diff --git a/Server/src/index.ts b/Server/src/index.ts new file mode 100644 index 0000000..376f75c --- /dev/null +++ b/Server/src/index.ts @@ -0,0 +1,11 @@ +import Logger from "./Plugs/Logger"; +let logger = new Logger("Server"); +logger.info('服务正启动...'); +import { server } from "./Server/Server"; +async function main() { + server.start(); +} + +main().catch((err) => { + logger.error(err); +}); \ No newline at end of file diff --git a/Server/tsconfig.json b/Server/tsconfig.json index a28f979..e7ae2dc 100644 --- a/Server/tsconfig.json +++ b/Server/tsconfig.json @@ -7,8 +7,6 @@ "baseUrl": ".", "paths": { "@/*": ["src/*"], - "@plugs/*": ["plugs/*"], - "@apis/*": ["apis/*"] } } }