(schism): started separating backend from frontend

This commit is contained in:
apetitco 2025-12-16 14:09:02 +01:00
parent 5ee7e7c0b7
commit 61d8e693c5
13 changed files with 1214 additions and 163 deletions

View file

@ -20,7 +20,11 @@
"fastify-plugin": "^5.1.0",
"joi": "^18.0.2",
"otp": "^1.1.2",
<<<<<<< HEAD
"typebox": "^1.0.64",
=======
"typebox": "^1.0.63",
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
"uuidv7": "^1.1.0"
},
"devDependencies": {

View file

@ -27,7 +27,11 @@
"fastify": "^5.6.2",
"fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0",
<<<<<<< HEAD
"typebox": "^1.0.64"
=======
"typebox": "^1.0.63"
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
},
"devDependencies": {
"@types/node": "^22.19.3",

View file

@ -27,7 +27,11 @@
"fastify": "^5.6.2",
"fastify-plugin": "^5.1.0",
"socket.io": "^4.8.1",
<<<<<<< HEAD
"typebox": "^1.0.64"
=======
"typebox": "^1.0.63"
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
},
"devDependencies": {
"@types/node": "^22.19.3",

View file

@ -33,7 +33,11 @@
"vite": "^7.3.0"
},
"dependencies": {
<<<<<<< HEAD
"@redocly/cli": "^2.13.0",
=======
"@redocly/cli": "^2.12.7",
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
"bindings": "^1.5.0"
}
}

380
src/pnpm-lock.yaml generated
View file

@ -9,8 +9,13 @@ importers:
.:
dependencies:
'@redocly/cli':
<<<<<<< HEAD
specifier: ^2.13.0
version: 2.13.0(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)
=======
specifier: ^2.12.7
version: 2.12.7(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
bindings:
specifier: ^1.5.0
version: 1.5.0
@ -41,7 +46,11 @@ importers:
version: 8.50.0(eslint@9.39.2)(typescript@5.9.3)
vite:
specifier: ^7.3.0
<<<<<<< HEAD
version: 7.3.0(@types/node@25.0.3)(yaml@2.8.2)
=======
version: 7.3.0(@types/node@25.0.2)(yaml@2.8.2)
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
'@shared':
dependencies:
@ -79,8 +88,13 @@ importers:
specifier: ^1.1.2
version: 1.1.2
typebox:
<<<<<<< HEAD
specifier: ^1.0.64
version: 1.0.64
=======
specifier: ^1.0.63
version: 1.0.63
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
uuidv7:
specifier: ^1.1.0
version: 1.1.0
@ -122,8 +136,13 @@ importers:
specifier: ^5.1.0
version: 5.1.0
typebox:
<<<<<<< HEAD
specifier: ^1.0.64
version: 1.0.64
=======
specifier: ^1.0.63
version: 1.0.63
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
devDependencies:
'@types/node':
specifier: ^22.19.3
@ -168,8 +187,13 @@ importers:
specifier: ^4.8.1
version: 4.8.1
typebox:
<<<<<<< HEAD
specifier: ^1.0.64
version: 1.0.64
=======
specifier: ^1.0.63
version: 1.0.63
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
devDependencies:
'@types/node':
specifier: ^22.19.3
@ -183,6 +207,18 @@ importers:
vite-tsconfig-paths:
specifier: ^5.1.4
version: 5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@22.19.3)(yaml@2.8.2))
<<<<<<< HEAD
=======
tic-tac-toe:
dependencies:
fastify-socket.io:
specifier: ^5.1.0
version: 5.1.0(fastify@5.6.2)(socket.io@4.8.1)
socket.io:
specifier: ^4.8.1
version: 4.8.1
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
user:
dependencies:
@ -211,8 +247,13 @@ importers:
specifier: ^5.1.0
version: 5.1.0
typebox:
<<<<<<< HEAD
specifier: ^1.0.64
version: 1.0.64
=======
specifier: ^1.0.63
version: 1.0.63
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
devDependencies:
'@types/node':
specifier: ^22.19.3
@ -250,158 +291,288 @@ packages:
'@emotion/unitless@0.8.1':
resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
<<<<<<< HEAD
'@esbuild/aix-ppc64@0.27.2':
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
=======
'@esbuild/aix-ppc64@0.27.1':
resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
<<<<<<< HEAD
'@esbuild/android-arm64@0.27.2':
resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
=======
'@esbuild/android-arm64@0.27.1':
resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
<<<<<<< HEAD
'@esbuild/android-arm@0.27.2':
resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
=======
'@esbuild/android-arm@0.27.1':
resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm]
os: [android]
<<<<<<< HEAD
'@esbuild/android-x64@0.27.2':
resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
=======
'@esbuild/android-x64@0.27.1':
resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [android]
<<<<<<< HEAD
'@esbuild/darwin-arm64@0.27.2':
resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
=======
'@esbuild/darwin-arm64@0.27.1':
resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
<<<<<<< HEAD
'@esbuild/darwin-x64@0.27.2':
resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
=======
'@esbuild/darwin-x64@0.27.1':
resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
<<<<<<< HEAD
'@esbuild/freebsd-arm64@0.27.2':
resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
=======
'@esbuild/freebsd-arm64@0.27.1':
resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
<<<<<<< HEAD
'@esbuild/freebsd-x64@0.27.2':
resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
=======
'@esbuild/freebsd-x64@0.27.1':
resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
<<<<<<< HEAD
'@esbuild/linux-arm64@0.27.2':
resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
=======
'@esbuild/linux-arm64@0.27.1':
resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-arm@0.27.2':
resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
=======
'@esbuild/linux-arm@0.27.1':
resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-ia32@0.27.2':
resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
=======
'@esbuild/linux-ia32@0.27.1':
resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-loong64@0.27.2':
resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
=======
'@esbuild/linux-loong64@0.27.1':
resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-mips64el@0.27.2':
resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
=======
'@esbuild/linux-mips64el@0.27.1':
resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-ppc64@0.27.2':
resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
=======
'@esbuild/linux-ppc64@0.27.1':
resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-riscv64@0.27.2':
resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
=======
'@esbuild/linux-riscv64@0.27.1':
resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-s390x@0.27.2':
resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
=======
'@esbuild/linux-s390x@0.27.1':
resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
<<<<<<< HEAD
'@esbuild/linux-x64@0.27.2':
resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
=======
'@esbuild/linux-x64@0.27.1':
resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
<<<<<<< HEAD
'@esbuild/netbsd-arm64@0.27.2':
resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
=======
'@esbuild/netbsd-arm64@0.27.1':
resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
<<<<<<< HEAD
'@esbuild/netbsd-x64@0.27.2':
resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
=======
'@esbuild/netbsd-x64@0.27.1':
resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
<<<<<<< HEAD
'@esbuild/openbsd-arm64@0.27.2':
resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
=======
'@esbuild/openbsd-arm64@0.27.1':
resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
<<<<<<< HEAD
'@esbuild/openbsd-x64@0.27.2':
resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
=======
'@esbuild/openbsd-x64@0.27.1':
resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
<<<<<<< HEAD
'@esbuild/openharmony-arm64@0.27.2':
resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
=======
'@esbuild/openharmony-arm64@0.27.1':
resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
<<<<<<< HEAD
'@esbuild/sunos-x64@0.27.2':
resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
=======
'@esbuild/sunos-x64@0.27.1':
resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
<<<<<<< HEAD
'@esbuild/win32-arm64@0.27.2':
resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
=======
'@esbuild/win32-arm64@0.27.1':
resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
<<<<<<< HEAD
'@esbuild/win32-ia32@0.27.2':
resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
=======
'@esbuild/win32-ia32@0.27.1':
resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
<<<<<<< HEAD
'@esbuild/win32-x64@0.27.2':
resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
=======
'@esbuild/win32-x64@0.27.1':
resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@ -679,8 +850,13 @@ packages:
'@redocly/ajv@8.17.1':
resolution: {integrity: sha512-EDtsGZS964mf9zAUXAl9Ew16eYbeyAFWhsPr0fX6oaJxgd8rApYlPBf0joyhnUHz88WxrigyFtTaqqzXNzPgqw==}
<<<<<<< HEAD
'@redocly/cli@2.13.0':
resolution: {integrity: sha512-VOGh8p5gKy+u94SbvMGaHvDM6TPw668D9iQkNSztoi4T5sj3ZwM7Y8Z3yZnMqC5s5epDcLAMq4jCO8UVn5ZWHg==}
=======
'@redocly/cli@2.12.7':
resolution: {integrity: sha512-cevNpojACA3JVUU3fqIzebY1CXipeBl84EMrriAgB4Pi0cHWImf12WkpLN/MCKMlW20/IzBzQ04CVlTyKFXuyw==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
hasBin: true
@ -694,12 +870,21 @@ packages:
resolution: {integrity: sha512-2+O+riuIUgVSuLl3Lyh5AplWZyVMNuG2F98/o6NrutKJfW4/GTZdPpZlIphS0HGgcOHgmWcCSHj+dWFlZaGSHw==}
engines: {node: '>=18.17.0', npm: '>=9.5.0'}
<<<<<<< HEAD
'@redocly/openapi-core@2.13.0':
resolution: {integrity: sha512-xQ4z5tsrXbIa4EfCniHv1zZ4etmQ0lpRcxy750iOamV5A/+19mgbPtD+UQCoT18puDAjcnOgpX7x2ha72qKrnw==}
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
'@redocly/respect-core@2.13.0':
resolution: {integrity: sha512-35OidNXWkmmsJiwgX+tFw7FaU8usZVvZ/lFBFNJga65pivEvaDlfiwKxIRTzM4iuNbc2FRvP2q30dlGAztv0tg==}
=======
'@redocly/openapi-core@2.12.7':
resolution: {integrity: sha512-b32Pvl4IE2QZFPpPXD7Qciwy1/AZ2EUaYJ++Oyngaz5WlyeGb9HX/fWmf2QO0YvSqNdK7OSY3m8lPBQ+zlNlgw==}
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
'@redocly/respect-core@2.12.7':
resolution: {integrity: sha512-pBm81qeCYkOC0BCAO6lnEDifLChpCUFP6CsBPNXTYgpFa606UjDULYVIcVUOvwZGlqv6euWIHNT8DfkzFGeltQ==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'}
'@rollup/rollup-android-arm-eabi@4.53.5':
@ -836,8 +1021,13 @@ packages:
'@types/node@22.19.3':
resolution: {integrity: sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==}
<<<<<<< HEAD
'@types/node@25.0.3':
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
=======
'@types/node@25.0.2':
resolution: {integrity: sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
'@types/stylis@4.2.5':
resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==}
@ -1273,8 +1463,13 @@ packages:
es6-promise@3.3.1:
resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
<<<<<<< HEAD
esbuild@0.27.2:
resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
=======
esbuild@0.27.1:
resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
engines: {node: '>=18'}
hasBin: true
@ -1385,9 +1580,18 @@ packages:
resolution: {integrity: sha512-7Jsfj2uLuGWvnxjrGDrHWpSm65+OcVx0ZbTD2wwkz6Wt6KjGm6+ZYwwpdXdwAlzbJYq+LCEMNvDJc4485AQ1vQ==}
hasBin: true
fastify-plugin@4.5.1:
resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==}
fastify-plugin@5.1.0:
resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==}
fastify-socket.io@5.1.0:
resolution: {integrity: sha512-GC1gjrxBGeTbMWV779XHF4uw3AtgKwSQJ9MnjGiMp91ZBuPXEdBYa7NnAMDEl3oZPgK9JO4BlNncTV+UAN+1kg==}
peerDependencies:
fastify: 4.x.x
socket.io: '>=4'
fastify@5.6.2:
resolution: {integrity: sha512-dPugdGnsvYkBlENLhCgX8yhyGCsCPrpA8lFWbTNU428l+YOnLgYHR69hzV8HWPC79n536EqzqQtvhtdaCE0dKg==}
@ -2438,8 +2642,13 @@ packages:
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
engines: {node: '>= 0.6'}
<<<<<<< HEAD
typebox@1.0.64:
resolution: {integrity: sha512-U6quDhQMzQRzBX8jvlE5mZlUnlMRTaZrG/QMAhOYVJ0D0rhq1iOXBQVSzBX0JgAh55jXQ7fWIv24i+lVimXcDw==}
=======
typebox@1.0.63:
resolution: {integrity: sha512-qqQ1IePTIL3Illa9C5GToVAUM5qRwOaDN4x/V4jBIt4V0S3lqttJbUNIYm+u+QXvvVxOnTddWxa+6hGuujIEwA==}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
typescript-eslint@8.50.0:
resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==}
@ -2670,6 +2879,7 @@ snapshots:
'@emotion/unitless@0.8.1': {}
<<<<<<< HEAD
'@esbuild/aix-ppc64@0.27.2':
optional: true
@ -2746,6 +2956,84 @@ snapshots:
optional: true
'@esbuild/win32-x64@0.27.2':
=======
'@esbuild/aix-ppc64@0.27.1':
optional: true
'@esbuild/android-arm64@0.27.1':
optional: true
'@esbuild/android-arm@0.27.1':
optional: true
'@esbuild/android-x64@0.27.1':
optional: true
'@esbuild/darwin-arm64@0.27.1':
optional: true
'@esbuild/darwin-x64@0.27.1':
optional: true
'@esbuild/freebsd-arm64@0.27.1':
optional: true
'@esbuild/freebsd-x64@0.27.1':
optional: true
'@esbuild/linux-arm64@0.27.1':
optional: true
'@esbuild/linux-arm@0.27.1':
optional: true
'@esbuild/linux-ia32@0.27.1':
optional: true
'@esbuild/linux-loong64@0.27.1':
optional: true
'@esbuild/linux-mips64el@0.27.1':
optional: true
'@esbuild/linux-ppc64@0.27.1':
optional: true
'@esbuild/linux-riscv64@0.27.1':
optional: true
'@esbuild/linux-s390x@0.27.1':
optional: true
'@esbuild/linux-x64@0.27.1':
optional: true
'@esbuild/netbsd-arm64@0.27.1':
optional: true
'@esbuild/netbsd-x64@0.27.1':
optional: true
'@esbuild/openbsd-arm64@0.27.1':
optional: true
'@esbuild/openbsd-x64@0.27.1':
optional: true
'@esbuild/openharmony-arm64@0.27.1':
optional: true
'@esbuild/sunos-x64@0.27.1':
optional: true
'@esbuild/win32-arm64@0.27.1':
optional: true
'@esbuild/win32-ia32@0.27.1':
optional: true
'@esbuild/win32-x64@0.27.1':
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
optional: true
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.2)':
@ -3065,14 +3353,23 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
<<<<<<< HEAD
'@redocly/cli@2.13.0(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)':
=======
'@redocly/cli@2.12.7(@opentelemetry/api@1.9.0)(ajv@8.17.1)(core-js@3.47.0)':
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
dependencies:
'@opentelemetry/exporter-trace-otlp-http': 0.202.0(@opentelemetry/api@1.9.0)
'@opentelemetry/resources': 2.0.1(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-node': 2.0.1(@opentelemetry/api@1.9.0)
'@opentelemetry/semantic-conventions': 1.34.0
<<<<<<< HEAD
'@redocly/openapi-core': 2.13.0(ajv@8.17.1)
'@redocly/respect-core': 2.13.0(ajv@8.17.1)
=======
'@redocly/openapi-core': 2.12.7(ajv@8.17.1)
'@redocly/respect-core': 2.12.7(ajv@8.17.1)
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
abort-controller: 3.0.0
chokidar: 3.6.0
colorette: 1.4.0
@ -3124,7 +3421,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
<<<<<<< HEAD
'@redocly/openapi-core@2.13.0(ajv@8.17.1)':
=======
'@redocly/openapi-core@2.12.7(ajv@8.17.1)':
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
dependencies:
'@redocly/ajv': 8.17.1
'@redocly/config': 0.41.0
@ -3138,12 +3439,20 @@ snapshots:
transitivePeerDependencies:
- ajv
<<<<<<< HEAD
'@redocly/respect-core@2.13.0(ajv@8.17.1)':
=======
'@redocly/respect-core@2.12.7(ajv@8.17.1)':
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
dependencies:
'@faker-js/faker': 7.6.0
'@noble/hashes': 1.8.0
'@redocly/ajv': 8.17.1
<<<<<<< HEAD
'@redocly/openapi-core': 2.13.0(ajv@8.17.1)
=======
'@redocly/openapi-core': 2.12.7(ajv@8.17.1)
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
better-ajv-errors: 1.2.0(ajv@8.17.1)
colorette: 2.0.20
json-pointer: 0.6.2
@ -3243,7 +3552,11 @@ snapshots:
dependencies:
undici-types: 6.21.0
<<<<<<< HEAD
'@types/node@25.0.3':
=======
'@types/node@25.0.2':
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
dependencies:
undici-types: 7.16.0
@ -3690,6 +4003,7 @@ snapshots:
es6-promise@3.3.1: {}
<<<<<<< HEAD
esbuild@0.27.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.2
@ -3718,6 +4032,36 @@ snapshots:
'@esbuild/win32-arm64': 0.27.2
'@esbuild/win32-ia32': 0.27.2
'@esbuild/win32-x64': 0.27.2
=======
esbuild@0.27.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.1
'@esbuild/android-arm': 0.27.1
'@esbuild/android-arm64': 0.27.1
'@esbuild/android-x64': 0.27.1
'@esbuild/darwin-arm64': 0.27.1
'@esbuild/darwin-x64': 0.27.1
'@esbuild/freebsd-arm64': 0.27.1
'@esbuild/freebsd-x64': 0.27.1
'@esbuild/linux-arm': 0.27.1
'@esbuild/linux-arm64': 0.27.1
'@esbuild/linux-ia32': 0.27.1
'@esbuild/linux-loong64': 0.27.1
'@esbuild/linux-mips64el': 0.27.1
'@esbuild/linux-ppc64': 0.27.1
'@esbuild/linux-riscv64': 0.27.1
'@esbuild/linux-s390x': 0.27.1
'@esbuild/linux-x64': 0.27.1
'@esbuild/netbsd-arm64': 0.27.1
'@esbuild/netbsd-x64': 0.27.1
'@esbuild/openbsd-arm64': 0.27.1
'@esbuild/openbsd-x64': 0.27.1
'@esbuild/openharmony-arm64': 0.27.1
'@esbuild/sunos-x64': 0.27.1
'@esbuild/win32-arm64': 0.27.1
'@esbuild/win32-ia32': 0.27.1
'@esbuild/win32-x64': 0.27.1
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
escalade@3.2.0: {}
@ -3858,8 +4202,17 @@ snapshots:
semver: 7.7.3
yargs-parser: 22.0.0
fastify-plugin@4.5.1: {}
fastify-plugin@5.1.0: {}
fastify-socket.io@5.1.0(fastify@5.6.2)(socket.io@4.8.1):
dependencies:
fastify: 5.6.2
fastify-plugin: 4.5.1
socket.io: 4.8.1
tslib: 2.8.1
fastify@5.6.2:
dependencies:
'@fastify/ajv-compiler': 4.0.5
@ -4551,7 +4904,11 @@ snapshots:
'@protobufjs/path': 1.1.2
'@protobufjs/pool': 1.1.0
'@protobufjs/utf8': 1.1.0
<<<<<<< HEAD
'@types/node': 25.0.3
=======
'@types/node': 25.0.2
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
long: 5.3.2
pump@3.0.3:
@ -4966,6 +5323,11 @@ snapshots:
tslib@2.6.2: {}
<<<<<<< HEAD
=======
tslib@2.8.1: {}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
tunnel-agent@0.6.0:
dependencies:
safe-buffer: 5.2.1
@ -4980,7 +5342,11 @@ snapshots:
media-typer: 1.1.0
mime-types: 3.0.2
<<<<<<< HEAD
typebox@1.0.64: {}
=======
typebox@1.0.63: {}
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
typescript-eslint@8.50.0(eslint@9.39.2)(typescript@5.9.3):
dependencies:
@ -5035,7 +5401,11 @@ snapshots:
vite@7.3.0(@types/node@22.19.3)(yaml@2.8.2):
dependencies:
<<<<<<< HEAD
esbuild: 0.27.2
=======
esbuild: 0.27.1
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
@ -5046,16 +5416,26 @@ snapshots:
fsevents: 2.3.3
yaml: 2.8.2
<<<<<<< HEAD
vite@7.3.0(@types/node@25.0.3)(yaml@2.8.2):
dependencies:
esbuild: 0.27.2
=======
vite@7.3.0(@types/node@25.0.2)(yaml@2.8.2):
dependencies:
esbuild: 0.27.1
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.6
rollup: 4.53.5
tinyglobby: 0.2.15
optionalDependencies:
<<<<<<< HEAD
'@types/node': 25.0.3
=======
'@types/node': 25.0.2
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
fsevents: 2.3.3
yaml: 2.8.2

View file

@ -0,0 +1,21 @@
{
"name": "tic-tac-toe",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "npm run build && node dist/run.js",
"build": "vite build",
"build:prod": "vite build --outDir=/dist --minify=true --sourcemap=false",
"REMOVEME-build:openapi": "VITE_ENTRYPOINT=src/openapi.ts vite build && node dist/openapi.cjs >openapi.json",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.24.0",
"dependencies": {
"fastify-socket.io": "^5.1.0",
"socket.io": "^4.8.1"
}
}

240
src/tic-tac-toe/src/app.ts Normal file
View file

@ -0,0 +1,240 @@
import { FastifyInstance, FastifyPluginAsync } from 'fastify';
import fastifySocketIO from 'fastify-socket.io';
import { TTC } from './game';
const app: FastifyPluginAsync = async (fastify: FastifyInstance, opts): Promise<void> => {
void opts;
await fastify.register(fastifySocketIO, {
cors: {
origin: '*',
methods: ['GET', 'POST'],
},
});
const game = new TTC();
fastify.ready().then(() => {
fastify.io.on('connection', (socket) => {
fastify.log.info(`Client connected: ${socket.id}`);
socket.emit('gameState', {
board: game.board,
turn: game.currentPlayer,
gameOver: game.isGameOver,
});
socket.on('makeMove', (idx: number) => {
const result = game.makeMove(idx);
if (result === 'invalidMove') {
socket.emit('error', 'Invalid Move');
}
else {
fastify.io.emit('gameState', {
board: game.board,
turn: game.currentPlayer,
lastResult: result,
});
}
});
socket.on('resetGame', () => {
game.reset();
fastify.io.emit('gameState', {
board: game.board,
turn: game.currentPlayer,
reset: true,
});
});
});
});
};
export default app;
// // TODO: Import the plugins defined for this microservice
// // TODO: Import the routes defined for this microservice
// // @brief The microservice app (as a plugin for Fastify), kinda like a main function I guess ???
// // @param fastify
// // @param opts
// export const app: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
// // Register all the fastify plugins that this app will use
// // Once it is done:
// fastify.ready((err) => {
// if (err) {
// throw err;
// }
// // TODO: Supposedly, something should be there I guess
// });
// };
// // Export it as the default for this file.
// export default app;
// // TODO: Understand what is this for in /src/chat/src/app.ts
// // declare module 'fastify' {
// // interface FastifyInstance {
// // io: Server<{
// // hello: (message: string) => string;
// // MsgObjectServer: (data: { message: ClientMessage }) => void;
// // message: (msg: string) => void;
// // testend: (sock_id_client: string) => void;
// // }>;
// // }
// // }
// // TODO: Same for this, also in /src/chat/src/app.ts
// // async function onReady(fastify: FastifyInstance) {
// // function connectedUser(io?: Server, target?: string): number {
// // let count = 0;
// // const seen = new Set<string>();
// // // <- only log/count unique usernames
// // for (const [socketId, username] of clientChat) {
// // // Basic sanity checks
// // if (typeof socketId !== 'string' || socketId.length === 0) {
// // clientChat.delete(socketId);
// // continue;
// // }
// // if (typeof username !== 'string' || username.length === 0) {
// // clientChat.delete(socketId);
// // continue;
// // }
// // // If we have the io instance, attempt to validate the socket is still connected
// // if (io && typeof io.sockets?.sockets?.get === 'function') {
// // const s = io.sockets.sockets.get(socketId) as
// // | Socket
// // | undefined;
// // // If socket not found or disconnected, remove from map and skip
// // if (!s || s.disconnected) {
// // clientChat.delete(socketId);
// // continue;
// // }
// // // Skip duplicates (DO NOT delete them — just don't count)
// // if (seen.has(username)) {
// // continue;
// // }
// // // socket exists and is connected
// // seen.add(username);
// // count++;
// // // console.log(color.green,"count: ", count);
// // console.log(color.yellow, 'Client:', color.reset, username);
// // const targetSocketId = target;
// // io.to(targetSocketId!).emit('listObj', username);
// // console.log(
// // color.yellow,
// // 'Chat Socket ID:',
// // color.reset,
// // socketId,
// // );
// // continue;
// // }
// // // If no io provided, assume entries in the map are valid and count them.
// // count++;
// // console.log(
// // color.red,
// // 'Client (unverified):',
// // color.reset,
// // username,
// // );
// // console.log(
// // color.red,
// // 'Chat Socket ID (unverified):',
// // color.reset,
// // socketId,
// // );
// // }
// // return count;
// // }
// // function broadcast(data: ClientMessage, sender?: string) {
// // fastify.io.fetchSockets().then((sockets) => {
// // for (const s of sockets) {
// // if (s.id !== sender) {
// // // Send REAL JSON object
// // const clientName = clientChat.get(s.id) || null;
// // if (clientName !== null) {
// // s.emit('MsgObjectServer', { message: data });
// // }
// // console.log(' Target window socket ID:', s.id);
// // console.log(' Target window ID:', [...s.rooms]);
// // console.log(' Sender window ID:', sender ? sender : 'none');
// // }
// // }
// // });
// // }
// // fastify.io.on('connection', (socket: Socket) => {
// // socket.on('message', (message: string) => {
// // console.info(
// // color.blue,
// // 'Socket connected!',
// // color.reset,
// // socket.id,
// // );
// // console.log(
// // color.blue,
// // 'Received message from client',
// // color.reset,
// // message,
// // );
// // const obj: ClientMessage = JSON.parse(message) as ClientMessage;
// // clientChat.set(socket.id, obj.user);
// // console.log(
// // color.green,
// // 'Message from client',
// // color.reset,
// // `Sender: login name: "${obj.user}" - windowID "${obj.SenderWindowID}" - text message: "${obj.text}"`,
// // );
// // // Send object directly — DO NOT wrap it in a string
// // broadcast(obj, obj.SenderWindowID);
// // console.log(
// // color.red,
// // 'connected in the Chat :',
// // connectedUser(fastify.io),
// // color.reset,
// // );
// // });
// // socket.on('testend', (sock_id_cl: string) => {
// // console.log('testend received from client socket id:', sock_id_cl);
// // });
// // socket.on('list', () => {
// // console.log(color.red, 'list activated', color.reset, socket.id);
// // connectedUser(fastify.io, socket.id);
// // });
// // socket.on('disconnecting', (reason) => {
// // const clientName = clientChat.get(socket.id) || null;
// // console.log(
// // color.green,
// // `Client disconnecting: ${clientName} (${socket.id}) reason:`,
// // reason,
// // );
// // if (reason === 'transport error') return;
// // if (clientName !== null) {
// // const obj = {
// // type: 'chat',
// // user: clientName,
// // token: '',
// // text: 'LEFT the chat',
// // timestamp: Date.now(),
// // SenderWindowID: socket.id,
// // };
// // broadcast(obj, obj.SenderWindowID);
// // // clientChat.delete(obj.user);
// // }
// // });
// // });
// // }

View file

@ -0,0 +1,81 @@
// Represents the possible states of a cell on the board.
// `null` means that the cell is empty.
type CellState = 'O' | 'X' | null
export class TTC {
private isGameOver: boolean = false;
public board: CellState[] = Array(9).fill(null);
private currentPlayer: 'O' | 'X' = 'X';
private changePlayer() {
this.currentPlayer = this.currentPlayer === 'X' ? 'O' : 'X';
}
// Analyzes the current board to determine if the game has ended.
private checkState(): 'winX' | 'winO' | 'draw' | 'ongoing' {
const checkRow = (row: number): ('X' | 'O' | null) => {
if (this.board[row * 3] === null) {return null;}
if (this.board[row * 3] === this.board[row * 3 + 1] && this.board[row * 3 + 1] === this.board[row * 3 + 2]) {return this.board[row * 3];}
return null;
};
const checkCol = (col: number): ('X' | 'O' | null) => {
if (this.board[col] === null) return null;
if (this.board[col] === this.board[col + 3] && this.board[col + 3] === this.board[col + 6]) {return this.board[col];}
return null;
};
const checkDiag = (): ('X' | 'O' | null) => {
if (this.board[4] === null) return null;
if (this.board[0] === this.board[4] && this.board[4] === this.board[8]) {return this.board[4];}
if (this.board[2] === this.board[4] && this.board[4] === this.board[6]) {return this.board[4];}
return null;
};
const row = (checkRow(0) ?? checkRow(1)) ?? checkRow(2);
const col = (checkCol(0) ?? checkCol(1)) ?? checkCol(2);
const diag = checkDiag();
if (row !== null) return `win${row}`;
if (col !== null) return `win${col}`;
if (diag !== null) return `win${diag}`;
if (this.board.filter(c => c === null).length === 0) {return 'draw';}
return 'ongoing';
}
public reset(): void {
this.board = [null, null, null, null, null, null, null, null, null];
this.currentPlayer = 'X';
this.isGameOver = false;
};
// Attempts to place the current player's mark on the specified cell.
// @param idx - The index of the board (0-8) to place the mark.
// @returns The resulting game state, or `invalidMove` if the move is illegal.
public makeMove(idx: number): 'winX' | 'winO' | 'draw' | 'ongoing' | 'invalidMove' {
if (this.isGameOver) {
return 'invalidMove';
}
if (idx < 0 || idx >= this.board.length) {
return 'invalidMove';
}
if (this.board[idx] !== null) {
return 'invalidMove';
}
this.board[idx] = this.currentPlayer;
this.changePlayer();
const result = this.checkState();
if (result !== 'ongoing') {
this.isGameOver = true;
}
return result;
}
}

View file

@ -26,7 +26,11 @@
"fastify": "^5.6.2",
"fastify-cli": "^7.4.1",
"fastify-plugin": "^5.1.0",
<<<<<<< HEAD
"typebox": "^1.0.64"
=======
"typebox": "^1.0.63"
>>>>>>> 16e6ae0 ((schism): started separating backend from frontend)
},
"devDependencies": {
"@types/node": "^22.19.3",