Implement most of status system (still kinda bootycheeks at checking if
you're connected), fionally fix prettierrc
This commit is contained in:
parent
126acf52f3
commit
e64910d895
29 changed files with 2001 additions and 879 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"useTabs": true,
|
"useTabs": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"printWidth": 100,
|
"printWidth": 100,
|
||||||
|
|
@ -12,5 +12,5 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tailwindStylesheet": "./src/routes/layout.css"
|
"tailwindStylesheet": "./src/app.css"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
82
bun.lock
82
bun.lock
|
|
@ -51,9 +51,9 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
|
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
|
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||||
|
|
||||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
|
|
@ -381,20 +381,10 @@
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
"bits-ui": ["bits-ui@2.15.2", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-S8eDbFkZCN17kZ7J9fD3MRXziV9ozjdFt2D3vTr2bvXCl7BtrIqguYt2U/zrFgLdR2erwybvCKv0JXYn8uKLDQ=="],
|
||||||
|
|
||||||
"better-sqlite3": ["better-sqlite3@12.5.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg=="],
|
|
||||||
|
|
||||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
|
||||||
|
|
||||||
"bits-ui": ["bits-ui@2.14.4", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-W6kenhnbd/YVvur+DKkaVJ6GldE53eLewur5AhUCqslYQ0vjZr8eWlOfwZnMiPB+PF5HMVqf61vXBvmyrAmPWg=="],
|
|
||||||
|
|
||||||
"bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
|
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||||
|
|
||||||
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
|
|
||||||
|
|
||||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||||
|
|
||||||
"bun-sqlite-key-value": ["bun-sqlite-key-value@1.13.1", "", { "peerDependencies": { "typescript": "^5.5.3" } }, "sha512-cb3thB8QXPeXB6B7NhObpADEYvtVNwqg/0ED7PgKt2OxVAxPSejkiTsy1+byQDC0AwLYajw3nhtr/ubKvcLcKw=="],
|
"bun-sqlite-key-value": ["bun-sqlite-key-value@1.13.1", "", { "peerDependencies": { "typescript": "^5.5.3" } }, "sha512-cb3thB8QXPeXB6B7NhObpADEYvtVNwqg/0ED7PgKt2OxVAxPSejkiTsy1+byQDC0AwLYajw3nhtr/ubKvcLcKw=="],
|
||||||
|
|
@ -407,8 +397,6 @@
|
||||||
|
|
||||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||||
|
|
||||||
"chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
|
||||||
|
|
||||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||||
|
|
||||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||||
|
|
@ -429,10 +417,6 @@
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
|
||||||
|
|
||||||
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
|
||||||
|
|
||||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||||
|
|
||||||
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
||||||
|
|
@ -447,8 +431,6 @@
|
||||||
|
|
||||||
"drizzle-orm": ["drizzle-orm@0.45.1", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA=="],
|
"drizzle-orm": ["drizzle-orm@0.45.1", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-Te0FOdKIistGNPMq2jscdqngBRfBpC8uMFVwqjf6gtTVJHIQ/dosgV/CLBU2N4ZJBsXL5savCba9b0YJskKdcA=="],
|
||||||
|
|
||||||
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
|
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
|
"enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
||||||
|
|
@ -483,8 +465,6 @@
|
||||||
|
|
||||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||||
|
|
||||||
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
|
||||||
|
|
||||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||||
|
|
||||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||||
|
|
@ -497,8 +477,6 @@
|
||||||
|
|
||||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||||
|
|
||||||
"file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
|
|
||||||
|
|
||||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||||
|
|
||||||
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
|
||||||
|
|
@ -507,16 +485,12 @@
|
||||||
|
|
||||||
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
||||||
|
|
||||||
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
|
|
||||||
|
|
||||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||||
|
|
||||||
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
|
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
|
||||||
|
|
||||||
"github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
|
|
||||||
|
|
||||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||||
|
|
||||||
"globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
|
"globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
|
||||||
|
|
@ -527,18 +501,12 @@
|
||||||
|
|
||||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
|
||||||
|
|
||||||
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||||
|
|
||||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||||
|
|
||||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||||
|
|
||||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
|
||||||
|
|
||||||
"ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
|
||||||
|
|
||||||
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
||||||
|
|
||||||
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
|
||||||
|
|
@ -611,14 +579,8 @@
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
|
||||||
|
|
||||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||||
|
|
||||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
|
||||||
|
|
||||||
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
|
||||||
|
|
||||||
"mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="],
|
"mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="],
|
||||||
|
|
||||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
||||||
|
|
@ -629,18 +591,12 @@
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
"napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
|
|
||||||
|
|
||||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||||
|
|
||||||
"node-abi": ["node-abi@3.85.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg=="],
|
|
||||||
|
|
||||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||||
|
|
||||||
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||||
|
|
||||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
|
||||||
|
|
||||||
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
|
||||||
|
|
||||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||||
|
|
@ -671,8 +627,6 @@
|
||||||
|
|
||||||
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
|
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
|
||||||
|
|
||||||
"prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": { "prebuild-install": "bin.js" } }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
|
|
||||||
|
|
||||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||||
|
|
||||||
"prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="],
|
"prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="],
|
||||||
|
|
@ -683,14 +637,8 @@
|
||||||
|
|
||||||
"promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="],
|
"promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="],
|
||||||
|
|
||||||
"pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
|
|
||||||
|
|
||||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||||
|
|
||||||
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
|
|
||||||
|
|
||||||
"readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
|
||||||
|
|
||||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
||||||
|
|
||||||
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
||||||
|
|
@ -705,8 +653,6 @@
|
||||||
|
|
||||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
||||||
|
|
||||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
||||||
|
|
||||||
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="],
|
"set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="],
|
||||||
|
|
@ -715,10 +661,6 @@
|
||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
"simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
|
|
||||||
|
|
||||||
"simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
|
|
||||||
|
|
||||||
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
@ -727,8 +669,6 @@
|
||||||
|
|
||||||
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
|
||||||
|
|
||||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
|
||||||
|
|
||||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||||
|
|
||||||
"style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
|
"style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
|
||||||
|
|
@ -755,20 +695,14 @@
|
||||||
|
|
||||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||||
|
|
||||||
"tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
|
|
||||||
|
|
||||||
"tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||||
|
|
||||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||||
|
|
||||||
"ts-api-utils": ["ts-api-utils@2.3.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg=="],
|
"ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="],
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
|
|
||||||
|
|
||||||
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
|
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
|
||||||
|
|
||||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||||
|
|
@ -797,8 +731,6 @@
|
||||||
|
|
||||||
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
|
||||||
|
|
||||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
|
||||||
|
|
||||||
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||||
|
|
||||||
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
|
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
|
||||||
|
|
@ -815,9 +747,9 @@
|
||||||
|
|
||||||
"@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="],
|
"@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
|
|
@ -837,8 +769,6 @@
|
||||||
|
|
||||||
"mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
|
"mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="],
|
||||||
|
|
||||||
"rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
|
||||||
|
|
||||||
"vite/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
"vite/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||||
|
|
|
||||||
9
drizzle/0007_outstanding_punisher.sql
Normal file
9
drizzle/0007_outstanding_punisher.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE `invite` (
|
||||||
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
|
`server_id` text NOT NULL,
|
||||||
|
`code` text NOT NULL,
|
||||||
|
FOREIGN KEY (`server_id`) REFERENCES `server`(`id`) ON UPDATE no action ON DELETE no action
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE `friendRequest` ADD `from_username` text NOT NULL REFERENCES user(id);--> statement-breakpoint
|
||||||
|
ALTER TABLE `friendRequest` ADD `to_username` text NOT NULL REFERENCES user(id);
|
||||||
9
drizzle/0008_mute_lilandra.sql
Normal file
9
drizzle/0008_mute_lilandra.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
CREATE TABLE `directMessage` (
|
||||||
|
`id` text PRIMARY KEY NOT NULL,
|
||||||
|
`name` text NOT NULL,
|
||||||
|
`server_id` text NOT NULL,
|
||||||
|
`messages` text DEFAULT '[]' NOT NULL,
|
||||||
|
FOREIGN KEY (`server_id`) REFERENCES `server`(`id`) ON UPDATE no action ON DELETE no action
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE `user` ADD `status_overwrite` integer DEFAULT 3 NOT NULL;
|
||||||
450
drizzle/meta/0007_snapshot.json
Normal file
450
drizzle/meta/0007_snapshot.json
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "c0ac7678-4e2c-433f-ac26-73c7b88cc38b",
|
||||||
|
"prevId": "e809c266-891b-4355-a87c-facd55a5293a",
|
||||||
|
"tables": {
|
||||||
|
"channel": {
|
||||||
|
"name": "channel",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"server_id": {
|
||||||
|
"name": "server_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"name": "messages",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"channel_server_id_server_id_fk": {
|
||||||
|
"name": "channel_server_id_server_id_fk",
|
||||||
|
"tableFrom": "channel",
|
||||||
|
"tableTo": "server",
|
||||||
|
"columnsFrom": [
|
||||||
|
"server_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"friendRequest": {
|
||||||
|
"name": "friendRequest",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"from_user": {
|
||||||
|
"name": "from_user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"from_username": {
|
||||||
|
"name": "from_username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"to_username": {
|
||||||
|
"name": "to_username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"to_user": {
|
||||||
|
"name": "to_user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"friendRequest_from_user_user_id_fk": {
|
||||||
|
"name": "friendRequest_from_user_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"from_user"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_from_username_user_id_fk": {
|
||||||
|
"name": "friendRequest_from_username_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"from_username"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_to_username_user_id_fk": {
|
||||||
|
"name": "friendRequest_to_username_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"to_username"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_to_user_user_id_fk": {
|
||||||
|
"name": "friendRequest_to_user_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"to_user"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"name": "group",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"name": "members",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"group_owner_user_id_fk": {
|
||||||
|
"name": "group_owner_user_id_fk",
|
||||||
|
"tableFrom": "group",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"invite": {
|
||||||
|
"name": "invite",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"server_id": {
|
||||||
|
"name": "server_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"name": "code",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"invite_server_id_server_id_fk": {
|
||||||
|
"name": "invite_server_id_server_id_fk",
|
||||||
|
"tableFrom": "invite",
|
||||||
|
"tableTo": "server",
|
||||||
|
"columnsFrom": [
|
||||||
|
"server_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"name": "server",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"name": "members",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"channels": {
|
||||||
|
"name": "channels",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"server_owner_user_id_fk": {
|
||||||
|
"name": "server_owner_user_id_fk",
|
||||||
|
"tableFrom": "server",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"session": {
|
||||||
|
"name": "session",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"session_user_id_user_id_fk": {
|
||||||
|
"name": "session_user_id_user_id_fk",
|
||||||
|
"tableFrom": "session",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"password_hash": {
|
||||||
|
"name": "password_hash",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"friends": {
|
||||||
|
"name": "friends",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"servers": {
|
||||||
|
"name": "servers",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"name": "groups",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"user_username_unique": {
|
||||||
|
"name": "user_username_unique",
|
||||||
|
"columns": [
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
511
drizzle/meta/0008_snapshot.json
Normal file
511
drizzle/meta/0008_snapshot.json
Normal file
|
|
@ -0,0 +1,511 @@
|
||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "bd16f3db-5965-4d36-89b7-d259cbd21149",
|
||||||
|
"prevId": "c0ac7678-4e2c-433f-ac26-73c7b88cc38b",
|
||||||
|
"tables": {
|
||||||
|
"channel": {
|
||||||
|
"name": "channel",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"server_id": {
|
||||||
|
"name": "server_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"name": "messages",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"channel_server_id_server_id_fk": {
|
||||||
|
"name": "channel_server_id_server_id_fk",
|
||||||
|
"tableFrom": "channel",
|
||||||
|
"tableTo": "server",
|
||||||
|
"columnsFrom": [
|
||||||
|
"server_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"directMessage": {
|
||||||
|
"name": "directMessage",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"server_id": {
|
||||||
|
"name": "server_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"messages": {
|
||||||
|
"name": "messages",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"directMessage_server_id_server_id_fk": {
|
||||||
|
"name": "directMessage_server_id_server_id_fk",
|
||||||
|
"tableFrom": "directMessage",
|
||||||
|
"tableTo": "server",
|
||||||
|
"columnsFrom": [
|
||||||
|
"server_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"friendRequest": {
|
||||||
|
"name": "friendRequest",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"from_user": {
|
||||||
|
"name": "from_user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"from_username": {
|
||||||
|
"name": "from_username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"to_username": {
|
||||||
|
"name": "to_username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"to_user": {
|
||||||
|
"name": "to_user",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"friendRequest_from_user_user_id_fk": {
|
||||||
|
"name": "friendRequest_from_user_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"from_user"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_from_username_user_id_fk": {
|
||||||
|
"name": "friendRequest_from_username_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"from_username"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_to_username_user_id_fk": {
|
||||||
|
"name": "friendRequest_to_username_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"to_username"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
},
|
||||||
|
"friendRequest_to_user_user_id_fk": {
|
||||||
|
"name": "friendRequest_to_user_user_id_fk",
|
||||||
|
"tableFrom": "friendRequest",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"to_user"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"name": "group",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"name": "members",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"group_owner_user_id_fk": {
|
||||||
|
"name": "group_owner_user_id_fk",
|
||||||
|
"tableFrom": "group",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"invite": {
|
||||||
|
"name": "invite",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"server_id": {
|
||||||
|
"name": "server_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"name": "code",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"invite_server_id_server_id_fk": {
|
||||||
|
"name": "invite_server_id_server_id_fk",
|
||||||
|
"tableFrom": "invite",
|
||||||
|
"tableTo": "server",
|
||||||
|
"columnsFrom": [
|
||||||
|
"server_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"name": "server",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"name": "owner",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"name": "members",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"channels": {
|
||||||
|
"name": "channels",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"server_owner_user_id_fk": {
|
||||||
|
"name": "server_owner_user_id_fk",
|
||||||
|
"tableFrom": "server",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"owner"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"session": {
|
||||||
|
"name": "session",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"session_user_id_user_id_fk": {
|
||||||
|
"name": "session_user_id_user_id_fk",
|
||||||
|
"tableFrom": "session",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "no action",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"name": "user",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"password_hash": {
|
||||||
|
"name": "password_hash",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"status_overwrite": {
|
||||||
|
"name": "status_overwrite",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": 3
|
||||||
|
},
|
||||||
|
"friends": {
|
||||||
|
"name": "friends",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"servers": {
|
||||||
|
"name": "servers",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"name": "groups",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "'[]'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"user_username_unique": {
|
||||||
|
"name": "user_username_unique",
|
||||||
|
"columns": [
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
},
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"checkConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"views": {},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,6 +50,20 @@
|
||||||
"when": 1767537153441,
|
"when": 1767537153441,
|
||||||
"tag": "0006_gifted_machine_man",
|
"tag": "0006_gifted_machine_man",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 7,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1767543898231,
|
||||||
|
"tag": "0007_outstanding_punisher",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 8,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1767549353944,
|
||||||
|
"tag": "0008_mute_lilandra",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import type { Handle } from '@sveltejs/kit';
|
import type { Handle } from '@sveltejs/kit';
|
||||||
import * as auth from '$lib/server/auth';
|
import * as auth from '$lib/server/auth';
|
||||||
|
import { kvStore } from '$lib/server/db';
|
||||||
|
import { _sendToSubscribers } from './routes/api/updates/+server';
|
||||||
|
import { Status } from '$lib';
|
||||||
|
|
||||||
const handleAuth: Handle = async ({ event, resolve }) => {
|
const handleAuth: Handle = async ({ event, resolve }) => {
|
||||||
const sessionToken = event.cookies.get(auth.sessionCookieName);
|
const sessionToken = event.cookies.get(auth.sessionCookieName);
|
||||||
|
|
@ -21,6 +24,57 @@ const handleAuth: Handle = async ({ event, resolve }) => {
|
||||||
event.locals.user = user;
|
event.locals.user = user;
|
||||||
event.locals.session = session;
|
event.locals.session = session;
|
||||||
|
|
||||||
|
if (event.locals.user) {
|
||||||
|
const id = event.locals.user.id;
|
||||||
|
const overwrite = event.locals.user.statusOverwrite as 1 | 2 | 3 | undefined;
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
const lastActiveKey = `user-${id}-last-active`;
|
||||||
|
const stateKey = `user-${id}-state`;
|
||||||
|
const timerKey = `user-${id}-offline-timer`;
|
||||||
|
|
||||||
|
const lastActive = kvStore.get<number>(lastActiveKey) ?? 0;
|
||||||
|
const state = kvStore.get<1 | 2 | 3>(stateKey) ?? Status.OFFLINE;
|
||||||
|
|
||||||
|
// always update activity
|
||||||
|
kvStore.set(lastActiveKey, now);
|
||||||
|
if (overwrite !== Status.OFFLINE) {
|
||||||
|
const shouldSend = state === Status.OFFLINE && now - lastActive > 5000;
|
||||||
|
|
||||||
|
if (shouldSend) {
|
||||||
|
const outgoingStatus = overwrite === Status.DND ? Status.DND : Status.ONLINE;
|
||||||
|
|
||||||
|
_sendToSubscribers(id, {
|
||||||
|
type: 'status',
|
||||||
|
id,
|
||||||
|
status: outgoingStatus
|
||||||
|
});
|
||||||
|
|
||||||
|
kvStore.set(stateKey, outgoingStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const existingTimer = kvStore.get<NodeJS.Timeout>(timerKey);
|
||||||
|
if (existingTimer) {
|
||||||
|
clearTimeout(existingTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const offlineTimer = setTimeout(() => {
|
||||||
|
const last = kvStore.get<number>(lastActiveKey) ?? 0;
|
||||||
|
|
||||||
|
if (Date.now() - last >= 10_000) {
|
||||||
|
_sendToSubscribers(id, {
|
||||||
|
type: 'status',
|
||||||
|
id,
|
||||||
|
status: Status.OFFLINE
|
||||||
|
});
|
||||||
|
|
||||||
|
kvStore.set(stateKey, Status.OFFLINE);
|
||||||
|
kvStore.delete(timerKey);
|
||||||
|
}
|
||||||
|
}, 10_000);
|
||||||
|
|
||||||
|
kvStore.set(timerKey, offlineTimer + '');
|
||||||
|
}
|
||||||
return resolve(event);
|
return resolve(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,27 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Data, type OverviewUser } from "$lib";
|
import { type Data, type OverviewUser } from '$lib';
|
||||||
import * as Collapsible from "$lib/components/ui/collapsible/index.js";
|
import * as Collapsible from '$lib/components/ui/collapsible/index.js';
|
||||||
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||||
import * as Dialog from "$lib/components/ui/dialog/index.js";
|
import * as Dialog from '$lib/components/ui/dialog/index.js';
|
||||||
import * as Tabs from "$lib/components/ui/tabs/index.js";
|
import * as Tabs from '$lib/components/ui/tabs/index.js';
|
||||||
import * as Card from "$lib/components/ui/card/index.js";
|
import * as Card from '$lib/components/ui/card/index.js';
|
||||||
import MessagesSquare from "@lucide/svelte/icons/messages-square";
|
import MessagesSquare from '@lucide/svelte/icons/messages-square';
|
||||||
import MinusIcon from "@lucide/svelte/icons/minus";
|
import MinusIcon from '@lucide/svelte/icons/minus';
|
||||||
import PlusIcon from "@lucide/svelte/icons/plus";
|
import PlusIcon from '@lucide/svelte/icons/plus';
|
||||||
import UserRoundPlus from '@lucide/svelte/icons/user-round-plus';
|
import UserRoundPlus from '@lucide/svelte/icons/user-round-plus';
|
||||||
import UsersRound from '@lucide/svelte/icons/users-round';
|
import UsersRound from '@lucide/svelte/icons/users-round';
|
||||||
import CirclePlus from '@lucide/svelte/icons/circle-plus';
|
import CirclePlus from '@lucide/svelte/icons/circle-plus';
|
||||||
import Input from "./ui/input/input.svelte";
|
import Input from './ui/input/input.svelte';
|
||||||
import Button, { buttonVariants } from "./ui/button/button.svelte";
|
import Button, { buttonVariants } from './ui/button/button.svelte';
|
||||||
import User from "./extra/User.svelte";
|
import User from './extra/User.svelte';
|
||||||
import type { SessionValidationResult } from "$lib/server/auth";
|
import type { SessionValidationResult } from '$lib/server/auth';
|
||||||
|
|
||||||
let { currentPage = $bindable<string|null>(), data, user, ...restProps }: {currentPage: string|null, data: Data, user: SessionValidationResult['user'] }= $props();
|
let {
|
||||||
|
currentPage = $bindable<string | null>(),
|
||||||
|
data,
|
||||||
|
user,
|
||||||
|
...restProps
|
||||||
|
}: { currentPage: string | null; data: Data; user: SessionValidationResult['user'] } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Sidebar.Root {...restProps}>
|
<Sidebar.Root {...restProps}>
|
||||||
|
|
@ -25,7 +30,7 @@
|
||||||
<Sidebar.MenuItem>
|
<Sidebar.MenuItem>
|
||||||
<Sidebar.MenuButton size="lg">
|
<Sidebar.MenuButton size="lg">
|
||||||
<div
|
<div
|
||||||
class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg"
|
class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"
|
||||||
>
|
>
|
||||||
<MessagesSquare class="size-4" />
|
<MessagesSquare class="size-4" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -33,17 +38,17 @@
|
||||||
<span class="font-medium">chat.sad.ovh</span>
|
<span class="font-medium">chat.sad.ovh</span>
|
||||||
</div>
|
</div>
|
||||||
</Sidebar.MenuButton>
|
</Sidebar.MenuButton>
|
||||||
<div class="w-full flex gap-2 justify-center">
|
<div class="flex w-full justify-center gap-2">
|
||||||
|
|
||||||
<Dialog.Root>
|
<Dialog.Root>
|
||||||
<Dialog.Trigger>
|
<Dialog.Trigger>
|
||||||
<Button variant={user!.friendRequests.length > 0 ? "destructive" : "outline"} size="icon">
|
<Button
|
||||||
|
variant={user!.friendRequests.length > 0 ? 'destructive' : 'outline'}
|
||||||
|
size="icon"
|
||||||
|
>
|
||||||
<UserRoundPlus />
|
<UserRoundPlus />
|
||||||
|
|
||||||
</Button>
|
</Button>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
|
|
||||||
|
|
||||||
<Dialog.Content class="sm:max-w-[425px]">
|
<Dialog.Content class="sm:max-w-[425px]">
|
||||||
<Dialog.Header>
|
<Dialog.Header>
|
||||||
<Dialog.Title>Add a friend</Dialog.Title>
|
<Dialog.Title>Add a friend</Dialog.Title>
|
||||||
|
|
@ -56,9 +61,7 @@
|
||||||
<form method="POST" action="?/addFriend" class="mb-4">
|
<form method="POST" action="?/addFriend" class="mb-4">
|
||||||
<Input name="username" placeholder="username" required class="mb-2" />
|
<Input name="username" placeholder="username" required class="mb-2" />
|
||||||
<Dialog.Footer>
|
<Dialog.Footer>
|
||||||
<Dialog.Close class={buttonVariants({ variant: "outline" })}>
|
<Dialog.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Dialog.Close>
|
||||||
Cancel
|
|
||||||
</Dialog.Close>
|
|
||||||
<Button type="submit">Send request</Button>
|
<Button type="submit">Send request</Button>
|
||||||
</Dialog.Footer>
|
</Dialog.Footer>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -72,10 +75,10 @@
|
||||||
|
|
||||||
<!-- Outgoing Requests -->
|
<!-- Outgoing Requests -->
|
||||||
<Tabs.Content value="outgoing">
|
<Tabs.Content value="outgoing">
|
||||||
{#if user.friendRequests.filter(r => r.fromUser === user.id).length === 0}
|
{#if user.friendRequests.filter((r) => r.fromUser === user.id).length === 0}
|
||||||
<p class="text-sm text-muted-foreground">No outgoing requests</p>
|
<p class="text-sm text-muted-foreground">No outgoing requests</p>
|
||||||
{:else}
|
{:else}
|
||||||
{#each user.friendRequests.filter(r => r.fromUser === user.id) as request (request.id)}
|
{#each user.friendRequests.filter((r) => r.fromUser === user.id) as request (request.id)}
|
||||||
<Card.Root class="mb-2">
|
<Card.Root class="mb-2">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{request.username}</Card.Title>
|
<Card.Title>{request.username}</Card.Title>
|
||||||
|
|
@ -84,9 +87,7 @@
|
||||||
<Card.Footer>
|
<Card.Footer>
|
||||||
<form method="POST" action="?/cancelFriendRequest">
|
<form method="POST" action="?/cancelFriendRequest">
|
||||||
<input type="hidden" name="requestId" value={request.id} />
|
<input type="hidden" name="requestId" value={request.id} />
|
||||||
<Button type="submit" variant="outline" size="sm">
|
<Button type="submit" variant="outline" size="sm">Cancel</Button>
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</form>
|
</form>
|
||||||
</Card.Footer>
|
</Card.Footer>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|
@ -96,10 +97,10 @@
|
||||||
|
|
||||||
<!-- Incoming Requests -->
|
<!-- Incoming Requests -->
|
||||||
<Tabs.Content value="incoming">
|
<Tabs.Content value="incoming">
|
||||||
{#if user.friendRequests.filter(r => r.toUser === user.id).length === 0}
|
{#if user.friendRequests.filter((r) => r.toUser === user.id).length === 0}
|
||||||
<p class="text-sm text-muted-foreground">No incoming requests</p>
|
<p class="text-sm text-muted-foreground">No incoming requests</p>
|
||||||
{:else}
|
{:else}
|
||||||
{#each user.friendRequests.filter(r => r.toUser === user.id) as request (request.id)}
|
{#each user.friendRequests.filter((r) => r.toUser === user.id) as request (request.id)}
|
||||||
<Card.Root class="mb-2">
|
<Card.Root class="mb-2">
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
<Card.Title>{request.username}</Card.Title>
|
<Card.Title>{request.username}</Card.Title>
|
||||||
|
|
@ -123,8 +124,6 @@
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
|
|
||||||
|
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
|
|
||||||
<Dialog.Root>
|
<Dialog.Root>
|
||||||
|
|
@ -138,26 +137,18 @@
|
||||||
<form method="POST" action="?/createGroup">
|
<form method="POST" action="?/createGroup">
|
||||||
<Dialog.Header>
|
<Dialog.Header>
|
||||||
<Dialog.Title>Create a group</Dialog.Title>
|
<Dialog.Title>Create a group</Dialog.Title>
|
||||||
<Dialog.Description>
|
<Dialog.Description>Add friends into your group!</Dialog.Description>
|
||||||
Add friends into your group!
|
|
||||||
</Dialog.Description>
|
|
||||||
</Dialog.Header>
|
</Dialog.Header>
|
||||||
|
|
||||||
{#each data.friends as friend (friend.id)}
|
{#each data.friends as friend (friend.id)}
|
||||||
<label class="flex items-center gap-2">
|
<label class="flex items-center gap-2">
|
||||||
<input
|
<input type="checkbox" name="member" value={friend.id} />
|
||||||
type="checkbox"
|
|
||||||
name="member"
|
|
||||||
value={friend.id}
|
|
||||||
/>
|
|
||||||
<User user={friend} />
|
<User user={friend} />
|
||||||
</label>
|
</label>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<Dialog.Footer>
|
<Dialog.Footer>
|
||||||
<Dialog.Close class={buttonVariants({ variant: "outline" })}>
|
<Dialog.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Dialog.Close>
|
||||||
Cancel
|
|
||||||
</Dialog.Close>
|
|
||||||
<Button type="submit">Create group</Button>
|
<Button type="submit">Create group</Button>
|
||||||
</Dialog.Footer>
|
</Dialog.Footer>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -175,17 +166,13 @@
|
||||||
<form method="POST" action="?/joinServer">
|
<form method="POST" action="?/joinServer">
|
||||||
<Dialog.Header>
|
<Dialog.Header>
|
||||||
<Dialog.Title>Join a server</Dialog.Title>
|
<Dialog.Title>Join a server</Dialog.Title>
|
||||||
<Dialog.Description>
|
<Dialog.Description>Enter an invite link.</Dialog.Description>
|
||||||
Enter an invite link.
|
|
||||||
</Dialog.Description>
|
|
||||||
</Dialog.Header>
|
</Dialog.Header>
|
||||||
|
|
||||||
<Input name="invite" placeholder="invite link" required />
|
<Input name="invite" placeholder="invite link" required />
|
||||||
|
|
||||||
<Dialog.Footer>
|
<Dialog.Footer>
|
||||||
<Dialog.Close class={buttonVariants({ variant: "outline" })}>
|
<Dialog.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Dialog.Close>
|
||||||
Cancel
|
|
||||||
</Dialog.Close>
|
|
||||||
<Button type="submit">Join</Button>
|
<Button type="submit">Join</Button>
|
||||||
</Dialog.Footer>
|
</Dialog.Footer>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -203,23 +190,18 @@
|
||||||
<form method="POST" action="?/createServer">
|
<form method="POST" action="?/createServer">
|
||||||
<Dialog.Header>
|
<Dialog.Header>
|
||||||
<Dialog.Title>Create a server</Dialog.Title>
|
<Dialog.Title>Create a server</Dialog.Title>
|
||||||
<Dialog.Description>
|
<Dialog.Description>Name your new server.</Dialog.Description>
|
||||||
Name your new server.
|
|
||||||
</Dialog.Description>
|
|
||||||
</Dialog.Header>
|
</Dialog.Header>
|
||||||
|
|
||||||
<Input name="name" placeholder="Server name" required />
|
<Input name="name" placeholder="Server name" required />
|
||||||
|
|
||||||
<Dialog.Footer>
|
<Dialog.Footer>
|
||||||
<Dialog.Close class={buttonVariants({ variant: "outline" })}>
|
<Dialog.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Dialog.Close>
|
||||||
Cancel
|
|
||||||
</Dialog.Close>
|
|
||||||
<Button type="submit">Create</Button>
|
<Button type="submit">Create</Button>
|
||||||
</Dialog.Footer>
|
</Dialog.Footer>
|
||||||
</form>
|
</form>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Sidebar.MenuItem>
|
</Sidebar.MenuItem>
|
||||||
</Sidebar.Menu>
|
</Sidebar.Menu>
|
||||||
|
|
@ -232,12 +214,8 @@
|
||||||
<Collapsible.Trigger>
|
<Collapsible.Trigger>
|
||||||
<Sidebar.MenuButton>
|
<Sidebar.MenuButton>
|
||||||
Friends
|
Friends
|
||||||
<PlusIcon
|
<PlusIcon class="ms-auto group-data-[state=open]/collapsible:hidden" />
|
||||||
class="ms-auto group-data-[state=open]/collapsible:hidden"
|
<MinusIcon class="ms-auto group-data-[state=closed]/collapsible:hidden" />
|
||||||
/>
|
|
||||||
<MinusIcon
|
|
||||||
class="ms-auto group-data-[state=closed]/collapsible:hidden"
|
|
||||||
/>
|
|
||||||
</Sidebar.MenuButton>
|
</Sidebar.MenuButton>
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
|
|
@ -245,11 +223,13 @@
|
||||||
{#each data.friends as friend (friend.id)}
|
{#each data.friends as friend (friend.id)}
|
||||||
<Sidebar.MenuSubItem>
|
<Sidebar.MenuSubItem>
|
||||||
<Sidebar.MenuSubButton>
|
<Sidebar.MenuSubButton>
|
||||||
|
<User
|
||||||
<User onclick={(e) => {
|
onclick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
currentPage = friend.id;
|
currentPage = friend.id;
|
||||||
}} user={friend}></User>
|
}}
|
||||||
|
user={friend}
|
||||||
|
></User>
|
||||||
</Sidebar.MenuSubButton>
|
</Sidebar.MenuSubButton>
|
||||||
</Sidebar.MenuSubItem>
|
</Sidebar.MenuSubItem>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
@ -263,12 +243,8 @@
|
||||||
<Collapsible.Trigger>
|
<Collapsible.Trigger>
|
||||||
<Sidebar.MenuButton>
|
<Sidebar.MenuButton>
|
||||||
Groups
|
Groups
|
||||||
<PlusIcon
|
<PlusIcon class="ms-auto group-data-[state=open]/collapsible:hidden" />
|
||||||
class="ms-auto group-data-[state=open]/collapsible:hidden"
|
<MinusIcon class="ms-auto group-data-[state=closed]/collapsible:hidden" />
|
||||||
/>
|
|
||||||
<MinusIcon
|
|
||||||
class="ms-auto group-data-[state=closed]/collapsible:hidden"
|
|
||||||
/>
|
|
||||||
</Sidebar.MenuButton>
|
</Sidebar.MenuButton>
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
|
|
@ -276,10 +252,13 @@
|
||||||
{#each data.groups as group (group.id)}
|
{#each data.groups as group (group.id)}
|
||||||
<Sidebar.MenuSubItem>
|
<Sidebar.MenuSubItem>
|
||||||
<Sidebar.MenuSubButton>
|
<Sidebar.MenuSubButton>
|
||||||
<a onclick={(e) => {
|
<a
|
||||||
|
onclick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
currentPage = group.id;
|
currentPage = group.id;
|
||||||
}} href="##">
|
}}
|
||||||
|
href="##"
|
||||||
|
>
|
||||||
{group.name} ({group.members} members)
|
{group.name} ({group.members} members)
|
||||||
</a>
|
</a>
|
||||||
</Sidebar.MenuSubButton>
|
</Sidebar.MenuSubButton>
|
||||||
|
|
@ -295,12 +274,8 @@
|
||||||
<Collapsible.Trigger>
|
<Collapsible.Trigger>
|
||||||
<Sidebar.MenuButton>
|
<Sidebar.MenuButton>
|
||||||
Servers
|
Servers
|
||||||
<PlusIcon
|
<PlusIcon class="ms-auto group-data-[state=open]/collapsible:hidden" />
|
||||||
class="ms-auto group-data-[state=open]/collapsible:hidden"
|
<MinusIcon class="ms-auto group-data-[state=closed]/collapsible:hidden" />
|
||||||
/>
|
|
||||||
<MinusIcon
|
|
||||||
class="ms-auto group-data-[state=closed]/collapsible:hidden"
|
|
||||||
/>
|
|
||||||
</Sidebar.MenuButton>
|
</Sidebar.MenuButton>
|
||||||
</Collapsible.Trigger>
|
</Collapsible.Trigger>
|
||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
|
|
@ -308,11 +283,19 @@
|
||||||
{#each data.servers as server (server.id)}
|
{#each data.servers as server (server.id)}
|
||||||
<Sidebar.MenuSubItem>
|
<Sidebar.MenuSubItem>
|
||||||
<Sidebar.MenuSubButton>
|
<Sidebar.MenuSubButton>
|
||||||
<a onclick={(e) => {
|
<a
|
||||||
|
onclick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
currentPage = server.id;
|
currentPage = server.id;
|
||||||
}} href="##" class="flex items-center gap-2">
|
}}
|
||||||
<img src={"https://api.dicebear.com/7.x/pixel-art/svg?seed=" + server.name} alt={server.name} class="size-6 rounded-full" />
|
href="##"
|
||||||
|
class="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={'https://api.dicebear.com/7.x/pixel-art/svg?seed=' + server.name}
|
||||||
|
alt={server.name}
|
||||||
|
class="size-6 rounded-full"
|
||||||
|
/>
|
||||||
{server.name}
|
{server.name}
|
||||||
</a>
|
</a>
|
||||||
</Sidebar.MenuSubButton>
|
</Sidebar.MenuSubButton>
|
||||||
|
|
|
||||||
9
src/lib/components/hooks/is-mobile.svelte.ts
Normal file
9
src/lib/components/hooks/is-mobile.svelte.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { MediaQuery } from "svelte/reactivity";
|
||||||
|
|
||||||
|
const DEFAULT_MOBILE_BREAKPOINT = 768;
|
||||||
|
|
||||||
|
export class IsMobile extends MediaQuery {
|
||||||
|
constructor(breakpoint: number = DEFAULT_MOBILE_BREAKPOINT) {
|
||||||
|
super(`max-width: ${breakpoint - 1}px`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
import { definePrefix, type Puuid } from "./puuid"
|
import { definePrefix, type Puuid } from './puuid';
|
||||||
|
|
||||||
export const UserID = definePrefix("user");
|
export const UserID = definePrefix('user');
|
||||||
export const GroupID = definePrefix("group");
|
export const GroupID = definePrefix('group');
|
||||||
export const ServerID = definePrefix("srv");
|
export const ServerID = definePrefix('srv');
|
||||||
export const FriendRequestID = definePrefix("frq");
|
export const FriendRequestID = definePrefix('frq');
|
||||||
|
|
||||||
export type UserId = Puuid<"user">;
|
export type UserId = Puuid<'user'>;
|
||||||
export type GroupId = Puuid<"group">;
|
export type GroupId = Puuid<'group'>;
|
||||||
export type ServerId = Puuid<"srv">;
|
export type ServerId = Puuid<'srv'>;
|
||||||
export type FriendRequestID = Puuid<"frq">;
|
export type FriendRequestID = Puuid<'frq'>;
|
||||||
|
|
||||||
export const Status: Record<string, 1 | 2 | 3> = {
|
export const Status: Record<string, 1 | 2 | 3> = {
|
||||||
OFFLINE: 1,
|
OFFLINE: 1,
|
||||||
DND: 2,
|
DND: 2,
|
||||||
ONLINE: 3
|
ONLINE: 3
|
||||||
}
|
};
|
||||||
|
|
||||||
export type OverviewUser = {
|
export type OverviewUser = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -36,13 +36,13 @@ export type OverviewGroup = {
|
||||||
image: string;
|
image: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface OverviewData {
|
|
||||||
friends: OverviewUser[],
|
|
||||||
groups: OverviewGroup[],
|
|
||||||
servers: OverviewServer[],
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface UserWithStatus extends OverviewUser {
|
export interface UserWithStatus extends OverviewUser {
|
||||||
status: 1|2|3,
|
status: 1 | 2 | 3;
|
||||||
statusMessage: string
|
statusMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OverviewData {
|
||||||
|
friends: UserWithStatus[];
|
||||||
|
groups: OverviewGroup[];
|
||||||
|
servers: OverviewServer[];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { v7 as uuidv7 } from "uuid";
|
import { v7 as uuidv7 } from 'uuid';
|
||||||
|
|
||||||
type Brand<K, T> = K & { __brand: T };
|
type Brand<K, T> = K & { __brand: T };
|
||||||
|
|
||||||
export type Puuid<Prefix extends string> = Brand<
|
export type Puuid<Prefix extends string> = Brand<string, { prefix: Prefix }>;
|
||||||
string,
|
|
||||||
{ prefix: Prefix }
|
|
||||||
>;
|
|
||||||
|
|
||||||
export function definePrefix<const P extends string>(prefix: P) {
|
export function definePrefix<const P extends string>(prefix: P) {
|
||||||
const withPrefix = (uuid: string) =>
|
const withPrefix = (uuid: string) => `${prefix}_${uuid}` as Puuid<P>;
|
||||||
`${prefix}_${uuid}` as Puuid<P>;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prefix,
|
prefix,
|
||||||
is(value: string): value is Puuid<P> {
|
is(value: string): value is Puuid<P> {
|
||||||
return value.startsWith(prefix + "_");
|
return value.startsWith(prefix + '_');
|
||||||
},
|
},
|
||||||
|
|
||||||
newV7(): Puuid<P> {
|
newV7(): Puuid<P> {
|
||||||
|
|
@ -27,16 +23,14 @@ export function definePrefix<const P extends string>(prefix: P) {
|
||||||
},
|
},
|
||||||
|
|
||||||
parse(value: string): Puuid<P> {
|
parse(value: string): Puuid<P> {
|
||||||
if (!value.startsWith(prefix + "_")) {
|
if (!value.startsWith(prefix + '_')) {
|
||||||
throw new Error(
|
throw new Error(`Invalid prefix, expected "${prefix}_"`);
|
||||||
`Invalid prefix, expected "${prefix}_"`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return value as Puuid<P>;
|
return value as Puuid<P>;
|
||||||
},
|
},
|
||||||
|
|
||||||
inner(id: Puuid<P>): string {
|
inner(id: Puuid<P>): string {
|
||||||
return id.slice(prefix.length + 1);
|
return id.slice(prefix.length + 1);
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,9 @@ export async function validateSessionToken(token: string) {
|
||||||
friends: table.user.friends,
|
friends: table.user.friends,
|
||||||
servers: table.user.servers,
|
servers: table.user.servers,
|
||||||
groups: table.user.groups,
|
groups: table.user.groups,
|
||||||
|
statusOverwrite: table.user.statusOverwrite
|
||||||
},
|
},
|
||||||
session: table.session,
|
session: table.session
|
||||||
})
|
})
|
||||||
.from(table.session)
|
.from(table.session)
|
||||||
.innerJoin(table.user, eq(table.session.userId, table.user.id))
|
.innerJoin(table.user, eq(table.session.userId, table.user.id))
|
||||||
|
|
@ -66,10 +67,10 @@ export async function validateSessionToken(token: string) {
|
||||||
? await db
|
? await db
|
||||||
.select({
|
.select({
|
||||||
id: table.user.id,
|
id: table.user.id,
|
||||||
username: table.user.username,
|
username: table.user.username
|
||||||
})
|
})
|
||||||
.from(table.user)
|
.from(table.user)
|
||||||
.where(inArray(table.user.id, (user.friends as string[])))
|
.where(inArray(table.user.id, user.friends as string[]))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const servers = (user.servers as string[]).length
|
const servers = (user.servers as string[]).length
|
||||||
|
|
@ -77,10 +78,10 @@ export async function validateSessionToken(token: string) {
|
||||||
.select({
|
.select({
|
||||||
id: table.server.id,
|
id: table.server.id,
|
||||||
name: table.server.name,
|
name: table.server.name,
|
||||||
ownerId: table.server.owner,
|
ownerId: table.server.owner
|
||||||
})
|
})
|
||||||
.from(table.server)
|
.from(table.server)
|
||||||
.where(inArray(table.server.id, (user.servers as string[])))
|
.where(inArray(table.server.id, user.servers as string[]))
|
||||||
: [];
|
: [];
|
||||||
const groups = (user.groups as string[]).length
|
const groups = (user.groups as string[]).length
|
||||||
? await db
|
? await db
|
||||||
|
|
@ -91,20 +92,30 @@ export async function validateSessionToken(token: string) {
|
||||||
members: table.group.members
|
members: table.group.members
|
||||||
})
|
})
|
||||||
.from(table.group)
|
.from(table.group)
|
||||||
.where(inArray(table.group.id, (user.groups as string[])))
|
.where(inArray(table.group.id, user.groups as string[]))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const friendRequests = await db
|
const friendRequests = await db
|
||||||
.select({
|
.select({
|
||||||
id: table.friendRequest.id,
|
id: table.friendRequest.id,
|
||||||
fromUser: table.friendRequest.fromUser,
|
fromUser: table.friendRequest.fromUser,
|
||||||
toUser: table.friendRequest.toUser,
|
toUser: table.friendRequest.toUser
|
||||||
})
|
})
|
||||||
.from(table.friendRequest)
|
.from(table.friendRequest)
|
||||||
.where(or(eq(table.friendRequest.fromUser, user.id), eq(table.friendRequest.toUser, user.id)))
|
.where(or(eq(table.friendRequest.fromUser, user.id), eq(table.friendRequest.toUser, user.id)));
|
||||||
|
|
||||||
|
return {
|
||||||
return { session, user: {...user, servers, friends, groups: groups.map(z => { return { ...z, members: (z.members as string[]).length}}), friendRequests} };
|
session,
|
||||||
|
user: {
|
||||||
|
...user,
|
||||||
|
servers,
|
||||||
|
friends,
|
||||||
|
groups: groups.map((z) => {
|
||||||
|
return { ...z, members: (z.members as string[]).length };
|
||||||
|
}),
|
||||||
|
friendRequests
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SessionValidationResult = Awaited<ReturnType<typeof validateSessionToken>>;
|
export type SessionValidationResult = Awaited<ReturnType<typeof validateSessionToken>>;
|
||||||
|
|
@ -139,7 +150,6 @@ export function validatePassword(password: unknown): password is string {
|
||||||
return typeof password === 'string' && password.length >= 6 && password.length <= 255;
|
return typeof password === 'string' && password.length >= 6 && password.length <= 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function validateEmail(email: unknown): email is string {
|
export function validateEmail(email: unknown): email is string {
|
||||||
return (
|
return (
|
||||||
typeof email === 'string' &&
|
typeof email === 'string' &&
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { drizzle } from 'drizzle-orm/bun-sqlite';
|
import { drizzle } from 'drizzle-orm/bun-sqlite';
|
||||||
import { Database } from 'bun:sqlite';
|
import { Database } from 'bun:sqlite';
|
||||||
import { BunSqliteKeyValue } from "bun-sqlite-key-value"
|
import { BunSqliteKeyValue } from 'bun-sqlite-key-value';
|
||||||
|
|
||||||
const sqlite = new Database('database.db');
|
const sqlite = new Database('database.db');
|
||||||
export const db = drizzle(sqlite);
|
export const db = drizzle(sqlite);
|
||||||
|
|
||||||
export const kvStore = new BunSqliteKeyValue("./kvStore.db")
|
export const kvStore = new BunSqliteKeyValue('./kvStore.db');
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Status } from '../../index.ts';
|
||||||
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
|
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
|
||||||
|
|
||||||
export const user = sqliteTable('user', {
|
export const user = sqliteTable('user', {
|
||||||
|
|
@ -5,10 +6,11 @@ export const user = sqliteTable('user', {
|
||||||
username: text('username').notNull().unique(),
|
username: text('username').notNull().unique(),
|
||||||
email: text('email').notNull().unique(),
|
email: text('email').notNull().unique(),
|
||||||
passwordHash: text('password_hash').notNull(),
|
passwordHash: text('password_hash').notNull(),
|
||||||
friends: text('friends', { mode: "json"}).default([]).notNull(),
|
statusOverwrite: integer('status_overwrite').default(Status.ONLINE).notNull(),
|
||||||
|
friends: text('friends', { mode: 'json' }).default([]).notNull(),
|
||||||
|
|
||||||
servers: text('servers', { mode: "json"}).default([]).notNull(), // string[] of ServerIDs
|
servers: text('servers', { mode: 'json' }).default([]).notNull(), // string[] of ServerIDs
|
||||||
groups: text('groups', { mode: "json"}).default([]).notNull(), // string[] of GroupIDs
|
groups: text('groups', { mode: 'json' }).default([]).notNull() // string[] of GroupIDs
|
||||||
});
|
});
|
||||||
|
|
||||||
export const session = sqliteTable('session', {
|
export const session = sqliteTable('session', {
|
||||||
|
|
@ -19,39 +21,66 @@ export const session = sqliteTable('session', {
|
||||||
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull()
|
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const server = sqliteTable("server", {
|
export const server = sqliteTable('server', {
|
||||||
id: text('id').primaryKey(),
|
id: text('id').primaryKey(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
owner: text('owner').notNull().references(() => user.id),
|
owner: text('owner')
|
||||||
members: text('members', { mode: "json"}).default([]).notNull(),
|
.notNull()
|
||||||
channels: text('channels', { mode: "json"}).default([]).notNull(), // string[] of ChannelIDs
|
.references(() => user.id),
|
||||||
})
|
members: text('members', { mode: 'json' }).default([]).notNull(),
|
||||||
|
channels: text('channels', { mode: 'json' }).default([]).notNull() // string[] of ChannelIDs
|
||||||
|
});
|
||||||
|
|
||||||
export const group = sqliteTable("group", {
|
export const group = sqliteTable('group', {
|
||||||
id: text('id').primaryKey(),
|
id: text('id').primaryKey(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
owner: text('owner').notNull().references(() => user.id),
|
owner: text('owner')
|
||||||
members: text('members', { mode: "json"}).default([]).notNull(),
|
.notNull()
|
||||||
})
|
.references(() => user.id),
|
||||||
|
members: text('members', { mode: 'json' }).default([]).notNull()
|
||||||
|
});
|
||||||
|
|
||||||
export const channel = sqliteTable("channel", {
|
export const channel = sqliteTable('channel', {
|
||||||
id: text('id').primaryKey(),
|
id: text('id').primaryKey(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
serverId: text('server_id').notNull().references(() => server.id),
|
serverId: text('server_id')
|
||||||
messages: text('messages', { mode: "json"}).default([]).notNull(),
|
.notNull()
|
||||||
})
|
.references(() => server.id),
|
||||||
|
messages: text('messages', { mode: 'json' }).default([]).notNull()
|
||||||
|
});
|
||||||
|
|
||||||
export const friendRequest = sqliteTable("friendRequest", {
|
export const directMessage = sqliteTable('directMessage', {
|
||||||
id: text('id').primaryKey(),
|
id: text('id').primaryKey(),
|
||||||
fromUser: text('from_user').notNull().references(() => user.id),
|
name: text('name').notNull(),
|
||||||
toUser: text('to_user').notNull().references(() => user.id),
|
serverId: text('server_id')
|
||||||
})
|
.notNull()
|
||||||
|
.references(() => server.id),
|
||||||
|
messages: text('messages', { mode: 'json' }).default([]).notNull()
|
||||||
|
});
|
||||||
|
|
||||||
export const invite = sqliteTable("invite", {
|
export const friendRequest = sqliteTable('friendRequest', {
|
||||||
id: text('id').primaryKey(),
|
id: text('id').primaryKey(),
|
||||||
serverId: text('server_id').notNull().references(() => server.id),
|
fromUser: text('from_user')
|
||||||
code: text('code').notNull(),
|
.notNull()
|
||||||
})
|
.references(() => user.id),
|
||||||
|
fromUsername: text('from_username')
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
toUsername: text('to_username')
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
toUser: text('to_user')
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const invite = sqliteTable('invite', {
|
||||||
|
id: text('id').primaryKey(),
|
||||||
|
serverId: text('server_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => server.id),
|
||||||
|
code: text('code').notNull()
|
||||||
|
});
|
||||||
export type Session = typeof session.$inferSelect;
|
export type Session = typeof session.$inferSelect;
|
||||||
export type User = typeof user.$inferSelect;
|
export type User = typeof user.$inferSelect;
|
||||||
export type Group = typeof group.$inferSelect;
|
export type Group = typeof group.$inferSelect;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import { clsx, type ClassValue } from "clsx";
|
import { clsx, type ClassValue } from 'clsx';
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, "child"> : T;
|
export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, "children"> : T;
|
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
|
||||||
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
|
||||||
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import favicon from '$lib/assets/favicon.svg';
|
import favicon from '$lib/assets/favicon.svg';
|
||||||
import { ModeWatcher } from "mode-watcher";
|
import { ModeWatcher } from 'mode-watcher';
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { fail, redirect } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
export const load: PageServerLoad = async (event) => {
|
export const load: PageServerLoad = async (event) => {
|
||||||
if (event.request.url.endsWith("/?logout")) {
|
if (event.request.url.endsWith('/?logout')) {
|
||||||
if (!event.locals.session) {
|
if (!event.locals.session) {
|
||||||
return fail(401);
|
return fail(401);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Title from "$lib/components/extra/Title.svelte";
|
import Title from '$lib/components/extra/Title.svelte';
|
||||||
import Button from "$lib/components/ui/button/button.svelte";
|
import Button from '$lib/components/ui/button/button.svelte';
|
||||||
import type { PageServerData } from './$types';
|
import type { PageServerData } from './$types';
|
||||||
|
|
||||||
let { data }: { data: PageServerData } = $props();
|
let { data }: { data: PageServerData } = $props();
|
||||||
|
|
@ -8,23 +8,33 @@
|
||||||
|
|
||||||
<div class="p-6 md:w-1/2">
|
<div class="p-6 md:w-1/2">
|
||||||
<Title class="text-5xl"></Title>
|
<Title class="text-5xl"></Title>
|
||||||
<div class="pb-2">A extremely simple chatting application. Supports mobile devices (as a PWA), and also works on almost every single screen size (responsive design!)</div>
|
<div class="pb-2">
|
||||||
|
A extremely simple chatting application. Supports mobile devices (as a PWA), and also works on
|
||||||
|
almost every single screen size (responsive design!)
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="pb-2">
|
<div class="pb-2">
|
||||||
Featurelist:
|
Featurelist:
|
||||||
<ul class="list-disc pl-6">
|
<ul class="list-disc pl-6">
|
||||||
<li>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</li>
|
<li>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</li>
|
||||||
<li>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,</li>
|
<li>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,</li>
|
||||||
<li>when an unknown printer took a galley of type and scrambled it to make a type specimen book.</li>
|
<li>
|
||||||
<li>It has survived not only five centuries, but also the leap into electronic typesetting,</li>
|
when an unknown printer took a galley of type and scrambled it to make a type specimen book.
|
||||||
<li>remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
It has survived not only five centuries, but also the leap into electronic typesetting,
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
remaining essentially unchanged. It was popularised in the 1960s with the release of
|
||||||
|
Letraset sheets containing Lorem Ipsum passages,
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pb-2">
|
<div class="pb-2">
|
||||||
Screenshots
|
Screenshots
|
||||||
|
|
||||||
<div class="grid grid-cols-2 grid-rows-2 w-76 gap-2">
|
<div class="grid w-76 grid-cols-2 grid-rows-2 gap-2">
|
||||||
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
||||||
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
||||||
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
<img src="https://placehold.co/150x150" alt="temporary placeholder image" />
|
||||||
|
|
@ -32,12 +42,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-3 w-[calc(80%)]">
|
<div class="flex w-[calc(80%)] flex-col gap-3">
|
||||||
{#if data.user?.id}
|
{#if data.user?.id}
|
||||||
<Button href='/app'>Enter</Button>
|
<Button href="/app">Enter</Button>
|
||||||
<Button href='/?logout'>Log out</Button>
|
<Button href="/?logout">Log out</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<Button href='/login'>Log in</Button> <Button href='/register'>Register</Button>
|
<Button href="/login">Log in</Button> <Button href="/register">Register</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
3
src/routes/api/health/+server.ts
Normal file
3
src/routes/api/health/+server.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
export async function GET() {
|
||||||
|
return new Response('OK!');
|
||||||
|
}
|
||||||
|
|
@ -10,10 +10,8 @@ export const GET: RequestHandler = async ({ params }) => {
|
||||||
const messages = Array.from({ length: 5 }, (_, i) => ({
|
const messages = Array.from({ length: 5 }, (_, i) => ({
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
authorId: `user_${Math.floor(Math.random() * 10)}`,
|
authorId: `user_${Math.floor(Math.random() * 10)}`,
|
||||||
content: isGroup
|
content: isGroup ? `Group message #${i + 1}` : `Server message #${i + 1}`,
|
||||||
? `Group message #${i + 1}`
|
timestamp: Date.now() - Math.floor(Math.random() * 100000)
|
||||||
: `Server message #${i + 1}`,
|
|
||||||
timestamp: Date.now() - Math.floor(Math.random() * 100000),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
|
|
@ -21,6 +19,6 @@ export const GET: RequestHandler = async ({ params }) => {
|
||||||
groupId: isGroup ? groupOrServerId : null,
|
groupId: isGroup ? groupOrServerId : null,
|
||||||
serverId: isGroup ? null : groupOrServerId,
|
serverId: isGroup ? null : groupOrServerId,
|
||||||
channelId: channelId ?? null,
|
channelId: channelId ?? null,
|
||||||
messages,
|
messages
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
import { json } from '@sveltejs/kit';
|
import { json } from '@sveltejs/kit';
|
||||||
import type { RequestHandler } from './$types';
|
import type { RequestHandler } from './$types';
|
||||||
import { Status } from '$lib';
|
import { kvStore } from '$lib/server/db';
|
||||||
|
|
||||||
|
|
||||||
export const GET: RequestHandler = async ({ params }) => {
|
export const GET: RequestHandler = async ({ params }) => {
|
||||||
const { userId } = params;
|
const { userId } = params;
|
||||||
|
|
||||||
const status = Object.values(Status)[Math.floor(Math.random() * Object.values(Status).length)];
|
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
userId,
|
userId,
|
||||||
status,
|
status: kvStore.get('user-' + userId + '-state'),
|
||||||
lastActive: Date.now() - Math.floor(Math.random() * 600000),
|
//@TODO Implement statusmessage
|
||||||
customStatus: Math.random() > 0.5 ? 'vibing 🟢' : null,
|
statusMessage: Math.random() > 0.5 ? 'vibing 🟢' : null
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
48
src/routes/api/updates/+server.ts
Normal file
48
src/routes/api/updates/+server.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
interface SubscribedTo {
|
||||||
|
subscribed: string[];
|
||||||
|
userId: string;
|
||||||
|
controller: ReadableStreamDefaultController;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const _clients = new Map<string, SubscribedTo>();
|
||||||
|
export function _sendToSubscribers(userId: string, payload: unknown) {
|
||||||
|
for (const client of _clients) {
|
||||||
|
if (client[1].subscribed.includes(userId)) {
|
||||||
|
try {
|
||||||
|
client[1].controller.enqueue(`data: ${JSON.stringify(payload)}\n\n`);
|
||||||
|
} catch {
|
||||||
|
_clients.delete(client[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function GET({ locals, request }) {
|
||||||
|
if (!locals.user) {
|
||||||
|
return new Response('No authentication', { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscribed = locals.user.friends.map((z) => z.id);
|
||||||
|
const reqId = crypto.randomUUID();
|
||||||
|
|
||||||
|
const stream = new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
_clients.set(reqId, { subscribed, userId: locals.user!.id, controller });
|
||||||
|
console.log(`SSE Client opened. ${_clients.size}`);
|
||||||
|
|
||||||
|
controller.enqueue(`data: ${JSON.stringify({ type: 'connected' })}\n\n`);
|
||||||
|
|
||||||
|
request.signal.addEventListener('abort', () => {
|
||||||
|
_clients.delete(reqId);
|
||||||
|
console.log(`SSE Client aborted. ${_clients.size}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Response(stream, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/event-stream',
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
Connection: 'keep-alive'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -6,13 +6,12 @@ import * as table from '$lib/server/db/schema';
|
||||||
import { FriendRequestID, ServerID } from '$lib';
|
import { FriendRequestID, ServerID } from '$lib';
|
||||||
import { eq } from 'drizzle-orm';
|
import { eq } from 'drizzle-orm';
|
||||||
import { and } from 'drizzle-orm';
|
import { and } from 'drizzle-orm';
|
||||||
import { User } from '$lib/server/db/schema';
|
import { type User } from '$lib/server/db/schema';
|
||||||
export const load: PageServerLoad = async () => {
|
export const load: PageServerLoad = async () => {
|
||||||
const user = requireLogin();
|
const user = requireLogin();
|
||||||
return { user };
|
return { user };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
addFriend: async ({ request, locals }) => {
|
addFriend: async ({ request, locals }) => {
|
||||||
const data = await request.formData();
|
const data = await request.formData();
|
||||||
|
|
@ -27,52 +26,80 @@ export const actions = {
|
||||||
|
|
||||||
let user: User[];
|
let user: User[];
|
||||||
if (username) {
|
if (username) {
|
||||||
user = await db.select().from(table.user).where(eq(table.user.username, username.toString())).limit(1);
|
user = await db
|
||||||
|
.select()
|
||||||
|
.from(table.user)
|
||||||
|
.where(eq(table.user.username, username.toString()))
|
||||||
|
.limit(1);
|
||||||
} else if (userId) {
|
} else if (userId) {
|
||||||
user = await db.select().from(table.user).where(eq(table.user.id, userId.toString())).limit(1);
|
user = await db
|
||||||
|
.select()
|
||||||
|
.from(table.user)
|
||||||
|
.where(eq(table.user.id, userId.toString()))
|
||||||
|
.limit(1);
|
||||||
} else {
|
} else {
|
||||||
return fail(400, { error: 'Missing username or userId' });
|
return fail(400, { error: 'Missing username or userId' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locals.user?.friends.find((z) => z.id == user[0].id)) {
|
||||||
|
return fail(400, { error: 'Already friends' });
|
||||||
|
}
|
||||||
|
|
||||||
if(user?.length == 0)
|
if (user?.length == 0) return fail(400, { error: 'User not found' });
|
||||||
return fail(400, { error: 'User not found' });
|
|
||||||
|
|
||||||
const friendRequest = await db.select()
|
const friendRequest = await db
|
||||||
|
.select()
|
||||||
.from(table.friendRequest)
|
.from(table.friendRequest)
|
||||||
.where(and(eq(table.friendRequest.fromUser, user[0].id), eq(table.friendRequest.toUser, locals.user!.id)))
|
.where(
|
||||||
|
and(
|
||||||
|
eq(table.friendRequest.fromUser, user[0].id),
|
||||||
|
eq(table.friendRequest.toUser, locals.user!.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
// user has already sent a request to us
|
// user has already sent a request to us
|
||||||
// means we want to accept it
|
// means we want to accept it
|
||||||
//
|
//
|
||||||
if (friendRequest?.length != 0) {
|
if (friendRequest?.length != 0) {
|
||||||
await db.delete(table.friendRequest)
|
await db
|
||||||
.where(and(eq(table.friendRequest.fromUser, user[0].id), eq(table.friendRequest.toUser, locals.user!.id)))
|
.delete(table.friendRequest)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(table.friendRequest.fromUser, user[0].id),
|
||||||
|
eq(table.friendRequest.toUser, locals.user!.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
||||||
// add other guy to us
|
// add other guy to us
|
||||||
await db.transaction(async (tx) => {
|
await db.transaction(async (tx) => {
|
||||||
await tx.update(table.user)
|
await tx
|
||||||
.set({ friends: locals.user?.friends.map(z => z.id).concat(user[0].id) })
|
.update(table.user)
|
||||||
|
.set({ friends: locals.user?.friends.map((z) => z.id).concat(user[0].id) })
|
||||||
.where(eq(table.user.id, locals.user!.id));
|
.where(eq(table.user.id, locals.user!.id));
|
||||||
|
|
||||||
await tx.update(table.user)
|
await tx
|
||||||
|
.update(table.user)
|
||||||
.set({ friends: (user[0].friends as string[]).concat(locals.user!.id) })
|
.set({ friends: (user[0].friends as string[]).concat(locals.user!.id) })
|
||||||
.where(eq(table.user.id, user[0].id));
|
.where(eq(table.user.id, user[0].id));
|
||||||
});
|
});
|
||||||
|
|
||||||
return {success: true}
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
// a request from us has already been sent to user
|
// a request from us has already been sent to user
|
||||||
if(locals.user?.friendRequests.find(z => z.toUser == user[0].id && z.fromUser == locals.user!.id))
|
if (
|
||||||
|
locals.user?.friendRequests.find(
|
||||||
|
(z) => z.toUser == user[0].id && z.fromUser == locals.user!.id
|
||||||
|
)
|
||||||
|
)
|
||||||
return fail(400, { error: 'Already sent request' });
|
return fail(400, { error: 'Already sent request' });
|
||||||
|
|
||||||
await db.insert(table.friendRequest).values({
|
await db.insert(table.friendRequest).values({
|
||||||
id: FriendRequestID.newV4(),
|
id: FriendRequestID.newV4(),
|
||||||
fromUser: locals.user!.id,
|
fromUser: locals.user!.id,
|
||||||
toUser: user[0].id,
|
toUser: user[0].id
|
||||||
});
|
});
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
|
@ -86,7 +113,8 @@ export const actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch the friend request
|
// fetch the friend request
|
||||||
const friendRequest = await db.select()
|
const friendRequest = await db
|
||||||
|
.select()
|
||||||
.from(table.friendRequest)
|
.from(table.friendRequest)
|
||||||
.where(eq(table.friendRequest.id, requestId))
|
.where(eq(table.friendRequest.id, requestId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
|
|
@ -103,9 +131,7 @@ export const actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the request
|
// delete the request
|
||||||
await db.delete(table.friendRequest)
|
await db.delete(table.friendRequest).where(eq(table.friendRequest.id, requestId)).limit(1);
|
||||||
.where(eq(table.friendRequest.id, requestId))
|
|
||||||
.limit(1);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
},
|
},
|
||||||
|
|
@ -117,8 +143,6 @@ export const actions = {
|
||||||
return fail(400, { error: 'No members selected' });
|
return fail(400, { error: 'No members selected' });
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(data, members, locals)
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -132,26 +156,30 @@ export const actions = {
|
||||||
|
|
||||||
const inv = await db.select().from(table.invite).where(eq(table.invite.code, invite)).limit(1);
|
const inv = await db.select().from(table.invite).where(eq(table.invite.code, invite)).limit(1);
|
||||||
|
|
||||||
if(inv?.length == 0)
|
if (inv?.length == 0) return fail(400, { error: 'Invalid invite' });
|
||||||
return fail(400, { error: 'Invalid invite' });
|
|
||||||
|
|
||||||
const server = await db.select().from(table.server).where(eq(table.server.id, inv[0].serverId)).limit(1);
|
const server = await db
|
||||||
|
.select()
|
||||||
|
.from(table.server)
|
||||||
|
.where(eq(table.server.id, inv[0].serverId))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
if(server?.length == 0)
|
if (server?.length == 0) return fail(400, { error: 'Invalid server' });
|
||||||
return fail(400, { error: 'Invalid server' });
|
|
||||||
|
|
||||||
if(locals.user!.servers.some(z => z.id == server[0].id))
|
if (locals.user!.servers.some((z) => z.id == server[0].id))
|
||||||
return fail(400, { error: 'Already in server' });
|
return fail(400, { error: 'Already in server' });
|
||||||
|
|
||||||
await db.transaction(async (tx) => {
|
await db.transaction(async (tx) => {
|
||||||
await tx.update(table.user)
|
await tx
|
||||||
.set({servers: locals.user!.servers.map(z => z.id).concat([server[0].id])})
|
.update(table.user)
|
||||||
|
.set({ servers: locals.user!.servers.map((z) => z.id).concat([server[0].id]) })
|
||||||
.where(eq(table.user.id, locals.user!.id));
|
.where(eq(table.user.id, locals.user!.id));
|
||||||
|
|
||||||
await tx.update(table.server)
|
await tx
|
||||||
|
.update(table.server)
|
||||||
.set({ members: (server[0].members as string[]).concat([locals.user!.id]) })
|
.set({ members: (server[0].members as string[]).concat([locals.user!.id]) })
|
||||||
.where(eq(table.server.id, server[0].id));
|
.where(eq(table.server.id, server[0].id));
|
||||||
})
|
});
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
},
|
},
|
||||||
|
|
@ -165,11 +193,13 @@ export const actions = {
|
||||||
}
|
}
|
||||||
const serverId = ServerID.newV4();
|
const serverId = ServerID.newV4();
|
||||||
|
|
||||||
await db.insert(table.server)
|
await db
|
||||||
|
.insert(table.server)
|
||||||
.values({ id: serverId, name, owner: locals.user!.id, members: [locals.user!.id] });
|
.values({ id: serverId, name, owner: locals.user!.id, members: [locals.user!.id] });
|
||||||
|
|
||||||
await db.update(table.user)
|
await db
|
||||||
.set({servers: locals.user!.servers.map(z => z.id).concat([serverId])})
|
.update(table.user)
|
||||||
|
.set({ servers: locals.user!.servers.map((z) => z.id).concat([serverId]) })
|
||||||
.where(eq(table.user.id, locals.user!.id));
|
.where(eq(table.user.id, locals.user!.id));
|
||||||
|
|
||||||
redirect(303, `/app`);
|
redirect(303, `/app`);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Status, type OverviewData,
|
import {
|
||||||
GroupID, UserID, ServerID,
|
Status,
|
||||||
type GroupId, type ServerId, type UserId,
|
type OverviewData,
|
||||||
type OverviewUser, type OverviewGroup, type OverviewServer,
|
GroupID,
|
||||||
type UserWithStatus} from "$lib";
|
UserID,
|
||||||
|
ServerID,
|
||||||
|
type GroupId,
|
||||||
|
type ServerId,
|
||||||
|
type UserId,
|
||||||
|
type OverviewUser,
|
||||||
|
type OverviewGroup,
|
||||||
|
type OverviewServer,
|
||||||
|
type UserWithStatus
|
||||||
|
} from '$lib';
|
||||||
import type { PageServerData } from './$types';
|
import type { PageServerData } from './$types';
|
||||||
import AppSidebar from "$lib/components/app-sidebar.svelte";
|
import AppSidebar from '$lib/components/app-sidebar.svelte';
|
||||||
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
|
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
|
||||||
import * as AlertDialog from "$lib/components/ui/alert-dialog/index.js";
|
import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
|
||||||
import { onMount } from "svelte";
|
import { onMount } from 'svelte';
|
||||||
import type { ActionData } from './$types';
|
import type { ActionData } from './$types';
|
||||||
let errorOpen = $state(true);
|
let errorOpen = $state(true);
|
||||||
let { form, data }: { form: ActionData, data: PageServerData } = $props();
|
let { form, data }: { form: ActionData; data: PageServerData } = $props();
|
||||||
let currentPageID: (UserId | GroupId | ServerId) | null = $state(null);
|
let currentPageID: (UserId | GroupId | ServerId) | null = $state(null);
|
||||||
let currentPage: OverviewUser | OverviewGroup | OverviewServer | undefined = $state();
|
let currentPage: OverviewUser | OverviewGroup | OverviewServer | undefined = $state();
|
||||||
|
|
||||||
|
|
@ -21,16 +30,14 @@
|
||||||
servers: []
|
servers: []
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(form, data, overview_data)
|
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (currentPageID) {
|
if (currentPageID) {
|
||||||
if (UserID.is(currentPageID)) {
|
if (UserID.is(currentPageID)) {
|
||||||
currentPage = overview_data.friends.find(friend => friend.id === currentPageID);
|
currentPage = overview_data.friends.find((friend) => friend.id === currentPageID);
|
||||||
} else if (GroupID.is(currentPageID)) {
|
} else if (GroupID.is(currentPageID)) {
|
||||||
currentPage = overview_data.groups.find(group => group.id === currentPageID);
|
currentPage = overview_data.groups.find((group) => group.id === currentPageID);
|
||||||
} else if (ServerID.is(currentPageID)) {
|
} else if (ServerID.is(currentPageID)) {
|
||||||
currentPage = overview_data.servers.find(server => server.id === currentPageID);
|
currentPage = overview_data.servers.find((server) => server.id === currentPageID);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentPage = undefined;
|
currentPage = undefined;
|
||||||
|
|
@ -39,23 +46,23 @@
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
async function run() {
|
async function run() {
|
||||||
overview_data.servers = data.user.servers.map(z => {
|
overview_data.servers = data.user.servers.map((z) => {
|
||||||
return {
|
return {
|
||||||
id: ServerID.parse(z.id),
|
id: ServerID.parse(z.id),
|
||||||
name: z.name,
|
name: z.name,
|
||||||
ownerId: z.ownerId,
|
ownerId: z.ownerId,
|
||||||
image: "https://api.dicebear.com/7.x/pixel-art/svg?seed=" + z.name,
|
image: 'https://api.dicebear.com/7.x/pixel-art/svg?seed=' + z.name
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
overview_data.groups = data.user.groups.map(z => {
|
overview_data.groups = data.user.groups.map((z) => {
|
||||||
return {
|
return {
|
||||||
id: GroupID.parse(z.id),
|
id: GroupID.parse(z.id),
|
||||||
name: z.name,
|
name: z.name,
|
||||||
ownerId: z.ownerId,
|
ownerId: z.ownerId,
|
||||||
members: z.members,
|
members: z.members,
|
||||||
image: "https://api.dicebear.com/7.x/pixel-art/svg?seed=" + z.name,
|
image: 'https://api.dicebear.com/7.x/pixel-art/svg?seed=' + z.name
|
||||||
};
|
};
|
||||||
})
|
});
|
||||||
overview_data.friends = await Promise.all(
|
overview_data.friends = await Promise.all(
|
||||||
data.user.friends.map(async (friend) => {
|
data.user.friends.map(async (friend) => {
|
||||||
const res = await fetch(`/api/status/${friend.id}`);
|
const res = await fetch(`/api/status/${friend.id}`);
|
||||||
|
|
@ -70,8 +77,8 @@
|
||||||
id: UserID.parse(friend.id),
|
id: UserID.parse(friend.id),
|
||||||
username: friend.username,
|
username: friend.username,
|
||||||
status: status.status,
|
status: status.status,
|
||||||
customStatus: status.customStatus,
|
statusMessage: status.statusMessage,
|
||||||
image: "https://api.dicebear.com/7.x/pixel-art/svg?seed=" + friend.username
|
image: 'https://api.dicebear.com/7.x/pixel-art/svg?seed=' + friend.username
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -80,15 +87,35 @@
|
||||||
run();
|
run();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const sse = new EventSource('/api/updates');
|
||||||
|
|
||||||
|
sse.addEventListener('message', (e) => {
|
||||||
|
const json = JSON.parse(e.data) as
|
||||||
|
| { type: 'connected' }
|
||||||
|
| { type: 'status'; id: string; status: 1 | 2 | 3 };
|
||||||
|
|
||||||
|
if (json.type == 'connected') {
|
||||||
|
console.log('SSE connected.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.type == 'status') {
|
||||||
|
const friend = overview_data.friends.find((z) => z.id == json.id);
|
||||||
|
if (friend) {
|
||||||
|
friend.status = json.status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if form}
|
{#if form}
|
||||||
<AlertDialog.Root bind:open={errorOpen}>
|
<AlertDialog.Root bind:open={errorOpen}>
|
||||||
<AlertDialog.Content>
|
<AlertDialog.Content>
|
||||||
<AlertDialog.Header>
|
<AlertDialog.Header>
|
||||||
<AlertDialog.Title>{form?.error ? "Ran into an error." : "Success!"}</AlertDialog.Title>
|
<AlertDialog.Title>{form?.error ? 'Ran into an error.' : 'Success!'}</AlertDialog.Title>
|
||||||
<AlertDialog.Description>
|
<AlertDialog.Description>
|
||||||
{form?.error || "Action completed succesfully."}
|
{form?.error || 'Action completed succesfully.'}
|
||||||
</AlertDialog.Description>
|
</AlertDialog.Description>
|
||||||
</AlertDialog.Header>
|
</AlertDialog.Header>
|
||||||
<AlertDialog.Footer>
|
<AlertDialog.Footer>
|
||||||
|
|
@ -98,7 +125,6 @@
|
||||||
</AlertDialog.Root>
|
</AlertDialog.Root>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
<Sidebar.Provider>
|
<Sidebar.Provider>
|
||||||
<AppSidebar bind:currentPage={currentPageID} user={data.user} data={overview_data} />
|
<AppSidebar bind:currentPage={currentPageID} user={data.user} data={overview_data} />
|
||||||
|
|
||||||
|
|
@ -107,21 +133,29 @@
|
||||||
<Sidebar.Trigger class="-ms-1" />
|
<Sidebar.Trigger class="-ms-1" />
|
||||||
{#if currentPageID && currentPage}
|
{#if currentPageID && currentPage}
|
||||||
{#if ServerID.is(currentPageID)}
|
{#if ServerID.is(currentPageID)}
|
||||||
{@const server = (currentPage as OverviewServer)}
|
{@const server = currentPage as OverviewServer}
|
||||||
|
|
||||||
<img src={server!.image} alt={server!.name} class="size-6 rounded-full" />
|
<img src={server!.image} alt={server!.name} class="size-6 rounded-full" />
|
||||||
|
|
||||||
<h1>{server!.name}</h1>
|
<h1>{server!.name}</h1>
|
||||||
{:else if UserID.is(currentPageID)}
|
{:else if UserID.is(currentPageID)}
|
||||||
{@const friend = (currentPage as UserWithStatus)}
|
{@const friend = currentPage as UserWithStatus}
|
||||||
|
|
||||||
<img src={friend.image} alt={friend!.username} class="size-6 rounded-full" />
|
<img src={friend.image} alt={friend!.username} class="size-6 rounded-full" />
|
||||||
|
|
||||||
<h1>{friend!.username} [{friend.status == Status.ONLINE ? "Online!" : friend.status == Status.DND ? "DND" : friend.status == Status.OFFLINE ? "Offline" : "Unknown"}]</h1>
|
<h1>
|
||||||
|
{friend!.username} [{friend.status == Status.ONLINE
|
||||||
|
? 'Online!'
|
||||||
|
: friend.status == Status.DND
|
||||||
|
? 'DND'
|
||||||
|
: friend.status == Status.OFFLINE
|
||||||
|
? 'Offline'
|
||||||
|
: 'Unknown'}]
|
||||||
|
</h1>
|
||||||
{:else if GroupID.is(currentPageID)}
|
{:else if GroupID.is(currentPageID)}
|
||||||
{@const group = (currentPage as OverviewGroup)}
|
{@const group = currentPage as OverviewGroup}
|
||||||
|
|
||||||
<h1>{group!.name} ({group.members} member{group.members > 1 ? "s" : ""})</h1>
|
<h1>{group!.name} ({group.members} member{group.members > 1 ? 's' : ''})</h1>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</header>
|
</header>
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,12 @@ export const actions: Actions = {
|
||||||
return fail(400, { message: 'Invalid password (min 6, max 255 characters)' });
|
return fail(400, { message: 'Invalid password (min 6, max 255 characters)' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await db.select()
|
const results = await db
|
||||||
|
.select()
|
||||||
.from(table.user)
|
.from(table.user)
|
||||||
.where(username_is_email ? eq(table.user.email, username) : eq(table.user.username, username));
|
.where(
|
||||||
|
username_is_email ? eq(table.user.email, username) : eq(table.user.username, username)
|
||||||
|
);
|
||||||
|
|
||||||
const existingUser = results.at(0);
|
const existingUser = results.at(0);
|
||||||
if (!existingUser) {
|
if (!existingUser) {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Title from "$lib/components/extra/Title.svelte";
|
import Title from '$lib/components/extra/Title.svelte';
|
||||||
import Button from "$lib/components/ui/button/button.svelte";
|
import Button from '$lib/components/ui/button/button.svelte';
|
||||||
import Input from "$lib/components/ui/input/input.svelte";
|
import Input from '$lib/components/ui/input/input.svelte';
|
||||||
import type { ActionData } from './$types';
|
import type { ActionData } from './$types';
|
||||||
|
|
||||||
let { form }: { form: ActionData } = $props();
|
let { form }: { form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex min-h-screen flex-col items-center justify-center gap-2">
|
<div class="flex min-h-screen flex-col items-center justify-center gap-2">
|
||||||
<div class='w-1/2 p-2 bg-secondary rounded-md '>
|
<div class="w-1/2 rounded-md bg-secondary p-2">
|
||||||
<div class="text-center pb-2">
|
<div class="pb-2 text-center">
|
||||||
<Title class="text-2xl"></Title>
|
<Title class="text-2xl"></Title>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="?/login">
|
<form method="post" action="?/login">
|
||||||
|
|
@ -20,7 +20,5 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p style="color: red">{form?.message ?? ''}</p>
|
<p style="color: red">{form?.message ?? ''}</p>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ export const actions: Actions = {
|
||||||
outputLen: 32,
|
outputLen: 32,
|
||||||
parallelism: 1
|
parallelism: 1
|
||||||
});
|
});
|
||||||
const results = await db.select()
|
const results = await db
|
||||||
|
.select()
|
||||||
.from(table.user)
|
.from(table.user)
|
||||||
.where(or(eq(table.user.email, email),
|
.where(or(eq(table.user.email, email), eq(table.user.username, username)));
|
||||||
eq(table.user.username, username)));
|
|
||||||
|
|
||||||
const existingUser = results.at(0);
|
const existingUser = results.at(0);
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
|
|
@ -53,8 +53,7 @@ export const actions: Actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.insert(table.user)
|
await db.insert(table.user).values({ id: userId, email, username, passwordHash });
|
||||||
.values({ id: userId, email, username, passwordHash });
|
|
||||||
|
|
||||||
const sessionToken = auth.generateSessionToken();
|
const sessionToken = auth.generateSessionToken();
|
||||||
const session = await auth.createSession(sessionToken, userId);
|
const session = await auth.createSession(sessionToken, userId);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Title from "$lib/components/extra/Title.svelte";
|
import Title from '$lib/components/extra/Title.svelte';
|
||||||
import Button from "$lib/components/ui/button/button.svelte";
|
import Button from '$lib/components/ui/button/button.svelte';
|
||||||
import Input from "$lib/components/ui/input/input.svelte";
|
import Input from '$lib/components/ui/input/input.svelte';
|
||||||
import type { ActionData } from './$types';
|
import type { ActionData } from './$types';
|
||||||
|
|
||||||
let { form }: { form: ActionData } = $props();
|
let { form }: { form: ActionData } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex min-h-screen flex-col items-center justify-center gap-2">
|
<div class="flex min-h-screen flex-col items-center justify-center gap-2">
|
||||||
<div class='w-1/2 p-2 bg-secondary rounded-md '>
|
<div class="w-1/2 rounded-md bg-secondary p-2">
|
||||||
<div class="text-center pb-2">
|
<div class="pb-2 text-center">
|
||||||
<Title class="text-2xl"></Title>
|
<Title class="text-2xl"></Title>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="?/register">
|
<form method="post" action="?/register">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue