Compare commits
No commits in common. "dev" and "main" have entirely different histories.
64
bun.lock
64
bun.lock
|
|
@ -3,19 +3,15 @@
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "todo",
|
"name": "todo",
|
||||||
"dependencies": {
|
|
||||||
"@prisma/client": "^6.18.0",
|
|
||||||
"@types/bun": "^1.3.1",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^6.1.1",
|
"@sveltejs/adapter-auto": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.47.3",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||||
"prisma": "^6.18.0",
|
"prisma": "^6.16.1",
|
||||||
"svelte": "^5.41.4",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.3.3",
|
"svelte-check": "^4.0.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^7.1.12",
|
"vite": "^7.0.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -84,19 +80,17 @@
|
||||||
|
|
||||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||||
|
|
||||||
"@prisma/client": ["@prisma/client@6.18.0", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-jnL2I9gDnPnw4A+4h5SuNn8Gc+1mL1Z79U/3I9eE2gbxJG1oSA+62ByPW4xkeDgwE0fqMzzpAZ7IHxYnLZ4iQA=="],
|
"@prisma/config": ["@prisma/config@6.16.1", "", { "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", "effect": "3.16.12", "empathic": "2.0.0" } }, "sha512-sz3uxRPNL62QrJ0EYiujCFkIGZ3hg+9hgC1Ae1HjoYuj0BxCqHua4JNijYvYCrh9LlofZDZcRBX3tHBfLvAngA=="],
|
||||||
|
|
||||||
"@prisma/config": ["@prisma/config@6.18.0", "", { "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", "effect": "3.18.4", "empathic": "2.0.0" } }, "sha512-rgFzspCpwsE+q3OF/xkp0fI2SJ3PfNe9LLMmuSVbAZ4nN66WfBiKqJKo/hLz3ysxiPQZf8h1SMf2ilqPMeWATQ=="],
|
"@prisma/debug": ["@prisma/debug@6.16.1", "", {}, "sha512-RWv/VisW5vJE4cDRTuAHeVedtGoItXTnhuLHsSlJ9202QKz60uiXWywBlVcqXVq8bFeIZoCoWH+R1duZJPwqLw=="],
|
||||||
|
|
||||||
"@prisma/debug": ["@prisma/debug@6.18.0", "", {}, "sha512-PMVPMmxPj0ps1VY75DIrT430MoOyQx9hmm174k6cmLZpcI95rAPXOQ+pp8ANQkJtNyLVDxnxVJ0QLbrm/ViBcg=="],
|
"@prisma/engines": ["@prisma/engines@6.16.1", "", { "dependencies": { "@prisma/debug": "6.16.1", "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "@prisma/fetch-engine": "6.16.1", "@prisma/get-platform": "6.16.1" } }, "sha512-EOnEM5HlosPudBqbI+jipmaW/vQEaF0bKBo4gVkGabasINHR6RpC6h44fKZEqx4GD8CvH+einD2+b49DQrwrAg=="],
|
||||||
|
|
||||||
"@prisma/engines": ["@prisma/engines@6.18.0", "", { "dependencies": { "@prisma/debug": "6.18.0", "@prisma/engines-version": "6.18.0-8.34b5a692b7bd79939a9a2c3ef97d816e749cda2f", "@prisma/fetch-engine": "6.18.0", "@prisma/get-platform": "6.18.0" } }, "sha512-i5RzjGF/ex6AFgqEe2o1IW8iIxJGYVQJVRau13kHPYEL1Ck8Zvwuzamqed/1iIljs5C7L+Opiz5TzSsUebkriA=="],
|
"@prisma/engines-version": ["@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "", {}, "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA=="],
|
||||||
|
|
||||||
"@prisma/engines-version": ["@prisma/engines-version@6.18.0-8.34b5a692b7bd79939a9a2c3ef97d816e749cda2f", "", {}, "sha512-T7Af4QsJQnSgWN1zBbX+Cha5t4qjHRxoeoWpK4JugJzG/ipmmDMY5S+O0N1ET6sCBNVkf6lz+Y+ZNO9+wFU8pQ=="],
|
"@prisma/fetch-engine": ["@prisma/fetch-engine@6.16.1", "", { "dependencies": { "@prisma/debug": "6.16.1", "@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43", "@prisma/get-platform": "6.16.1" } }, "sha512-fl/PKQ8da5YTayw86WD3O9OmKJEM43gD3vANy2hS5S1CnfW2oPXk+Q03+gUWqcKK306QqhjjIHRFuTZ31WaosQ=="],
|
||||||
|
|
||||||
"@prisma/fetch-engine": ["@prisma/fetch-engine@6.18.0", "", { "dependencies": { "@prisma/debug": "6.18.0", "@prisma/engines-version": "6.18.0-8.34b5a692b7bd79939a9a2c3ef97d816e749cda2f", "@prisma/get-platform": "6.18.0" } }, "sha512-TdaBvTtBwP3IoqVYoGIYpD4mWlk0pJpjTJjir/xLeNWlwog7Sl3bD2J0jJ8+5+q/6RBg+acb9drsv5W6lqae7A=="],
|
"@prisma/get-platform": ["@prisma/get-platform@6.16.1", "", { "dependencies": { "@prisma/debug": "6.16.1" } }, "sha512-kUfg4vagBG7dnaGRcGd1c0ytQFcDj2SUABiuveIpL3bthFdTLI6PJeLEia6Q8Dgh+WhPdo0N2q0Fzjk63XTyaA=="],
|
||||||
|
|
||||||
"@prisma/get-platform": ["@prisma/get-platform@6.18.0", "", { "dependencies": { "@prisma/debug": "6.18.0" } }, "sha512-uXNJCJGhxTCXo2B25Ta91Rk1/Nmlqg9p7G9GKh8TPhxvAyXCvMNQoogj4JLEUy+3ku8g59cpyQIKFhqY2xO2bg=="],
|
|
||||||
|
|
||||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="],
|
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.1", "", { "os": "android", "cpu": "arm" }, "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag=="],
|
||||||
|
|
||||||
|
|
@ -144,32 +138,24 @@
|
||||||
|
|
||||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="],
|
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="],
|
||||||
|
|
||||||
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@6.1.1", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-cBNt4jgH4KuaNO5gRSB2CZKkGtz+OCZ8lPjRQGjhvVUD4akotnj2weUia6imLl2v07K3IgsQRyM36909miSwoQ=="],
|
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@6.1.0", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-shOuLI5D2s+0zTv2ab5M5PqfknXqWbKi+0UwB9yLTRIdzsK1R93JOO8jNhIYSHdW+IYXIYnLniu+JZqXs7h9Wg=="],
|
||||||
|
|
||||||
"@sveltejs/kit": ["@sveltejs/kit@2.47.3", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-zN2yzBc2dIES2BSzLhNP2weYhwB77kgM/oAktICZVmmljyEmPZrlUwr14jjdK9/eDu7WdAuf6gTdYIJLTcN3Fw=="],
|
"@sveltejs/kit": ["@sveltejs/kit@2.39.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-8yZpfCfv9FQfJUBxtD8XMS+T/+ls5xdPZvMwKg4qNS9fmzfWsah3Dz8IR5cmbXtCzHkgr0j/+v6zq5Fk4IuTBA=="],
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="],
|
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.0", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-nJsV36+o7rZUDlrnSduMNl11+RoDE1cKqOI0yUEBCcqFoAZOk47TwD3dPKS2WmRutke9StXnzsPBslY7prDM9w=="],
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="],
|
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
|
|
||||||
|
|
||||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.5.0", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-y1dMvuvJspJiPSDZUQ+WMBvF7dpnEqN4x9DDC9ie5Fs/HUZJA3wFp7EhHoVaKX/iI0cRoECV8X2jL8zi0xrHCg=="],
|
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="],
|
|
||||||
|
|
||||||
"acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
"acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||||
|
|
||||||
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
|
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
|
||||||
|
|
||||||
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
|
|
||||||
|
|
||||||
"c12": ["c12@3.1.0", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="],
|
"c12": ["c12@3.1.0", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^16.6.1", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.4.2", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^1.0.0", "pkg-types": "^2.2.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw=="],
|
||||||
|
|
||||||
"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=="],
|
||||||
|
|
@ -184,8 +170,6 @@
|
||||||
|
|
||||||
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
|
||||||
|
|
||||||
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
"debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
|
||||||
|
|
||||||
"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=="],
|
||||||
|
|
@ -200,7 +184,7 @@
|
||||||
|
|
||||||
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
||||||
|
|
||||||
"effect": ["effect@3.18.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA=="],
|
"effect": ["effect@3.16.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg=="],
|
||||||
|
|
||||||
"empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="],
|
"empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="],
|
||||||
|
|
||||||
|
|
@ -256,7 +240,7 @@
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||||
|
|
||||||
"prisma": ["prisma@6.18.0", "", { "dependencies": { "@prisma/config": "6.18.0", "@prisma/engines": "6.18.0" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-bXWy3vTk8mnRmT+SLyZBQoC2vtV9Z8u7OHvEu+aULYxwiop/CPiFZ+F56KsNRNf35jw+8wcu8pmLsjxpBxAO9g=="],
|
"prisma": ["prisma@6.16.1", "", { "dependencies": { "@prisma/config": "6.16.1", "@prisma/engines": "6.16.1" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-MFkMU0eaDDKAT4R/By2IA9oQmwLTxokqv2wegAErr9Rf+oIe7W2sYpE/Uxq0H2DliIR7vnV63PkC1bEwUtl98w=="],
|
||||||
|
|
||||||
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
||||||
|
|
||||||
|
|
@ -274,9 +258,9 @@
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
"svelte": ["svelte@5.41.4", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-sBrVmskY0eij5+CSSuMK1kOk1xSiRh0BRTEhUnxnd1x3p42GbQmm4rwq4WMD23rUG3QR53Nfv8kpaER3tV5F4A=="],
|
"svelte": ["svelte@5.38.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-UY+OhrWK7WI22bCZ00P/M3HtyWgwJPi9IxSRkoAE2MeAy6kl7ZlZWJZ8RaB+X4KD/G+wjis+cGVnVYaoqbzBqg=="],
|
||||||
|
|
||||||
"svelte-check": ["svelte-check@4.3.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg=="],
|
"svelte-check": ["svelte-check@4.3.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": "bin/svelte-check" }, "sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg=="],
|
||||||
|
|
||||||
"tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
|
"tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="],
|
||||||
|
|
||||||
|
|
@ -284,11 +268,9 @@
|
||||||
|
|
||||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
"vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="],
|
||||||
|
|
||||||
"vite": ["vite@7.1.12", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug=="],
|
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" } }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,10 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "todo",
|
"name": "todo",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
|
||||||
"@prisma/client": "^6.16.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^6.0.0",
|
"@sveltejs/adapter-auto": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.22.0",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||||
"prisma": "^6.16.1",
|
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
|
|
@ -520,91 +516,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-QaBCOY29lLAxEFFJgBPyW3WInCW52fJeQTmWx/h6YsP5u0bwuqP51aP0uhqFvhK9DaZPwvai/M4tSDYLVE9vRg==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18.18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"prisma": "*",
|
|
||||||
"typescript": ">=5.1.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"prisma": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/config": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-sz3uxRPNL62QrJ0EYiujCFkIGZ3hg+9hgC1Ae1HjoYuj0BxCqHua4JNijYvYCrh9LlofZDZcRBX3tHBfLvAngA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"c12": "3.1.0",
|
|
||||||
"deepmerge-ts": "7.1.5",
|
|
||||||
"effect": "3.16.12",
|
|
||||||
"empathic": "2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/debug": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-RWv/VisW5vJE4cDRTuAHeVedtGoItXTnhuLHsSlJ9202QKz60uiXWywBlVcqXVq8bFeIZoCoWH+R1duZJPwqLw==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/engines": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-EOnEM5HlosPudBqbI+jipmaW/vQEaF0bKBo4gVkGabasINHR6RpC6h44fKZEqx4GD8CvH+einD2+b49DQrwrAg==",
|
|
||||||
"devOptional": true,
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@prisma/debug": "6.16.1",
|
|
||||||
"@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
|
||||||
"@prisma/fetch-engine": "6.16.1",
|
|
||||||
"@prisma/get-platform": "6.16.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/engines-version": {
|
|
||||||
"version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz",
|
|
||||||
"integrity": "sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/fetch-engine": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-fl/PKQ8da5YTayw86WD3O9OmKJEM43gD3vANy2hS5S1CnfW2oPXk+Q03+gUWqcKK306QqhjjIHRFuTZ31WaosQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@prisma/debug": "6.16.1",
|
|
||||||
"@prisma/engines-version": "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43",
|
|
||||||
"@prisma/get-platform": "6.16.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@prisma/get-platform": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-kUfg4vagBG7dnaGRcGd1c0ytQFcDj2SUABiuveIpL3bthFdTLI6PJeLEia6Q8Dgh+WhPdo0N2q0Fzjk63XTyaA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@prisma/debug": "6.16.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.50.1",
|
"version": "4.50.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz",
|
||||||
|
|
@ -903,7 +814,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
|
||||||
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
|
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@sveltejs/acorn-typescript": {
|
"node_modules/@sveltejs/acorn-typescript": {
|
||||||
|
|
@ -1051,40 +962,11 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c12": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"chokidar": "^4.0.3",
|
|
||||||
"confbox": "^0.2.2",
|
|
||||||
"defu": "^6.1.4",
|
|
||||||
"dotenv": "^16.6.1",
|
|
||||||
"exsolve": "^1.0.7",
|
|
||||||
"giget": "^2.0.0",
|
|
||||||
"jiti": "^2.4.2",
|
|
||||||
"ohash": "^2.0.11",
|
|
||||||
"pathe": "^2.0.3",
|
|
||||||
"perfect-debounce": "^1.0.0",
|
|
||||||
"pkg-types": "^2.2.0",
|
|
||||||
"rc9": "^2.1.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"magicast": "^0.3.5"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"magicast": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"readdirp": "^4.0.1"
|
"readdirp": "^4.0.1"
|
||||||
|
|
@ -1096,16 +978,6 @@
|
||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/citty": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
|
|
||||||
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"consola": "^3.2.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/clsx": {
|
"node_modules/clsx": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
|
|
@ -1116,23 +988,6 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/confbox": {
|
|
||||||
"version": "0.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
|
|
||||||
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/consola": {
|
|
||||||
"version": "3.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
|
|
||||||
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "^14.18.0 || >=16.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/cookie": {
|
"node_modules/cookie": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
|
|
@ -1171,30 +1026,6 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/deepmerge-ts": {
|
|
||||||
"version": "7.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz",
|
|
||||||
"integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/defu": {
|
|
||||||
"version": "6.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
|
||||||
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/destr": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/devalue": {
|
"node_modules/devalue": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz",
|
||||||
|
|
@ -1202,40 +1033,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
|
||||||
"version": "16.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
|
||||||
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://dotenvx.com"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/effect": {
|
|
||||||
"version": "3.16.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz",
|
|
||||||
"integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@standard-schema/spec": "^1.0.0",
|
|
||||||
"fast-check": "^3.23.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/empathic": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
||||||
|
|
@ -1295,36 +1092,6 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/exsolve": {
|
|
||||||
"version": "1.0.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
|
|
||||||
"integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/fast-check": {
|
|
||||||
"version": "3.23.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz",
|
|
||||||
"integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==",
|
|
||||||
"devOptional": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/dubzzz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/fast-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"pure-rand": "^6.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fdir": {
|
"node_modules/fdir": {
|
||||||
"version": "6.5.0",
|
"version": "6.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
|
||||||
|
|
@ -1358,24 +1125,6 @@
|
||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/giget": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"citty": "^0.1.6",
|
|
||||||
"consola": "^3.4.0",
|
|
||||||
"defu": "^6.1.4",
|
|
||||||
"node-fetch-native": "^1.6.6",
|
|
||||||
"nypm": "^0.6.0",
|
|
||||||
"pathe": "^2.0.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"giget": "dist/cli.mjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-reference": {
|
"node_modules/is-reference": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
||||||
|
|
@ -1386,16 +1135,6 @@
|
||||||
"@types/estree": "^1.0.6"
|
"@types/estree": "^1.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jiti": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"jiti": "lib/jiti-cli.mjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -1469,54 +1208,6 @@
|
||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-fetch-native": {
|
|
||||||
"version": "1.6.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
|
|
||||||
"integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/nypm": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz",
|
|
||||||
"integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"citty": "^0.1.6",
|
|
||||||
"consola": "^3.4.2",
|
|
||||||
"pathe": "^2.0.3",
|
|
||||||
"pkg-types": "^2.3.0",
|
|
||||||
"tinyexec": "^1.0.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"nypm": "dist/cli.mjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^14.16.0 || >=16.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ohash": {
|
|
||||||
"version": "2.0.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
|
||||||
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/pathe": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/perfect-debounce": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
|
|
@ -1537,18 +1228,6 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pkg-types": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"confbox": "^0.2.2",
|
|
||||||
"exsolve": "^1.0.7",
|
|
||||||
"pathe": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
|
|
@ -1578,65 +1257,11 @@
|
||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
|
||||||
"version": "6.16.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.1.tgz",
|
|
||||||
"integrity": "sha512-MFkMU0eaDDKAT4R/By2IA9oQmwLTxokqv2wegAErr9Rf+oIe7W2sYpE/Uxq0H2DliIR7vnV63PkC1bEwUtl98w==",
|
|
||||||
"devOptional": true,
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@prisma/config": "6.16.1",
|
|
||||||
"@prisma/engines": "6.16.1"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"prisma": "build/index.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18.18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": ">=5.1.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"typescript": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pure-rand": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
|
|
||||||
"devOptional": true,
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/dubzzz"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/fast-check"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/rc9": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"defu": "^6.1.4",
|
|
||||||
"destr": "^2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14.18.0"
|
"node": ">= 14.18.0"
|
||||||
|
|
@ -1782,13 +1407,6 @@
|
||||||
"typescript": ">=5.0.0"
|
"typescript": ">=5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tinyexec": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
|
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
|
@ -1820,7 +1438,7 @@
|
||||||
"version": "5.9.2",
|
"version": "5.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
|
||||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
|
|
|
||||||
22
package.json
22
package.json
|
|
@ -2,14 +2,14 @@
|
||||||
"name": "todo",
|
"name": "todo",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/adapter-auto": "^6.1.1",
|
"@sveltejs/adapter-auto": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.47.3",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||||
"prisma": "^6.18.0",
|
"prisma": "^6.16.1",
|
||||||
"svelte": "^5.41.4",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.3.3",
|
"svelte-check": "^4.0.0",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^7.1.12"
|
"vite": "^7.0.4"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
@ -20,9 +20,5 @@
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module"
|
||||||
"dependencies": {
|
|
||||||
"@prisma/client": "^6.18.0",
|
|
||||||
"@types/bun": "^1.3.1"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "public"."User" (
|
|
||||||
"id" SERIAL NOT NULL,
|
|
||||||
"display_name" TEXT NOT NULL,
|
|
||||||
"email" TEXT NOT NULL,
|
|
||||||
"password_hash" TEXT NOT NULL,
|
|
||||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "public"."Task" (
|
|
||||||
"id" SERIAL NOT NULL,
|
|
||||||
"userId" INTEGER NOT NULL,
|
|
||||||
"checked" BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
"checked_at" TIMESTAMP(3),
|
|
||||||
"content" TEXT NOT NULL,
|
|
||||||
"parentId" INTEGER,
|
|
||||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "Task_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email");
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "public"."Task" ADD CONSTRAINT "Task_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "public"."Task" ADD CONSTRAINT "Task_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Task"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `content` on the `Task` table. All the data in the column will be lost.
|
|
||||||
- Added the required column `topic` to the `Task` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE "public"."Task" RENAME COLUMN "content" TO "topic";
|
|
||||||
ALTER TABLE "public"."Task" ADD COLUMN "description" TEXT;
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
# Please do not edit this file manually
|
|
||||||
# It should be added in your version-control system (e.g., Git)
|
|
||||||
provider = "postgresql"
|
|
||||||
|
|
@ -1,37 +1,15 @@
|
||||||
|
// This is your Prisma schema file,
|
||||||
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||||
|
|
||||||
|
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||||
|
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||||
|
|
||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
output = "../node_modules/.prisma/client"
|
output = "../.generated.prisma"
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
provider = "postgresql"
|
provider = "postgresql"
|
||||||
url = env("DATABASE_URL")
|
url = env("DATABASE_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
|
||||||
id Int @id @default(autoincrement())
|
|
||||||
display_name String
|
|
||||||
email String @unique
|
|
||||||
password_hash String
|
|
||||||
tasks Task[]
|
|
||||||
created_at DateTime @default(now())
|
|
||||||
updated_at DateTime @updatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
model Task {
|
|
||||||
id Int @id @default(autoincrement())
|
|
||||||
userId Int
|
|
||||||
user User @relation(fields: [userId], references: [id])
|
|
||||||
|
|
||||||
checked Boolean @default(false)
|
|
||||||
checked_at DateTime?
|
|
||||||
topic String
|
|
||||||
description String?
|
|
||||||
|
|
||||||
parentId Int?
|
|
||||||
parent Task? @relation("Subtasks", fields: [parentId], references: [id])
|
|
||||||
subtasks Task[] @relation("Subtasks")
|
|
||||||
|
|
||||||
created_at DateTime @default(now())
|
|
||||||
updated_at DateTime @updatedAt
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,8 @@
|
||||||
// for information about these interfaces
|
// for information about these interfaces
|
||||||
declare global {
|
declare global {
|
||||||
namespace App {
|
namespace App {
|
||||||
interface Error {
|
// interface Error {}
|
||||||
message: string
|
// interface Locals {}
|
||||||
cause?: number,
|
|
||||||
}
|
|
||||||
interface Locals {
|
|
||||||
user?: User
|
|
||||||
}
|
|
||||||
// interface PageData {}
|
// interface PageData {}
|
||||||
// interface PageState {}
|
// interface PageState {}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
|
||||||
<link rel="stylesheet" href="%sveltekit.assets%/global.css" />
|
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
</head>
|
</head>
|
||||||
<body data-sveltekit-preload-data="hover">
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
import type { Handle } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import { error, redirect, json, fail } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import { Error401Cause } from "$lib/errors"
|
|
||||||
|
|
||||||
import Config from "$lib/server/config"
|
|
||||||
import UserMgmt from "$lib/server/usermgmt"
|
|
||||||
|
|
||||||
function action_fail<T = undefined>(status: number, data: T) {
|
|
||||||
return json(fail(status, data))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const handle: Handle = async ({ event, resolve }) => {
|
|
||||||
|
|
||||||
const token = event.cookies.get("session")
|
|
||||||
let session = await UserMgmt.session_login(token ?? "")
|
|
||||||
|
|
||||||
if (session && event.route.id !== "/api/refresh") {
|
|
||||||
if (session.expires.getTime() < Date.now() + Config.session_refresh_grace) {
|
|
||||||
|
|
||||||
const response = await event.fetch("/api/refresh", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
token: token
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const new_session = await response.json()
|
|
||||||
|
|
||||||
if (new_session && new_session.token !== null && new_session.expires !== null) {
|
|
||||||
event.cookies.set("session", new_session.token, {
|
|
||||||
expires: new Date(new_session.expires),
|
|
||||||
httpOnly: true,
|
|
||||||
secure: true,
|
|
||||||
sameSite: "strict",
|
|
||||||
path: "/"
|
|
||||||
})
|
|
||||||
// For mobile
|
|
||||||
/*event.setHeaders({
|
|
||||||
"X-Authorization-Refresh": new_session.token
|
|
||||||
})*/
|
|
||||||
|
|
||||||
session = await UserMgmt.session_login(new_session.token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.locals.user = session?.user
|
|
||||||
|
|
||||||
if (!event.route.id) {
|
|
||||||
return error(404, { message: "Diese Seite existiert nicht" })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.route.id.startsWith("/api")) {
|
|
||||||
if (event.route.id.startsWith("/api/users") && !event.locals.user) {
|
|
||||||
return error(401, { cause: Error401Cause.NotLoggedIn, message: "Please log in" })
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!event.locals.user && !event.route.id.startsWith("/login")) {
|
|
||||||
if (event.request.method === "POST") {
|
|
||||||
if (event.request.headers.get("x-sveltekit-action")) {
|
|
||||||
return action_fail(401, { cause: Error401Cause.NotLoggedIn, message: "Bitte melden Sie sich an." })
|
|
||||||
}
|
|
||||||
return error(401, { cause: Error401Cause.NotLoggedIn, message: "Bitte melden Sie sich an." })
|
|
||||||
}
|
|
||||||
return redirect(307, "/login")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await resolve(event)
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
|
@ -1,99 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
|
|
||||||
let { checked = $bindable(), ...props} = $props()
|
|
||||||
|
|
||||||
let loaded = $state(false)
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
loaded = true
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="shell" class:loaded={loaded}>
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" bind:checked/>
|
|
||||||
<svg width="10px" height="10px" viewBox="0 0 12 9">
|
|
||||||
<polyline points="1,5 4,8 11,1" fill="none"></polyline>
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateY(-50%) translateX(-50%);
|
|
||||||
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
label:hover {
|
|
||||||
border-color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
label:has(>input:checked) {
|
|
||||||
background: green;
|
|
||||||
}
|
|
||||||
.loaded label:has(>input:checked) {
|
|
||||||
animation: pop 0.6s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loaded label::before {
|
|
||||||
content: "";
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
|
|
||||||
background: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
opacity: 1;
|
|
||||||
|
|
||||||
transform: scale(0);
|
|
||||||
transition-delay: 0.2s;
|
|
||||||
}
|
|
||||||
.loaded label:has(>input:checked)::before {
|
|
||||||
transform: scale(2.2);
|
|
||||||
opacity: 0;
|
|
||||||
transition: all 0.6s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pop {
|
|
||||||
50% {
|
|
||||||
transform: translateY(-50%) translateX(-50%) scale(1.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
left: 3px;
|
|
||||||
stroke: white;
|
|
||||||
stroke-width: 1.5px;
|
|
||||||
stroke-dasharray: 16px;
|
|
||||||
stroke-dashoffset: 16px;
|
|
||||||
}
|
|
||||||
.loaded svg {
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
label:has(> input:checked) > svg {
|
|
||||||
stroke-dashoffset: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
<script module lang="ts">
|
|
||||||
import type { Task } from "@prisma/client";
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
task: Task | null
|
|
||||||
form: string
|
|
||||||
open?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
let { task, form, open = $bindable() }: Props = $props();
|
|
||||||
|
|
||||||
let submitButton: HTMLButtonElement;
|
|
||||||
let topicTextArea: HTMLTextAreaElement;
|
|
||||||
let descriptionTextArea: HTMLTextAreaElement;
|
|
||||||
|
|
||||||
function cancelOverlay() {
|
|
||||||
// add change alert
|
|
||||||
open = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<svelte:window onkeydown={(event) => {
|
|
||||||
if (event instanceof KeyboardEvent) {
|
|
||||||
if (event.key === "Escape") {
|
|
||||||
cancelOverlay()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}} />
|
|
||||||
|
|
||||||
<div class="overlay" class:open={open}>
|
|
||||||
|
|
||||||
<div class="background" role="presentation" aria-hidden="true" onclick={() => { cancelOverlay() }}></div>
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
|
|
||||||
<textarea class="topic" form={form} bind:this={topicTextArea} name="topic" placeholder="What would you like to do" rows="1">{task?.topic ?? ""}</textarea>
|
|
||||||
|
|
||||||
<textarea class="description" form={form} bind:this={descriptionTextArea} name="description" placeholder="Add a description here.">{task?.description ?? ""}</textarea>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
form={form}
|
|
||||||
bind:this={submitButton}
|
|
||||||
onclick={(event) => {
|
|
||||||
if (topicTextArea.value.length != 0) {
|
|
||||||
(event.target as HTMLButtonElement).form?.requestSubmit()
|
|
||||||
}
|
|
||||||
event.preventDefault()
|
|
||||||
}}
|
|
||||||
>Save and close</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.overlay {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.open {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(body:has(.overlay.open)) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.background {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
background-color: black;
|
|
||||||
opacity: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%) translateY(-50%);
|
|
||||||
|
|
||||||
width: 75%;
|
|
||||||
min-height: 20%;
|
|
||||||
|
|
||||||
background: darkgreen;
|
|
||||||
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-width: 100%;
|
|
||||||
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
field-sizing: content;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.topic {
|
|
||||||
font-size: 24px;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-bottom: 1px solid black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.description {
|
|
||||||
|
|
||||||
min-height: 10em;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-left: 1px solid black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
<script module>
|
|
||||||
|
|
||||||
import type { Task } from "@prisma/client"
|
|
||||||
|
|
||||||
import Checkbox from "./checkbox.svelte"
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
export interface TaskComponentProps {
|
|
||||||
task: Task
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
const { task }: TaskComponentProps = $props()
|
|
||||||
|
|
||||||
let loaded = $state(false)
|
|
||||||
onMount(() => { loaded = true })
|
|
||||||
|
|
||||||
let checked = $state(task.checked)
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="container" class:loaded={loaded}>
|
|
||||||
<div class="main-task">
|
|
||||||
<div class="checkbox">
|
|
||||||
<Checkbox bind:checked={checked}/>
|
|
||||||
</div>
|
|
||||||
<div class="taskheader">
|
|
||||||
<div><h2 class="taskheader">{task.content}</h2></div>
|
|
||||||
</div>
|
|
||||||
{#if true}
|
|
||||||
<div class="taskcontent">{@html [task.content, "<br>"].join().repeat(5)}</div>
|
|
||||||
{/if}
|
|
||||||
<div class="due">
|
|
||||||
Due: <br/>
|
|
||||||
{new Date(task.created_at).toLocaleDateString()} <br/>
|
|
||||||
{new Date(task.created_at).toLocaleTimeString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.container {
|
|
||||||
width: var(--width, 100%);
|
|
||||||
min-height: var(--min-height, 50px);
|
|
||||||
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
justify-items: center;
|
|
||||||
justify-content: stretch;
|
|
||||||
align-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-task {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 25px auto fit-content(11ch);
|
|
||||||
grid-template-areas:
|
|
||||||
'checkboxArea headerArea dueArea';
|
|
||||||
|
|
||||||
column-gap: 10px;
|
|
||||||
|
|
||||||
align-content: stretch;
|
|
||||||
}
|
|
||||||
.main-task:has(.taskcontent) {
|
|
||||||
grid-template-areas:
|
|
||||||
'checkboxArea headerArea dueArea'
|
|
||||||
'. contentArea dueArea';
|
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox {
|
|
||||||
grid-area: checkboxArea;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.taskheader {
|
|
||||||
grid-area: headerArea;
|
|
||||||
width: fit-content;
|
|
||||||
transform: translateY(0.075em);
|
|
||||||
}
|
|
||||||
.taskheader h2 {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.taskcontent {
|
|
||||||
grid-area: contentArea;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.due {
|
|
||||||
grid-area: dueArea;
|
|
||||||
min-width: 11ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loaded {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
.loaded .checked {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
export class ArgumentError extends Error {
|
|
||||||
constructor(message: string) {
|
|
||||||
super(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DuplicateError extends Error {
|
|
||||||
fields: Array<string>
|
|
||||||
|
|
||||||
constructor(fields: Array<string>, message: string) {
|
|
||||||
super(message)
|
|
||||||
this.fields = fields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum Error401Cause {
|
|
||||||
NotLoggedIn
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum RegisterResponseCause {
|
|
||||||
Server = 1,
|
|
||||||
MalformedRequest,
|
|
||||||
EmailLength,
|
|
||||||
EmailFormat,
|
|
||||||
EmailDuplicate,
|
|
||||||
PasswordLength,
|
|
||||||
DisplayNameLength
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum LoginResponseCause {
|
|
||||||
Server = 1,
|
|
||||||
MalformedRequest,
|
|
||||||
EmailLength,
|
|
||||||
PasswordLength,
|
|
||||||
NotFound,
|
|
||||||
Timeout
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum RefreshResponseCause {
|
|
||||||
Server = 1,
|
|
||||||
MalformedRequest,
|
|
||||||
InvalidToken,
|
|
||||||
InvalidSession
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
// place files you want to import through the `$lib` alias in this folder.
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
import Bun from "bun"
|
|
||||||
import path from "node:path"
|
|
||||||
|
|
||||||
const to_absolute_path = (p: string): string => {
|
|
||||||
if (path.isAbsolute(p)) {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
return path.resolve(process.cwd(), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolve_env_to_path = (env: string|undefined, fallback: string): string => {
|
|
||||||
if (!env) {
|
|
||||||
return to_absolute_path(fallback)
|
|
||||||
}
|
|
||||||
return to_absolute_path(env)
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolve_env_to_boolean = (env: string|undefined, fallback: boolean): boolean => {
|
|
||||||
if (!env) {
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
const str = env.toLowerCase()
|
|
||||||
|
|
||||||
switch (str) {
|
|
||||||
case "false":
|
|
||||||
case "no":
|
|
||||||
case "off": return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
class Config {
|
|
||||||
private _log_dir: string
|
|
||||||
private _log_to_file_when_debug: boolean
|
|
||||||
|
|
||||||
readonly is_debug: boolean = process.env.NODE_ENV != "production"
|
|
||||||
readonly is_production: boolean = process.env.NODE_ENV == "production"
|
|
||||||
|
|
||||||
private _session_timeout: number = 15 * 60 * 1000
|
|
||||||
private _session_refresh_grace: number = 5 * 60 * 1000 // time until expiration
|
|
||||||
|
|
||||||
readonly bypass_login = this.is_debug && process.env.BYPASS_LOGIN == "true"
|
|
||||||
|
|
||||||
get log_dir(): string {
|
|
||||||
return this._log_dir
|
|
||||||
}
|
|
||||||
get log_to_file_when_debug(): boolean {
|
|
||||||
return this._log_to_file_when_debug
|
|
||||||
}
|
|
||||||
|
|
||||||
get session_timeout(): number { return this._session_timeout }
|
|
||||||
get session_refresh_grace(): number { return this._session_refresh_grace }
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this._log_dir = resolve_env_to_path(process.env.APP_LOG_DIR, "./data/logs")
|
|
||||||
this._log_to_file_when_debug = resolve_env_to_boolean(process.env.LOG_TO_FILE_WHEN_DEBUG, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const _config = new Config()
|
|
||||||
|
|
||||||
export default _config;
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
import { PrismaClient } from "@prisma/client"
|
|
||||||
|
|
||||||
const prisma = new PrismaClient()
|
|
||||||
|
|
||||||
export default prisma
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
export enum LogSeverity {
|
|
||||||
FATAL,
|
|
||||||
ERROR,
|
|
||||||
WARN,
|
|
||||||
INFO,
|
|
||||||
DEBUG,
|
|
||||||
TRACE
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum LogModule {
|
|
||||||
PROCESS,
|
|
||||||
USER,
|
|
||||||
DATABASE
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Logger {
|
|
||||||
readonly module = {
|
|
||||||
...LogModule
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract log(severity: LogSeverity, module: LogModule, message: string): void
|
|
||||||
fatal(module: LogModule, message: string): void { this.log(LogSeverity.FATAL, module, message) }
|
|
||||||
error(module: LogModule, message: string): void { this.log(LogSeverity.ERROR, module, message) }
|
|
||||||
warn(module: LogModule, message: string): void { this.log(LogSeverity.WARN, module, message) }
|
|
||||||
info(module: LogModule, message: string): void { this.log(LogSeverity.INFO, module, message) }
|
|
||||||
debug(module: LogModule, message: string): void { this.log(LogSeverity.DEBUG, module, message) }
|
|
||||||
trace(module: LogModule, message: string): void { this.log(LogSeverity.TRACE, module, message) }
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_log_string(severity: LogSeverity, module: LogModule, message: string): string {
|
|
||||||
return `${(new Date()).toISOString()} [${LogModule[module]}] [${LogSeverity[severity]}] ${message}`
|
|
||||||
}
|
|
||||||
|
|
||||||
class DebugLogger extends Logger {
|
|
||||||
|
|
||||||
log(severity: LogSeverity, module: LogModule, message: string): void {
|
|
||||||
console.log(create_log_string(severity, module, message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _logger: Logger = new DebugLogger()
|
|
||||||
|
|
||||||
|
|
||||||
export default _logger
|
|
||||||
|
|
@ -1,203 +0,0 @@
|
||||||
import Bun from "bun"
|
|
||||||
import Crypto from "node:crypto"
|
|
||||||
import { Prisma } from "@prisma/client"
|
|
||||||
|
|
||||||
import { ArgumentError, DuplicateError } from "$lib/errors"
|
|
||||||
|
|
||||||
import Config from "$lib/server/config"
|
|
||||||
import Log from "$lib/server/log"
|
|
||||||
import db from "$lib/server/database"
|
|
||||||
|
|
||||||
export type User = Prisma.UserGetPayload<Prisma.UserDefaultArgs>
|
|
||||||
|
|
||||||
export interface SessionData {
|
|
||||||
user: User
|
|
||||||
token: string
|
|
||||||
issued: Date
|
|
||||||
expires: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
interface CacheUserInfo {
|
|
||||||
user: User
|
|
||||||
last_update: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CacheSessionInfo {
|
|
||||||
user_id: number
|
|
||||||
issued: Date
|
|
||||||
expires: Date
|
|
||||||
}
|
|
||||||
|
|
||||||
class Cache {
|
|
||||||
private _id_map: Map<number, CacheUserInfo> = new Map()
|
|
||||||
private _session_map: Map<string, CacheSessionInfo> = new Map()
|
|
||||||
|
|
||||||
add(user: User, token: string, issued: Date, expires: Date): SessionData {
|
|
||||||
this._id_map.set(user.id, {
|
|
||||||
user: user,
|
|
||||||
last_update: new Date()
|
|
||||||
})
|
|
||||||
this._session_map.set(token, {
|
|
||||||
user_id: user.id,
|
|
||||||
issued: issued,
|
|
||||||
expires: expires
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
user: user,
|
|
||||||
token: token,
|
|
||||||
issued: issued,
|
|
||||||
expires: expires
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate_session(session: SessionData) {
|
|
||||||
this._session_map.delete(session.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
get_session(token: string): SessionData|null {
|
|
||||||
const session_info = this._session_map.get(token)
|
|
||||||
if (!session_info) return null
|
|
||||||
|
|
||||||
const user_info = this._id_map.get(session_info.user_id)
|
|
||||||
if (!user_info) return null
|
|
||||||
|
|
||||||
return {
|
|
||||||
user: user_info.user,
|
|
||||||
token: token,
|
|
||||||
issued: session_info.issued,
|
|
||||||
expires: session_info.expires
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class UserMgmt {
|
|
||||||
_cache: Cache = new Cache()
|
|
||||||
|
|
||||||
async register(email: string, password: string, display_name: string): Promise<User|null> {
|
|
||||||
if (email.length == 0 || password.length == 0 || display_name.length == 0) {
|
|
||||||
throw new ArgumentError("No field may be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const user = await db.user.create({
|
|
||||||
data: {
|
|
||||||
email: email,
|
|
||||||
password_hash: await Bun.password.hash(password, "argon2id"),
|
|
||||||
display_name: display_name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Log.info(Log.module.USER, `Created user with id ${user.id}`)
|
|
||||||
|
|
||||||
return user;
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code == "P2002") {
|
|
||||||
const duplicates = Array.isArray(e.meta?.target) ? e.meta.target as Array<string> : ["unknown"]
|
|
||||||
throw new DuplicateError(duplicates, "Already exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.error(Log.module.DATABASE, `Failed to create User in database! Error: ${JSON.stringify(e)}`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async login(email: string, password: string): Promise<SessionData|null> {
|
|
||||||
const user = await db.user.findUnique({
|
|
||||||
where: {
|
|
||||||
email: email
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
// throw of timing attacks
|
|
||||||
await Bun.password.verify("a", "$argon2id$v=19$m=16,t=2,p=1$ZHB6Zjd4NXV6RXZBZk9wRg$QaYjeAGLon+x3c5I1KB7UQ")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await Bun.password.verify(password, user.password_hash)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const session_info = this._generate_session_for_user(user)
|
|
||||||
|
|
||||||
return session_info
|
|
||||||
}
|
|
||||||
|
|
||||||
async session_login(token: string): Promise<SessionData|null> {
|
|
||||||
const session = this._cache.get_session(token)
|
|
||||||
if (!session) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (session?.expires.getTime() < Date.now()) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
|
|
||||||
async refresh_session(token: string): Promise<SessionData|null> {
|
|
||||||
const session = await this.session_login(token)
|
|
||||||
if (!session) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const new_session = this._generate_session_for_user(session.user)
|
|
||||||
this._cache.invalidate_session(session)
|
|
||||||
|
|
||||||
return new_session
|
|
||||||
}
|
|
||||||
|
|
||||||
private _generate_session_for_user(user: User): SessionData {
|
|
||||||
const token = Crypto.randomBytes(32).toBase64()
|
|
||||||
const session_info = this._cache.add(user, token, new Date(), new Date(Date.now() + Config.session_timeout))
|
|
||||||
|
|
||||||
return session_info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LOGIN_BYPASS_Mgmt extends UserMgmt {
|
|
||||||
global_session: SessionData | null = null
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
|
|
||||||
db.user.findFirst().then((user) => {
|
|
||||||
if (!user) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.global_session = {
|
|
||||||
token: "",
|
|
||||||
user: user,
|
|
||||||
expires: new Date(8640000000000000), // Max Time
|
|
||||||
issued: new Date()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async login(): Promise<SessionData | null> {
|
|
||||||
if (!this.global_session) {
|
|
||||||
const user = await db.user.findFirst()
|
|
||||||
if (user) {
|
|
||||||
this.global_session = {
|
|
||||||
token: "",
|
|
||||||
user: user,
|
|
||||||
expires: new Date(8640000000000000), // Max Time
|
|
||||||
issued: new Date()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.global_session
|
|
||||||
}
|
|
||||||
|
|
||||||
async session_login(): Promise<SessionData | null> {
|
|
||||||
return this.login()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _manager = (Config.is_debug && Config.bypass_login) ? new _LOGIN_BYPASS_Mgmt() : new UserMgmt()
|
|
||||||
|
|
||||||
export default _manager
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
function check_email_format(email: string) {
|
|
||||||
const trimmed = email.trim()
|
|
||||||
|
|
||||||
if (trimmed.length > 254) return false
|
|
||||||
|
|
||||||
const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$/;
|
|
||||||
return emailRegex.test(trimmed)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
check_email_format,
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import favicon from '$lib/assets/favicon.svg';
|
||||||
|
|
||||||
let { children } = $props();
|
let { children } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<link rel="icon" href={favicon} />
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
import type { Actions, PageServerLoad } from "./$types"
|
|
||||||
|
|
||||||
import { fail } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ locals, fetch }) => {
|
|
||||||
|
|
||||||
const response = await fetch("/api/users/tasks", {
|
|
||||||
method: "GET"
|
|
||||||
})
|
|
||||||
|
|
||||||
return { tasks: await response.json() }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
edit: async ({ request, fetch }) => {
|
|
||||||
|
|
||||||
const data = await request.formData()
|
|
||||||
|
|
||||||
const response = await fetch("/api/users/tasks/create", {
|
|
||||||
method: "POST",
|
|
||||||
body: data
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(data)
|
|
||||||
|
|
||||||
return { }
|
|
||||||
}
|
|
||||||
} satisfies Actions
|
|
||||||
|
|
@ -1,100 +1,2 @@
|
||||||
<script lang="ts">
|
<h1>Welcome to SvelteKit</h1>
|
||||||
import { enhance } from '$app/forms'
|
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
||||||
import { pushState, replaceState } from '$app/navigation'
|
|
||||||
import { page } from "$app/state"
|
|
||||||
|
|
||||||
import Task from '$lib/components/task.svelte'
|
|
||||||
import TaskOverlay from '$lib/components/task-overlay.svelte'
|
|
||||||
|
|
||||||
const { data } = $props()
|
|
||||||
$inspect(data)
|
|
||||||
|
|
||||||
let open = $state(false);
|
|
||||||
let lastOpen = false
|
|
||||||
let selectedTask = $state(null)
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
open
|
|
||||||
selectedTask
|
|
||||||
|
|
||||||
if (open != lastOpen) {
|
|
||||||
lastOpen = open
|
|
||||||
if (open) {
|
|
||||||
//pushState(`/tasks/${data.tasks[0].id}`, {})
|
|
||||||
} else {
|
|
||||||
if (page.route.id !== "/") {
|
|
||||||
history.back()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<form id="form_edit_task" method="POST"
|
|
||||||
action="?/edit"
|
|
||||||
use:enhance={({ }) => {
|
|
||||||
|
|
||||||
return async ({ result }) => {
|
|
||||||
|
|
||||||
if (result.type === 'success') {
|
|
||||||
open = false
|
|
||||||
} else /*if (result.type === 'error' || result.type === 'failure')*/ {
|
|
||||||
console.log(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
></form>
|
|
||||||
<div class="container">
|
|
||||||
<h1>Tasks</h1>
|
|
||||||
|
|
||||||
<div class="create_task">
|
|
||||||
<input form="form_edit_task" name="content" placeholder="Create task here" onclick={() => { open = true }}/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#each data.tasks as task}
|
|
||||||
<Task task={task} --width="75%" />
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if open}
|
|
||||||
<TaskOverlay task={selectedTask} bind:open={open} form="form_edit_task" />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.container {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create_task {
|
|
||||||
width: 75%;
|
|
||||||
padding: 5px;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 25px auto 11ch;
|
|
||||||
grid-template-areas:
|
|
||||||
'. headerArea .';
|
|
||||||
|
|
||||||
column-gap: 10px;
|
|
||||||
|
|
||||||
align-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.create_task input {
|
|
||||||
grid-area: headerArea;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import type { RequestHandler } from "./$types"
|
|
||||||
|
|
||||||
import { error, json, text } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import UserMgmt from "$lib/server/usermgmt"
|
|
||||||
|
|
||||||
import { LoginResponseCause } from "$lib/errors"
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request, cookies }) => {
|
|
||||||
|
|
||||||
const data = await request.formData()
|
|
||||||
|
|
||||||
const email = data.get("email")
|
|
||||||
const password = data.get("password")
|
|
||||||
|
|
||||||
if (data.keys.length > 2 || !(typeof email === "string" && typeof password === "string")) {
|
|
||||||
return error(400, { cause: LoginResponseCause.MalformedRequest, message: "Invalid request" })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (email.length == 0) {
|
|
||||||
return error(400, { cause: LoginResponseCause.EmailLength, message: "Email must be provided" })
|
|
||||||
}
|
|
||||||
if (password.length == 0) {
|
|
||||||
return error(400, { cause: LoginResponseCause.PasswordLength, message: "Password must be provided" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = await UserMgmt.login(email, password)
|
|
||||||
if (!session) {
|
|
||||||
return error(401, { message: "Invalid username or password" })
|
|
||||||
}
|
|
||||||
|
|
||||||
return json({ token: session.token, expires: session.expires })
|
|
||||||
}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import type { RequestHandler } from "./$types"
|
|
||||||
|
|
||||||
import { error, json } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import UserMgmt from "$lib/server/usermgmt"
|
|
||||||
import { RefreshResponseCause } from "$lib/errors"
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request }) => {
|
|
||||||
|
|
||||||
const data = await request.json()
|
|
||||||
|
|
||||||
const token = data["token"]
|
|
||||||
if (!token || typeof token !== "string") {
|
|
||||||
return error(400, { cause: RefreshResponseCause.MalformedRequest, message: "token must be provided as string." })
|
|
||||||
}
|
|
||||||
|
|
||||||
const new_session = await UserMgmt.refresh_session(token)
|
|
||||||
|
|
||||||
if (!new_session) {
|
|
||||||
return error(401, { cause: RefreshResponseCause.InvalidSession, message: "No session for token" })
|
|
||||||
}
|
|
||||||
|
|
||||||
return json({
|
|
||||||
token: new_session.token,
|
|
||||||
expires: new_session.expires
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import type { RequestHandler } from "./$types"
|
|
||||||
|
|
||||||
import { json, error } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import UserMgmt from "$lib/server/usermgmt"
|
|
||||||
|
|
||||||
import Util from "$lib/util"
|
|
||||||
import { DuplicateError, RegisterResponseCause } from "$lib/errors"
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request }) => {
|
|
||||||
|
|
||||||
const data = await request.formData()
|
|
||||||
|
|
||||||
const email = data.get("email")
|
|
||||||
const password = data.get("password")
|
|
||||||
const display_name = data.get("display_name")
|
|
||||||
|
|
||||||
if (data.keys.length > 3 || !(typeof email === "string" && typeof password === "string" && typeof display_name === "string")) {
|
|
||||||
return error(400, { cause: RegisterResponseCause.MalformedRequest, message: "Invalid field arguments" })
|
|
||||||
}
|
|
||||||
if (email.length == 0) {
|
|
||||||
return error(400, { cause: RegisterResponseCause.EmailLength, message: "email must not be empty" })
|
|
||||||
}
|
|
||||||
if (password.length == 0) {
|
|
||||||
return error(400, { cause: RegisterResponseCause.PasswordLength, message: "password must not be empty" })
|
|
||||||
}
|
|
||||||
if (display_name.length == 0) {
|
|
||||||
return error(400, { cause: RegisterResponseCause.DisplayNameLength, message: "Display name must not be empty" })
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Util.check_email_format(email)) {
|
|
||||||
return error(400, { cause: RegisterResponseCause.EmailFormat, message: "invalid email format" })
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const user = await UserMgmt.register(email, password, display_name)
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof DuplicateError) {
|
|
||||||
if (e.fields.includes("email")) {
|
|
||||||
return error(409, { cause: RegisterResponseCause.EmailDuplicate, message: "email already in use" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return error(500, { cause: RegisterResponseCause.Server, message: "Server failed to create user"})
|
|
||||||
}
|
|
||||||
|
|
||||||
return json({})
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import type { RequestHandler } from "./$types";
|
|
||||||
|
|
||||||
import { json, error } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import { Error401Cause } from "$lib/errors";
|
|
||||||
|
|
||||||
import db from "$lib/server/database"
|
|
||||||
|
|
||||||
enum StatusFilterValues {
|
|
||||||
all,
|
|
||||||
open,
|
|
||||||
done,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GET: RequestHandler = async ({ request, locals, url }) => {
|
|
||||||
|
|
||||||
const filter_param = url.searchParams.get("status")
|
|
||||||
const filter = (filter_param && filter_param in StatusFilterValues)
|
|
||||||
? StatusFilterValues[filter_param as keyof typeof StatusFilterValues]
|
|
||||||
: StatusFilterValues.all
|
|
||||||
|
|
||||||
const tasks = await db.task.findMany({
|
|
||||||
where: {
|
|
||||||
userId: {
|
|
||||||
equals: locals.user.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return json(tasks)
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import type { RequestHandler } from "./$types";
|
|
||||||
|
|
||||||
import { json, error } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import db from "$lib/server/database"
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request, locals }) => {
|
|
||||||
|
|
||||||
const data = await request.formData()
|
|
||||||
|
|
||||||
const content = data.get("content")
|
|
||||||
|
|
||||||
if (!content || typeof content !== "string") {
|
|
||||||
return error(400, { message: "content must be specified" })
|
|
||||||
}
|
|
||||||
|
|
||||||
const task = await db.task.create({
|
|
||||||
data: {
|
|
||||||
content: content,
|
|
||||||
user: {
|
|
||||||
connect: {
|
|
||||||
id: locals.user.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return json(task)
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import type { Actions } from "./$types"
|
|
||||||
|
|
||||||
import { fail } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
import Log from "$lib/server/log"
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
login: async ({ request, fetch, cookies }) => {
|
|
||||||
|
|
||||||
console.log("login")
|
|
||||||
|
|
||||||
const formData = await request.formData()
|
|
||||||
|
|
||||||
const result = await fetch("/api/login", {
|
|
||||||
method: "POST",
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!result.ok) {
|
|
||||||
return fail(401, { email: formData.get("email") ?? "", message: "Benutzername oder Passwort ist falsch." })
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = await (async () => {
|
|
||||||
try {
|
|
||||||
return await result.json()
|
|
||||||
} catch (e) {
|
|
||||||
Log.error(Log.module.PROCESS, `Failed to parse body of login response from endpoint`)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
if (!body || !body.token || !body.expires) {
|
|
||||||
return fail(502, "Invalid response from login endpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
cookies.set("session", body.token, {
|
|
||||||
expires: new Date(body.expires),
|
|
||||||
httpOnly: true,
|
|
||||||
secure: true,
|
|
||||||
sameSite: "strict",
|
|
||||||
path: "/"
|
|
||||||
})
|
|
||||||
|
|
||||||
return { message: "Erfolg" }
|
|
||||||
}
|
|
||||||
} satisfies Actions;
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
import type { PageProps } from "./$types"
|
|
||||||
|
|
||||||
const { form }: PageProps = $props()
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<form action="?/login" method="POST" id="form_login"></form>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<h1>Login</h1>
|
|
||||||
<p class="error_msg">{form?.message}</p>
|
|
||||||
<label for="username">E-Mail: </label><input type="text" id="username" form="form_login" name="email" />
|
|
||||||
<label for="password">Passwort: </label><input type="password" id="password" form="form_login" name="password" />
|
|
||||||
<button type="submit" form="form_login">-></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p><a href="/login/register">Noch nicht registriert? Klicke hier!</a></p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
padding-top: 100px;
|
|
||||||
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
gap: 10px 50px;
|
|
||||||
grid-template-columns: 1fr 3fr;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > h1 {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
grid-column: 1 / span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > p {
|
|
||||||
width: 100%;
|
|
||||||
grid-column: 1 / span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > button {
|
|
||||||
width: 50%;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: auto;
|
|
||||||
grid-column: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error_msg {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import { RegisterResponseCause } from "$lib/errors";
|
|
||||||
import type { Actions } from "./$types";
|
|
||||||
|
|
||||||
import { fail } from "@sveltejs/kit"
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
register: async ({ request, fetch }) => {
|
|
||||||
|
|
||||||
console.log("register")
|
|
||||||
|
|
||||||
const result = await fetch("/api/register", {
|
|
||||||
method: "POST",
|
|
||||||
body: await request.formData()
|
|
||||||
})
|
|
||||||
|
|
||||||
const result_body = await result.json()
|
|
||||||
|
|
||||||
if (!result.ok) {
|
|
||||||
if (!result_body.cause) {
|
|
||||||
return fail(500, { message: "Interner Fehler, versuche es erneut." })
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (result_body.cause) {
|
|
||||||
case RegisterResponseCause.MalformedRequest: return fail(400, { message: "Bitte versuche es erneut." })
|
|
||||||
case RegisterResponseCause.EmailLength: return fail(400, { message: "Bitte gib eine Email ein." })
|
|
||||||
case RegisterResponseCause.EmailFormat: return fail(400, { message: "Das Format der Email ist nicht gültig." })
|
|
||||||
case RegisterResponseCause.EmailDuplicate: return fail(409, { message: "Email wird bereits verwendet." })
|
|
||||||
case RegisterResponseCause.DisplayNameLength: return fail(400, { message: "Bitt gib einen Display Namen ein" })
|
|
||||||
case RegisterResponseCause.PasswordLength: return fail(400, { message: "Bitte gib ein Passwort ein." })
|
|
||||||
default:
|
|
||||||
return fail(500, { message: "Ein interner Fehler ist aufgetreten. Bitte versuche es erneut."})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return { message: "Erfolg" }
|
|
||||||
}
|
|
||||||
} satisfies Actions
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
import type { PageProps } from "./$types"
|
|
||||||
|
|
||||||
const { form }: PageProps = $props()
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<form action="?/register" method="POST" id="form_register"></form>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<div class="grid">
|
|
||||||
<h1>Login</h1>
|
|
||||||
<p class="error_msg">{form?.message}</p>
|
|
||||||
<label for="username">E-Mail: </label><input type="text" id="username" form="form_register" name="email" />
|
|
||||||
<label for="password">Passwort: </label><input type="password" id="password" form="form_register" name="password" />
|
|
||||||
<label for="display_name">Anzeigename: </label><input type="text" id="display_name" form="form_register" name="display_name" />
|
|
||||||
<button type="submit" form="form_register">Registrieren</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p><a href="/login">Schon registriert? Klicke hier!</a></p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
padding-top: 100px;
|
|
||||||
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
gap: 10px 50px;
|
|
||||||
grid-template-columns: 1fr 3fr;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > h1 {
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
grid-column: 1 / span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > p {
|
|
||||||
width: 100%;
|
|
||||||
grid-column: 1 / span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > button {
|
|
||||||
width: 50%;
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-left: auto;
|
|
||||||
grid-column: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error_msg {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
body {
|
|
||||||
--primary-bg-color: darkgreen;
|
|
||||||
--primary-text-color: black;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
background-color: var(--primary-bg-color, white);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
color: var(--primary-text-color, black);
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue