Compare commits
20 Commits
281cc0dda7
...
gpio-strea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d085b08dd | ||
|
|
903c66b1d9 | ||
|
|
85cbf665f0 | ||
|
|
f9e21db529 | ||
|
|
df5423b294 | ||
|
|
11783ba2fb | ||
|
|
2b614dcb79 | ||
|
|
2cf11a3f36 | ||
|
|
3c3519f2e8 | ||
|
|
ef62037515 | ||
|
|
b88bd7fe1e | ||
|
|
54ea14af63 | ||
|
|
b7097bcae5 | ||
|
|
ea4988034c | ||
|
|
cf4104329f | ||
|
|
a357d5d9b1 | ||
|
|
6b422d649a | ||
|
|
79ec9f4eff | ||
|
|
f1dc322162 | ||
|
|
fb145c7531 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
src/server/public/dist
|
src/server/public/dist
|
||||||
|
src/server/shrinko8
|
||||||
.env
|
.env
|
||||||
5
TODO.md
5
TODO.md
@@ -8,10 +8,11 @@
|
|||||||
- [x] Update GH Workflow to be by push
|
- [x] Update GH Workflow to be by push
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
- [ ] Fix css bug on chromium
|
- [x] Fix css bug on chromium
|
||||||
- [ ] Add user page to show all projects
|
- [x] Add user page to show all projects
|
||||||
|
|
||||||
## Later
|
## Later
|
||||||
|
- [ ] GPIO shared within room
|
||||||
- [ ] Update pico console handle
|
- [ ] Update pico console handle
|
||||||
- [ ] Add readme prop to picobook.json (figure out best name) and display it in React
|
- [ ] Add readme prop to picobook.json (figure out best name) and display it in React
|
||||||
- [ ] Multiplayer support
|
- [ ] Multiplayer support
|
||||||
|
|||||||
420
package-lock.json
generated
420
package-lock.json
generated
@@ -13,12 +13,13 @@
|
|||||||
"@fastify/cookie": "^9.0.4",
|
"@fastify/cookie": "^9.0.4",
|
||||||
"@fastify/secure-session": "^7.1.0",
|
"@fastify/secure-session": "^7.1.0",
|
||||||
"@fastify/static": "^6.10.2",
|
"@fastify/static": "^6.10.2",
|
||||||
|
"@fastify/websocket": "^10.0.1",
|
||||||
"@firebox/components": "^0.1.5",
|
"@firebox/components": "^0.1.5",
|
||||||
"@firebox/tsutil": "^0.1.2",
|
"@firebox/tsutil": "^0.1.2",
|
||||||
"@sinclair/typebox": "^0.31.5",
|
"@sinclair/typebox": "^0.31.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"fastify": "^4.22.0",
|
"fastify": "^4.26.2",
|
||||||
"isomorphic-git": "^1.25.6",
|
"isomorphic-git": "^1.25.6",
|
||||||
"react-pico-8": "^4.1.0",
|
"react-pico-8": "^4.1.0",
|
||||||
"react-router-dom": "^6.18.0",
|
"react-router-dom": "^6.18.0",
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
"@types/react": "^18.2.21",
|
"@types/react": "^18.2.21",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/uuid": "^9.0.7",
|
"@types/uuid": "^9.0.7",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
"esbuild": "^0.19.2",
|
"esbuild": "^0.19.2",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -955,9 +957,9 @@
|
|||||||
"integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A=="
|
"integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A=="
|
||||||
},
|
},
|
||||||
"node_modules/@fastify/error": {
|
"node_modules/@fastify/error": {
|
||||||
"version": "3.3.0",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
|
||||||
"integrity": "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w=="
|
"integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@fastify/fast-json-stringify-compiler": {
|
"node_modules/@fastify/fast-json-stringify-compiler": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
@@ -1081,6 +1083,16 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@fastify/websocket": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fastify/websocket/-/websocket-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-8/pQIxTPRD8U94aILTeJ+2O3el/r19+Ej5z1O1mXlqplsUH7KzCjAI0sgd5DM/NoPjAi5qLFNIjgM5+9/rGSNw==",
|
||||||
|
"dependencies": {
|
||||||
|
"duplexify": "^4.1.2",
|
||||||
|
"fastify-plugin": "^4.0.0",
|
||||||
|
"ws": "^8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@firebox/components": {
|
"node_modules/@firebox/components": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"resolved": "https://nodepack.playbox.link/@firebox/components/-/components-0.1.5.tgz",
|
"resolved": "https://nodepack.playbox.link/@firebox/components/-/components-0.1.5.tgz",
|
||||||
@@ -1233,6 +1245,15 @@
|
|||||||
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
|
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||||
|
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/abbrev": {
|
"node_modules/abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -1394,13 +1415,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/avvio": {
|
"node_modules/avvio": {
|
||||||
"version": "8.2.1",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-8.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz",
|
||||||
"integrity": "sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==",
|
"integrity": "sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fastify/error": "^3.3.0",
|
||||||
"archy": "^1.0.0",
|
"archy": "^1.0.0",
|
||||||
"debug": "^4.0.0",
|
"debug": "^4.0.0",
|
||||||
"fastq": "^1.6.1"
|
"fastq": "^1.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-macros": {
|
"node_modules/babel-plugin-macros": {
|
||||||
@@ -1859,12 +1881,31 @@
|
|||||||
"url": "https://dotenvx.com"
|
"url": "https://dotenvx.com"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/duplexify": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1",
|
||||||
|
"stream-shift": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/error-ex": {
|
"node_modules/error-ex": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||||
@@ -2033,9 +2074,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fast-content-type-parse": {
|
"node_modules/fast-content-type-parse": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz",
|
||||||
"integrity": "sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA=="
|
"integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ=="
|
||||||
},
|
},
|
||||||
"node_modules/fast-decode-uri-component": {
|
"node_modules/fast-decode-uri-component": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -2069,9 +2110,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fast-redact": {
|
"node_modules/fast-redact": {
|
||||||
"version": "3.3.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
|
||||||
"integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==",
|
"integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
@@ -2082,26 +2123,36 @@
|
|||||||
"integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg=="
|
"integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg=="
|
||||||
},
|
},
|
||||||
"node_modules/fastify": {
|
"node_modules/fastify": {
|
||||||
"version": "4.22.0",
|
"version": "4.26.2",
|
||||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.26.2.tgz",
|
||||||
"integrity": "sha512-HLoBmetdQ6zaJohKW6jzUww8NnwHzkbIbUEyAzM+Nnf7cZVSXRuUV+6b2/xLmu6GGkruIFJ/bIQoKWYRx4wnAQ==",
|
"integrity": "sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/ajv-compiler": "^3.5.0",
|
"@fastify/ajv-compiler": "^3.5.0",
|
||||||
"@fastify/error": "^3.2.0",
|
"@fastify/error": "^3.4.0",
|
||||||
"@fastify/fast-json-stringify-compiler": "^4.3.0",
|
"@fastify/fast-json-stringify-compiler": "^4.3.0",
|
||||||
"abstract-logging": "^2.0.1",
|
"abstract-logging": "^2.0.1",
|
||||||
"avvio": "^8.2.1",
|
"avvio": "^8.3.0",
|
||||||
"fast-content-type-parse": "^1.0.0",
|
"fast-content-type-parse": "^1.1.0",
|
||||||
"fast-json-stringify": "^5.7.0",
|
"fast-json-stringify": "^5.8.0",
|
||||||
"find-my-way": "^7.6.0",
|
"find-my-way": "^8.0.0",
|
||||||
"light-my-request": "^5.9.1",
|
"light-my-request": "^5.11.0",
|
||||||
"pino": "^8.12.0",
|
"pino": "^8.17.0",
|
||||||
"process-warning": "^2.2.0",
|
"process-warning": "^3.0.0",
|
||||||
"proxy-addr": "^2.0.7",
|
"proxy-addr": "^2.0.7",
|
||||||
"rfdc": "^1.3.0",
|
"rfdc": "^1.3.0",
|
||||||
"secure-json-parse": "^2.5.0",
|
"secure-json-parse": "^2.7.0",
|
||||||
"semver": "^7.5.0",
|
"semver": "^7.5.4",
|
||||||
"tiny-lru": "^11.0.1"
|
"toad-cache": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fastify-plugin": {
|
"node_modules/fastify-plugin": {
|
||||||
@@ -2110,9 +2161,9 @@
|
|||||||
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ=="
|
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ=="
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.15.0",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
|
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
@@ -2158,9 +2209,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/find-my-way": {
|
"node_modules/find-my-way": {
|
||||||
"version": "7.6.2",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.1.0.tgz",
|
||||||
"integrity": "sha512-0OjHn1b1nCX3eVbm9ByeEHiscPYiHLfhei1wOUU9qffQkk98wE0Lo8VrVYfSGMgnSnDh86DxedduAnBf4nwUEw==",
|
"integrity": "sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-querystring": "^1.0.0",
|
"fast-querystring": "^1.0.0",
|
||||||
@@ -2945,15 +2996,23 @@
|
|||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
||||||
},
|
},
|
||||||
"node_modules/light-my-request": {
|
"node_modules/light-my-request": {
|
||||||
"version": "5.10.0",
|
"version": "5.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.12.0.tgz",
|
||||||
"integrity": "sha512-ZU2D9GmAcOUculTTdH9/zryej6n8TzT+fNGdNtm6SDp5MMMpHrJJkvAdE3c6d8d2chE9i+a//dS9CWZtisknqA==",
|
"integrity": "sha512-P526OX6E7aeCIfw/9UyJNsAISfcFETghysaWHQAlQYayynShT08MOj4c6fBCvTWBrHXSvqBAKDp3amUPSCQI4w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.6.0",
|
||||||
"process-warning": "^2.0.0",
|
"process-warning": "^3.0.0",
|
||||||
"set-cookie-parser": "^2.4.1"
|
"set-cookie-parser": "^2.4.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/light-my-request/node_modules/cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lines-and-columns": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
@@ -3332,9 +3391,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/on-exit-leak-free": {
|
"node_modules/on-exit-leak-free": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||||
"integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w=="
|
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
@@ -3673,20 +3735,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pino": {
|
"node_modules/pino": {
|
||||||
"version": "8.15.0",
|
"version": "8.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/pino/-/pino-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/pino/-/pino-8.19.0.tgz",
|
||||||
"integrity": "sha512-olUADJByk4twxccmAxb1RiGKOSvddHugCV3wkqjyv+3Sooa2KLrmXrKEWOKi0XPCLasRR5jBXxioE1jxUa4KzQ==",
|
"integrity": "sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"atomic-sleep": "^1.0.0",
|
"atomic-sleep": "^1.0.0",
|
||||||
"fast-redact": "^3.1.1",
|
"fast-redact": "^3.1.1",
|
||||||
"on-exit-leak-free": "^2.1.0",
|
"on-exit-leak-free": "^2.1.0",
|
||||||
"pino-abstract-transport": "v1.0.0",
|
"pino-abstract-transport": "v1.1.0",
|
||||||
"pino-std-serializers": "^6.0.0",
|
"pino-std-serializers": "^6.0.0",
|
||||||
"process-warning": "^2.0.0",
|
"process-warning": "^3.0.0",
|
||||||
"quick-format-unescaped": "^4.0.3",
|
"quick-format-unescaped": "^4.0.3",
|
||||||
"real-require": "^0.2.0",
|
"real-require": "^0.2.0",
|
||||||
"safe-stable-stringify": "^2.3.1",
|
"safe-stable-stringify": "^2.3.1",
|
||||||
"sonic-boom": "^3.1.0",
|
"sonic-boom": "^3.7.0",
|
||||||
"thread-stream": "^2.0.0"
|
"thread-stream": "^2.0.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -3694,9 +3756,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pino-abstract-transport": {
|
"node_modules/pino-abstract-transport": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz",
|
||||||
"integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==",
|
"integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readable-stream": "^4.0.0",
|
"readable-stream": "^4.0.0",
|
||||||
"split2": "^4.0.0"
|
"split2": "^4.0.0"
|
||||||
@@ -3726,9 +3788,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pino-abstract-transport/node_modules/readable-stream": {
|
"node_modules/pino-abstract-transport/node_modules/readable-stream": {
|
||||||
"version": "4.4.2",
|
"version": "4.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
|
||||||
"integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
|
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
@@ -3798,9 +3860,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/process-warning": {
|
"node_modules/process-warning": {
|
||||||
"version": "2.2.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
|
||||||
"integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg=="
|
"integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="
|
||||||
},
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
@@ -4252,9 +4314,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sonic-boom": {
|
"node_modules/sonic-boom": {
|
||||||
"version": "3.3.0",
|
"version": "3.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz",
|
||||||
"integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==",
|
"integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"atomic-sleep": "^1.0.0"
|
"atomic-sleep": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -4287,6 +4349,11 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stream-shift": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="
|
||||||
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
@@ -4398,21 +4465,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/thread-stream": {
|
"node_modules/thread-stream": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz",
|
||||||
"integrity": "sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw==",
|
"integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"real-require": "^0.2.0"
|
"real-require": "^0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tiny-lru": {
|
|
||||||
"version": "11.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz",
|
|
||||||
"integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
@@ -4445,6 +4504,14 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toad-cache": {
|
||||||
|
"version": "3.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz",
|
||||||
|
"integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/toidentifier": {
|
"node_modules/toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
@@ -4683,6 +4750,26 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||||
|
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
@@ -5342,9 +5429,9 @@
|
|||||||
"integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A=="
|
"integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A=="
|
||||||
},
|
},
|
||||||
"@fastify/error": {
|
"@fastify/error": {
|
||||||
"version": "3.3.0",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
|
||||||
"integrity": "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w=="
|
"integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ=="
|
||||||
},
|
},
|
||||||
"@fastify/fast-json-stringify-compiler": {
|
"@fastify/fast-json-stringify-compiler": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
@@ -5441,6 +5528,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@fastify/websocket": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fastify/websocket/-/websocket-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-8/pQIxTPRD8U94aILTeJ+2O3el/r19+Ej5z1O1mXlqplsUH7KzCjAI0sgd5DM/NoPjAi5qLFNIjgM5+9/rGSNw==",
|
||||||
|
"requires": {
|
||||||
|
"duplexify": "^4.1.2",
|
||||||
|
"fastify-plugin": "^4.0.0",
|
||||||
|
"ws": "^8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@firebox/components": {
|
"@firebox/components": {
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"resolved": "https://nodepack.playbox.link/@firebox/components/-/components-0.1.5.tgz",
|
"resolved": "https://nodepack.playbox.link/@firebox/components/-/components-0.1.5.tgz",
|
||||||
@@ -5571,6 +5668,15 @@
|
|||||||
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
|
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/ws": {
|
||||||
|
"version": "8.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||||
|
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
@@ -5690,13 +5796,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"avvio": {
|
"avvio": {
|
||||||
"version": "8.2.1",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/avvio/-/avvio-8.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz",
|
||||||
"integrity": "sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==",
|
"integrity": "sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@fastify/error": "^3.3.0",
|
||||||
"archy": "^1.0.0",
|
"archy": "^1.0.0",
|
||||||
"debug": "^4.0.0",
|
"debug": "^4.0.0",
|
||||||
"fastq": "^1.6.1"
|
"fastq": "^1.17.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"babel-plugin-macros": {
|
"babel-plugin-macros": {
|
||||||
@@ -6018,12 +6125,31 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||||
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg=="
|
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg=="
|
||||||
},
|
},
|
||||||
|
"duplexify": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||||
|
"requires": {
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1",
|
||||||
|
"stream-shift": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
"version": "8.0.0",
|
"version": "8.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"end-of-stream": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"error-ex": {
|
"error-ex": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||||
@@ -6148,9 +6274,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fast-content-type-parse": {
|
"fast-content-type-parse": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz",
|
||||||
"integrity": "sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA=="
|
"integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ=="
|
||||||
},
|
},
|
||||||
"fast-decode-uri-component": {
|
"fast-decode-uri-component": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -6184,9 +6310,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fast-redact": {
|
"fast-redact": {
|
||||||
"version": "3.3.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
|
||||||
"integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ=="
|
"integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="
|
||||||
},
|
},
|
||||||
"fast-uri": {
|
"fast-uri": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
@@ -6194,26 +6320,26 @@
|
|||||||
"integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg=="
|
"integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg=="
|
||||||
},
|
},
|
||||||
"fastify": {
|
"fastify": {
|
||||||
"version": "4.22.0",
|
"version": "4.26.2",
|
||||||
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.26.2.tgz",
|
||||||
"integrity": "sha512-HLoBmetdQ6zaJohKW6jzUww8NnwHzkbIbUEyAzM+Nnf7cZVSXRuUV+6b2/xLmu6GGkruIFJ/bIQoKWYRx4wnAQ==",
|
"integrity": "sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@fastify/ajv-compiler": "^3.5.0",
|
"@fastify/ajv-compiler": "^3.5.0",
|
||||||
"@fastify/error": "^3.2.0",
|
"@fastify/error": "^3.4.0",
|
||||||
"@fastify/fast-json-stringify-compiler": "^4.3.0",
|
"@fastify/fast-json-stringify-compiler": "^4.3.0",
|
||||||
"abstract-logging": "^2.0.1",
|
"abstract-logging": "^2.0.1",
|
||||||
"avvio": "^8.2.1",
|
"avvio": "^8.3.0",
|
||||||
"fast-content-type-parse": "^1.0.0",
|
"fast-content-type-parse": "^1.1.0",
|
||||||
"fast-json-stringify": "^5.7.0",
|
"fast-json-stringify": "^5.8.0",
|
||||||
"find-my-way": "^7.6.0",
|
"find-my-way": "^8.0.0",
|
||||||
"light-my-request": "^5.9.1",
|
"light-my-request": "^5.11.0",
|
||||||
"pino": "^8.12.0",
|
"pino": "^8.17.0",
|
||||||
"process-warning": "^2.2.0",
|
"process-warning": "^3.0.0",
|
||||||
"proxy-addr": "^2.0.7",
|
"proxy-addr": "^2.0.7",
|
||||||
"rfdc": "^1.3.0",
|
"rfdc": "^1.3.0",
|
||||||
"secure-json-parse": "^2.5.0",
|
"secure-json-parse": "^2.7.0",
|
||||||
"semver": "^7.5.0",
|
"semver": "^7.5.4",
|
||||||
"tiny-lru": "^11.0.1"
|
"toad-cache": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fastify-plugin": {
|
"fastify-plugin": {
|
||||||
@@ -6222,9 +6348,9 @@
|
|||||||
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ=="
|
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ=="
|
||||||
},
|
},
|
||||||
"fastq": {
|
"fastq": {
|
||||||
"version": "1.15.0",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
|
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
@@ -6257,9 +6383,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"find-my-way": {
|
"find-my-way": {
|
||||||
"version": "7.6.2",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.1.0.tgz",
|
||||||
"integrity": "sha512-0OjHn1b1nCX3eVbm9ByeEHiscPYiHLfhei1wOUU9qffQkk98wE0Lo8VrVYfSGMgnSnDh86DxedduAnBf4nwUEw==",
|
"integrity": "sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-querystring": "^1.0.0",
|
"fast-querystring": "^1.0.0",
|
||||||
@@ -6812,13 +6938,20 @@
|
|||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
||||||
},
|
},
|
||||||
"light-my-request": {
|
"light-my-request": {
|
||||||
"version": "5.10.0",
|
"version": "5.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.12.0.tgz",
|
||||||
"integrity": "sha512-ZU2D9GmAcOUculTTdH9/zryej6n8TzT+fNGdNtm6SDp5MMMpHrJJkvAdE3c6d8d2chE9i+a//dS9CWZtisknqA==",
|
"integrity": "sha512-P526OX6E7aeCIfw/9UyJNsAISfcFETghysaWHQAlQYayynShT08MOj4c6fBCvTWBrHXSvqBAKDp3amUPSCQI4w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.6.0",
|
||||||
"process-warning": "^2.0.0",
|
"process-warning": "^3.0.0",
|
||||||
"set-cookie-parser": "^2.4.1"
|
"set-cookie-parser": "^2.4.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lines-and-columns": {
|
"lines-and-columns": {
|
||||||
@@ -7085,9 +7218,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"on-exit-leak-free": {
|
"on-exit-leak-free": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||||
"integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w=="
|
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="
|
||||||
},
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
@@ -7330,27 +7463,27 @@
|
|||||||
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
|
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
|
||||||
},
|
},
|
||||||
"pino": {
|
"pino": {
|
||||||
"version": "8.15.0",
|
"version": "8.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/pino/-/pino-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/pino/-/pino-8.19.0.tgz",
|
||||||
"integrity": "sha512-olUADJByk4twxccmAxb1RiGKOSvddHugCV3wkqjyv+3Sooa2KLrmXrKEWOKi0XPCLasRR5jBXxioE1jxUa4KzQ==",
|
"integrity": "sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"atomic-sleep": "^1.0.0",
|
"atomic-sleep": "^1.0.0",
|
||||||
"fast-redact": "^3.1.1",
|
"fast-redact": "^3.1.1",
|
||||||
"on-exit-leak-free": "^2.1.0",
|
"on-exit-leak-free": "^2.1.0",
|
||||||
"pino-abstract-transport": "v1.0.0",
|
"pino-abstract-transport": "v1.1.0",
|
||||||
"pino-std-serializers": "^6.0.0",
|
"pino-std-serializers": "^6.0.0",
|
||||||
"process-warning": "^2.0.0",
|
"process-warning": "^3.0.0",
|
||||||
"quick-format-unescaped": "^4.0.3",
|
"quick-format-unescaped": "^4.0.3",
|
||||||
"real-require": "^0.2.0",
|
"real-require": "^0.2.0",
|
||||||
"safe-stable-stringify": "^2.3.1",
|
"safe-stable-stringify": "^2.3.1",
|
||||||
"sonic-boom": "^3.1.0",
|
"sonic-boom": "^3.7.0",
|
||||||
"thread-stream": "^2.0.0"
|
"thread-stream": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pino-abstract-transport": {
|
"pino-abstract-transport": {
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz",
|
||||||
"integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==",
|
"integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"readable-stream": "^4.0.0",
|
"readable-stream": "^4.0.0",
|
||||||
"split2": "^4.0.0"
|
"split2": "^4.0.0"
|
||||||
@@ -7366,9 +7499,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "4.4.2",
|
"version": "4.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
|
||||||
"integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==",
|
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
@@ -7419,9 +7552,9 @@
|
|||||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
|
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
|
||||||
},
|
},
|
||||||
"process-warning": {
|
"process-warning": {
|
||||||
"version": "2.2.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
|
||||||
"integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg=="
|
"integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="
|
||||||
},
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
@@ -7734,9 +7867,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sonic-boom": {
|
"sonic-boom": {
|
||||||
"version": "3.3.0",
|
"version": "3.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz",
|
||||||
"integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==",
|
"integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"atomic-sleep": "^1.0.0"
|
"atomic-sleep": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -7760,6 +7893,11 @@
|
|||||||
"internal-slot": "^1.0.4"
|
"internal-slot": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"stream-shift": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="
|
||||||
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
@@ -7840,18 +7978,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"thread-stream": {
|
"thread-stream": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz",
|
||||||
"integrity": "sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw==",
|
"integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"real-require": "^0.2.0"
|
"real-require": "^0.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tiny-lru": {
|
|
||||||
"version": "11.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz",
|
|
||||||
"integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg=="
|
|
||||||
},
|
|
||||||
"tmp": {
|
"tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
@@ -7875,6 +8008,11 @@
|
|||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"toad-cache": {
|
||||||
|
"version": "3.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz",
|
||||||
|
"integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw=="
|
||||||
|
},
|
||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
@@ -8051,6 +8189,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "8.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||||
|
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
"prod-start": "echo \"building frontend\" && npm run prod-build-client && echo \"${DATABASE_URL}\" && echo \"running migrations\" && npm run prod-migrate && echo \"starting server\" && npm run withenv ./src/server/index.ts",
|
"prod-start": "echo \"building frontend\" && npm run prod-build-client && echo \"${DATABASE_URL}\" && echo \"running migrations\" && npm run prod-migrate && echo \"starting server\" && npm run withenv ./src/server/index.ts",
|
||||||
"withenv": "tsx ./scripts/run-with-env.ts",
|
"withenv": "tsx ./scripts/run-with-env.ts",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build-p8client": "bun build src/client/pico8-client/veryRawRenderCart.js --outdir src/client/pico8-client/build"
|
"build-p8client": "bun build src/client/pico8-client/veryRawRenderCart.js --outdir src/client/pico8-client/build",
|
||||||
|
"add-pico": "npm run withenv ./scripts/do-release.ts"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -29,12 +30,13 @@
|
|||||||
"@fastify/cookie": "^9.0.4",
|
"@fastify/cookie": "^9.0.4",
|
||||||
"@fastify/secure-session": "^7.1.0",
|
"@fastify/secure-session": "^7.1.0",
|
||||||
"@fastify/static": "^6.10.2",
|
"@fastify/static": "^6.10.2",
|
||||||
|
"@fastify/websocket": "^10.0.1",
|
||||||
"@firebox/components": "^0.1.5",
|
"@firebox/components": "^0.1.5",
|
||||||
"@firebox/tsutil": "^0.1.2",
|
"@firebox/tsutil": "^0.1.2",
|
||||||
"@sinclair/typebox": "^0.31.5",
|
"@sinclair/typebox": "^0.31.5",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
"fastify": "^4.22.0",
|
"fastify": "^4.26.2",
|
||||||
"isomorphic-git": "^1.25.6",
|
"isomorphic-git": "^1.25.6",
|
||||||
"react-pico-8": "^4.1.0",
|
"react-pico-8": "^4.1.0",
|
||||||
"react-router-dom": "^6.18.0",
|
"react-router-dom": "^6.18.0",
|
||||||
@@ -48,6 +50,7 @@
|
|||||||
"@types/react": "^18.2.21",
|
"@types/react": "^18.2.21",
|
||||||
"@types/react-dom": "^18.2.7",
|
"@types/react-dom": "^18.2.7",
|
||||||
"@types/uuid": "^9.0.7",
|
"@types/uuid": "^9.0.7",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
"esbuild": "^0.19.2",
|
"esbuild": "^0.19.2",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
27
scripts/do-release.ts
Normal file
27
scripts/do-release.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { insertRelease } from "../src/server/dbal/dbal";
|
||||||
|
import { ManifestType } from "../src/server/types";
|
||||||
|
import { getCarts } from "../src/server/util/carts";
|
||||||
|
import fs from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const doRelease = async (dir: string) => {
|
||||||
|
const manifest = JSON.parse(await fs.readFile(path.join(dir, "picobook.json"), "utf8"));
|
||||||
|
|
||||||
|
if (!ManifestType.Check(manifest)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const carts = await getCarts(dir, manifest.carts);
|
||||||
|
|
||||||
|
await insertRelease({
|
||||||
|
manifest,
|
||||||
|
carts,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv[2]) {
|
||||||
|
// console.log(process.argv[3]);
|
||||||
|
await doRelease(process.argv[3]);
|
||||||
|
} else {
|
||||||
|
console.log("must pass in a path to a repo");
|
||||||
|
}
|
||||||
62
src/client/AuthorPage.tsx
Normal file
62
src/client/AuthorPage.tsx
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import { Link, useParams } from "react-router-dom"
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { DbRelease } from "../server/dbal/dbal";
|
||||||
|
import { css } from "@emotion/css";
|
||||||
|
|
||||||
|
type Info = {
|
||||||
|
author: string | null;
|
||||||
|
games: {slug: string; releases: DbRelease[]}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AuthorPage = () => {
|
||||||
|
const {author} = useParams();
|
||||||
|
const [info, setInfo] = useState<Info | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchInfo = async () => {
|
||||||
|
let url = `/api/author?author=${author}`;
|
||||||
|
const information = await fetch(url);
|
||||||
|
const json = await information.json();
|
||||||
|
console.log('json', json);
|
||||||
|
setInfo(json);
|
||||||
|
}
|
||||||
|
fetchInfo();
|
||||||
|
}, [setInfo, author]);
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
LOADING...
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.author) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
NOT FOUND
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={css`
|
||||||
|
margin: auto;
|
||||||
|
width: max-content;
|
||||||
|
max-inline-size: 66ch;
|
||||||
|
padding: 1.5em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
`}>
|
||||||
|
<h1>{author}</h1>
|
||||||
|
{
|
||||||
|
info.games.map(game => (
|
||||||
|
<Link key={game.slug} to={`/u/${author}/${game.slug}`}>
|
||||||
|
<h3>{game.releases[0].manifest.title ?? game.slug}</h3>
|
||||||
|
</Link>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
136
src/client/GamePage.tsx
Normal file
136
src/client/GamePage.tsx
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
import { Link, useParams, useSearchParams } from "react-router-dom"
|
||||||
|
import { Pico8Console, Pico8ConsoleImperatives } from "./pico8-client/Pico8Console";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { DbRelease } from "../server/dbal/dbal";
|
||||||
|
import { css } from "@emotion/css";
|
||||||
|
import { useWebsocket } from "./hooks/useWebsocket";
|
||||||
|
import { PicoPortal } from "./components/PicoPortal";
|
||||||
|
|
||||||
|
type Info = {
|
||||||
|
release: DbRelease | null;
|
||||||
|
versions: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GamePage = () => {
|
||||||
|
const {author, slug} = useParams();
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const room = searchParams.get('room');
|
||||||
|
const picoRef = useRef<Pico8ConsoleImperatives>(null);
|
||||||
|
const socket = useWebsocket({
|
||||||
|
url: `/api/ws/room?room=${room}&`,
|
||||||
|
// url: "wss://echo.websocket.org",
|
||||||
|
onMessage({message}) {
|
||||||
|
if (picoRef.current) {
|
||||||
|
const handle = picoRef.current.getPicoConsoleHandle();
|
||||||
|
if (handle) {
|
||||||
|
handle.buttons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const msg = message as any;
|
||||||
|
// if (msg.type === "gpio") {
|
||||||
|
// if (picoRef.current) {
|
||||||
|
// const handle = picoRef.current.getPicoConsoleHandle();
|
||||||
|
// if (handle) {
|
||||||
|
// console.log("updating pico gpio");
|
||||||
|
// (handle.gpio as any).dontSend = true;
|
||||||
|
// handle.gpio.length = 0;
|
||||||
|
// handle.gpio.push(...msg.gpio);
|
||||||
|
// (handle.gpio as any).dontSend = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
console.log('message', message);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// const version = searchParams.get('v');
|
||||||
|
const [v, setVersion] = useState<string | null>(null);
|
||||||
|
const [info, setInfo] = useState<Info | null>(null);
|
||||||
|
|
||||||
|
const version = v ?? info?.release?.version ?? info?.versions[0];
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchInfo = async () => {
|
||||||
|
let url = `/api/release?author=${author}&slug=${slug}`;
|
||||||
|
if (version) {
|
||||||
|
url += `&version=${version}`;
|
||||||
|
}
|
||||||
|
const information = await fetch(url);
|
||||||
|
const json = await information.json();
|
||||||
|
setInfo(json);
|
||||||
|
}
|
||||||
|
fetchInfo();
|
||||||
|
}, [setInfo, author, slug, version]);
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
LOADING...
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.release) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
NOT FOUND
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={css`
|
||||||
|
margin: auto;
|
||||||
|
width: max-content;
|
||||||
|
max-inline-size: 66ch;
|
||||||
|
padding: 1.5em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
`}>
|
||||||
|
<div>
|
||||||
|
<h1>{info.release.manifest.title ?? slug!.split("-").map(word => word[0].toUpperCase()+word.slice(1)).join(" ")}</h1>
|
||||||
|
<h2>by <Link to={`/u/${info.release.author}`}>{info.release.author}</Link></h2>
|
||||||
|
</div>
|
||||||
|
<div className={css`
|
||||||
|
width: 512px;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
`}>
|
||||||
|
<div className={css`
|
||||||
|
border: 2px solid transparent;
|
||||||
|
&:focus-within {
|
||||||
|
border: 2px solid limegreen;
|
||||||
|
}
|
||||||
|
`}>
|
||||||
|
<Pico8Console
|
||||||
|
ref={picoRef}
|
||||||
|
carts={info.release.carts}
|
||||||
|
// onGpioChange={(gpio: number[]) => {
|
||||||
|
// console.log("sending gpio");
|
||||||
|
// socket.sendMessage({
|
||||||
|
// type: "gpio",
|
||||||
|
// gpio,
|
||||||
|
// });
|
||||||
|
// }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={css`
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
`}>
|
||||||
|
Version: <select defaultValue={info.release.version} onChange={(ev) => setVersion(ev.target.value)}>
|
||||||
|
{
|
||||||
|
[...info.versions].reverse().map(v => (
|
||||||
|
<option key={v} value={v}>{v}</option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<PicoPortal />
|
||||||
|
{/* <div>
|
||||||
|
<p>This is a paragraph about this game. It is a cool game. And a cool website to play it on. It automagically connects from GitHub.</p>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
3
src/client/HomePage.tsx
Normal file
3
src/client/HomePage.tsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export const HomePage = () => {
|
||||||
|
return <div>Welcome to Picobook!</div>
|
||||||
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
import { css } from "@emotion/css";
|
import { css } from "@emotion/css";
|
||||||
import { Pico8Console } from "./pico8-client/Pico8Console";
|
import { Pico8Console } from "./pico8-client/Pico8Console";
|
||||||
import testcarts from "./testcarts";
|
import testcarts from "./testcarts";
|
||||||
|
import { Routing } from "./routing";
|
||||||
|
|
||||||
const App = (props: {}) => {
|
const App = (props: {}) => {
|
||||||
return (
|
return (
|
||||||
<div className={css`
|
<Routing/>
|
||||||
min-height: 100vh;
|
// <div className={css`
|
||||||
`}>
|
// min-height: 100vh;
|
||||||
<h1>Picobook</h1>
|
// `}>
|
||||||
<Pico8Console carts={testcarts.carts} />
|
// <h1>Picobook</h1>
|
||||||
</div>
|
// <Pico8Console carts={testcarts.carts} />
|
||||||
|
// </div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
26
src/client/components/PicoPortal.tsx
Normal file
26
src/client/components/PicoPortal.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { Pico8Console, Pico8ConsoleImperatives } from "../pico8-client/Pico8Console"
|
||||||
|
|
||||||
|
export const PicoPortal = () => {
|
||||||
|
const emptyCartData: number[] = new Array(32786).fill(0);
|
||||||
|
const cart = {name: "empty", rom: emptyCartData};
|
||||||
|
// const picoRef = useRef<Pico8ConsoleImperatives>(null);
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<Pico8Console
|
||||||
|
ref={(ref) => {
|
||||||
|
if (!ref) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handle = ref.getPicoConsoleHandle();
|
||||||
|
if (!handle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handle.buttons.subscribe((buttons) => {
|
||||||
|
console.log(buttons);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
carts={[cart]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
46
src/client/hooks/useWebsocket.ts
Normal file
46
src/client/hooks/useWebsocket.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
export const useWebsocket = (props: {url: string; onMessage: (stuff: {socket: WebSocket; message: unknown}) => void}) => {
|
||||||
|
const {url, onMessage} = props;
|
||||||
|
const onMessageRef = useRef(onMessage);
|
||||||
|
const ws = useRef<WebSocket | null>(null);
|
||||||
|
onMessageRef.current = onMessage;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const webSocket = new WebSocket(url);
|
||||||
|
|
||||||
|
webSocket.addEventListener("open", () => {
|
||||||
|
console.log("WebSocket is open now.");
|
||||||
|
});
|
||||||
|
|
||||||
|
webSocket.addEventListener("message", (event: any) => {
|
||||||
|
onMessageRef.current({socket: webSocket, message: JSON.parse(event.data)});
|
||||||
|
});
|
||||||
|
|
||||||
|
webSocket.addEventListener("error", (event) => {
|
||||||
|
console.log("WebSocket error: ", event);
|
||||||
|
});
|
||||||
|
|
||||||
|
webSocket.addEventListener("close", () => {
|
||||||
|
console.log("WebSocket is closed now.");
|
||||||
|
ws.current = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.current = webSocket;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
webSocket.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
}, [url]);
|
||||||
|
|
||||||
|
const sendMessage = useCallback((message: unknown) => {
|
||||||
|
if (ws.current && ws.current.readyState === WebSocket.OPEN) {
|
||||||
|
ws.current.send(JSON.stringify(message));
|
||||||
|
} else {
|
||||||
|
console.error("WebSocket is not open. Message not sent.");
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {sendMessage};
|
||||||
|
};
|
||||||
@@ -2,22 +2,49 @@ import { css } from "@emotion/css";
|
|||||||
import { PicoCart, PicoPlayerHandle, makePicoConsole } from "./renderCart";
|
import { PicoCart, PicoPlayerHandle, makePicoConsole } from "./renderCart";
|
||||||
import { ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
import { ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||||
|
|
||||||
type Pico8ConsoleImperatives = {
|
export type Pico8ConsoleImperatives = {
|
||||||
getPicoConsoleHandle(): PicoPlayerHandle | null;
|
getPicoConsoleHandle(): PicoPlayerHandle | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Pico8Console = forwardRef((props: { carts: PicoCart[] }, forwardedRef: ForwardedRef<Pico8ConsoleImperatives>) => {
|
export type Pico8ConsoleProps = {
|
||||||
const {carts} = props;
|
carts: PicoCart[],
|
||||||
|
// onGpioChange?(gpio: number[]): void,
|
||||||
|
}
|
||||||
|
|
||||||
|
// const noop = () => {};
|
||||||
|
|
||||||
|
export const Pico8Console = forwardRef((props: Pico8ConsoleProps, forwardedRef: ForwardedRef<Pico8ConsoleImperatives>) => {
|
||||||
|
const {
|
||||||
|
carts,
|
||||||
|
// onGpioChange = noop
|
||||||
|
} = props;
|
||||||
|
const [playing, setPlaying] = useState(false);
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [handle, setHandle] = useState<PicoPlayerHandle | null>(null);
|
const [handle, setHandle] = useState<PicoPlayerHandle | null>(null);
|
||||||
const attachConsole = useCallback(async () => {
|
const attachConsole = useCallback(async () => {
|
||||||
const picoConsole = await makePicoConsole({
|
const picoConsole = await makePicoConsole({
|
||||||
carts,
|
carts,
|
||||||
});
|
});
|
||||||
|
picoConsole.canvas.tabIndex=0;
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
ref.current.appendChild(picoConsole.canvas);
|
ref.current.appendChild(picoConsole.canvas);
|
||||||
|
|
||||||
|
// Set the width and height because pico8 adds them as properties on chrome-based browsers
|
||||||
|
picoConsole.canvas.style.width = "";
|
||||||
|
picoConsole.canvas.style.height = "";
|
||||||
|
|
||||||
|
picoConsole.canvas.focus();
|
||||||
}
|
}
|
||||||
setHandle(picoConsole);
|
setHandle(picoConsole);
|
||||||
|
// picoConsole.gpio.subscribe(onGpioChange);
|
||||||
|
picoConsole.canvas.addEventListener('keydown',(event) => {
|
||||||
|
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(event.key)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}, {passive: false});
|
||||||
|
picoConsole.canvas.addEventListener('click', () => {
|
||||||
|
picoConsole.canvas.focus();
|
||||||
|
})
|
||||||
}, [carts]);
|
}, [carts]);
|
||||||
useImperativeHandle(forwardedRef, () => ({
|
useImperativeHandle(forwardedRef, () => ({
|
||||||
getPicoConsoleHandle() {
|
getPicoConsoleHandle() {
|
||||||
@@ -25,8 +52,37 @@ export const Pico8Console = forwardRef((props: { carts: PicoCart[] }, forwardedR
|
|||||||
}
|
}
|
||||||
}), [handle]);
|
}), [handle]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (playing) {
|
||||||
attachConsole();
|
attachConsole();
|
||||||
}, [attachConsole]);
|
return () => {
|
||||||
|
if (ref.current) {
|
||||||
|
ref.current.innerHTML = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [playing, attachConsole]);
|
||||||
|
if (!playing) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={css`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
`}
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={() => {setPlaying(true)}}
|
||||||
|
>
|
||||||
|
Play!
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className={css`
|
<div ref={ref} className={css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -18435,6 +18435,7 @@ use chrome, FireFox or Internet Explorer 11`);
|
|||||||
var require_veryRawRenderCart = __commonJS((exports, module) => {
|
var require_veryRawRenderCart = __commonJS((exports, module) => {
|
||||||
var __dirname = "/home/dylan/repos/picobook/src/client/pico8-client";
|
var __dirname = "/home/dylan/repos/picobook/src/client/pico8-client";
|
||||||
window.P8 = function(Module, cartNames, cartDatas) {
|
window.P8 = function(Module, cartNames, cartDatas) {
|
||||||
|
const codo_textarea_el = Module.codo_textarea || document.getElementById("codo_textarea");
|
||||||
let p8_touch_detected;
|
let p8_touch_detected;
|
||||||
let p8_dropped_cart;
|
let p8_dropped_cart;
|
||||||
let p8_dropped_cart_name;
|
let p8_dropped_cart_name;
|
||||||
@@ -19390,7 +19391,7 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
}, function() {
|
}, function() {
|
||||||
if (typeof codo_key_buffer === "undefined")
|
if (typeof codo_key_buffer === "undefined")
|
||||||
codo_key_buffer = [];
|
codo_key_buffer = [];
|
||||||
document.addEventListener("keydown", function(e) {
|
Module["canvas"].addEventListener("keydown", function(e) {
|
||||||
var val = -1;
|
var val = -1;
|
||||||
if (e.key.length == 1) {
|
if (e.key.length == 1) {
|
||||||
val = e.key.charCodeAt(0);
|
val = e.key.charCodeAt(0);
|
||||||
@@ -19406,7 +19407,7 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
if (val == -1) {
|
if (val == -1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var el2 = document.getElementById("codo_textarea");
|
var el2 = codo_textarea_el;
|
||||||
codo_key_buffer.push(val);
|
codo_key_buffer.push(val);
|
||||||
});
|
});
|
||||||
}, function() {
|
}, function() {
|
||||||
@@ -19515,7 +19516,7 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
}, function() {
|
}, function() {
|
||||||
if (document.hidden)
|
if (document.hidden)
|
||||||
return 0;
|
return 0;
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el && el == document.activeElement)
|
if (el && el == document.activeElement)
|
||||||
return 1;
|
return 1;
|
||||||
el = document.activeElement;
|
el = document.activeElement;
|
||||||
@@ -19529,13 +19530,13 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el && el.style.display != "none") {
|
if (el && el.style.display != "none") {
|
||||||
el.focus();
|
el.focus();
|
||||||
el.select();
|
el.select();
|
||||||
}
|
}
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el && el.style.display != "none") {
|
if (el && el.style.display != "none") {
|
||||||
el.select();
|
el.select();
|
||||||
}
|
}
|
||||||
@@ -19550,7 +19551,7 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
}, function() {
|
}, function() {
|
||||||
Module["canvas"].exitPointerLock();
|
Module["canvas"].exitPointerLock();
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el) {
|
if (el) {
|
||||||
}
|
}
|
||||||
}, function() {
|
}, function() {
|
||||||
@@ -19558,21 +19559,21 @@ var require_veryRawRenderCart = __commonJS((exports, module) => {
|
|||||||
}, function($0, $1) {
|
}, function($0, $1) {
|
||||||
_codo_str_out = Module.UTF8ToString($0, $1);
|
_codo_str_out = Module.UTF8ToString($0, $1);
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el) {
|
if (el) {
|
||||||
el.value = _codo_str_out;
|
el.value = _codo_str_out;
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
return 1;
|
return 1;
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el && el.style.display == "none" && (typeof p8_touch_detected === "undefined" || !p8_touch_detected)) {
|
if (el && el.style.display == "none" && (typeof p8_touch_detected === "undefined" || !p8_touch_detected)) {
|
||||||
el.style.display = "";
|
el.style.display = "";
|
||||||
el.focus();
|
el.focus();
|
||||||
el.select();
|
el.select();
|
||||||
}
|
}
|
||||||
}, function() {
|
}, function() {
|
||||||
el = typeof codo_textarea === "undefined" ? document.getElementById("codo_textarea") : codo_textarea;
|
el = typeof codo_textarea === "undefined" ? codo_textarea_el : codo_textarea;
|
||||||
if (el && el.style.display != "none" && el.value != "") {
|
if (el && el.style.display != "none" && el.value != "") {
|
||||||
_codo_text_value = el.value;
|
_codo_text_value = el.value;
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import "./build/veryRawRenderCart.js";
|
|||||||
|
|
||||||
export type PicoBool = 0 | 1;
|
export type PicoBool = 0 | 1;
|
||||||
|
|
||||||
export type RenderCart = (Module: {canvas: HTMLCanvasElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
export type RenderCart = (Module: {canvas: HTMLCanvasElement, codo_textarea?: HTMLTextAreaElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
||||||
p8_touch_detected?: PicoBool;
|
p8_touch_detected?: PicoBool;
|
||||||
p8_dropped_cart?: string;
|
p8_dropped_cart?: string;
|
||||||
p8_dropped_cart_name?: string;
|
p8_dropped_cart_name?: string;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { assertNever } from "@firebox/tsutil";
|
import { assertNever } from "@firebox/tsutil";
|
||||||
import { pngToRom } from "./pngToRom";
|
import { pngToRom } from "./pngToRom";
|
||||||
import { RenderCart, renderCart as rawRenderCart } from "./rawRenderCart";
|
import { RenderCart, renderCart as rawRenderCart } from "./rawRenderCart";
|
||||||
|
import { Watched, watch } from "../util/watch";
|
||||||
|
|
||||||
export type PicoCart = {
|
export type PicoCart = {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -20,13 +21,16 @@ type PlayerButtons = {
|
|||||||
menu: boolean;
|
menu: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RawHandle = ReturnType<RenderCart>;
|
||||||
|
|
||||||
export type PicoPlayerHandle = {
|
export type PicoPlayerHandle = {
|
||||||
raw: ReturnType<RenderCart>;
|
raw: RawHandle;
|
||||||
rawModule: unknown;
|
rawModule: unknown;
|
||||||
// external things
|
// external things
|
||||||
readonly canvas: HTMLCanvasElement;
|
readonly canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
// i/o
|
// i/o
|
||||||
|
buttons: Watched<NonNullable<RawHandle["pico8_buttons"]>>;
|
||||||
setButtons: (buttons: PlayerButtons[]) => void;
|
setButtons: (buttons: PlayerButtons[]) => void;
|
||||||
setMouse: (mouse: {
|
setMouse: (mouse: {
|
||||||
x: number;
|
x: number;
|
||||||
@@ -35,7 +39,10 @@ export type PicoPlayerHandle = {
|
|||||||
rightClick: boolean;
|
rightClick: boolean;
|
||||||
}) => void;
|
}) => void;
|
||||||
setGamepadCount: (count: number) => void;
|
setGamepadCount: (count: number) => void;
|
||||||
readonly gpio: number[]; // read + write (should be 256-tuple)
|
gpio: (
|
||||||
|
number[]
|
||||||
|
// & {subscribe: (f: (gpio: number[]) => void) => void}
|
||||||
|
); // read + write (should be 256-tuple)
|
||||||
|
|
||||||
// state
|
// state
|
||||||
readonly state: {
|
readonly state: {
|
||||||
@@ -80,12 +87,18 @@ const getRom = async (cart: PicoCart) => {
|
|||||||
|
|
||||||
export const makePicoConsole = async (props: {
|
export const makePicoConsole = async (props: {
|
||||||
canvas?: HTMLCanvasElement;
|
canvas?: HTMLCanvasElement;
|
||||||
|
codoTextarea?: HTMLTextAreaElement;
|
||||||
audioContext?: AudioContext;
|
audioContext?: AudioContext;
|
||||||
carts: PicoCart[];
|
carts: PicoCart[];
|
||||||
}): Promise<PicoPlayerHandle> => {
|
}): Promise<PicoPlayerHandle> => {
|
||||||
const {carts, canvas = document.createElement("canvas"), audioContext = new AudioContext()} = props;
|
const {carts, canvas = document.createElement("canvas"), codoTextarea = document.createElement("textarea"), audioContext = new AudioContext()} = props;
|
||||||
canvas.style.imageRendering = "pixelated";
|
canvas.style.imageRendering = "pixelated";
|
||||||
const Module = {canvas};
|
codoTextarea.style.display="none";
|
||||||
|
codoTextarea.style.position="fixed";
|
||||||
|
codoTextarea.style.left="-9999px";
|
||||||
|
codoTextarea.style.height="0px";
|
||||||
|
codoTextarea.style.overflow="hidden";
|
||||||
|
const Module = {canvas, keyboardListeningElement: canvas};
|
||||||
const cartsDatas = await Promise.all(carts.map(cart => getRom(cart)));
|
const cartsDatas = await Promise.all(carts.map(cart => getRom(cart)));
|
||||||
const handle = rawRenderCart(Module, carts.map(cart => cart.name), cartsDatas, audioContext);
|
const handle = rawRenderCart(Module, carts.map(cart => cart.name), cartsDatas, audioContext);
|
||||||
handle.pico8_state = {};
|
handle.pico8_state = {};
|
||||||
@@ -109,6 +122,46 @@ export const makePicoConsole = async (props: {
|
|||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
];
|
];
|
||||||
|
// let gpioChanged = (gpio: number[]) => {};
|
||||||
|
// const gpioInner = [
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
// ];
|
||||||
|
// handle.pico8_gpio = new Proxy(gpioInner, {
|
||||||
|
// get(target, prop) {
|
||||||
|
// return target[prop as any];
|
||||||
|
// },
|
||||||
|
// set(target, prop, newValue) {
|
||||||
|
// const t = target as any;
|
||||||
|
// if (t.setting) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// const prev = [...target];
|
||||||
|
// target[prop as any] = newValue;
|
||||||
|
// const next = [...target];
|
||||||
|
// if (!t.dontSend && prev.some((p, i) => p !== next[i])) {
|
||||||
|
// gpioChanged(target);
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// (handle as any).pico8_gpio.subscribe = (f: (gpio: number[]) => void) => {
|
||||||
|
// gpioChanged = f;
|
||||||
|
// }
|
||||||
handle.pico8_gamepads = {count: 0};
|
handle.pico8_gamepads = {count: 0};
|
||||||
return {
|
return {
|
||||||
raw: handle,
|
raw: handle,
|
||||||
@@ -124,10 +177,11 @@ export const makePicoConsole = async (props: {
|
|||||||
shutdownRequested: !!handle.pico8_state.shutdown_requested!,
|
shutdownRequested: !!handle.pico8_state.shutdown_requested!,
|
||||||
soundVolume: handle.pico8_state.sound_volume!,
|
soundVolume: handle.pico8_state.sound_volume!,
|
||||||
},
|
},
|
||||||
gpio: handle.pico8_gpio,
|
gpio: handle.pico8_gpio as PicoPlayerHandle["gpio"],
|
||||||
setMouse({x, y, leftClick, rightClick}) {
|
setMouse({x, y, leftClick, rightClick}) {
|
||||||
handle.pico8_mouse = [x, y, bitfield(leftClick, rightClick)];
|
handle.pico8_mouse = [x, y, bitfield(leftClick, rightClick)];
|
||||||
},
|
},
|
||||||
|
buttons: watch(handle.pico8_buttons!),
|
||||||
setButtons(buttons) {
|
setButtons(buttons) {
|
||||||
// TODO: pad this properly here instead of casting
|
// TODO: pad this properly here instead of casting
|
||||||
handle.pico8_buttons = buttons.map(({left, right, up, down, o, x, menu}) => bitfield(left, right, up, down, o, x, menu)) as any;
|
handle.pico8_buttons = buttons.map(({left, right, up, down, o, x, menu}) => bitfield(left, right, up, down, o, x, menu)) as any;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
45
src/client/routing.tsx
Normal file
45
src/client/routing.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Outlet, RouterProvider, ScrollRestoration, createBrowserRouter, redirect } from "react-router-dom"
|
||||||
|
import { HomePage } from "./HomePage";
|
||||||
|
import { GamePage } from "./GamePage";
|
||||||
|
import { AuthorPage } from "./AuthorPage";
|
||||||
|
import { css } from "@emotion/css";
|
||||||
|
|
||||||
|
const RouteRoot = () => {
|
||||||
|
return <>
|
||||||
|
{/* <Nav> */}
|
||||||
|
<div className={css`
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: hsl(230, 10%, 10%);
|
||||||
|
color: white;
|
||||||
|
`}>
|
||||||
|
<ScrollRestoration />
|
||||||
|
<Outlet/>
|
||||||
|
</div>
|
||||||
|
{/* </Nav> */}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = createBrowserRouter([
|
||||||
|
{
|
||||||
|
element: <RouteRoot/>,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: <HomePage/>,
|
||||||
|
// loader: () => {
|
||||||
|
// return redirect("/megachat");
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/u/:author",
|
||||||
|
element: <AuthorPage/>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/u/:author/:slug",
|
||||||
|
element: <GamePage/>,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const Routing = () => <RouterProvider router={router} />;
|
||||||
67
src/client/util/watch.ts
Normal file
67
src/client/util/watch.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
const deepEqual = (a: any, b: any) => {
|
||||||
|
if (a === b) return true;
|
||||||
|
|
||||||
|
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
|
||||||
|
|
||||||
|
let keysA = Object.keys(a), keysB = Object.keys(b);
|
||||||
|
|
||||||
|
if (keysA.length !== keysB.length) return false;
|
||||||
|
|
||||||
|
for (let key of keysA) {
|
||||||
|
if (!keysB.includes(key)) return false;
|
||||||
|
|
||||||
|
if (typeof a[key] === 'function' || typeof b[key] === 'function') {
|
||||||
|
if (a[key].toString() !== b[key].toString()) return false;
|
||||||
|
} else {
|
||||||
|
if (!deepEqual(a[key], b[key])) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Watched<T> = {
|
||||||
|
value: T;
|
||||||
|
subscribe: (f: (newVal: T, oldVal: T) => void) => void;
|
||||||
|
unsubscribe: (f: (newVal: T, oldVal: T) => void) => void;
|
||||||
|
locked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const watch = <T extends Record<any,any> | any[]>(target: T): Watched<T> => {
|
||||||
|
let listeners: Array<(newVal: T, oldVal: T) => void> = [];
|
||||||
|
let locked = false;
|
||||||
|
const proxy = new Proxy(target, {
|
||||||
|
get(t: any, prop) {
|
||||||
|
return t[prop as any];
|
||||||
|
},
|
||||||
|
set(t: any, prop, newValue) {
|
||||||
|
if (locked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const prev = structuredClone(t);
|
||||||
|
t[prop as any] = newValue;
|
||||||
|
if (deepEqual(prev, t)) {
|
||||||
|
listeners.forEach(listener => listener(t, prev));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
get value() {
|
||||||
|
return target;
|
||||||
|
},
|
||||||
|
subscribe(f) {
|
||||||
|
listeners.push(f)
|
||||||
|
},
|
||||||
|
unsubscribe(f) {
|
||||||
|
listeners = listeners.filter(l => l !== f);
|
||||||
|
},
|
||||||
|
get locked() {
|
||||||
|
return locked;
|
||||||
|
},
|
||||||
|
set locked(newVal: boolean) {
|
||||||
|
locked = newVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
34
src/server/api/getAuthor.ts
Normal file
34
src/server/api/getAuthor.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { Type } from "@sinclair/typebox";
|
||||||
|
import { FirRouteInput, FirRouteOptions } from "../util/routewrap.ts";
|
||||||
|
import { getAuthorGames, getReleases } from "../dbal/dbal.ts";
|
||||||
|
|
||||||
|
const method = "GET";
|
||||||
|
const url = "/api/author";
|
||||||
|
|
||||||
|
const payloadT = Type.Any();
|
||||||
|
|
||||||
|
const handler = async ({payload}: FirRouteInput<typeof payloadT>) => {
|
||||||
|
const {author} = payload;
|
||||||
|
|
||||||
|
if (typeof author !== "string") {
|
||||||
|
return {
|
||||||
|
author: null,
|
||||||
|
releases: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
console.log("author", author);
|
||||||
|
|
||||||
|
const games = await getAuthorGames({author});
|
||||||
|
|
||||||
|
return {
|
||||||
|
author,
|
||||||
|
games,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
payloadT,
|
||||||
|
handler,
|
||||||
|
} as const satisfies FirRouteOptions<typeof payloadT>;
|
||||||
81
src/server/api/room.ts
Normal file
81
src/server/api/room.ts
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import { Type } from "@sinclair/typebox";
|
||||||
|
import { FirRouteOptions, FirWebsocketHandler, FirWebsocketInput } from "../util/routewrap.js";
|
||||||
|
import { WebSocket } from "@fastify/websocket";
|
||||||
|
import { FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
const method = "GET";
|
||||||
|
const url = "/api/ws/room";
|
||||||
|
|
||||||
|
const payloadT = Type.Any();
|
||||||
|
|
||||||
|
type Room = {
|
||||||
|
name: string;
|
||||||
|
sockets: WebSocket[];
|
||||||
|
}
|
||||||
|
|
||||||
|
let rooms: Room[] = [];
|
||||||
|
|
||||||
|
const getRoomName = (req: FastifyRequest) => {
|
||||||
|
return (req.query as any).room;
|
||||||
|
}
|
||||||
|
|
||||||
|
const websocket = {
|
||||||
|
onOpen({socket, req}) {
|
||||||
|
const roomName = getRoomName(req);
|
||||||
|
let room = rooms.find(r => r.name === roomName);
|
||||||
|
if (!room) {
|
||||||
|
console.log("creating room", roomName);
|
||||||
|
room = {
|
||||||
|
name: roomName,
|
||||||
|
sockets: [],
|
||||||
|
};
|
||||||
|
rooms.push(room);
|
||||||
|
}
|
||||||
|
if (!room.sockets.includes(socket)) {
|
||||||
|
console.log("adding socket to room", roomName);
|
||||||
|
room.sockets.push(socket);
|
||||||
|
}
|
||||||
|
console.log('rooms', rooms);
|
||||||
|
},
|
||||||
|
onClose({socket, req}) {
|
||||||
|
const roomName = getRoomName(req);
|
||||||
|
const room = rooms.find(r => r.name === roomName);
|
||||||
|
if (room) {
|
||||||
|
room.sockets = room.sockets.filter(sock => sock !== socket);
|
||||||
|
if (room.sockets.length === 0) {
|
||||||
|
rooms = rooms.filter(r => r !== room);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('rooms', rooms);
|
||||||
|
},
|
||||||
|
onMessage({socket, payload, req}) {
|
||||||
|
const roomName = getRoomName(req);
|
||||||
|
let room = rooms.find(r => r.name === roomName);
|
||||||
|
if (!room) {
|
||||||
|
console.log("creating room", roomName);
|
||||||
|
room = {
|
||||||
|
name: roomName,
|
||||||
|
sockets: [],
|
||||||
|
};
|
||||||
|
rooms.push(room);
|
||||||
|
}
|
||||||
|
if (!room.sockets.includes(socket)) {
|
||||||
|
console.log("adding socket to room", roomName);
|
||||||
|
room.sockets.push(socket);
|
||||||
|
}
|
||||||
|
console.log("replying to everyone else in room", roomName);
|
||||||
|
room.sockets.forEach(sock => {
|
||||||
|
if (sock !== socket) {
|
||||||
|
sock.send(JSON.stringify(payload));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('rooms', rooms);
|
||||||
|
},
|
||||||
|
} as const satisfies FirWebsocketHandler;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
payloadT,
|
||||||
|
websocket,
|
||||||
|
} as const satisfies FirRouteOptions<typeof payloadT>;
|
||||||
@@ -38,12 +38,18 @@ const compareByVersion = (a: DbRelease, b: DbRelease) => compareVersions(a.versi
|
|||||||
|
|
||||||
export const getReleases = async (where: {
|
export const getReleases = async (where: {
|
||||||
author: string;
|
author: string;
|
||||||
slug: string;
|
slug?: string;
|
||||||
version?: string;
|
version?: string;
|
||||||
}): Promise<DbRelease[]> => {
|
}): Promise<DbRelease[]> => {
|
||||||
const {author, slug, version} = where;
|
const {author, slug, version} = where;
|
||||||
let rows: DbReleaseInternal[];
|
let rows: DbReleaseInternal[];
|
||||||
if (!version) {
|
if (!slug) {
|
||||||
|
rows = await db.query(sql`
|
||||||
|
SELECT * from releases
|
||||||
|
WHERE
|
||||||
|
author = ${author}
|
||||||
|
`);
|
||||||
|
} else if (!version) {
|
||||||
rows = await db.query(sql`
|
rows = await db.query(sql`
|
||||||
SELECT * from releases
|
SELECT * from releases
|
||||||
WHERE
|
WHERE
|
||||||
@@ -84,9 +90,27 @@ export const getRelease = async (where: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getAuthorGames = async (where: {
|
||||||
|
author: string;
|
||||||
|
}) => {
|
||||||
|
const releases = await getReleases(where);
|
||||||
|
const games = releases.reduce((accum, curr) => {
|
||||||
|
const found = accum.find(r => r.slug === curr.slug);
|
||||||
|
if (found) {
|
||||||
|
found.releases.push(curr);
|
||||||
|
} else {
|
||||||
|
accum.push({slug: curr.slug, releases: [curr]});
|
||||||
|
}
|
||||||
|
return accum;
|
||||||
|
}, [] as {slug: string; releases: DbRelease[]}[]);
|
||||||
|
games.forEach(game => {
|
||||||
|
game.releases.sort(compareByVersion).reverse();
|
||||||
|
});
|
||||||
|
return games;
|
||||||
|
}
|
||||||
|
|
||||||
export const insertRelease = async (props: {manifest: PicobookManifest, carts: {name: string; rom: number[]}[]}) => {
|
export const insertRelease = async (props: {manifest: PicobookManifest, carts: {name: string; rom: number[]}[]}) => {
|
||||||
const {manifest, carts} = props;
|
const {manifest, carts} = props;
|
||||||
// console.log('carts', JSON.stringify(carts));
|
|
||||||
const {id: slug, author, repo, version} = manifest;
|
const {id: slug, author, repo, version} = manifest;
|
||||||
const id = uuidv4();
|
const id = uuidv4();
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|||||||
43
src/server/file.ts
Normal file
43
src/server/file.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Import the framework and instantiate it
|
||||||
|
import Fastify from 'fastify'
|
||||||
|
import {fastifyWebsocket} from '@fastify/websocket';
|
||||||
|
|
||||||
|
const server = Fastify({
|
||||||
|
logger: true
|
||||||
|
});
|
||||||
|
|
||||||
|
server.register(fastifyWebsocket);
|
||||||
|
|
||||||
|
server.get("/api/ws/room", { websocket: true }, function wsHandler (socket) {
|
||||||
|
console.log("Client connected!");
|
||||||
|
|
||||||
|
console.log(socket);
|
||||||
|
|
||||||
|
socket.on('upgrade', () => {
|
||||||
|
console.log('upgraded');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('message', message => {
|
||||||
|
console.log('Message from server:', message);
|
||||||
|
socket.send(`Echo: ${message}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('close', () => {
|
||||||
|
console.log('WebSocket connection closed');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('error', error => {
|
||||||
|
console.error('WebSocket error:', error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run the server!
|
||||||
|
try {
|
||||||
|
// Note: host needs to be 0.0.0.0 rather than omitted or localhost, otherwise
|
||||||
|
// it always returns an empty reply when used inside docker...
|
||||||
|
// See: https://github.com/fastify/fastify/issues/935
|
||||||
|
await server.listen({ port: parseInt(process.env["PORT"] ?? "3000"), host: "0.0.0.0" })
|
||||||
|
} catch (err) {
|
||||||
|
server.log.error(err)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
// Import the framework and instantiate it
|
// Import the framework and instantiate it
|
||||||
import Fastify from 'fastify'
|
import Fastify from 'fastify'
|
||||||
import fastifyStatic from '@fastify/static'
|
import fastifyStatic from '@fastify/static'
|
||||||
|
import {fastifyWebsocket} from '@fastify/websocket';
|
||||||
import { routeList } from "./routelist.ts";
|
import { routeList } from "./routelist.ts";
|
||||||
import { route } from "./util/routewrap.ts";
|
import { attachRoute } from "./util/routewrap.ts";
|
||||||
import { git } from './util/git.ts';
|
import { git } from './util/git.ts';
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {fileURLToPath} from 'url';
|
import {fileURLToPath} from 'url';
|
||||||
@@ -17,14 +18,22 @@ const server = Fastify({
|
|||||||
logger: true
|
logger: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.register(fastifyWebsocket);
|
||||||
|
|
||||||
server.register(fastifyStatic, {
|
server.register(fastifyStatic, {
|
||||||
root: new URL('public', import.meta.url).toString().slice("file://".length),
|
root: new URL('public', import.meta.url).toString().slice("file://".length),
|
||||||
prefix: '/',
|
prefix: '/',
|
||||||
});
|
});
|
||||||
|
|
||||||
routeList.forEach(firRoute => {
|
routeList.forEach(firRoute => {
|
||||||
server.route(route(firRoute));
|
attachRoute(server, firRoute);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
server.setNotFoundHandler((req, res) => {
|
||||||
|
if (!req.url.startsWith("/api")) {
|
||||||
|
res.sendFile('index.html');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Run the server!
|
// Run the server!
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="dist/index.js" type="module"></script>
|
<script src="/dist/index.js" type="module"></script>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--measure: 64ch;
|
--measure: 64ch;
|
||||||
|
|||||||
@@ -1120,7 +1120,22 @@ canvas{
|
|||||||
|
|
||||||
<!-- Add content below the cart here -->
|
<!-- Add content below the cart here -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
Content here<br/>
|
||||||
|
<input type="text"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div> <!-- body_0 -->
|
</div> <!-- body_0 -->
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import echo from "./api/echo.ts";
|
import echo from "./api/echo.ts";
|
||||||
|
import getAuthor from "./api/getAuthor.ts";
|
||||||
import getRelease from "./api/getRelease.ts";
|
import getRelease from "./api/getRelease.ts";
|
||||||
import release from "./api/release.ts";
|
import release from "./api/release.ts";
|
||||||
|
import room from "./api/room.ts";
|
||||||
import webhook from "./api/webhook.ts";
|
import webhook from "./api/webhook.ts";
|
||||||
|
|
||||||
export const routeList = [
|
export const routeList = [
|
||||||
@@ -8,6 +10,8 @@ export const routeList = [
|
|||||||
webhook,
|
webhook,
|
||||||
release,
|
release,
|
||||||
getRelease,
|
getRelease,
|
||||||
|
getAuthor,
|
||||||
|
room,
|
||||||
];
|
];
|
||||||
|
|
||||||
export type RouteList = typeof routeList;
|
export type RouteList = typeof routeList;
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
import { Static, TSchema } from "@sinclair/typebox";
|
import { Static, TSchema } from "@sinclair/typebox";
|
||||||
import { Value } from "@sinclair/typebox/value";
|
import { Value } from "@sinclair/typebox/value";
|
||||||
import { HTTPMethods } from "fastify"
|
import { FastifyInstance, FastifyRequest, HTTPMethods } from "fastify"
|
||||||
import { RouteOptions } from "fastify/types/route.js";
|
import { RouteOptions } from "fastify/types/route.js";
|
||||||
|
import { type WebSocket } from "@fastify/websocket";
|
||||||
|
|
||||||
|
type WebsocketConnection = Parameters<Defined<RouteOptions["wsHandler"]>>[0];
|
||||||
|
|
||||||
type URLString = string;
|
type URLString = string;
|
||||||
|
|
||||||
@@ -9,22 +12,94 @@ export type FirRouteInput<TPayloadSchema extends TSchema> = {
|
|||||||
payload: Static<TPayloadSchema>,
|
payload: Static<TPayloadSchema>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FirWebsocketInput<TPayloadSchema extends TSchema> = {
|
||||||
|
socket: WebsocketConnection,
|
||||||
|
req: FastifyRequest,
|
||||||
|
payload: Static<TPayloadSchema>,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FirWebsocketHandler<TIn extends TSchema = TSchema> = {
|
||||||
|
onMessage?(input: FirWebsocketInput<TIn>): void,
|
||||||
|
onOpen?(input: {socket: WebSocket, req: FastifyRequest}): void,
|
||||||
|
onClose?(input: {socket: WebSocket, req: FastifyRequest}): void,
|
||||||
|
onError?(input: {socket: WebSocket, req: FastifyRequest, error: unknown}): void,
|
||||||
|
};
|
||||||
|
|
||||||
export type FirRouteOptions<TIn extends TSchema = TSchema, TOut extends TSchema = TSchema> = {
|
export type FirRouteOptions<TIn extends TSchema = TSchema, TOut extends TSchema = TSchema> = {
|
||||||
method: HTTPMethods,
|
method: HTTPMethods,
|
||||||
url: URLString,
|
url: URLString,
|
||||||
payloadT: TIn,
|
payloadT: TIn,
|
||||||
responseT?: TOut,
|
responseT?: TOut,
|
||||||
|
} & ({
|
||||||
handler: (input: FirRouteInput<TIn>) => Static<TOut> | Promise<Static<TOut>>,
|
handler: (input: FirRouteInput<TIn>) => Static<TOut> | Promise<Static<TOut>>,
|
||||||
}
|
} | {
|
||||||
|
websocket: FirWebsocketHandler<TIn>,
|
||||||
|
})
|
||||||
|
|
||||||
export const route = <TIn extends TSchema, TOut extends TSchema>(routeOptions: FirRouteOptions<TIn, TOut>): RouteOptions => {
|
type Defined<T> = T extends undefined ? never : T;
|
||||||
|
|
||||||
|
export const attachRoute = <TIn extends TSchema, TOut extends TSchema>(server: FastifyInstance, routeOptions: FirRouteOptions<TIn, TOut>) => {
|
||||||
const {
|
const {
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
payloadT,
|
payloadT,
|
||||||
handler,
|
|
||||||
} = routeOptions;
|
} = routeOptions;
|
||||||
|
|
||||||
|
if ("websocket" in routeOptions) {
|
||||||
|
console.log('SETTING UP WS');
|
||||||
|
const {websocket} = routeOptions;
|
||||||
|
server.register(async function(fastify: FastifyInstance) {
|
||||||
|
fastify.get('/api/ws/room', { websocket: true }, (socket: WebSocket, req: FastifyRequest) => {
|
||||||
|
websocket.onOpen && websocket.onOpen({socket, req});
|
||||||
|
socket.on('message', (message: any) => {
|
||||||
|
const payload = JSON.parse(message.toString());
|
||||||
|
if (Value.Check(payloadT, payload)) {
|
||||||
|
websocket.onMessage && websocket.onMessage({socket, payload, req});
|
||||||
|
} else {
|
||||||
|
throw new Error("Payload wrong shape.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.on('close', () => {
|
||||||
|
websocket.onClose && websocket.onClose({socket, req});
|
||||||
|
});
|
||||||
|
socket.on('error', (error: any) => {
|
||||||
|
websocket.onError && websocket.onError({socket, error, req});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
|
||||||
|
// const {websocket} = routeOptions;
|
||||||
|
// const augmentedWsHandler = (conn: Parameters<Defined<RouteOptions["wsHandler"]>>[0]) => {
|
||||||
|
// console.log('HELLO');
|
||||||
|
// conn.on("message", (message) => {
|
||||||
|
// const payload = JSON.parse(message.toString());
|
||||||
|
// if (Value.Check(payloadT, payload)) {
|
||||||
|
// websocket({socket: conn, payload});
|
||||||
|
// } else {
|
||||||
|
// throw new Error("Payload wrong shape.");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// method: 'GET', // WebSocket upgrades are GET requests
|
||||||
|
// url,
|
||||||
|
// // websocket: true,
|
||||||
|
// wsHandler: augmentedWsHandler,
|
||||||
|
// handler: (...args) => {
|
||||||
|
// console.log('socket!');
|
||||||
|
// const socket = args[0].socket.on("message", () => {
|
||||||
|
// console.log("connected!");
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// // handler: (request, reply) => {
|
||||||
|
// // reply.code(405).send({ message: 'Method Not Allowed' }); // Handle non-WebSocket requests
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
const {handler} = routeOptions;
|
||||||
const augmentedHandler = (request: Parameters<RouteOptions["handler"]>[0]) => {
|
const augmentedHandler = (request: Parameters<RouteOptions["handler"]>[0]) => {
|
||||||
const {
|
const {
|
||||||
body,
|
body,
|
||||||
@@ -34,14 +109,13 @@ export const route = <TIn extends TSchema, TOut extends TSchema>(routeOptions: F
|
|||||||
if (Value.Check(payloadT, payload)) {
|
if (Value.Check(payloadT, payload)) {
|
||||||
return handler({payload});
|
return handler({payload});
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
throw new Error("Payload wrong shape.");
|
throw new Error("Payload wrong shape.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
server.route({
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
handler: augmentedHandler,
|
handler: augmentedHandler,
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user