From dafaf8d4ee8e498253e421ba17cec62f8fcc7675 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:25:02 +0700 Subject: [PATCH 01/10] Add Directus db wrapper --- package.json | 10 +- pnpm-lock.yaml | 1014 +++++++++++++++++++++++++++++++++++++++++++- src/directus_db.ts | 116 +++++ 3 files changed, 1134 insertions(+), 6 deletions(-) create mode 100644 src/directus_db.ts diff --git a/package.json b/package.json index 329d587..29d43ea 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,16 @@ "start": "node dist/index.js", "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/index.js\"", "buildDocker": "docker build -t nuark/huacu_server:latest .", - "pushDocker": "docker push nuark/huacu_server:latest" + "pushDocker": "docker push nuark/huacu_server:latest", + "test": "vitest", + "coverage": "vitest run --coverage" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { + "@directus/sdk": "^10.3.1", + "@noble/hashes": "^1.2.0", "@socket.io/admin-ui": "^0.5.1", "dotenv": "^16.0.3", "express": "^4.18.2", @@ -24,8 +28,10 @@ "@types/express": "^4.17.17", "@types/node": "^18.14.4", "@types/uuid": "^9.0.1", + "@vitest/coverage-c8": "^0.29.2", "concurrently": "^7.6.0", "nodemon": "^2.0.21", - "typescript": "^4.9.5" + "typescript": "^4.9.5", + "vitest": "^0.29.2" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 661a7a5..bf12170 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,10 +1,13 @@ lockfileVersion: 5.4 specifiers: + '@directus/sdk': ^10.3.1 + '@noble/hashes': ^1.2.0 '@socket.io/admin-ui': ^0.5.1 '@types/express': ^4.17.17 '@types/node': ^18.14.4 '@types/uuid': ^9.0.1 + '@vitest/coverage-c8': ^0.29.2 concurrently: ^7.6.0 dotenv: ^16.0.3 express: ^4.18.2 @@ -12,8 +15,11 @@ specifiers: socket.io: ^4.6.1 typescript: ^4.9.5 uuid: ^9.0.0 + vitest: ^0.29.2 dependencies: + '@directus/sdk': 10.3.1 + '@noble/hashes': 1.2.0 '@socket.io/admin-ui': 0.5.1_socket.io@4.6.1 dotenv: 16.0.3 express: 4.18.2 @@ -24,12 +30,249 @@ devDependencies: '@types/express': 4.17.17 '@types/node': 18.14.4 '@types/uuid': 9.0.1 + '@vitest/coverage-c8': 0.29.2_vitest@0.29.2 concurrently: 7.6.0 nodemon: 2.0.21 typescript: 4.9.5 + vitest: 0.29.2 packages: + /@bcoe/v8-coverage/0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@directus/sdk/10.3.1: + resolution: {integrity: sha512-+FUs1kQ27dmrHbAxO+FmCmmAHZrzyyZn+cXZMCtixkeBD8KYBFM7sUKtesQskSmsp5wUksrq2L9Cm+Z93G/ONg==} + dependencies: + axios: 0.27.2 + transitivePeerDependencies: + - debug + dev: false + + /@esbuild/android-arm/0.16.17: + resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.16.17: + resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.16.17: + resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.16.17: + resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.16.17: + resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.16.17: + resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.16.17: + resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.16.17: + resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.16.17: + resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.16.17: + resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.16.17: + resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.16.17: + resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.16.17: + resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.16.17: + resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.16.17: + resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.16.17: + resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.16.17: + resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.16.17: + resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.16.17: + resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.16.17: + resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.16.17: + resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.16.17: + resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@istanbuljs/schema/0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/trace-mapping/0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@noble/hashes/1.2.0: + resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} + dev: false + /@socket.io/admin-ui/0.5.1_socket.io@4.6.1: resolution: {integrity: sha512-1dlGL2FGm6T+uL1e6iDvbo2eCINwvW7iVbjIblwh5kPPRM1SP8lmZrbFZf4QNJ/cqQ+JLcx49eXGM9WAB4TK7w==} peerDependencies: @@ -58,6 +301,16 @@ packages: '@types/node': 18.14.4 dev: true + /@types/chai-subset/1.3.3: + resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + dependencies: + '@types/chai': 4.3.4 + dev: true + + /@types/chai/4.3.4: + resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} + dev: true + /@types/connect/3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: @@ -91,6 +344,10 @@ packages: '@types/serve-static': 1.15.1 dev: true + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + /@types/mime/3.0.1: resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} dev: true @@ -117,6 +374,49 @@ packages: resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} dev: true + /@vitest/coverage-c8/0.29.2_vitest@0.29.2: + resolution: {integrity: sha512-NmD3WirQCeQjjKfHu4iEq18DVOBFbLn9TKVdMpyi5YW2EtnS+K22/WE+9/wRrepOhyeTxuEFgxUVkCAE1GhbnQ==} + peerDependencies: + vitest: '>=0.29.0 <1' + dependencies: + c8: 7.13.0 + picocolors: 1.0.0 + std-env: 3.3.2 + vitest: 0.29.2 + dev: true + + /@vitest/expect/0.29.2: + resolution: {integrity: sha512-wjrdHB2ANTch3XKRhjWZN0UueFocH0cQbi2tR5Jtq60Nb3YOSmakjdAvUa2JFBu/o8Vjhj5cYbcMXkZxn1NzmA==} + dependencies: + '@vitest/spy': 0.29.2 + '@vitest/utils': 0.29.2 + chai: 4.3.7 + dev: true + + /@vitest/runner/0.29.2: + resolution: {integrity: sha512-A1P65f5+6ru36AyHWORhuQBJrOOcmDuhzl5RsaMNFe2jEkoj0faEszQS4CtPU/LxUYVIazlUtZTY0OEZmyZBnA==} + dependencies: + '@vitest/utils': 0.29.2 + p-limit: 4.0.0 + pathe: 1.1.0 + dev: true + + /@vitest/spy/0.29.2: + resolution: {integrity: sha512-Hc44ft5kaAytlGL2PyFwdAsufjbdOvHklwjNy/gy/saRbg9Kfkxfh+PklLm1H2Ib/p586RkQeNFKYuJInUssyw==} + dependencies: + tinyspy: 1.1.1 + dev: true + + /@vitest/utils/0.29.2: + resolution: {integrity: sha512-F14/Uc+vCdclStS2KEoXJlOLAEyqRhnw0gM27iXw9bMTcyKRPJrQ+rlC6XZ125GIPvvKYMPpVxNhiou6PsEeYQ==} + dependencies: + cli-truncate: 3.1.0 + diff: 5.1.0 + loupe: 2.3.6 + picocolors: 1.0.0 + pretty-format: 27.5.1 + dev: true + /abbrev/1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} dev: true @@ -129,11 +429,27 @@ packages: negotiator: 0.6.3 dev: false + /acorn-walk/8.2.0: + resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn/8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} dev: true + /ansi-regex/6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + /ansi-styles/4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -141,6 +457,16 @@ packages: color-convert: 2.0.1 dev: true + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles/6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + /anymatch/3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -153,6 +479,23 @@ packages: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: false + /assertion-error/1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /asynckit/0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /axios/0.27.2: + resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + transitivePeerDependencies: + - debug + dev: false + /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -210,6 +553,30 @@ packages: engines: {node: '>= 0.8'} dev: false + /c8/7.13.0: + resolution: {integrity: sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==} + engines: {node: '>=10.12.0'} + hasBin: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@istanbuljs/schema': 0.1.3 + find-up: 5.0.0 + foreground-child: 2.0.0 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-report: 3.0.0 + istanbul-reports: 3.1.5 + rimraf: 3.0.2 + test-exclude: 6.0.0 + v8-to-istanbul: 9.1.0 + yargs: 16.2.0 + yargs-parser: 20.2.9 + dev: true + + /cac/6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: @@ -217,6 +584,19 @@ packages: get-intrinsic: 1.2.0 dev: false + /chai/4.3.7: + resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 4.1.3 + get-func-name: 2.0.0 + loupe: 2.3.6 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + /chalk/4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -225,6 +605,10 @@ packages: supports-color: 7.2.0 dev: true + /check-error/1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + dev: true + /chokidar/3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -240,6 +624,22 @@ packages: fsevents: 2.3.2 dev: true + /cli-truncate/3.1.0: + resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + slice-ansi: 5.0.0 + string-width: 5.1.2 + dev: true + + /cliui/7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + /cliui/8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -260,6 +660,13 @@ packages: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + /concat-map/0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} dev: true @@ -292,6 +699,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /convert-source-map/1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + /cookie-signature/1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: false @@ -314,6 +725,15 @@ packages: vary: 1.1.2 dev: false + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + /date-fns/2.29.3: resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} engines: {node: '>=0.11'} @@ -352,6 +772,17 @@ packages: optional: true dependencies: ms: 2.1.2 + + /deep-eql/4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /delayed-stream/1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} dev: false /depd/2.0.0: @@ -364,11 +795,20 @@ packages: engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} dev: false + /diff/5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + dev: true + /dotenv/16.0.3: resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} engines: {node: '>=12'} dev: false + /eastasianwidth/0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + /ee-first/1.1.1: resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} dev: false @@ -377,6 +817,10 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + /encodeurl/1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -407,6 +851,36 @@ packages: - utf-8-validate dev: false + /esbuild/0.16.17: + resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.16.17 + '@esbuild/android-arm64': 0.16.17 + '@esbuild/android-x64': 0.16.17 + '@esbuild/darwin-arm64': 0.16.17 + '@esbuild/darwin-x64': 0.16.17 + '@esbuild/freebsd-arm64': 0.16.17 + '@esbuild/freebsd-x64': 0.16.17 + '@esbuild/linux-arm': 0.16.17 + '@esbuild/linux-arm64': 0.16.17 + '@esbuild/linux-ia32': 0.16.17 + '@esbuild/linux-loong64': 0.16.17 + '@esbuild/linux-mips64el': 0.16.17 + '@esbuild/linux-ppc64': 0.16.17 + '@esbuild/linux-riscv64': 0.16.17 + '@esbuild/linux-s390x': 0.16.17 + '@esbuild/linux-x64': 0.16.17 + '@esbuild/netbsd-x64': 0.16.17 + '@esbuild/openbsd-x64': 0.16.17 + '@esbuild/sunos-x64': 0.16.17 + '@esbuild/win32-arm64': 0.16.17 + '@esbuild/win32-ia32': 0.16.17 + '@esbuild/win32-x64': 0.16.17 + dev: true + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -482,6 +956,41 @@ packages: - supports-color dev: false + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /follow-redirects/1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /foreground-child/2.0.0: + resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} + engines: {node: '>=8.0.0'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 3.0.7 + dev: true + + /form-data/4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /forwarded/0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -492,6 +1001,10 @@ packages: engines: {node: '>= 0.6'} dev: false + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + /fsevents/2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -502,13 +1015,16 @@ packages: /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: false /get-caller-file/2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} dev: true + /get-func-name/2.0.0: + resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} + dev: true + /get-intrinsic/1.2.0: resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: @@ -524,6 +1040,17 @@ packages: is-glob: 4.0.3 dev: true + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + /has-flag/3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -544,7 +1071,10 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: false + + /html-escaper/2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true /http-errors/2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} @@ -568,9 +1098,15 @@ packages: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} dev: true + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false /ipaddr.js/1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} @@ -584,6 +1120,12 @@ packages: binary-extensions: 2.2.0 dev: true + /is-core-module/2.11.0: + resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + dependencies: + has: 1.0.3 + dev: true + /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -594,6 +1136,11 @@ packages: engines: {node: '>=8'} dev: true + /is-fullwidth-code-point/4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + /is-glob/4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -606,10 +1153,65 @@ packages: engines: {node: '>=0.12.0'} dev: true + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-reports/3.1.5: + resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jsonc-parser/3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /local-pkg/0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + /lodash/4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true + /loupe/2.3.6: + resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + dependencies: + get-func-name: 2.0.0 + dev: true + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + /media-typer/0.3.0: resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} engines: {node: '>= 0.6'} @@ -648,17 +1250,31 @@ packages: brace-expansion: 1.1.11 dev: true + /mlly/1.1.1: + resolution: {integrity: sha512-Jnlh4W/aI4GySPo6+DyTN17Q75KKbLTyFK8BrGhjNP4rxuUjbRWhE6gHg3bs33URWAF44FRm7gdQA348i3XxRw==} + dependencies: + acorn: 8.8.2 + pathe: 1.1.0 + pkg-types: 1.0.2 + ufo: 1.1.1 + 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==} + /nanoid/3.3.4: + resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + /negotiator/0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -709,20 +1325,104 @@ packages: ee-first: 1.1.1 dev: false + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit/4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + /parseurl/1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} dev: false + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + /path-to-regexp/0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} dev: false + /pathe/1.1.0: + resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} + dev: true + + /pathval/1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} dev: true + /pkg-types/1.0.2: + resolution: {integrity: sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ==} + dependencies: + jsonc-parser: 3.2.0 + mlly: 1.1.1 + pathe: 1.1.0 + dev: true + + /postcss/8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.4 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /pretty-format/27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + /proxy-addr/2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -757,6 +1457,10 @@ packages: unpipe: 1.0.0 dev: false + /react-is/17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + /readdirp/3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -769,6 +1473,30 @@ packages: engines: {node: '>=0.10.0'} dev: true + /resolve/1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.11.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup/3.18.0: + resolution: {integrity: sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + /rxjs/7.8.0: resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} dependencies: @@ -788,6 +1516,11 @@ packages: hasBin: true dev: true + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + /semver/7.0.0: resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} hasBin: true @@ -830,6 +1563,18 @@ packages: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: false + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + /shell-quote/1.8.0: resolution: {integrity: sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==} dev: true @@ -842,6 +1587,14 @@ packages: object-inspect: 1.12.3 dev: false + /siginfo/2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit/3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + /simple-update-notifier/1.1.0: resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} engines: {node: '>=8.10.0'} @@ -849,6 +1602,14 @@ packages: semver: 7.0.0 dev: true + /slice-ansi/5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + /socket.io-adapter/2.5.2: resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} dependencies: @@ -884,15 +1645,33 @@ packages: - utf-8-validate dev: false + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + /spawn-command/0.0.2-1: resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==} dev: true + /stackback/0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + /statuses/2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} dev: false + /std-env/3.3.2: + resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} + dev: true + /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -902,6 +1681,15 @@ packages: strip-ansi: 6.0.1 dev: true + /string-width/5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.0.1 + dev: true + /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -909,6 +1697,19 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-ansi/7.0.1: + resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-literal/1.0.1: + resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} + dependencies: + acorn: 8.8.2 + dev: true + /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -930,6 +1731,34 @@ packages: has-flag: 4.0.0 dev: true + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /test-exclude/6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /tinybench/2.4.0: + resolution: {integrity: sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==} + dev: true + + /tinypool/0.3.1: + resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy/1.1.1: + resolution: {integrity: sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==} + engines: {node: '>=14.0.0'} + dev: true + /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -958,6 +1787,11 @@ packages: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} dev: true + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + /type-is/1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -972,6 +1806,10 @@ packages: hasBin: true dev: true + /ufo/1.1.1: + resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} + dev: true + /undefsafe/2.0.5: resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} dev: true @@ -991,11 +1829,147 @@ packages: hasBin: true dev: false + /v8-to-istanbul/9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.17 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + dev: true + /vary/1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} dev: false + /vite-node/0.29.2_@types+node@18.14.4: + resolution: {integrity: sha512-5oe1z6wzI3gkvc4yOBbDBbgpiWiApvuN4P55E8OI131JGrSuo4X3SOZrNmZYo4R8Zkze/dhi572blX0zc+6SdA==} + engines: {node: '>=v14.16.0'} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + mlly: 1.1.1 + pathe: 1.1.0 + picocolors: 1.0.0 + vite: 4.1.4_@types+node@18.14.4 + transitivePeerDependencies: + - '@types/node' + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite/4.1.4_@types+node@18.14.4: + resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.14.4 + esbuild: 0.16.17 + postcss: 8.4.21 + resolve: 1.22.1 + rollup: 3.18.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /vitest/0.29.2: + resolution: {integrity: sha512-ydK9IGbAvoY8wkg29DQ4ivcVviCaUi3ivuPKfZEVddMTenFHUfB8EEDXQV8+RasEk1ACFLgMUqAaDuQ/Nk+mQA==} + engines: {node: '>=v14.16.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/chai': 4.3.4 + '@types/chai-subset': 1.3.3 + '@types/node': 18.14.4 + '@vitest/expect': 0.29.2 + '@vitest/runner': 0.29.2 + '@vitest/spy': 0.29.2 + '@vitest/utils': 0.29.2 + acorn: 8.8.2 + acorn-walk: 8.2.0 + cac: 6.7.14 + chai: 4.3.7 + debug: 4.3.4 + local-pkg: 0.4.3 + pathe: 1.1.0 + picocolors: 1.0.0 + source-map: 0.6.1 + std-env: 3.3.2 + strip-literal: 1.0.1 + tinybench: 2.4.0 + tinypool: 0.3.1 + tinyspy: 1.1.1 + vite: 4.1.4_@types+node@18.14.4 + vite-node: 0.29.2_@types+node@18.14.4 + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /why-is-node-running/2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + /wrap-ansi/7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -1005,6 +1979,10 @@ packages: strip-ansi: 6.0.1 dev: true + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + /ws/8.11.0: resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} engines: {node: '>=10.0.0'} @@ -1023,11 +2001,29 @@ packages: engines: {node: '>=10'} dev: true + /yargs-parser/20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + /yargs-parser/21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} dev: true + /yargs/16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: true + /yargs/17.7.1: resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} engines: {node: '>=12'} @@ -1040,3 +2036,13 @@ packages: y18n: 5.0.8 yargs-parser: 21.1.1 dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue/1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true diff --git a/src/directus_db.ts b/src/directus_db.ts new file mode 100644 index 0000000..687ae66 --- /dev/null +++ b/src/directus_db.ts @@ -0,0 +1,116 @@ +import { Directus } from "@directus/sdk"; +import { blake3 } from "@noble/hashes/blake3"; + +export type HuacuUser = { + id: string; + login: string; + password: string; +}; + +export type HuacuStat = { + id: string; + dateCreated: string; + dateUpdated: string; + belongs_to: string; + games_won: number; + games_lost: number; +}; + +export type HuacuCollection = { + huacu_users: HuacuUser; + huacu_stats: HuacuStat; +}; + +function hexify(data: Uint8Array): string { + return Buffer.from(data).toString("hex"); +} + +export class DirectusDB { + private directus: Directus; + + constructor() { + const staticAccessToken = "dDAa9RSZKLuKESwMTfTWUQZcEQWqsKJn"; + this.directus = new Directus("https://directus.nuark.xyz", { + auth: { + staticToken: staticAccessToken, + }, + }); + } + + async registerUser(login: string, password: string) { + const hash = hexify(blake3(password)); + const user = { + login: login, + password: hash, + }; + try { + const newUser = await this.directus.items("huacu_users").createOne(user); + // Now we need to create a stats entry for this user + const stats = { + belongs_to: newUser!.id, + }; + await this.directus.items("huacu_stats").createOne(stats); + return newUser; + } catch (e) { + return null; + } + } + + async authenticateUser(login: string, password: string): Promise { + const hash = hexify(blake3(password)); + const response = await this.directus.items("huacu_users").readByQuery({ + filter: { + login: { + _eq: login, + }, + password: { + _eq: hash, + }, + }, + }); + if (response.data?.length === 1) { + return response.data[0]; + } + return null; + } + + async removeUser(login: string, password: string) { + const user = await this.authenticateUser(login, password); + if (user === null) { + return false; + } + + await this.directus.items("huacu_users").deleteOne(user.id); + return true; + } + + async getStats(userId: string) { + try { + const response = await this.directus.items("huacu_stats").readByQuery({ + filter: { + belongs_to: { + _eq: userId, + }, + }, + }); + return response!.data![0]; + } catch (e) { + // Actually, this should never happen in real life + // because we create a stats entry for every user + return null; + } + } + + async updateStats(userId: string, incrementWin: boolean, incrementLost: boolean) { + try { + const stats = (await this.getStats(userId))!; + await this.directus.items("huacu_stats").updateOne(stats.id, { + games_won: stats.games_won + (incrementWin ? 1 : 0), + games_lost: stats.games_lost + (incrementLost ? 1 : 0), + }); + return true; + } catch (e) { + return false; + } + } +} From dc33c47b4b0d821bfe946b69c449f2e5061e6be6 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:25:27 +0700 Subject: [PATCH 02/10] Add tests for Directus DB wrapper --- test/directus_db.test.ts | 85 ++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 8 ++-- 2 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 test/directus_db.test.ts diff --git a/test/directus_db.test.ts b/test/directus_db.test.ts new file mode 100644 index 0000000..05eeba2 --- /dev/null +++ b/test/directus_db.test.ts @@ -0,0 +1,85 @@ +import { assert, describe, expect, it } from "vitest"; +import { DirectusDB } from "../src/directus_db"; + +describe( + "Direcuts DB wrapper tests", + () => { + const db = new DirectusDB(); + + it("Test user registration, query and deletion", async () => { + const login = "__________test"; + const password = "__________test"; + + // To clean if previous times test failed + await db.removeUser(login, password); + + // Creating user + const resp1 = await db.registerUser(login, password); + expect(resp1).not.toBe(null); + expect(resp1!.login).toBe(login); + + // Checking if user exists + const resp2 = await db.authenticateUser(login, password); + expect(resp2).not.toBe(null); + expect(resp2!.login).toBe(login); + + // Creating user again, which is not allowed + const resp3 = await db.registerUser(login, password); + expect(resp3).toBe(null); + + // Using double password to produce erroring response + const resp4 = await db.authenticateUser(login, password + password); + expect(resp4).toBe(null); + + // Deleting user with wrong password + const result1 = await db.removeUser(login, password + password); + expect(result1).toBe(false); + + // Deleting user + const result2 = await db.removeUser(login, password); + expect(result2).toBe(true); + + // Checking if user exists + const resp5 = await db.authenticateUser(login, password); + expect(resp5).toBe(null); + }); + + it("Test user stats", async () => { + const login = "__________test"; + const password = "__________test"; + + await db.removeUser(login, password); + const testUser = await db.registerUser(login, password); + + // Checking if stats exist + let stats = await db.getStats(testUser!.id); + expect(stats).not.toBe(null); + expect(stats!.belongs_to).toBe(testUser!.id); + expect(stats!.games_won).toBe(0); + expect(stats!.games_lost).toBe(0); + + // Updating stats (win times) and checking if they were updated + const result1 = await db.updateStats(testUser!.id, true, false); + expect(result1).toBe(true); + stats = await db.getStats(testUser!.id); + expect(stats).not.toBe(null); + expect(stats!.belongs_to).toBe(testUser!.id); + expect(stats!.games_won).toBe(1); + expect(stats!.games_lost).toBe(0); + + // Updating stats (lost times) and checking if they were updated + const result2 = await db.updateStats(testUser!.id, false, true); + expect(result2).toBe(true); + stats = await db.getStats(testUser!.id); + expect(stats).not.toBe(null); + expect(stats!.belongs_to).toBe(testUser!.id); + expect(stats!.games_won).toBe(1); + expect(stats!.games_lost).toBe(1); + + // Garbage user id should return false + const result3 = await db.updateStats("asdasdasd", false, true); + expect(result3).toBe(false); + }); + }, + { timeout: 10000 } +); diff --git a/tsconfig.json b/tsconfig.json index ad9258d..a47160d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ @@ -25,7 +25,7 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, + "module": "NodeNext" /* Specify what module code is generated. */, "rootDir": "./src" /* Specify the root folder within your source files. */, // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ @@ -99,5 +99,7 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ - } + }, + + "exclude": ["test"] } From a118bda224653cd4d21de1b849b98736b444853a Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:25:52 +0700 Subject: [PATCH 03/10] .*ignore update to exclude coverage folder --- .dockerignore | 3 ++- .gitignore | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index 76add87..5a19e8a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ node_modules -dist \ No newline at end of file +dist +coverage \ No newline at end of file diff --git a/.gitignore b/.gitignore index 76add87..5a19e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -dist \ No newline at end of file +dist +coverage \ No newline at end of file From f4e75bd90b7973b49e6c79f746980d98238da6fe Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:26:55 +0700 Subject: [PATCH 04/10] Moved models out of index.ts --- src/index.ts | 160 +------------------------------------------------- src/models.ts | 159 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 159 deletions(-) create mode 100644 src/models.ts diff --git a/src/index.ts b/src/index.ts index 4030e9a..df5956f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { v4 as uuidv4 } from "uuid"; import { Server, Socket } from "socket.io"; import { instrument } from "@socket.io/admin-ui"; +import { Client, AvailableGame, Game } from "./models"; import { pallette, availableColors } from "./pallette"; const app = express(); @@ -17,165 +18,6 @@ const io = new Server(server, { }, }); -class Client { - private _login: string; - private _password: string; - private _inGame: Boolean; - - public get login() { - return this._login; - } - public get password() { - return this._password; - } - public get inGame() { - return this._inGame; - } - - constructor(login: string, password: string) { - this._login = login; - this._password = password; - this._inGame = false; - } - - public setInGame(inGame: Boolean) { - this._inGame = inGame; - } - - public simplify() { - return { - login: this.login, - inGame: this.inGame, - }; - } -} - -class Game { - private id: string; - private guesser: Client; - private suggester: Client; - private tries: number; - - private guesses: Set; - private colors: Set; - - public get Id() { - return this.id; - } - public get Guesser() { - return this.guesser; - } - public get Suggester() { - return this.suggester; - } - public get Tries() { - return this.tries; - } - public get Guesses() { - return this.guesses; - } - public get Colors() { - return this.colors; - } - - constructor(id: string, guesser: Client, suggester: Client, tries: number) { - this.id = id; - this.guesser = guesser; - this.suggester = suggester; - this.tries = tries; - this.guesses = new Set(); - this.colors = new Set(); - - while (this.colors.size < 6) { - const key = availableColors[Math.floor(Math.random() * availableColors.length)]; - this.colors.add(key); - } - } - - public Opponent(player: Client): Client { - if (this.guesser === player) { - return this.suggester; - } - return this.guesser; - } - - public Guess(player: Client, guess: string) { - if (this.guesses.has(guess)) { - return true; - } - this.guesses.add(guess); - const opponent = this.Opponent(player); - const opponentSocket = Array.from(onlineClients.keys()).find((socket) => onlineClients.get(socket) === opponent); - if (opponentSocket) { - opponentSocket.emit("guess", guess); - } else { - console.log("opponent socket not found"); - return false; - } - return true; - } - - public GameWon() { - for (const color of this.colors) { - if (!this.guesses.has(color)) { - return false; - } - } - return true; - } - - public GameLost() { - const countOfGuesses = this.guesses.size; - const countOfCorrectGuesses = Array.from(this.guesses).filter((guess) => this.colors.has(guess)).length; - return countOfGuesses - countOfCorrectGuesses >= this.tries; - } - - public simplify() { - return { - id: this.id, - guesser: this.guesser.login, - suggester: this.suggester.login, - tries: this.tries, - }; - } -} - -class AvailableGame { - private _id: string; - private _player: Client; - private _tries: number; - private _neededRole: string; - - public get id(): string { - return this._id; - } - public get player(): Client { - return this._player; - } - public get tries(): number { - return this._tries; - } - public get neededRole(): string { - return this._neededRole; - } - - constructor(id: string, player: Client, tries: number, neededRole: string) { - this._id = id; - this._player = player; - this._tries = tries; - this._neededRole = neededRole; - } - - simplify() { - return { - id: this.id, - player: this.player.login, - tries: this.tries, - neededRole: this.neededRole, - }; - } -} - let registeredClients: Client[] = []; let onlineClients: Map = new Map(); let availableGames: Map = new Map(); diff --git a/src/models.ts b/src/models.ts new file mode 100644 index 0000000..fa1b41b --- /dev/null +++ b/src/models.ts @@ -0,0 +1,159 @@ +import { Socket } from "socket.io"; +import { availableColors } from "./pallette"; + +export class Client { + private _login: string; + private _password: string; + private _inGame: Boolean; + private _socket: Socket; + + public get login() { + return this._login; + } + public get password() { + return this._password; + } + public get inGame() { + return this._inGame; + } + public get socket() { + return this._socket; + } + + constructor(login: string, password: string, socket: Socket) { + this._login = login; + this._password = password; + this._inGame = false; + this._socket = socket; + } + + public setInGame(inGame: Boolean) { + this._inGame = inGame; + } + + public simplify() { + return { + login: this.login, + inGame: this.inGame, + }; + } +} + +export class Game { + private id: string; + private guesser: Client; + private suggester: Client; + private tries: number; + + private guesses: Set; + private colors: Set; + + public get Id() { + return this.id; + } + public get Guesser() { + return this.guesser; + } + public get Suggester() { + return this.suggester; + } + public get Tries() { + return this.tries; + } + public get Guesses() { + return this.guesses; + } + public get Colors() { + return this.colors; + } + + constructor(id: string, guesser: Client, suggester: Client, tries: number) { + this.id = id; + this.guesser = guesser; + this.suggester = suggester; + this.tries = tries; + this.guesses = new Set(); + this.colors = new Set(); + + while (this.colors.size < 6) { + const key = availableColors[Math.floor(Math.random() * availableColors.length)]; + this.colors.add(key); + } + } + + public Opponent(player: Client): Client { + if (this.guesser === player) { + return this.suggester; + } + return this.guesser; + } + + public Guess(player: Client, guess: string) { + if (this.guesses.has(guess)) { + return true; + } + this.guesses.add(guess); + this.Opponent(player).socket.emit("guess", guess); + return true; + } + + public GameWon() { + for (const color of this.colors) { + if (!this.guesses.has(color)) { + return false; + } + } + return true; + } + + public GameLost() { + const countOfGuesses = this.guesses.size; + const countOfCorrectGuesses = Array.from(this.guesses).filter((guess) => this.colors.has(guess)).length; + return countOfGuesses - countOfCorrectGuesses >= this.tries; + } + + public simplify() { + return { + id: this.id, + guesser: this.guesser.login, + suggester: this.suggester.login, + tries: this.tries, + }; + } +} + +export class AvailableGame { + private _id: string; + private _player: Client; + private _tries: number; + private _neededRole: string; + + public get id(): string { + return this._id; + } + public get player(): Client { + return this._player; + } + public get tries(): number { + return this._tries; + } + public get neededRole(): string { + return this._neededRole; + } + + constructor(id: string, player: Client, tries: number, neededRole: string) { + this._id = id; + this._player = player; + this._tries = tries; + this._neededRole = neededRole; + } + + simplify() { + return { + id: this.id, + player: this.player.login, + tries: this.tries, + neededRole: this.neededRole, + }; + } +} From 18ed995ec9fbbc1594539bfe2cccaa0b586c2ee0 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:35:52 +0700 Subject: [PATCH 05/10] Refactored out logging (need better solution) and socket seraching --- src/index.ts | 85 ++++++++++++++-------------------------------------- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/src/index.ts b/src/index.ts index df5956f..862acc2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import express, { Express, Request, Response } from "express"; +import express from "express"; import http from "http"; import { v4 as uuidv4 } from "uuid"; @@ -28,50 +28,44 @@ app.get("/", (req, res) => { }); app.get("/pallette", (req, res) => { - res.json(pallette); + res.json({ + availableColors, + pallette, + }); }); io.on("connection", (socket) => { - console.log("someone connected"); - socket.emit("hello", "I don't know you"); socket.on("register", (login, password) => { - console.log("user send register with login: " + login + " and password: " + password); if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) { socket.emit("register", false, "Login or password is too short or too long"); - console.log("user tried to register with too short or too long login or password"); return; } if (registeredClients.find((client) => client.login === login)) { socket.emit("register", false, "User with this login already exists"); - console.log("user tried to register with existing login"); return; } - registeredClients.push(new Client(login, password)); - onlineClients.set(socket, new Client(login, password)); + const client = new Client(login, password, socket); + registeredClients.push(client); + onlineClients.set(socket, client); socket.emit("register", true, "User registered successfully"); - console.log("user registered successfully"); }); socket.on("login", (login, password) => { - console.log("user send login with login: " + login + " and password: " + password); if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) { socket.emit("login", false, "Login or password is too short or too long"); - console.log("user tried to login with too short or too long login or password"); return; } if (!registeredClients.find((client) => client.login === login)) { socket.emit("login", false, "User with this login does not exist"); - console.log("user tried to login with non existing login"); return; } if (registeredClients.find((client) => client.login === login && client.password !== password)) { socket.emit("login", false, "Wrong password"); - console.log("user tried to login with wrong password"); return; } - onlineClients.set(socket, new Client(login, password)); + onlineClients.set(socket, new Client(login, password, socket)); socket.emit("login", true, "User logged in successfully"); registerSocketLoggedInFunctions(socket); @@ -82,7 +76,6 @@ io.on("connection", (socket) => { socket.on("disconnect", () => { const client = onlineClients.get(socket); if (client !== undefined) { - console.log("user " + client.login + " disconnected"); for (const game of Array.from(availableGames.values())) { if (game.player === client) { availableGames.delete(game.id); @@ -93,10 +86,8 @@ io.on("connection", (socket) => { const game = Array.from(runningGames.values()).find((game) => game.Guesser === client || game.Suggester === client); if (game !== undefined) { const opponentPlayer = game.Opponent(client); - const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login); - if (otherClientSocket !== undefined) { - otherClientSocket.emit("leaveGameResponse", true, 410); - } + opponentPlayer.socket.emit("leaveGameResponse", true, 410); + client.setInGame(false); opponentPlayer.setInGame(false); @@ -105,7 +96,6 @@ io.on("connection", (socket) => { } onlineClients.delete(socket); } else { - console.log("anonymous disconnected"); } io.emit("updateNeeded"); @@ -121,10 +111,6 @@ instrument(io, { }, }); -server.listen(9800, () => { - console.log("⚡️ listening on *:9800"); -}); - function registerSocketLoggedInFunctions(socket: Socket) { socket.on("getUpdate", getUpdateEventHandler); socket.on("createGame", createGameEventHandler); @@ -187,12 +173,6 @@ function registerSocketLoggedInFunctions(socket: Socket) { return; } - const gameSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === game.player.login); - if (gameSocket === undefined) { - socket.emit("joinGameResponse", false, "Player is not online"); - return; - } - availableGames.delete(gameId); io.emit("updateNeeded"); @@ -208,10 +188,8 @@ function registerSocketLoggedInFunctions(socket: Socket) { suggester.setInGame(true); guesser.setInGame(true); const gameInfo = new Game(uuidv4(), guesser, suggester, game.tries); - const suggesterSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === suggester.login)!; - const guesserSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === guesser.login)!; - suggesterSocket.emit("joinGameResponse", true, gameInfo.simplify(), Array.from(gameInfo.Colors)); - guesserSocket.emit("joinGameResponse", true, gameInfo.simplify(), []); + suggester.socket.emit("joinGameResponse", true, gameInfo.simplify(), Array.from(gameInfo.Colors)); + guesser.socket.emit("joinGameResponse", true, gameInfo.simplify(), []); runningGames.set(gameInfo.Id, gameInfo); } @@ -235,25 +213,15 @@ function registerSocketLoggedInFunctions(socket: Socket) { const game = runningGames.get(gameId); if (game === undefined || !client.inGame) { socket.emit("chatResponse", false, 400); - console.log("user " + client.login + " tried to chat in non existing game"); - return; } const opponentPlayer = game.Opponent(client); - const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login); - if (otherClientSocket === undefined) { - socket.emit("chatResponse", false, 404); - console.log("user " + client.login + " tried to chat with non existing user"); - - return; - } - socket.emit("chatResponse", true, { from: client.login, message, }); - otherClientSocket.emit("chatResponse", true, { + opponentPlayer.socket.emit("chatResponse", true, { from: client.login, message, }); @@ -263,32 +231,26 @@ function registerSocketLoggedInFunctions(socket: Socket) { const game = runningGames.get(gameId); if (game === undefined || !client.inGame) { socket.emit("guessResponse", false, 400); - console.log("user " + client.login + " tried to guess in non existing game"); return; } if (game.Guesser.login !== client.login) { socket.emit("guessResponse", false, 400); - console.log("user " + client.login + " tried to guess in game he is not guessing in"); return; } if (!game.Guess(client, guess)) { socket.emit("guessResponse", false, 400); - console.log("user " + client.login + " tried to guess but something gone terribly wrong"); return; } const opponentPlayer = game.Opponent(client); - const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login)!; if (game.GameWon()) { - console.log(`game ${gameId} won by ${client.login} and ${opponentPlayer.login}`); - socket.emit("gameStatus", [true]); - otherClientSocket.emit("gameStatus", [true]); + opponentPlayer.socket.emit("gameStatus", [true]); client.setInGame(false); opponentPlayer.setInGame(false); @@ -296,10 +258,8 @@ function registerSocketLoggedInFunctions(socket: Socket) { return; } if (game.GameLost()) { - console.log(`game ${gameId} lost by ${client.login} and ${opponentPlayer.login}`); - socket.emit("gameStatus", [false]); - otherClientSocket.emit("gameStatus", [false]); + opponentPlayer.socket.emit("gameStatus", [false]); client.setInGame(false); opponentPlayer.setInGame(false); @@ -311,20 +271,19 @@ function registerSocketLoggedInFunctions(socket: Socket) { const game = runningGames.get(gameId); if (game === undefined || !client.inGame) { socket.emit("guessResponse", false, 400); - console.log("user " + client.login + " tried to guess in non existing game"); - return; } - socket.emit("leaveGameResponse", true, 200); const opponentPlayer = game.Opponent(client); - const otherClientSocket = Array.from(onlineClients.keys()).find((key) => onlineClients.get(key)?.login === opponentPlayer.login); - if (otherClientSocket !== undefined) { - otherClientSocket.emit("leaveGameResponse", true, 410); - } + opponentPlayer.socket.emit("leaveGameResponse", true, 410); + socket.emit("leaveGameResponse", true, 200); client.setInGame(false); opponentPlayer.setInGame(false); runningGames.delete(game.Id); } } + +server.listen(9800, () => { + console.log("⚡ Listening on *:9800"); +}); From 203c8ece2b2ee3d2bcd3d3ccaa1b9fd84de8f575 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:42:22 +0700 Subject: [PATCH 06/10] Forgot to add cleanup to test --- test/directus_db.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/directus_db.test.ts b/test/directus_db.test.ts index 05eeba2..c5318c5 100644 --- a/test/directus_db.test.ts +++ b/test/directus_db.test.ts @@ -79,7 +79,10 @@ describe( // Garbage user id should return false const result3 = await db.updateStats("asdasdasd", false, true); expect(result3).toBe(false); + + // Deleting user + await db.removeUser(login, password); }); }, - { timeout: 10000 } + { timeout: 30000 } ); From d6591a2685e960cf084c854db7043ff1656163cc Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 14:59:14 +0700 Subject: [PATCH 07/10] Implemented auth flow with db --- src/index.ts | 38 +++++++++++++++++++++++++------------- src/models.ts | 13 +++++++------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/index.ts b/src/index.ts index 862acc2..9be7cc2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,9 @@ import { instrument } from "@socket.io/admin-ui"; import { Client, AvailableGame, Game } from "./models"; import { pallette, availableColors } from "./pallette"; +import { DirectusDB } from "./directus_db"; + +const db = new DirectusDB(); const app = express(); const server = http.createServer(app); @@ -18,7 +21,7 @@ const io = new Server(server, { }, }); -let registeredClients: Client[] = []; +let cachedClients: Client[] = []; let onlineClients: Map = new Map(); let availableGames: Map = new Map(); let runningGames: Map = new Map(); @@ -37,35 +40,37 @@ app.get("/pallette", (req, res) => { io.on("connection", (socket) => { socket.emit("hello", "I don't know you"); - socket.on("register", (login, password) => { + socket.on("register", async (login, password) => { if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) { socket.emit("register", false, "Login or password is too short or too long"); return; } - if (registeredClients.find((client) => client.login === login)) { + + const newUser = await db.registerUser(login, password); + + if (newUser === null) { socket.emit("register", false, "User with this login already exists"); return; } - const client = new Client(login, password, socket); - registeredClients.push(client); + const client = new Client(newUser!.id, login, socket); + cachedClients.push(client); onlineClients.set(socket, client); socket.emit("register", true, "User registered successfully"); }); - socket.on("login", (login, password) => { + socket.on("login", async (login, password) => { if (login.length < 3 || login.length > 20 || password.length < 3 || password.length > 20) { socket.emit("login", false, "Login or password is too short or too long"); return; } - if (!registeredClients.find((client) => client.login === login)) { - socket.emit("login", false, "User with this login does not exist"); + + const user = await db.authenticateUser(login, password); + if (user === null) { + socket.emit("login", false, "Wrong login or password"); return; } - if (registeredClients.find((client) => client.login === login && client.password !== password)) { - socket.emit("login", false, "Wrong password"); - return; - } - onlineClients.set(socket, new Client(login, password, socket)); + + onlineClients.set(socket, new Client(user!.id, login, socket)); socket.emit("login", true, "User logged in successfully"); registerSocketLoggedInFunctions(socket); @@ -255,6 +260,10 @@ function registerSocketLoggedInFunctions(socket: Socket) { client.setInGame(false); opponentPlayer.setInGame(false); runningGames.delete(gameId); + + db.updateStats(client.id, true, false); + db.updateStats(opponentPlayer.id, true, false); + return; } if (game.GameLost()) { @@ -264,6 +273,9 @@ function registerSocketLoggedInFunctions(socket: Socket) { client.setInGame(false); opponentPlayer.setInGame(false); runningGames.delete(gameId); + + db.updateStats(client.id, false, true); + db.updateStats(opponentPlayer.id, false, true); } } diff --git a/src/models.ts b/src/models.ts index fa1b41b..6427379 100644 --- a/src/models.ts +++ b/src/models.ts @@ -2,17 +2,17 @@ import { Socket } from "socket.io"; import { availableColors } from "./pallette"; export class Client { + private _id: string; private _login: string; - private _password: string; private _inGame: Boolean; private _socket: Socket; + public get id() { + return this._id; + } public get login() { return this._login; } - public get password() { - return this._password; - } public get inGame() { return this._inGame; } @@ -20,9 +20,9 @@ export class Client { return this._socket; } - constructor(login: string, password: string, socket: Socket) { + constructor(id: string, login: string, socket: Socket) { + this._id = id; this._login = login; - this._password = password; this._inGame = false; this._socket = socket; } @@ -33,6 +33,7 @@ export class Client { public simplify() { return { + id: this.id, login: this.login, inGame: this.inGame, }; From f7b2d9ca324b94628ce31e4e03d811b98a28d75a Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 19:17:36 +0700 Subject: [PATCH 08/10] New pallette, stats api and acc. removal api --- assets/extracted.png | Bin 0 -> 1054 bytes src/index.ts | 56 +++- src/pallette.ts | 680 ++++++++++++++++++++++++++++++------------- 3 files changed, 533 insertions(+), 203 deletions(-) create mode 100644 assets/extracted.png diff --git a/assets/extracted.png b/assets/extracted.png new file mode 100644 index 0000000000000000000000000000000000000000..6ecd59730cc4bb20ac220d6edf3f69b9c037a990 GIT binary patch literal 1054 zcmV+(1mXLMP)0|*Hru{S;R1Shs@aaG;RIrQCo+a(-g z{jk`3>+m+ziWMVf`Ww~C(GETY~6%V*+8>dt6hLbV7r;t~59GTsL> zYjf*OigIOkF-OsndCesNOCg`iE%OKL=G|+lGiVU(zyY|C;61q`;UtIG#3Se^azq@- zk9*hLjI5**(dx1f#Z}f9jwL%MtEMF;m-8I#M+&BXLzICi*%rOMCV7M9C0vWWBRNXl zK@BJ)$pL9_b)8@eA^TjqQZmv#xR68A8}gEiW6Y$lCWhn;dJzzL2tfU}xUFa=@duI~ zaw5J!EYPDEs1tXlXrt?Pf7hkz0RMX{lUomo2X$-`%!W@YZ^}J5!v!7b_3QEChs9sR(ow#edsUHk zi{8EWwKP_VDMkPi0kKZy>%gC+^2X=NiNEi+8D+~}=)ZzC(NPoa@JUr6TSeVpef^th z?4oKisj66LBc*i?BG8>lg_tEW1f2ML$D2##DUDawTX7pVP6j8JT#V>JUnWOVt(=PMO>jJVHMoP{S)r9taI9a-|aur zK9vd9fL_6Ly)q*=${Y`*YPOCh=n;4ZKfv}Fd+3U~lgt%WmHF{sM4}*iDR1t@{O#Md zs6S%6vOGE}q;)m3)zo}M?!6wIs#!)Q6-cvQb-qDOnjO+K6?fn-}Ki-@jUI z4m_+WKdI`^r2hy6A!J2P!E!N#4iYWei24JRfR0SPrWWjr3Mwb&2_}~8fWTcRcFL{& YACU5;jv~GMJOBUy07*qoM6N<$f<934NB{r; literal 0 HcmV?d00001 diff --git a/src/index.ts b/src/index.ts index 9be7cc2..8a2d730 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,7 +71,7 @@ io.on("connection", (socket) => { } onlineClients.set(socket, new Client(user!.id, login, socket)); - socket.emit("login", true, "User logged in successfully"); + socket.emit("login", true, "User logged in successfully", user!.id); registerSocketLoggedInFunctions(socket); @@ -82,7 +82,7 @@ io.on("connection", (socket) => { const client = onlineClients.get(socket); if (client !== undefined) { for (const game of Array.from(availableGames.values())) { - if (game.player === client) { + if (game.player.id === client.id) { availableGames.delete(game.id); return; } @@ -100,7 +100,9 @@ io.on("connection", (socket) => { } } onlineClients.delete(socket); - } else { + + // now need to remove client from cachedClients + cachedClients = cachedClients.filter((e) => e.id !== client.id); } io.emit("updateNeeded"); @@ -117,6 +119,7 @@ instrument(io, { }); function registerSocketLoggedInFunctions(socket: Socket) { + socket.on("logout", logoutEventHandler); socket.on("getUpdate", getUpdateEventHandler); socket.on("createGame", createGameEventHandler); socket.on("joinGame", joinGameEventHandler); @@ -124,9 +127,16 @@ function registerSocketLoggedInFunctions(socket: Socket) { socket.on("chat", chatEventHandler); socket.on("guess", guessEventHandler); socket.on("leaveGame", leaveGameEventHandler); + socket.on("deleteAccount", deleteAccountEventHandler); + socket.on("getUserData", getUserDataEventHandler); const client = onlineClients.get(socket)!; + function logoutEventHandler(): void { + socket.emit("hello"); + socket.disconnect(true); + } + function getUpdateEventHandler(): void { socket.emit("update", true, { availableGames: Array.from(availableGames.values()).map((e) => e.simplify()), @@ -294,6 +304,46 @@ function registerSocketLoggedInFunctions(socket: Socket) { opponentPlayer.setInGame(false); runningGames.delete(game.Id); } + + async function deleteAccountEventHandler(password: string): Promise { + try { + const deletionResult = await db.removeUser(client.login, password); + if (deletionResult) { + socket.emit("deleteAccountResponse", [true]); + socket.emit("hello"); + socket.disconnect(true); + } else { + socket.emit("deleteAccountResponse", [false, "Wrong password or something went wrong"]); + } + } catch (e) { + if (e instanceof Error) { + socket.emit("deleteAccountResponse", false, e.message); + } else { + socket.emit("deleteAccountResponse", false, "Unknown error"); + // TODO: log error + } + } + } + + async function getUserDataEventHandler(userId: string | undefined): Promise { + try { + const stats = await db.getStats(userId ?? client.id); + if (stats === undefined) { + socket.emit("getUserDataResponse", false, "User does not exist"); + return; + } + + socket.emit("getUserDataResponse", true, { + [userId ?? "client"]: { wins: stats!.games_won, losses: stats!.games_lost }, + }); + } catch (e) { + if (e instanceof Error) { + socket.emit("getUserDataResponse", false, e.message); + } else { + socket.emit("getUserDataResponse", false, "Unknown error"); + } + } + } } server.listen(9800, () => { diff --git a/src/pallette.ts b/src/pallette.ts index b178070..91b5bc8 100644 --- a/src/pallette.ts +++ b/src/pallette.ts @@ -1,204 +1,484 @@ export const pallette = { - A0: [0, 0, 186], - A1: [0, 26, 186], - A2: [0, 51, 186], - A3: [0, 77, 186], - A4: [0, 102, 186], - A5: [0, 128, 186], - A6: [0, 153, 186], - A7: [0, 179, 186], - A8: [0, 204, 186], - A9: [0, 230, 186], - B0: [13, 0, 186], - B1: [13, 26, 186], - B2: [13, 51, 186], - B3: [13, 77, 186], - B4: [13, 102, 186], - B5: [13, 128, 186], - B6: [13, 153, 186], - B7: [13, 179, 186], - B8: [13, 204, 186], - B9: [13, 230, 186], - C0: [26, 0, 186], - C1: [26, 26, 186], - C2: [26, 51, 186], - C3: [26, 77, 186], - C4: [26, 102, 186], - C5: [26, 128, 186], - C6: [26, 153, 186], - C7: [26, 179, 186], - C8: [26, 204, 186], - C9: [26, 230, 186], - D0: [38, 0, 186], - D1: [38, 26, 186], - D2: [38, 51, 186], - D3: [38, 77, 186], - D4: [38, 102, 186], - D5: [38, 128, 186], - D6: [38, 153, 186], - D7: [38, 179, 186], - D8: [38, 204, 186], - D9: [38, 230, 186], - E0: [51, 0, 186], - E1: [51, 26, 186], - E2: [51, 51, 186], - E3: [51, 77, 186], - E4: [51, 102, 186], - E5: [51, 128, 186], - E6: [51, 153, 186], - E7: [51, 179, 186], - E8: [51, 204, 186], - E9: [51, 230, 186], - F0: [64, 0, 186], - F1: [64, 26, 186], - F2: [64, 51, 186], - F3: [64, 77, 186], - F4: [64, 102, 186], - F5: [64, 128, 186], - F6: [64, 153, 186], - F7: [64, 179, 186], - F8: [64, 204, 186], - F9: [64, 230, 186], - G0: [77, 0, 186], - G1: [77, 26, 186], - G2: [77, 51, 186], - G3: [77, 77, 186], - G4: [77, 102, 186], - G5: [77, 128, 186], - G6: [77, 153, 186], - G7: [77, 179, 186], - G8: [77, 204, 186], - G9: [77, 230, 186], - H0: [89, 0, 186], - H1: [89, 26, 186], - H2: [89, 51, 186], - H3: [89, 77, 186], - H4: [89, 102, 186], - H5: [89, 128, 186], - H6: [89, 153, 186], - H7: [89, 179, 186], - H8: [89, 204, 186], - H9: [89, 230, 186], - I0: [102, 0, 186], - I1: [102, 26, 186], - I2: [102, 51, 186], - I3: [102, 77, 186], - I4: [102, 102, 186], - I5: [102, 128, 186], - I6: [102, 153, 186], - I7: [102, 179, 186], - I8: [102, 204, 186], - I9: [102, 230, 186], - J0: [115, 0, 186], - J1: [115, 26, 186], - J2: [115, 51, 186], - J3: [115, 77, 186], - J4: [115, 102, 186], - J5: [115, 128, 186], - J6: [115, 153, 186], - J7: [115, 179, 186], - J8: [115, 204, 186], - J9: [115, 230, 186], - K0: [128, 0, 186], - K1: [128, 26, 186], - K2: [128, 51, 186], - K3: [128, 77, 186], - K4: [128, 102, 186], - K5: [128, 128, 186], - K6: [128, 153, 186], - K7: [128, 179, 186], - K8: [128, 204, 186], - K9: [128, 230, 186], - L0: [140, 0, 186], - L1: [140, 26, 186], - L2: [140, 51, 186], - L3: [140, 77, 186], - L4: [140, 102, 186], - L5: [140, 128, 186], - L6: [140, 153, 186], - L7: [140, 179, 186], - L8: [140, 204, 186], - L9: [140, 230, 186], - M0: [153, 0, 186], - M1: [153, 26, 186], - M2: [153, 51, 186], - M3: [153, 77, 186], - M4: [153, 102, 186], - M5: [153, 128, 186], - M6: [153, 153, 186], - M7: [153, 179, 186], - M8: [153, 204, 186], - M9: [153, 230, 186], - N0: [166, 0, 186], - N1: [166, 26, 186], - N2: [166, 51, 186], - N3: [166, 77, 186], - N4: [166, 102, 186], - N5: [166, 128, 186], - N6: [166, 153, 186], - N7: [166, 179, 186], - N8: [166, 204, 186], - N9: [166, 230, 186], - O0: [179, 0, 186], - O1: [179, 26, 186], - O2: [179, 51, 186], - O3: [179, 77, 186], - O4: [179, 102, 186], - O5: [179, 128, 186], - O6: [179, 153, 186], - O7: [179, 179, 186], - O8: [179, 204, 186], - O9: [179, 230, 186], - P0: [191, 0, 186], - P1: [191, 26, 186], - P2: [191, 51, 186], - P3: [191, 77, 186], - P4: [191, 102, 186], - P5: [191, 128, 186], - P6: [191, 153, 186], - P7: [191, 179, 186], - P8: [191, 204, 186], - P9: [191, 230, 186], - Q0: [204, 0, 186], - Q1: [204, 26, 186], - Q2: [204, 51, 186], - Q3: [204, 77, 186], - Q4: [204, 102, 186], - Q5: [204, 128, 186], - Q6: [204, 153, 186], - Q7: [204, 179, 186], - Q8: [204, 204, 186], - Q9: [204, 230, 186], - R0: [217, 0, 186], - R1: [217, 26, 186], - R2: [217, 51, 186], - R3: [217, 77, 186], - R4: [217, 102, 186], - R5: [217, 128, 186], - R6: [217, 153, 186], - R7: [217, 179, 186], - R8: [217, 204, 186], - R9: [217, 230, 186], - S0: [230, 0, 186], - S1: [230, 26, 186], - S2: [230, 51, 186], - S3: [230, 77, 186], - S4: [230, 102, 186], - S5: [230, 128, 186], - S6: [230, 153, 186], - S7: [230, 179, 186], - S8: [230, 204, 186], - S9: [230, 230, 186], - T0: [242, 0, 186], - T1: [242, 26, 186], - T2: [242, 51, 186], - T3: [242, 77, 186], - T4: [242, 102, 186], - T5: [242, 128, 186], - T6: [242, 153, 186], - T7: [242, 179, 186], - T8: [242, 204, 186], - T9: [242, 230, 186], + A1: [107, 38, 5], + A2: [117, 33, 5], + A3: [128, 26, 12], + A4: [148, 13, 17], + A5: [162, 3, 21], + A6: [174, 0, 25], + A7: [190, 0, 26], + A8: [217, 1, 25], + A9: [246, 1, 18], + A10: [255, 0, 13], + A11: [255, 0, 6], + A12: [255, 0, 8], + A13: [255, 0, 30], + A14: [255, 0, 48], + A15: [255, 1, 65], + A16: [255, 0, 80], + A17: [250, 0, 98], + A18: [247, 0, 117], + A19: [236, 0, 136], + A20: [230, 1, 146], + A21: [218, 0, 146], + A22: [203, 19, 149], + A23: [198, 35, 152], + A24: [183, 39, 153], + A25: [173, 46, 153], + A26: [158, 49, 154], + A27: [151, 56, 156], + A28: [142, 57, 158], + A29: [135, 59, 159], + A30: [124, 62, 161], + B1: [146, 71, 14], + B2: [161, 63, 16], + B3: [171, 55, 16], + B4: [185, 52, 21], + B5: [199, 43, 21], + B6: [216, 12, 24], + B7: [237, 2, 19], + B8: [250, 0, 14], + B9: [255, 0, 8], + B10: [255, 0, 24], + B11: [255, 0, 34], + B12: [254, 0, 52], + B13: [255, 1, 55], + B14: [255, 0, 76], + B15: [255, 0, 94], + B16: [255, 0, 110], + B17: [255, 1, 126], + B18: [255, 0, 144], + B19: [240, 1, 147], + B20: [226, 35, 151], + B21: [207, 49, 159], + B22: [198, 48, 158], + B23: [180, 48, 157], + B24: [170, 54, 155], + B25: [165, 54, 156], + B26: [152, 55, 152], + B27: [140, 58, 158], + B28: [137, 59, 160], + B29: [120, 58, 157], + B30: [113, 57, 158], + C1: [176, 94, 21], + C2: [184, 85, 18], + C3: [200, 84, 11], + C4: [208, 69, 14], + C5: [223, 57, 17], + C6: [235, 45, 19], + C7: [249, 25, 13], + C8: [254, 0, 3], + C9: [255, 7, 23], + C10: [255, 26, 55], + C11: [255, 35, 70], + C12: [255, 25, 74], + C13: [255, 21, 90], + C14: [255, 0, 104], + C15: [255, 0, 120], + C16: [255, 1, 136], + C17: [255, 0, 154], + C18: [239, 47, 156], + C19: [220, 60, 158], + C20: [200, 66, 161], + C21: [195, 64, 160], + C22: [179, 64, 157], + C23: [172, 62, 157], + C24: [161, 60, 156], + C25: [152, 62, 158], + C26: [142, 57, 160], + C27: [132, 57, 158], + C28: [124, 56, 157], + C29: [110, 55, 156], + C30: [97, 46, 149], + D1: [213, 128, 1], + D2: [230, 125, 0], + D3: [238, 112, 1], + D4: [248, 114, 3], + D5: [249, 94, 1], + D6: [253, 81, 0], + D7: [255, 83, 0], + D8: [255, 70, 29], + D9: [254, 61, 44], + D10: [255, 71, 73], + D11: [255, 79, 95], + D12: [255, 81, 104], + D13: [255, 73, 111], + D14: [255, 66, 124], + D15: [255, 60, 142], + D16: [255, 59, 157], + D17: [241, 73, 161], + D18: [223, 76, 165], + D19: [205, 88, 169], + D20: [195, 81, 168], + D21: [177, 79, 166], + D22: [167, 72, 162], + D23: [160, 71, 165], + D24: [153, 69, 163], + D25: [140, 65, 160], + D26: [132, 62, 160], + D27: [119, 59, 159], + D28: [110, 54, 155], + D29: [95, 50, 153], + D30: [73, 46, 143], + E1: [247, 152, 0], + E2: [254, 148, 0], + E3: [255, 139, 0], + E4: [255, 133, 3], + E5: [255, 125, 1], + E6: [255, 110, 1], + E7: [254, 110, 39], + E8: [255, 100, 52], + E9: [255, 100, 69], + E10: [254, 111, 97], + E11: [255, 109, 112], + E12: [255, 110, 125], + E13: [254, 109, 138], + E14: [254, 102, 153], + E15: [255, 93, 168], + E16: [249, 103, 176], + E17: [226, 107, 175], + E18: [211, 108, 177], + E19: [200, 109, 178], + E20: [183, 99, 174], + E21: [168, 91, 171], + E22: [157, 85, 171], + E23: [148, 82, 169], + E24: [141, 79, 165], + E25: [130, 69, 162], + E26: [118, 68, 163], + E27: [105, 61, 158], + E28: [95, 50, 151], + E29: [79, 42, 156], + E30: [54, 43, 135], + F1: [254, 177, 1], + F2: [255, 173, 1], + F3: [255, 166, 0], + F4: [251, 171, 0], + F5: [254, 160, 24], + F6: [255, 159, 49], + F7: [254, 146, 71], + F8: [255, 136, 80], + F9: [255, 130, 90], + F10: [255, 129, 110], + F11: [254, 136, 122], + F12: [254, 138, 139], + F13: [254, 135, 154], + F14: [255, 134, 165], + F15: [255, 129, 182], + F16: [239, 136, 189], + F17: [221, 136, 193], + F18: [208, 137, 193], + F19: [196, 128, 189], + F20: [180, 119, 186], + F21: [165, 115, 186], + F22: [152, 101, 178], + F23: [138, 93, 174], + F24: [130, 88, 172], + F25: [119, 79, 168], + F26: [105, 75, 165], + F27: [95, 66, 158], + F28: [79, 51, 154], + F29: [61, 46, 149], + F30: [46, 41, 125], + G1: [254, 189, 0], + G2: [254, 189, 1], + G3: [255, 180, 0], + G4: [250, 180, 0], + G5: [255, 183, 75], + G6: [255, 168, 63], + G7: [254, 167, 87], + G8: [254, 158, 98], + G9: [255, 157, 110], + G10: [255, 156, 127], + G11: [255, 154, 146], + G12: [255, 153, 151], + G13: [255, 153, 166], + G14: [255, 150, 170], + G15: [255, 152, 199], + G16: [237, 162, 203], + G17: [218, 165, 207], + G18: [211, 172, 216], + G19: [190, 149, 205], + G20: [174, 138, 199], + G21: [159, 130, 194], + G22: [141, 118, 186], + G23: [129, 109, 180], + G24: [118, 101, 179], + G25: [105, 94, 173], + G26: [89, 85, 170], + G27: [81, 75, 163], + G28: [70, 66, 163], + G29: [50, 55, 155], + G30: [42, 47, 139], + H1: [255, 205, 2], + H2: [255, 204, 0], + H3: [255, 197, 1], + H4: [255, 196, 4], + H5: [255, 196, 32], + H6: [255, 188, 63], + H7: [253, 186, 73], + H8: [255, 182, 93], + H9: [255, 175, 112], + H10: [255, 171, 122], + H11: [255, 171, 137], + H12: [255, 176, 157], + H13: [254, 180, 171], + H14: [252, 181, 179], + H15: [247, 179, 200], + H16: [223, 181, 217], + H17: [210, 183, 218], + H18: [206, 189, 221], + H19: [183, 170, 214], + H20: [165, 162, 207], + H21: [154, 149, 205], + H22: [131, 137, 199], + H23: [116, 126, 195], + H24: [104, 118, 191], + H25: [90, 108, 180], + H26: [77, 100, 180], + H27: [68, 90, 175], + H28: [59, 80, 169], + H29: [40, 70, 160], + H30: [30, 60, 158], + I1: [254, 225, 1], + I2: [254, 220, 0], + I3: [255, 216, 1], + I4: [252, 216, 0], + I5: [255, 222, 5], + I6: [254, 214, 54], + I7: [254, 216, 69], + I8: [255, 212, 82], + I9: [251, 219, 108], + I10: [241, 226, 133], + I11: [239, 221, 149], + I12: [233, 226, 174], + I13: [227, 224, 193], + I14: [220, 225, 202], + I15: [208, 226, 210], + I16: [192, 223, 228], + I17: [188, 218, 244], + I18: [187, 217, 243], + I19: [158, 203, 236], + I20: [144, 187, 229], + I21: [130, 172, 222], + I22: [112, 162, 221], + I23: [105, 146, 210], + I24: [94, 135, 201], + I25: [76, 123, 191], + I26: [68, 110, 186], + I27: [57, 99, 181], + I28: [48, 93, 178], + I29: [43, 80, 169], + I30: [31, 72, 164], + J1: [252, 236, 1], + J2: [253, 235, 1], + J3: [254, 234, 0], + J4: [255, 236, 0], + J5: [252, 239, 0], + J6: [251, 243, 48], + J7: [250, 240, 80], + J8: [240, 239, 112], + J9: [230, 236, 126], + J10: [221, 233, 147], + J11: [213, 232, 166], + J12: [207, 233, 186], + J13: [206, 233, 202], + J14: [199, 235, 209], + J15: [193, 232, 214], + J16: [176, 232, 231], + J17: [164, 230, 244], + J18: [164, 229, 249], + J19: [139, 223, 249], + J20: [107, 216, 255], + J21: [98, 201, 242], + J22: [89, 183, 234], + J23: [76, 172, 222], + J24: [72, 154, 214], + J25: [58, 141, 207], + J26: [59, 126, 197], + J27: [44, 113, 191], + J28: [35, 104, 182], + J29: [42, 92, 177], + J30: [36, 82, 168], + K1: [249, 240, 0], + K2: [249, 240, 1], + K3: [248, 239, 0], + K4: [249, 237, 3], + K5: [244, 236, 47], + K6: [236, 237, 74], + K7: [231, 234, 105], + K8: [222, 230, 118], + K9: [212, 229, 117], + K10: [198, 223, 132], + K11: [182, 223, 144], + K12: [171, 219, 157], + K13: [170, 220, 169], + K14: [167, 220, 178], + K15: [162, 221, 191], + K16: [165, 222, 215], + K17: [158, 222, 222], + K18: [153, 224, 228], + K19: [131, 219, 233], + K20: [109, 217, 243], + K21: [71, 213, 249], + K22: [40, 205, 250], + K23: [45, 192, 236], + K24: [52, 173, 226], + K25: [47, 160, 220], + K26: [45, 140, 208], + K27: [33, 127, 199], + K28: [36, 116, 187], + K29: [34, 103, 181], + K30: [34, 95, 178], + L1: [244, 237, 1], + L2: [242, 235, 0], + L3: [235, 233, 0], + L4: [234, 233, 1], + L5: [229, 231, 0], + L6: [219, 229, 36], + L7: [209, 224, 71], + L8: [186, 219, 86], + L9: [168, 217, 89], + L10: [157, 214, 107], + L11: [146, 212, 115], + L12: [136, 211, 129], + L13: [126, 210, 148], + L14: [122, 207, 152], + L15: [121, 210, 166], + L16: [120, 209, 177], + L17: [122, 211, 191], + L18: [116, 212, 200], + L19: [101, 212, 205], + L20: [91, 209, 213], + L21: [58, 206, 220], + L22: [0, 205, 226], + L23: [3, 201, 246], + L24: [0, 190, 242], + L25: [0, 172, 232], + L26: [2, 156, 218], + L27: [25, 138, 208], + L28: [21, 121, 196], + L29: [37, 115, 190], + L30: [30, 102, 184], + M1: [226, 227, 1], + M2: [218, 226, 1], + M3: [211, 226, 1], + M4: [203, 223, 1], + M5: [198, 219, 0], + M6: [180, 215, 11], + M7: [168, 212, 41], + M8: [148, 208, 52], + M9: [126, 202, 67], + M10: [112, 200, 78], + M11: [96, 199, 92], + M12: [81, 199, 103], + M13: [78, 197, 117], + M14: [77, 197, 126], + M15: [76, 199, 136], + M16: [78, 200, 143], + M17: [78, 199, 156], + M18: [81, 203, 164], + M19: [85, 203, 169], + M20: [63, 202, 181], + M21: [35, 200, 186], + M22: [0, 198, 197], + M23: [3, 196, 211], + M24: [0, 197, 224], + M25: [0, 190, 234], + M26: [0, 174, 234], + M27: [0, 160, 222], + M28: [0, 142, 210], + M29: [1, 129, 200], + M30: [0, 116, 189], + N1: [191, 218, 1], + N2: [182, 215, 0], + N3: [172, 212, 1], + N4: [159, 207, 1], + N5: [147, 206, 0], + N6: [133, 205, 1], + N7: [109, 197, 27], + N8: [93, 196, 29], + N9: [77, 191, 41], + N10: [47, 185, 46], + N11: [23, 184, 55], + N12: [0, 181, 71], + N13: [0, 186, 75], + N14: [0, 187, 98], + N15: [0, 191, 108], + N16: [12, 193, 112], + N17: [27, 191, 120], + N18: [29, 195, 133], + N19: [40, 196, 135], + N20: [47, 194, 140], + N21: [25, 195, 156], + N22: [0, 198, 171], + N23: [3, 196, 177], + N24: [0, 195, 197], + N25: [0, 195, 209], + N26: [0, 189, 221], + N27: [0, 177, 227], + N28: [1, 170, 227], + N29: [0, 154, 216], + N30: [1, 135, 206], + O1: [149, 197, 1], + O2: [142, 198, 1], + O3: [134, 197, 4], + O4: [121, 194, 29], + O5: [107, 191, 33], + O6: [81, 182, 42], + O7: [69, 179, 44], + O8: [40, 172, 53], + O9: [28, 170, 52], + O10: [3, 160, 53], + O11: [0, 161, 58], + O12: [3, 167, 55], + O13: [1, 172, 58], + O14: [2, 180, 56], + O15: [2, 183, 68], + O16: [3, 186, 82], + O17: [2, 188, 89], + O18: [0, 190, 104], + O19: [2, 189, 110], + O20: [2, 190, 113], + O21: [0, 193, 128], + O22: [3, 191, 141], + O23: [3, 193, 157], + O24: [3, 191, 167], + O25: [1, 192, 185], + O26: [3, 195, 200], + O27: [1, 193, 214], + O28: [3, 182, 215], + O29: [1, 173, 221], + O30: [4, 162, 227], + P1: [112, 167, 40], + P2: [100, 172, 36], + P3: [92, 170, 50], + P4: [80, 165, 46], + P5: [57, 167, 52], + P6: [29, 162, 55], + P7: [0, 154, 56], + P8: [0, 153, 57], + P9: [0, 149, 59], + P10: [1, 139, 61], + P11: [0, 144, 59], + P12: [0, 148, 56], + P13: [0, 158, 58], + P14: [0, 165, 61], + P15: [0, 174, 61], + P16: [0, 181, 60], + P17: [0, 183, 59], + P18: [0, 184, 72], + P19: [0, 185, 84], + P20: [3, 186, 93], + P21: [0, 188, 104], + P22: [0, 190, 120], + P23: [2, 189, 136], + P24: [0, 187, 152], + P25: [0, 191, 160], + P26: [0, 191, 175], + P27: [0, 191, 192], + P28: [1, 192, 202], + P29: [0, 187, 218], + P30: [0, 182, 232], }; export const availableColors = Object.keys(pallette); From 7f63fb4a0e58626c7dc47f743ee3ea13d15cf81b Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 19:35:18 +0700 Subject: [PATCH 09/10] Improvements upon Dockerfile --- Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b3b80a5..cf33d3d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,10 +4,13 @@ EXPOSE 9800 WORKDIR /home/node/app -COPY . . +COPY ./package.json ./ RUN npm install -g pnpm RUN pnpm install + +COPY . . + RUN pnpm run build CMD ["node", "dist/index.js"] \ No newline at end of file From ef53588e906ebe87d596454b360c4d13c4fd5cb1 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 5 Mar 2023 21:54:56 +0700 Subject: [PATCH 10/10] Add asyncapi docs endpoint --- src/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/index.ts b/src/index.ts index 8a2d730..4c570c2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import express from "express"; import http from "http"; +import path from "path"; import { v4 as uuidv4 } from "uuid"; import { Server, Socket } from "socket.io"; @@ -30,6 +31,14 @@ app.get("/", (req, res) => { res.send("

Hello world

"); }); +app.get("/asyncapi", (req, res) => { + res.sendFile(path.resolve(__dirname + "/../assets/asyncapi.html")); +}); + +app.get("/extracted", (req, res) => { + res.sendFile(path.resolve(__dirname + "/../assets/extracted.png")); +}); + app.get("/pallette", (req, res) => { res.json({ availableColors,