Initial working draft - no styling
Random album selection works Drag and Drop works Solution checking works Stage and high score tracking works High score and stage tied to session cookie
This commit is contained in:
parent
0407df4a2a
commit
19127be9a2
14 changed files with 935 additions and 5 deletions
|
@ -24,7 +24,9 @@
|
|||
"@tailwindcss/container-queries": "^0.1.1",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"@types/better-sqlite3": "^7.6.12",
|
||||
"@types/spotify-web-api-node": "^5.0.11",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"bits-ui": "1.0.0-next.78",
|
||||
"clsx": "^2.1.1",
|
||||
"drizzle-kit": "^0.30.2",
|
||||
"eslint": "^9.18.0",
|
||||
|
@ -36,6 +38,7 @@
|
|||
"prettier-plugin-tailwindcss": "^0.6.10",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"svelte-dnd-action": "^0.9.54",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwind-variants": "^0.3.1",
|
||||
"tailwindcss": "^3.4.17",
|
||||
|
@ -46,6 +49,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.8.0",
|
||||
"drizzle-orm": "^0.38.4"
|
||||
"drizzle-orm": "^0.38.4",
|
||||
"nanoid": "^5.0.9",
|
||||
"spotify-web-api-node": "^5.0.2",
|
||||
"svelte-kit-sessions": "^0.4.0"
|
||||
}
|
||||
}
|
||||
|
|
421
pnpm-lock.yaml
generated
421
pnpm-lock.yaml
generated
|
@ -14,6 +14,15 @@ importers:
|
|||
drizzle-orm:
|
||||
specifier: ^0.38.4
|
||||
version: 0.38.4(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)
|
||||
nanoid:
|
||||
specifier: ^5.0.9
|
||||
version: 5.0.9
|
||||
spotify-web-api-node:
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
svelte-kit-sessions:
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7)))(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7)))(svelte@5.19.0)
|
||||
devDependencies:
|
||||
'@eslint/compat':
|
||||
specifier: ^1.2.5
|
||||
|
@ -39,9 +48,15 @@ importers:
|
|||
'@types/better-sqlite3':
|
||||
specifier: ^7.6.12
|
||||
version: 7.6.12
|
||||
'@types/spotify-web-api-node':
|
||||
specifier: ^5.0.11
|
||||
version: 5.0.11
|
||||
autoprefixer:
|
||||
specifier: ^10.4.20
|
||||
version: 10.4.20(postcss@8.5.1)
|
||||
bits-ui:
|
||||
specifier: 1.0.0-next.78
|
||||
version: 1.0.0-next.78(svelte@5.19.0)
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
|
@ -75,6 +90,9 @@ importers:
|
|||
svelte-check:
|
||||
specifier: ^4.0.0
|
||||
version: 4.1.4(picomatch@4.0.2)(svelte@5.19.0)(typescript@5.7.3)
|
||||
svelte-dnd-action:
|
||||
specifier: ^0.9.54
|
||||
version: 0.9.54(svelte@5.19.0)
|
||||
tailwind-merge:
|
||||
specifier: ^2.6.0
|
||||
version: 2.6.0
|
||||
|
@ -569,6 +587,15 @@ packages:
|
|||
resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@floating-ui/core@1.6.9':
|
||||
resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==}
|
||||
|
||||
'@floating-ui/dom@1.6.13':
|
||||
resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==}
|
||||
|
||||
'@floating-ui/utils@0.2.9':
|
||||
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
|
||||
|
||||
'@humanfs/core@0.19.1':
|
||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
@ -589,10 +616,17 @@ packages:
|
|||
resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
|
||||
engines: {node: '>=18.18'}
|
||||
|
||||
'@internationalized/date@3.7.0':
|
||||
resolution: {integrity: sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ==}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@isaacs/ttlcache@1.4.1':
|
||||
resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -790,6 +824,9 @@ packages:
|
|||
svelte: ^5.0.0-next.96 || ^5.0.0
|
||||
vite: ^5.0.0
|
||||
|
||||
'@swc/helpers@0.5.15':
|
||||
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
|
||||
|
||||
'@tailwindcss/container-queries@0.1.1':
|
||||
resolution: {integrity: sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==}
|
||||
peerDependencies:
|
||||
|
@ -818,6 +855,12 @@ packages:
|
|||
'@types/resolve@1.20.2':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@types/spotify-api@0.0.25':
|
||||
resolution: {integrity: sha512-okhoy0U9fPWtwqCfbDyW8VxamhqvXE0gXIVeMOh5HcvEFQvWW2X0VsvdiX/OyiGQpZbZiOJXIGrbnIPfK0AIpA==}
|
||||
|
||||
'@types/spotify-web-api-node@5.0.11':
|
||||
resolution: {integrity: sha512-RS3IkSqH9geC61e8qd+Oy7giOTtiY7ywm0Z4bu5uYuc7XuOcLfDwKjmle85IbpTEdazeCgmIbo8nMLg7WDVvgw==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.20.0':
|
||||
resolution: {integrity: sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
@ -916,6 +959,9 @@ packages:
|
|||
resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
|
||||
autoprefixer@10.4.20:
|
||||
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
@ -943,6 +989,12 @@ packages:
|
|||
bindings@1.5.0:
|
||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||
|
||||
bits-ui@1.0.0-next.78:
|
||||
resolution: {integrity: sha512-jZjG2ObZ/CNyCNaXecpItC7hRXqJAgEfMhr06/eNrf3wHiiPyhdcy4OkzLcJyxeOrDyj+xma8cZTd3JRWqJdAw==}
|
||||
engines: {node: '>=18', pnpm: '>=8.7.0'}
|
||||
peerDependencies:
|
||||
svelte: ^5.11.0
|
||||
|
||||
bl@4.1.0:
|
||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
||||
|
||||
|
@ -967,6 +1019,14 @@ packages:
|
|||
buffer@5.7.1:
|
||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
call-bound@1.0.3:
|
||||
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
callsites@3.1.0:
|
||||
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -1004,6 +1064,10 @@ packages:
|
|||
color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
@ -1011,6 +1075,9 @@ packages:
|
|||
commondir@1.0.1:
|
||||
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
|
||||
|
||||
component-emitter@1.3.1:
|
||||
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
|
||||
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
|
@ -1018,6 +1085,9 @@ packages:
|
|||
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
cookiejar@2.1.4:
|
||||
resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -1051,6 +1121,10 @@ packages:
|
|||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
detect-libc@2.0.3:
|
||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1160,6 +1234,10 @@ packages:
|
|||
sqlite3:
|
||||
optional: true
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
eastasianwidth@0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
|
||||
|
@ -1175,6 +1253,18 @@ packages:
|
|||
end-of-stream@1.4.4:
|
||||
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
|
||||
|
||||
es-define-property@1.0.1:
|
||||
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-errors@1.3.0:
|
||||
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
esbuild-register@3.6.0:
|
||||
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
|
||||
peerDependencies:
|
||||
|
@ -1301,6 +1391,9 @@ packages:
|
|||
fast-levenshtein@2.0.6:
|
||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||
|
||||
fast-safe-stringify@2.1.1:
|
||||
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
||||
|
||||
fastq@1.18.0:
|
||||
resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==}
|
||||
|
||||
|
@ -1338,6 +1431,14 @@ packages:
|
|||
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
form-data@3.0.2:
|
||||
resolution: {integrity: sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
formidable@1.2.6:
|
||||
resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==}
|
||||
deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau'
|
||||
|
||||
fraction.js@4.3.7:
|
||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||
|
||||
|
@ -1352,6 +1453,14 @@ packages:
|
|||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-proto@1.0.1:
|
||||
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
get-tsconfig@4.8.1:
|
||||
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
|
||||
|
||||
|
@ -1378,6 +1487,10 @@ packages:
|
|||
resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
gopd@1.2.0:
|
||||
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
|
@ -1385,6 +1498,10 @@ packages:
|
|||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
has-symbols@1.1.0:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -1413,6 +1530,9 @@ packages:
|
|||
ini@1.3.8:
|
||||
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
||||
|
||||
inline-style-parser@0.2.4:
|
||||
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1510,14 +1630,35 @@ packages:
|
|||
magic-string@0.30.17:
|
||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
methods@1.1.2:
|
||||
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
micromatch@4.0.8:
|
||||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
mime@2.6.0:
|
||||
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
hasBin: true
|
||||
|
||||
mimic-response@3.1.0:
|
||||
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -1562,6 +1703,11 @@ packages:
|
|||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
nanoid@5.0.9:
|
||||
resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==}
|
||||
engines: {node: ^18 || >=20}
|
||||
hasBin: true
|
||||
|
||||
napi-build-utils@1.0.2:
|
||||
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
|
||||
|
||||
|
@ -1591,6 +1737,10 @@ packages:
|
|||
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
object-inspect@1.13.3:
|
||||
resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
|
||||
|
@ -1794,6 +1944,10 @@ packages:
|
|||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
qs@6.14.0:
|
||||
resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
|
||||
engines: {node: '>=0.6'}
|
||||
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
|
@ -1840,6 +1994,16 @@ packages:
|
|||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
runed@0.20.0:
|
||||
resolution: {integrity: sha512-YqPxaUdWL5nUXuSF+/v8a+NkVN8TGyEGbQwTA25fLY35MR/2bvZ1c6sCbudoo1kT4CAJPh4kUkcgGVxW127WKw==}
|
||||
peerDependencies:
|
||||
svelte: ^5.7.0
|
||||
|
||||
runed@0.22.0:
|
||||
resolution: {integrity: sha512-ZWVXWhOr0P5xdNgtviz6D1ivLUDWKLCbeC5SUEJ3zBkqLReVqWHenFxMNFeFaiC5bfxhFxyxzyzB+98uYFtwdA==}
|
||||
peerDependencies:
|
||||
svelte: ^5.7.0
|
||||
|
||||
sade@1.8.1:
|
||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -1863,6 +2027,22 @@ packages:
|
|||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
side-channel-list@1.0.0:
|
||||
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
side-channel-map@1.0.1:
|
||||
resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
side-channel-weakmap@1.0.2:
|
||||
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
side-channel@1.1.0:
|
||||
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
|
@ -1888,6 +2068,9 @@ packages:
|
|||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
spotify-web-api-node@5.0.2:
|
||||
resolution: {integrity: sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1915,11 +2098,19 @@ packages:
|
|||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
style-to-object@1.0.8:
|
||||
resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==}
|
||||
|
||||
sucrase@3.35.0:
|
||||
resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
hasBin: true
|
||||
|
||||
superagent@6.1.0:
|
||||
resolution: {integrity: sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==}
|
||||
engines: {node: '>= 7.0.0'}
|
||||
deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net
|
||||
|
||||
supports-color@7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1936,6 +2127,11 @@ packages:
|
|||
svelte: ^4.0.0 || ^5.0.0-next.0
|
||||
typescript: '>=5.0.0'
|
||||
|
||||
svelte-dnd-action@0.9.54:
|
||||
resolution: {integrity: sha512-Hue0e449cd3WOASOeawFhEDUb6WFz6QyMVzuEd2RCWhzUAZS6PvOCLZeJyDkx4uKgYve9PR08yzTlEV0oKaH8A==}
|
||||
peerDependencies:
|
||||
svelte: '>=3.23.0 || ^5.0.0-next.0'
|
||||
|
||||
svelte-eslint-parser@0.43.0:
|
||||
resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
@ -1945,6 +2141,18 @@ packages:
|
|||
svelte:
|
||||
optional: true
|
||||
|
||||
svelte-kit-sessions@0.4.0:
|
||||
resolution: {integrity: sha512-cWjHwd+EGIuZ0p8CxSqE5EMOT8EUsoYfAnbE8QB+r6FonroYiMvTLUgv8b9dVLC55Yw3UtTntjUaZ5fKJF3XOA==}
|
||||
peerDependencies:
|
||||
'@sveltejs/kit': ^1.0.0 || ^2.0.0
|
||||
svelte: ^5.1.13
|
||||
|
||||
svelte-toolbelt@0.7.0:
|
||||
resolution: {integrity: sha512-i/Tv4NwAWWqJnK5H0F8y/ubDnogDYlwwyzKhrspTUFzrFuGnYshqd2g4/R43ds841wmaFiSW/HsdsdWhPOlrAA==}
|
||||
engines: {node: '>=18', pnpm: '>=8.7.0'}
|
||||
peerDependencies:
|
||||
svelte: ^5.0.0
|
||||
|
||||
svelte@5.19.0:
|
||||
resolution: {integrity: sha512-qvd2GvvYnJxS/MteQKFSMyq8cQrAAut28QZ39ySv9k3ggmhw4Au4Rfcsqva74i0xMys//OhbhVCNfXPrDzL/Bg==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -2002,6 +2210,9 @@ packages:
|
|||
ts-interface-checker@0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
tunnel-agent@0.6.0:
|
||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||
|
||||
|
@ -2382,6 +2593,17 @@ snapshots:
|
|||
'@eslint/core': 0.10.0
|
||||
levn: 0.4.1
|
||||
|
||||
'@floating-ui/core@1.6.9':
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.9
|
||||
|
||||
'@floating-ui/dom@1.6.13':
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.6.9
|
||||
'@floating-ui/utils': 0.2.9
|
||||
|
||||
'@floating-ui/utils@0.2.9': {}
|
||||
|
||||
'@humanfs/core@0.19.1': {}
|
||||
|
||||
'@humanfs/node@0.16.6':
|
||||
|
@ -2395,6 +2617,10 @@ snapshots:
|
|||
|
||||
'@humanwhocodes/retry@0.4.1': {}
|
||||
|
||||
'@internationalized/date@3.7.0':
|
||||
dependencies:
|
||||
'@swc/helpers': 0.5.15
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
dependencies:
|
||||
string-width: 5.1.2
|
||||
|
@ -2404,6 +2630,8 @@ snapshots:
|
|||
wrap-ansi: 8.1.0
|
||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||
|
||||
'@isaacs/ttlcache@1.4.1': {}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.8':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
|
@ -2578,6 +2806,10 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@swc/helpers@0.5.15':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@tailwindcss/container-queries@0.1.1(tailwindcss@3.4.17)':
|
||||
dependencies:
|
||||
tailwindcss: 3.4.17
|
||||
|
@ -2603,6 +2835,12 @@ snapshots:
|
|||
|
||||
'@types/resolve@1.20.2': {}
|
||||
|
||||
'@types/spotify-api@0.0.25': {}
|
||||
|
||||
'@types/spotify-web-api-node@5.0.11':
|
||||
dependencies:
|
||||
'@types/spotify-api': 0.0.25
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.20.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3))(eslint@9.18.0(jiti@1.21.7))(typescript@5.7.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
|
@ -2720,6 +2958,8 @@ snapshots:
|
|||
|
||||
aria-query@5.3.2: {}
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
|
||||
autoprefixer@10.4.20(postcss@8.5.1):
|
||||
dependencies:
|
||||
browserslist: 4.24.4
|
||||
|
@ -2747,6 +2987,16 @@ snapshots:
|
|||
dependencies:
|
||||
file-uri-to-path: 1.0.0
|
||||
|
||||
bits-ui@1.0.0-next.78(svelte@5.19.0):
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.6.9
|
||||
'@floating-ui/dom': 1.6.13
|
||||
'@internationalized/date': 3.7.0
|
||||
esm-env: 1.2.2
|
||||
runed: 0.22.0(svelte@5.19.0)
|
||||
svelte: 5.19.0
|
||||
svelte-toolbelt: 0.7.0(svelte@5.19.0)
|
||||
|
||||
bl@4.1.0:
|
||||
dependencies:
|
||||
buffer: 5.7.1
|
||||
|
@ -2780,6 +3030,16 @@ snapshots:
|
|||
base64-js: 1.5.1
|
||||
ieee754: 1.2.1
|
||||
|
||||
call-bind-apply-helpers@1.0.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
function-bind: 1.1.2
|
||||
|
||||
call-bound@1.0.3:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
get-intrinsic: 1.2.7
|
||||
|
||||
callsites@3.1.0: {}
|
||||
|
||||
camelcase-css@2.0.1: {}
|
||||
|
@ -2817,14 +3077,22 @@ snapshots:
|
|||
|
||||
color-name@1.1.4: {}
|
||||
|
||||
combined-stream@1.0.8:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
commander@4.1.1: {}
|
||||
|
||||
commondir@1.0.1: {}
|
||||
|
||||
component-emitter@1.3.1: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
cookie@0.6.0: {}
|
||||
|
||||
cookiejar@2.1.4: {}
|
||||
|
||||
cross-spawn@7.0.6:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
@ -2847,6 +3115,8 @@ snapshots:
|
|||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
detect-libc@2.0.3: {}
|
||||
|
||||
devalue@5.1.1: {}
|
||||
|
@ -2869,6 +3139,12 @@ snapshots:
|
|||
'@types/better-sqlite3': 7.6.12
|
||||
better-sqlite3: 11.8.1
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
eastasianwidth@0.2.0: {}
|
||||
|
||||
electron-to-chromium@1.5.83: {}
|
||||
|
@ -2881,6 +3157,14 @@ snapshots:
|
|||
dependencies:
|
||||
once: 1.4.0
|
||||
|
||||
es-define-property@1.0.1: {}
|
||||
|
||||
es-errors@1.3.0: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
|
||||
esbuild-register@3.6.0(esbuild@0.19.12):
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
|
@ -3100,6 +3384,8 @@ snapshots:
|
|||
|
||||
fast-levenshtein@2.0.6: {}
|
||||
|
||||
fast-safe-stringify@2.1.1: {}
|
||||
|
||||
fastq@1.18.0:
|
||||
dependencies:
|
||||
reusify: 1.0.4
|
||||
|
@ -3135,6 +3421,14 @@ snapshots:
|
|||
cross-spawn: 7.0.6
|
||||
signal-exit: 4.1.0
|
||||
|
||||
form-data@3.0.2:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
|
||||
formidable@1.2.6: {}
|
||||
|
||||
fraction.js@4.3.7: {}
|
||||
|
||||
fs-constants@1.0.0: {}
|
||||
|
@ -3144,6 +3438,24 @@ snapshots:
|
|||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
get-intrinsic@1.2.7:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.1
|
||||
es-define-property: 1.0.1
|
||||
es-errors: 1.3.0
|
||||
es-object-atoms: 1.1.1
|
||||
function-bind: 1.1.2
|
||||
get-proto: 1.0.1
|
||||
gopd: 1.2.0
|
||||
has-symbols: 1.1.0
|
||||
hasown: 2.0.2
|
||||
math-intrinsics: 1.1.0
|
||||
|
||||
get-proto@1.0.1:
|
||||
dependencies:
|
||||
dunder-proto: 1.0.1
|
||||
es-object-atoms: 1.1.1
|
||||
|
||||
get-tsconfig@4.8.1:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
@ -3171,10 +3483,14 @@ snapshots:
|
|||
|
||||
globals@15.14.0: {}
|
||||
|
||||
gopd@1.2.0: {}
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
has-flag@4.0.0: {}
|
||||
|
||||
has-symbols@1.1.0: {}
|
||||
|
||||
hasown@2.0.2:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
@ -3196,6 +3512,8 @@ snapshots:
|
|||
|
||||
ini@1.3.8: {}
|
||||
|
||||
inline-style-parser@0.2.4: {}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
dependencies:
|
||||
binary-extensions: 2.3.0
|
||||
|
@ -3277,13 +3595,25 @@ snapshots:
|
|||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
merge2@1.4.1: {}
|
||||
|
||||
methods@1.1.2: {}
|
||||
|
||||
micromatch@4.0.8:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
mime-db@1.52.0: {}
|
||||
|
||||
mime-types@2.1.35:
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
|
||||
mime@2.6.0: {}
|
||||
|
||||
mimic-response@3.1.0: {}
|
||||
|
||||
mini-svg-data-uri@1.4.4: {}
|
||||
|
@ -3316,6 +3646,8 @@ snapshots:
|
|||
|
||||
nanoid@3.3.8: {}
|
||||
|
||||
nanoid@5.0.9: {}
|
||||
|
||||
napi-build-utils@1.0.2: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
@ -3334,6 +3666,8 @@ snapshots:
|
|||
|
||||
object-hash@3.0.0: {}
|
||||
|
||||
object-inspect@1.13.3: {}
|
||||
|
||||
once@1.4.0:
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
|
@ -3471,6 +3805,10 @@ snapshots:
|
|||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
qs@6.14.0:
|
||||
dependencies:
|
||||
side-channel: 1.1.0
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
rc@1.2.8:
|
||||
|
@ -3537,6 +3875,16 @@ snapshots:
|
|||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
runed@0.20.0(svelte@5.19.0):
|
||||
dependencies:
|
||||
esm-env: 1.2.2
|
||||
svelte: 5.19.0
|
||||
|
||||
runed@0.22.0(svelte@5.19.0):
|
||||
dependencies:
|
||||
esm-env: 1.2.2
|
||||
svelte: 5.19.0
|
||||
|
||||
sade@1.8.1:
|
||||
dependencies:
|
||||
mri: 1.2.0
|
||||
|
@ -3553,6 +3901,34 @@ snapshots:
|
|||
|
||||
shebang-regex@3.0.0: {}
|
||||
|
||||
side-channel-list@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
object-inspect: 1.13.3
|
||||
|
||||
side-channel-map@1.0.1:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
|
||||
side-channel-weakmap@1.0.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.3
|
||||
es-errors: 1.3.0
|
||||
get-intrinsic: 1.2.7
|
||||
object-inspect: 1.13.3
|
||||
side-channel-map: 1.0.1
|
||||
|
||||
side-channel@1.1.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
object-inspect: 1.13.3
|
||||
side-channel-list: 1.0.0
|
||||
side-channel-map: 1.0.1
|
||||
side-channel-weakmap: 1.0.2
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
simple-concat@1.0.1: {}
|
||||
|
@ -3578,6 +3954,12 @@ snapshots:
|
|||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
spotify-web-api-node@5.0.2:
|
||||
dependencies:
|
||||
superagent: 6.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
|
@ -3606,6 +3988,10 @@ snapshots:
|
|||
|
||||
strip-json-comments@3.1.1: {}
|
||||
|
||||
style-to-object@1.0.8:
|
||||
dependencies:
|
||||
inline-style-parser: 0.2.4
|
||||
|
||||
sucrase@3.35.0:
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.8
|
||||
|
@ -3616,6 +4002,22 @@ snapshots:
|
|||
pirates: 4.0.6
|
||||
ts-interface-checker: 0.1.13
|
||||
|
||||
superagent@6.1.0:
|
||||
dependencies:
|
||||
component-emitter: 1.3.1
|
||||
cookiejar: 2.1.4
|
||||
debug: 4.4.0
|
||||
fast-safe-stringify: 2.1.1
|
||||
form-data: 3.0.2
|
||||
formidable: 1.2.6
|
||||
methods: 1.1.2
|
||||
mime: 2.6.0
|
||||
qs: 6.14.0
|
||||
readable-stream: 3.6.2
|
||||
semver: 7.6.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
supports-color@7.2.0:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
@ -3634,6 +4036,10 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- picomatch
|
||||
|
||||
svelte-dnd-action@0.9.54(svelte@5.19.0):
|
||||
dependencies:
|
||||
svelte: 5.19.0
|
||||
|
||||
svelte-eslint-parser@0.43.0(svelte@5.19.0):
|
||||
dependencies:
|
||||
eslint-scope: 7.2.2
|
||||
|
@ -3644,6 +4050,19 @@ snapshots:
|
|||
optionalDependencies:
|
||||
svelte: 5.19.0
|
||||
|
||||
svelte-kit-sessions@0.4.0(@sveltejs/kit@2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7)))(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7)))(svelte@5.19.0):
|
||||
dependencies:
|
||||
'@isaacs/ttlcache': 1.4.1
|
||||
'@sveltejs/kit': 2.16.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7)))(svelte@5.19.0)(vite@5.4.11(@types/node@22.10.7))
|
||||
svelte: 5.19.0
|
||||
|
||||
svelte-toolbelt@0.7.0(svelte@5.19.0):
|
||||
dependencies:
|
||||
clsx: 2.1.1
|
||||
runed: 0.20.0(svelte@5.19.0)
|
||||
style-to-object: 1.0.8
|
||||
svelte: 5.19.0
|
||||
|
||||
svelte@5.19.0:
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
|
@ -3736,6 +4155,8 @@ snapshots:
|
|||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
tunnel-agent@0.6.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
|
13
src/hooks.server.ts
Normal file
13
src/hooks.server.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { SESH_SECRET } from '$env/static/private';
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
import { sveltekitSessionHandle } from 'svelte-kit-sessions';
|
||||
|
||||
export const handle: Handle = sveltekitSessionHandle({
|
||||
secret: SESH_SECRET
|
||||
});
|
||||
|
||||
declare module 'svelte-kit-sessions' {
|
||||
interface SessionData {
|
||||
userId: string;
|
||||
}
|
||||
}
|
39
src/lib/components/DNDGroup.svelte
Normal file
39
src/lib/components/DNDGroup.svelte
Normal file
|
@ -0,0 +1,39 @@
|
|||
<script lang="ts">
|
||||
import { dndzone } from 'svelte-dnd-action';
|
||||
import { flip } from 'svelte/animate';
|
||||
|
||||
let { items = $bindable(), image = false, type = 'default' } = $props();
|
||||
|
||||
const flipDurationMs = 300;
|
||||
|
||||
function handleDndConsider(e: CustomEvent<any>) {
|
||||
items = e.detail.items;
|
||||
}
|
||||
function handleDndFinalize(e: CustomEvent<any>) {
|
||||
items = e.detail.items;
|
||||
}
|
||||
</script>
|
||||
|
||||
<section
|
||||
use:dndzone={{ items, flipDurationMs, type: type }}
|
||||
onconsider={handleDndConsider}
|
||||
onfinalize={handleDndFinalize}
|
||||
class="grid grid-cols-3"
|
||||
>
|
||||
{#if image}
|
||||
{#each items as item, i (item.id)}
|
||||
<div animate:flip={{ duration: flipDurationMs }}>
|
||||
<img class="object-cover" alt="Album Art" src={item.value} />
|
||||
<input type="hidden" name="{type}_{i}" value={item.value} />
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each items as item, i (item.id)}
|
||||
<div animate:flip={{ duration: flipDurationMs }}>
|
||||
<p class="text-center">{item.value}</p>
|
||||
|
||||
<input type="hidden" name="{type}_{i}" value={item.value} />
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</section>
|
75
src/lib/components/ui/button/button.svelte
Normal file
75
src/lib/components/ui/button/button.svelte
Normal file
|
@ -0,0 +1,75 @@
|
|||
<script lang="ts" module>
|
||||
import type { WithElementRef } from "bits-ui";
|
||||
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
|
||||
import { type VariantProps, tv } from "tailwind-variants";
|
||||
|
||||
export const buttonVariants = tv({
|
||||
base: "focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm",
|
||||
outline:
|
||||
"border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2",
|
||||
sm: "h-8 rounded-md px-3 text-xs",
|
||||
lg: "h-10 rounded-md px-8",
|
||||
icon: "h-9 w-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
});
|
||||
|
||||
export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
|
||||
export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
|
||||
|
||||
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
|
||||
WithElementRef<HTMLAnchorAttributes> & {
|
||||
variant?: ButtonVariant;
|
||||
size?: ButtonSize;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
class: className,
|
||||
variant = "default",
|
||||
size = "default",
|
||||
ref = $bindable(null),
|
||||
href = undefined,
|
||||
type = "button",
|
||||
children,
|
||||
...restProps
|
||||
}: ButtonProps = $props();
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
bind:this={ref}
|
||||
class={cn(buttonVariants({ variant, size }), className)}
|
||||
{href}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
bind:this={ref}
|
||||
class={cn(buttonVariants({ variant, size }), className)}
|
||||
{type}
|
||||
{...restProps}
|
||||
>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
{/if}
|
17
src/lib/components/ui/button/index.ts
Normal file
17
src/lib/components/ui/button/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import Root, {
|
||||
type ButtonProps,
|
||||
type ButtonSize,
|
||||
type ButtonVariant,
|
||||
buttonVariants,
|
||||
} from "./button.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
type ButtonProps as Props,
|
||||
//
|
||||
Root as Button,
|
||||
buttonVariants,
|
||||
type ButtonProps,
|
||||
type ButtonSize,
|
||||
type ButtonVariant,
|
||||
};
|
47
src/lib/server/AlbumState.svelte.ts
Normal file
47
src/lib/server/AlbumState.svelte.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import type { AlbumSolveState } from '$lib/types';
|
||||
|
||||
class AlbumState {
|
||||
private albums: SpotifyApi.AlbumObjectSimplified[] | undefined = undefined;
|
||||
|
||||
setAlbums(data: SpotifyApi.AlbumObjectSimplified[]) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.albums = data;
|
||||
}
|
||||
|
||||
checkSolve(data: AlbumSolveState[]) {
|
||||
if (!data || !this.albums) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const solve of data) {
|
||||
const search = this.albums.filter((album) => album.name === solve.name);
|
||||
|
||||
if (!search) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matching = search.at(0);
|
||||
|
||||
if (!matching) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matching.images.at(0)?.url !== solve.imageUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const artistName of solve.artists) {
|
||||
if (!matching.artists.find((artist) => artist.name === artistName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export const albumState = new AlbumState();
|
60
src/lib/server/PlayerState.svelte.ts
Normal file
60
src/lib/server/PlayerState.svelte.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import type { Player } from '$lib/types';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
|
||||
export class PlayerState {
|
||||
players = $state<Player[]>([]);
|
||||
|
||||
newPlayer(id: string) {
|
||||
this.players.push({ id: id, stage: 0, highscore: 0 });
|
||||
}
|
||||
|
||||
getStage(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return player.stage;
|
||||
}
|
||||
|
||||
nextStage(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.stage += 1;
|
||||
}
|
||||
|
||||
score(id: string, win: boolean) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (win) {
|
||||
player.stage += 1;
|
||||
|
||||
if (player.stage > player.highscore) {
|
||||
player.highscore = player.stage;
|
||||
}
|
||||
} else {
|
||||
player.stage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
getHighscore(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return player.highscore;
|
||||
}
|
||||
}
|
||||
|
||||
export const playerState = new PlayerState();
|
62
src/lib/server/Spotify.svelte.ts
Normal file
62
src/lib/server/Spotify.svelte.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import SpotifyWebApi from 'spotify-web-api-node';
|
||||
import { CLIENT_ID, CLIENT_SECRET } from '$env/static/private';
|
||||
import { getRandomSearch } from '$lib/utils';
|
||||
|
||||
class SpotifyAPI {
|
||||
private api = new SpotifyWebApi({
|
||||
clientId: CLIENT_ID,
|
||||
clientSecret: CLIENT_SECRET
|
||||
});
|
||||
private exiresAt: Date = $state(new Date());
|
||||
|
||||
async refreshAccessToken() {
|
||||
// If current token is valid for at least 100ms more
|
||||
if (this.exiresAt.getTime() - new Date().getTime() > 10) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return await this.api.clientCredentialsGrant().then(
|
||||
(data) => {
|
||||
console.log(data.body);
|
||||
if (!data.body['expires_in'] || !data.body['access_token']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const new_date = new Date();
|
||||
new_date.setSeconds(new_date.getSeconds() + Number(data.body['expires_in']));
|
||||
|
||||
this.exiresAt = new_date;
|
||||
this.api.setAccessToken(data.body['access_token']);
|
||||
|
||||
return true;
|
||||
},
|
||||
function (err) {
|
||||
console.log('Something went wrong when retrieving an access token', err);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async getRandomAlbum() {
|
||||
if (!(await this.refreshAccessToken())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const randomSearch = getRandomSearch();
|
||||
const randomOffset = Math.floor(Math.random() * 1000);
|
||||
|
||||
return await this.api.search(randomSearch, ['album'], { limit: 1, offset: randomOffset }).then(
|
||||
function (data) {
|
||||
if (data.body.albums?.items?.at(0)) {
|
||||
return data.body.albums.items.at(0);
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
console.log(err);
|
||||
return undefined;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const spotifyAPI = new SpotifyAPI();
|
11
src/lib/types.ts
Normal file
11
src/lib/types.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export type AlbumSolveState = {
|
||||
name: string;
|
||||
artists: string[];
|
||||
imageUrl: string;
|
||||
};
|
||||
|
||||
export type Player = {
|
||||
id: string;
|
||||
stage: number;
|
||||
highscore: number;
|
||||
};
|
|
@ -1,6 +1,62 @@
|
|||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { type ClassValue, clsx } from 'clsx';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
export function getRandomSearch() {
|
||||
// A list of all characters that can be chosen.
|
||||
const characters = 'abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
// Gets a random character from the characters string.
|
||||
const randomCharacter = characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
let randomSearch = '';
|
||||
|
||||
// Places the wildcard character at the beginning, or both beginning and end, randomly.
|
||||
switch (Math.round(Math.random())) {
|
||||
case 0:
|
||||
randomSearch = randomCharacter + '%';
|
||||
break;
|
||||
case 1:
|
||||
randomSearch = '%' + randomCharacter + '%';
|
||||
break;
|
||||
}
|
||||
|
||||
return randomSearch;
|
||||
}
|
||||
|
||||
export function shuffleObjectValues<T extends object>(arr: Array<T>): Array<T> {
|
||||
// Create a copy of the array
|
||||
const copy = structuredClone(arr);
|
||||
|
||||
// Get all keys from the first object
|
||||
const keys = Object.keys(copy[0] as object);
|
||||
|
||||
keys.forEach((key: string) => {
|
||||
// Get all values for this key with proper type assertion
|
||||
const values = copy.map((obj) => (obj as { [key: string]: unknown })[key]);
|
||||
|
||||
// Fisher-Yates shuffle algorithm
|
||||
for (let i = values.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[values[i], values[j]] = [values[j], values[i]];
|
||||
}
|
||||
|
||||
// Reassign shuffled values back to objects
|
||||
copy.forEach((obj, index) => {
|
||||
(obj as { [key: string]: unknown })[key] = values[index];
|
||||
});
|
||||
});
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
export function shuffleArray<T>(array: T[]): T[] {
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
|
83
src/routes/+page.server.ts
Normal file
83
src/routes/+page.server.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { shuffleArray } from '$lib/utils';
|
||||
import { nanoid } from 'nanoid';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { AlbumSolveState } from '$lib/types';
|
||||
import { albumState } from '$lib/server/AlbumState.svelte';
|
||||
import { playerState } from '$lib/server/PlayerState.svelte';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
const count = 3;
|
||||
export const load: PageServerLoad = async ({ fetch, locals }) => {
|
||||
const { session } = locals;
|
||||
|
||||
if (!session?.data?.userId) {
|
||||
await session.setData({ userId: nanoid() });
|
||||
await session.save();
|
||||
}
|
||||
|
||||
const user = session.data.userId;
|
||||
let stage = playerState.getStage(user);
|
||||
|
||||
if (!stage) {
|
||||
playerState.newPlayer(user);
|
||||
stage = playerState.getStage(user);
|
||||
}
|
||||
|
||||
const highscore = playerState.getHighscore(user);
|
||||
|
||||
const albumData = await fetch(`/api/getAlbums/${count}`)
|
||||
.then((res) => {
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
return data;
|
||||
});
|
||||
|
||||
const albumNames = albumData.albums.map((album) => ({ id: nanoid(), value: album.name }));
|
||||
const albumImages = albumData.albums.map((album) => ({
|
||||
id: nanoid(),
|
||||
value: album.images.at(0).url
|
||||
}));
|
||||
const albumArtists = albumData.albums.map((album) => ({
|
||||
id: nanoid(),
|
||||
value: album.artists.map((artist) => artist.name).join(', ')
|
||||
}));
|
||||
|
||||
return {
|
||||
names: shuffleArray(albumNames),
|
||||
images: shuffleArray(albumImages),
|
||||
artists: shuffleArray(albumArtists),
|
||||
stage: stage,
|
||||
highscore: highscore
|
||||
};
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
default: async ({ request, locals }) => {
|
||||
const { session } = locals; // you can access `locals.session`
|
||||
|
||||
if (!session?.data?.userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = session.data.userId;
|
||||
const data = await request.formData();
|
||||
|
||||
const state: AlbumSolveState[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const name = data.get(`names_${i}`);
|
||||
const image = data.get(`images_${i}`);
|
||||
const artists = data.get(`artists_${i}`);
|
||||
|
||||
const artistList = artists.split(', ');
|
||||
|
||||
state.push({ name: name, imageUrl: image, artists: artistList });
|
||||
}
|
||||
|
||||
const solved = albumState.checkSolve(state);
|
||||
|
||||
playerState.score(user, solved);
|
||||
return { loading: false };
|
||||
}
|
||||
};
|
|
@ -1,2 +1,22 @@
|
|||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import DndGroup from '$lib/components/DNDGroup.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { enhance } from '$app/forms';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
let { data }: { data: PageData } = $props();
|
||||
$inspect(data);
|
||||
</script>
|
||||
|
||||
<form method="POST" use:enhance class="grid gap-8">
|
||||
<DndGroup items={data.names} type="names"></DndGroup>
|
||||
<DndGroup items={data.artists} type="artists"></DndGroup>
|
||||
<DndGroup items={data.images} image type="images"></DndGroup>
|
||||
|
||||
<div class="flex justify-evenly">
|
||||
<p>Stage: {data.stage}</p>
|
||||
<Button type="submit" variant="outline" onsubmit={() => invalidateAll()}>Submit</Button>
|
||||
<p>High Score: {data.highscore}</p>
|
||||
</div>
|
||||
</form>
|
||||
|
|
20
src/routes/api/getAlbums/[count]/+server.ts
Normal file
20
src/routes/api/getAlbums/[count]/+server.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { albumState } from '$lib/server/AlbumState.svelte';
|
||||
import { spotifyAPI } from '$lib/server/Spotify.svelte';
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
export async function GET({ params }) {
|
||||
const count = params.count || 1;
|
||||
|
||||
const albums: SpotifyApi.AlbumObjectSimplified[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const album = await spotifyAPI.getRandomAlbum();
|
||||
if (album) {
|
||||
albums.push(album);
|
||||
}
|
||||
}
|
||||
|
||||
albumState.setAlbums(albums);
|
||||
|
||||
return json({ albums: albums });
|
||||
}
|
Loading…
Add table
Reference in a new issue