chat persistence
parent
7d49867b14
commit
d50029146c
|
|
@ -1,12 +1,14 @@
|
||||||
version: '3.1'
|
version: '3.1'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mariadb
|
image: mariadb
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
MARIADB_ROOT_PASSWORD: example
|
MARIADB_ROOT_PASSWORD: example
|
||||||
|
MARIADB_ROOT_HOST: '127.0.0.1'
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
|
||||||
adminer:
|
adminer:
|
||||||
image: adminer
|
image: adminer
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "vite-electron-builder",
|
"name": "viscord",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "vite-electron-builder",
|
"name": "viscord",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/mysql": "^2.15.21",
|
||||||
"@types/react": "^18.0.15",
|
"@types/react": "^18.0.15",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-timeago": "^4.1.3",
|
"@types/react-timeago": "^4.1.3",
|
||||||
|
|
@ -17,6 +18,7 @@
|
||||||
"eslint-plugin-react": "^7.30.1",
|
"eslint-plugin-react": "^7.30.1",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"get-port": "^6.1.2",
|
"get-port": "^6.1.2",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-time-ago": "^7.2.1",
|
"react-time-ago": "^7.2.1",
|
||||||
|
|
@ -914,6 +916,14 @@
|
||||||
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
|
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mysql": {
|
||||||
|
"version": "2.15.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.21.tgz",
|
||||||
|
"integrity": "sha512-NPotx5CVful7yB+qZbWtXL2fA4e7aEHkihHLjklc6ID8aq7bhguHgeIoC1EmSNTAuCgI6ZXrjt2ZSaXnYX0EUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "16.11.39",
|
"version": "16.11.39",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.39.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.39.tgz",
|
||||||
|
|
@ -1883,6 +1893,14 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/bignumber.js": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/binary-extensions": {
|
"node_modules/binary-extensions": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
|
|
@ -2599,8 +2617,7 @@
|
||||||
"node_modules/core-util-is": {
|
"node_modules/core-util-is": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/crc": {
|
"node_modules/crc": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.0",
|
||||||
|
|
@ -5203,8 +5220,7 @@
|
||||||
"node_modules/isarray": {
|
"node_modules/isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/isbinaryfile": {
|
"node_modules/isbinaryfile": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
|
|
@ -5672,6 +5688,20 @@
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/mysql": {
|
||||||
|
"version": "2.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
|
||||||
|
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
|
||||||
|
"dependencies": {
|
||||||
|
"bignumber.js": "9.0.0",
|
||||||
|
"readable-stream": "2.3.7",
|
||||||
|
"safe-buffer": "5.1.2",
|
||||||
|
"sqlstring": "2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nano-staged": {
|
"node_modules/nano-staged": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/nano-staged/-/nano-staged-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/nano-staged/-/nano-staged-0.8.0.tgz",
|
||||||
|
|
@ -6187,8 +6217,7 @@
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/progress": {
|
"node_modules/progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|
@ -6436,7 +6465,6 @@
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
|
@ -6950,6 +6978,14 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/sqlstring": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stat-mode": {
|
"node_modules/stat-mode": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
|
||||||
|
|
@ -6971,7 +7007,6 @@
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -7694,8 +7729,7 @@
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/utils-merge": {
|
"node_modules/utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
|
@ -8823,6 +8857,14 @@
|
||||||
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
|
"integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/mysql": {
|
||||||
|
"version": "2.15.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.21.tgz",
|
||||||
|
"integrity": "sha512-NPotx5CVful7yB+qZbWtXL2fA4e7aEHkihHLjklc6ID8aq7bhguHgeIoC1EmSNTAuCgI6ZXrjt2ZSaXnYX0EUg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "16.11.39",
|
"version": "16.11.39",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.39.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.39.tgz",
|
||||||
|
|
@ -9544,6 +9586,11 @@
|
||||||
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bignumber.js": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
|
||||||
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
|
|
@ -10082,8 +10129,7 @@
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"crc": {
|
"crc": {
|
||||||
"version": "3.8.0",
|
"version": "3.8.0",
|
||||||
|
|
@ -11940,8 +11986,7 @@
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"isbinaryfile": {
|
"isbinaryfile": {
|
||||||
"version": "4.0.10",
|
"version": "4.0.10",
|
||||||
|
|
@ -12309,6 +12354,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
|
"mysql": {
|
||||||
|
"version": "2.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
|
||||||
|
"integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
|
||||||
|
"requires": {
|
||||||
|
"bignumber.js": "9.0.0",
|
||||||
|
"readable-stream": "2.3.7",
|
||||||
|
"safe-buffer": "5.1.2",
|
||||||
|
"sqlstring": "2.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nano-staged": {
|
"nano-staged": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/nano-staged/-/nano-staged-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/nano-staged/-/nano-staged-0.8.0.tgz",
|
||||||
|
|
@ -12684,8 +12740,7 @@
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"progress": {
|
"progress": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|
@ -12871,7 +12926,6 @@
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
"inherits": "~2.0.3",
|
"inherits": "~2.0.3",
|
||||||
|
|
@ -13259,6 +13313,11 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"sqlstring": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ=="
|
||||||
|
},
|
||||||
"stat-mode": {
|
"stat-mode": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
|
||||||
|
|
@ -13274,7 +13333,6 @@
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -13813,8 +13871,7 @@
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"utils-merge": {
|
"utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
"vue-tsc": "0.38.8"
|
"vue-tsc": "0.38.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/mysql": "^2.15.21",
|
||||||
"@types/react": "^18.0.15",
|
"@types/react": "^18.0.15",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-timeago": "^4.1.3",
|
"@types/react-timeago": "^4.1.3",
|
||||||
|
|
@ -65,6 +66,7 @@
|
||||||
"eslint-plugin-react": "^7.30.1",
|
"eslint-plugin-react": "^7.30.1",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"get-port": "^6.1.2",
|
"get-port": "^6.1.2",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-time-ago": "^7.2.1",
|
"react-time-ago": "^7.2.1",
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,19 @@ const connect = async () => {
|
||||||
|
|
||||||
connect();
|
connect();
|
||||||
|
|
||||||
export function send(action: string, data?: any) {
|
export async function send(action: string, data?: any) {
|
||||||
if(socket === null) return;
|
if(socket === null) return;
|
||||||
|
if(socket && socket.readyState === socket.CONNECTING) {
|
||||||
|
try {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
socket?.addEventListener('open', resolve);
|
||||||
|
socket?.addEventListener('close', reject);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(socket.readyState !== socket.OPEN) return;
|
||||||
|
}
|
||||||
const message = JSON.stringify({ action, data });
|
const message = JSON.stringify({ action, data });
|
||||||
socket.send(message);
|
socket.send(message);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ export default () => {
|
||||||
message(data: Message) {
|
message(data: Message) {
|
||||||
setMessages([...messages, data]);
|
setMessages([...messages, data]);
|
||||||
},
|
},
|
||||||
|
recent(data: { messages: Message[] }) {
|
||||||
|
setMessages(data.messages);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
registerRouter(actions);
|
registerRouter(actions);
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -56,9 +59,16 @@ export default () => {
|
||||||
};
|
};
|
||||||
}, [messages]);
|
}, [messages]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(messages.length === 0) {
|
||||||
|
console.log('sending recents request');
|
||||||
|
send('recent');
|
||||||
|
}
|
||||||
|
}, [messages]);
|
||||||
|
|
||||||
const sendMessage = useCallback(() => {
|
const sendMessage = useCallback(() => {
|
||||||
if(textBoxRef.current === null) return;
|
if(textBoxRef.current === null) return;
|
||||||
send('message', createMessage('Version 3', textBoxRef.current.innerText));
|
send('message', createMessage('Val', textBoxRef.current.innerText));
|
||||||
textBoxRef.current.innerText = '';
|
textBoxRef.current.innerText = '';
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
@ -93,7 +103,7 @@ export default () => {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}}>
|
}}>
|
||||||
{messages.map(message => (
|
{messages.map(message => (
|
||||||
<div style={{
|
<div key={message.uid} style={{
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns: '128px 1fr',
|
gridTemplateColumns: '128px 1fr',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_USER=root
|
||||||
|
DB_PASSWORD=example
|
||||||
|
DB_DB=viscord
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
SET NAMES utf8;
|
||||||
|
SET time_zone = '+00:00';
|
||||||
|
SET foreign_key_checks = 0;
|
||||||
|
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
CREATE DATABASE `viscord` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
|
||||||
|
USE `viscord`;
|
||||||
|
|
||||||
|
CREATE TABLE `messages` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`uid` tinytext NOT NULL,
|
||||||
|
`from` tinytext NOT NULL,
|
||||||
|
`text` longtext NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
CREATE TABLE `migrations` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
INSERT INTO `migrations` ()
|
||||||
|
VALUES ();
|
||||||
|
|
||||||
|
-- 2022-07-21 01:27:49
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
USE `viscord`;
|
||||||
|
|
||||||
|
ALTER TABLE `messages`
|
||||||
|
ADD COLUMN `t_sent` BIGINT UNSIGNED AFTER `text`;
|
||||||
|
|
||||||
|
INSERT INTO `migrations` ()
|
||||||
|
VALUES ();
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// import migration from './migrations/1-chat-persistence.sql';
|
||||||
|
|
||||||
|
import { createConnection } from 'mysql';
|
||||||
|
import { readdirSync, readFileSync } from 'fs';
|
||||||
|
import { dirname, resolve } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
const host = 'localhost';
|
||||||
|
const user = 'root';
|
||||||
|
const password = 'example';
|
||||||
|
|
||||||
|
interface Migration {
|
||||||
|
sql: string;
|
||||||
|
version: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const migrations: Migration[] =
|
||||||
|
readdirSync(resolve(__dirname, 'migrations'))
|
||||||
|
.sort((a, b) => {
|
||||||
|
const an = Number(a.split('-')[0]);
|
||||||
|
const bn = Number(b.split('-')[0]);
|
||||||
|
return an > bn ? 1 : an < bn ? -1 : 0;
|
||||||
|
})
|
||||||
|
.map(path => {
|
||||||
|
const fullpath = resolve(__dirname, 'migrations', path);
|
||||||
|
const n = Number(path.split('-')[0]);
|
||||||
|
return {
|
||||||
|
sql: readFileSync(fullpath).toString(),
|
||||||
|
version: n,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const connection = createConnection({
|
||||||
|
host,
|
||||||
|
user,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
const migrationConnection = createConnection({
|
||||||
|
host,
|
||||||
|
user,
|
||||||
|
password,
|
||||||
|
multipleStatements: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const connected: Promise<null> = new Promise((res, rej) => {
|
||||||
|
connection.connect((err) => {
|
||||||
|
if(err === null) {
|
||||||
|
console.log('connected to database!');
|
||||||
|
res(null);
|
||||||
|
} else {
|
||||||
|
console.error(err);
|
||||||
|
rej(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function update() {
|
||||||
|
// console.log(migrations);
|
||||||
|
console.log('waiting for connection...');
|
||||||
|
await connected;
|
||||||
|
// determine version
|
||||||
|
const currentVersion: number = await new Promise((resolve, rej) => {
|
||||||
|
connection.query(`
|
||||||
|
SELECT SCHEMA_NAME
|
||||||
|
FROM INFORMATION_SCHEMA.SCHEMATA
|
||||||
|
WHERE SCHEMA_NAME = 'viscord'
|
||||||
|
`, async (err, res, fields) => {
|
||||||
|
if(res.length === 0) {
|
||||||
|
resolve(0);
|
||||||
|
} else {
|
||||||
|
const version: number = await new Promise((resolve, reject) => {
|
||||||
|
connection.query(`
|
||||||
|
SELECT max(id) as 'version' FROM viscord.migrations;
|
||||||
|
`, function (err, results, fields) {
|
||||||
|
resolve(results[0].version);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
resolve(version);
|
||||||
|
// check the version table!
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const expectedVersion = migrations.length;
|
||||||
|
|
||||||
|
if(currentVersion >= expectedVersion) {
|
||||||
|
console.log('database up to date!');
|
||||||
|
} else {
|
||||||
|
const difference = expectedVersion - currentVersion;
|
||||||
|
console.log(`database ${difference} version${difference !== 1 ? 's' : ''} behind`);
|
||||||
|
// console.log(`${currentVersion} >>> ${expectedVersion}`);
|
||||||
|
const neededMigrations = migrations.filter(m => m.version > currentVersion);
|
||||||
|
for(const migration of neededMigrations) {
|
||||||
|
console.log(`${currentVersion} >>> ${migration.version}`);
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
migrationConnection.query(migration.sql, (err, res) => {
|
||||||
|
if(err !== null) return reject(err);
|
||||||
|
console.log(`executed ${res.length} statement${res.length !== 0 ? 's' : ''}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log('database version:', currentVersion)
|
||||||
|
|
||||||
|
// console.log(response);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { connection } from './migrate';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function(a: any, ...opts: any[]): Promise<any[]> {
|
||||||
|
const b64 = a.split('base64,')[1];
|
||||||
|
const text = Buffer.from(b64, 'base64').toString();
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
connection.query(text, [...opts], (err, results) => {
|
||||||
|
if(!err) return resolve(results);
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// console.log(...opts)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
INSERT INTO viscord.messages
|
||||||
|
(`text`, `from`, `uid`, `t_sent`)
|
||||||
|
VALUES (
|
||||||
|
?,
|
||||||
|
?,
|
||||||
|
?,
|
||||||
|
UNIX_TIMESTAMP()
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
SELECT * FROM viscord.messages
|
||||||
|
ORDER BY t_sent
|
||||||
|
LIMIT 100;
|
||||||
|
|
@ -8,7 +8,7 @@ const wss = new WebSocketServer({
|
||||||
});
|
});
|
||||||
|
|
||||||
wss.on('connection', (ws) => {
|
wss.on('connection', (ws) => {
|
||||||
ws.on('message', (str) => {
|
ws.on('message', async (str) => {
|
||||||
try {
|
try {
|
||||||
const message = JSON.parse(str.toString());
|
const message = JSON.parse(str.toString());
|
||||||
if(typeof message.action !== 'string') {
|
if(typeof message.action !== 'string') {
|
||||||
|
|
@ -17,7 +17,10 @@ wss.on('connection', (ws) => {
|
||||||
}
|
}
|
||||||
const {action, data} = message;
|
const {action, data} = message;
|
||||||
try {
|
try {
|
||||||
router(action, data);
|
const _return = await (router(action, data) as unknown as Promise<any>);
|
||||||
|
if(_return) {
|
||||||
|
ws.send(JSON.stringify(_return));
|
||||||
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.warn(`error in action ${action}`);
|
console.warn(`error in action ${action}`);
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
|
@ -40,3 +43,13 @@ export function broadcast(action: string, data?: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default wss;
|
export default wss;
|
||||||
|
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
import { update } from './db/migrate';
|
||||||
|
|
||||||
|
try {
|
||||||
|
update();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ export default function router(routes: any) {
|
||||||
}
|
}
|
||||||
return function(route: any, data: any) {
|
return function(route: any, data: any) {
|
||||||
if(route in routes) {
|
if(route in routes) {
|
||||||
routes[route](data);
|
return routes[route](data);
|
||||||
} else {
|
} else {
|
||||||
console.warn(`route <${route}> not found`);
|
console.warn(`route <${route}> not found`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,30 @@
|
||||||
import router from '../router';
|
import router from '../router';
|
||||||
import { broadcast } from '../index';
|
import { broadcast } from '../index';
|
||||||
|
import query from '../db/query';
|
||||||
|
import newMessage from '../db/snippets/message/new.sql';
|
||||||
|
import recentMessages from '../db/snippets/message/recent.sql';
|
||||||
|
|
||||||
export default router({
|
export default router({
|
||||||
up() {
|
up() {
|
||||||
console.log(Date.now());
|
console.log(Date.now());
|
||||||
},
|
},
|
||||||
message(data: string) {
|
message(data: any) {
|
||||||
|
query(newMessage, data.text, data.from, data.uid, data.timestamp);
|
||||||
broadcast('message', data);
|
broadcast('message', data);
|
||||||
},
|
},
|
||||||
|
async recent() {
|
||||||
|
console.log('got recents request');
|
||||||
|
const messages = await query(recentMessages);
|
||||||
|
return {
|
||||||
|
action: 'recent',
|
||||||
|
data: {
|
||||||
|
messages: messages.map(v => ({
|
||||||
|
from: v.from,
|
||||||
|
uid: v.uid,
|
||||||
|
timestamp: v.t_sent * 1000,
|
||||||
|
text: v.text,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -3,7 +3,6 @@ import {join} from 'path';
|
||||||
|
|
||||||
const PACKAGE_ROOT = __dirname;
|
const PACKAGE_ROOT = __dirname;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('vite').UserConfig}
|
* @type {import('vite').UserConfig}
|
||||||
* @see https://vitejs.dev/config/
|
* @see https://vitejs.dev/config/
|
||||||
|
|
@ -17,6 +16,9 @@ const config = {
|
||||||
'/@/': join(PACKAGE_ROOT, 'src') + '/',
|
'/@/': join(PACKAGE_ROOT, 'src') + '/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
assetsInclude: [
|
||||||
|
'**/*.sql',
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
ssr: true,
|
ssr: true,
|
||||||
sourcemap: 'inline',
|
sourcemap: 'inline',
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ const setupServerPackageWatcher = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Proxy all logs */
|
/** Proxy all logs */
|
||||||
spawnProcess.stdout.on('data', d => d.toString().trim() && logger.warn(d.toString(), {timestamp: true}));
|
spawnProcess.stdout.on('data', d => d.toString().trim() && logger.info(d.toString().trim(), {timestamp: true}));
|
||||||
|
|
||||||
/** Proxy error logs but stripe some noisy messages. See {@link stderrFilterPatterns} */
|
/** Proxy error logs but stripe some noisy messages. See {@link stderrFilterPatterns} */
|
||||||
spawnProcess.stderr.on('data', d => {
|
spawnProcess.stderr.on('data', d => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
declare module '*.sql';
|
||||||
Reference in New Issue