+36
-176
bun.lock
+36
-176
bun.lock
···
4
4
"": {
5
5
"name": "easytodo.link",
6
6
"dependencies": {
7
-
"@atproto/api": "latest",
8
-
"@atproto/oauth-client-node": "latest",
9
-
"@oslojs/encoding": "latest",
10
-
"@tailwindcss/vite": "latest",
11
-
"drizzle-orm": "latest",
12
-
"oslo": "latest",
13
-
"postgres": "latest",
14
-
"svelte-french-toast": "latest",
15
-
"tailwindcss": "latest",
7
+
"@tailwindcss/vite": "^4.1.13",
8
+
"oslo": "^1.2.1",
9
+
"svelte-french-toast": "^1.2.0",
10
+
"tailwindcss": "^4.1.13",
16
11
},
17
12
"devDependencies": {
18
-
"@sveltejs/adapter-netlify": "latest",
19
-
"@sveltejs/kit": "latest",
20
-
"@sveltejs/vite-plugin-svelte": "latest",
21
-
"drizzle-kit": "latest",
22
-
"svelte": "latest",
23
-
"svelte-check": "latest",
24
-
"tslib": "latest",
25
-
"typescript": "latest",
26
-
"vite": "latest",
13
+
"@deno/svelte-adapter": "^0.1.0",
14
+
"@sveltejs/kit": "^2.43.5",
15
+
"@sveltejs/vite-plugin-svelte": "^6.2.1",
16
+
"svelte": "^5.39.6",
17
+
"svelte-check": "^4.3.2",
18
+
"tslib": "^2.8.1",
19
+
"typescript": "^5.9.2",
20
+
"vite": "^7.1.7",
27
21
},
28
22
},
29
23
},
30
24
"packages": {
31
-
"@atproto-labs/did-resolver": ["@atproto-labs/did-resolver@0.2.1", "", { "dependencies": { "@atproto-labs/fetch": "0.2.3", "@atproto-labs/pipe": "0.1.1", "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.0", "zod": "^3.23.8" } }, "sha512-zSoHyqwwRYUtMNLW+RrWsImt1U5S47nJv5FfmAXTmon6wVKjxKD/PFrD1pg/4G6THqJmQHTs1Hj+54XVupYnvQ=="],
32
-
33
-
"@atproto-labs/fetch": ["@atproto-labs/fetch@0.2.3", "", { "dependencies": { "@atproto-labs/pipe": "0.1.1" } }, "sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw=="],
34
-
35
-
"@atproto-labs/fetch-node": ["@atproto-labs/fetch-node@0.1.10", "", { "dependencies": { "@atproto-labs/fetch": "0.2.3", "@atproto-labs/pipe": "0.1.1", "ipaddr.js": "^2.1.0", "undici": "^6.14.1" } }, "sha512-o7hGaonA71A6p7O107VhM6UBUN/g9tTyYohMp1q0Kf6xQ4npnuZYRSHSf2g6reSfGQJ1GoFNjBObETTT1ge/jQ=="],
36
-
37
-
"@atproto-labs/handle-resolver": ["@atproto-labs/handle-resolver@0.3.1", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.0", "zod": "^3.23.8" } }, "sha512-mLZdMNvwomgnn9sffKO1/xr02ctgeiT0FUVw7JekbchTckub2RM7qMu8Rw1mC4bpCpW+i7DXDiOxpoajkppwYQ=="],
38
-
39
-
"@atproto-labs/handle-resolver-node": ["@atproto-labs/handle-resolver-node@0.1.19", "", { "dependencies": { "@atproto-labs/fetch-node": "0.1.10", "@atproto-labs/handle-resolver": "0.3.1", "@atproto/did": "0.2.0" } }, "sha512-nNVCfiKudvMYfDcWCa9koOMOpCYaC0wG4Uys5dZev99s/Nka7tRlIZIV+u+GWivnG9lqCupKATkoyCd6Per8Gw=="],
40
-
41
-
"@atproto-labs/identity-resolver": ["@atproto-labs/identity-resolver@0.3.1", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.1", "@atproto-labs/handle-resolver": "0.3.1" } }, "sha512-jCgotRRqPykPwh4gh0FBLOqeofv1G8OH/DZ5s88HWm7biUZeksZwDrEvL5TnqEFUpXT3O9Hcyp/XEpfCAplRoQ=="],
42
-
43
-
"@atproto-labs/pipe": ["@atproto-labs/pipe@0.1.1", "", {}, "sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg=="],
44
-
45
-
"@atproto-labs/simple-store": ["@atproto-labs/simple-store@0.3.0", "", {}, "sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ=="],
46
-
47
-
"@atproto-labs/simple-store-memory": ["@atproto-labs/simple-store-memory@0.1.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "lru-cache": "^10.2.0" } }, "sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw=="],
48
-
49
-
"@atproto/api": ["@atproto/api@0.17.0", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/lexicon": "^0.5.1", "@atproto/syntax": "^0.4.1", "@atproto/xrpc": "^0.7.5", "await-lock": "^2.2.2", "multiformats": "^9.9.0", "tlds": "^1.234.0", "zod": "^3.23.8" } }, "sha512-FNS9SW7/3kslAnJH7F4fO9/jPjXzC0NMD6u9NjJ/h4EnaIEpWHZQPkmD9Q2hvAwD6+Uo2boYZEPKkOa55Lr5Dg=="],
50
-
51
-
"@atproto/common-web": ["@atproto/common-web@0.4.3", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg=="],
52
-
53
-
"@atproto/did": ["@atproto/did@0.2.0", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-BskT39KYbwY1DUsWekkHh47xS+wvJpFq5F9acsicNfYniinyAMnNTzGKQEhnjQuG7K0qQItg/SnmC+y0tJXV7Q=="],
54
-
55
-
"@atproto/jwk": ["@atproto/jwk@0.5.0", "", { "dependencies": { "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-Qi2NtEqhkG+uz3CKia4+H05WMV/z//dz3ESo5+cyBKrOnxVTJ5ZubMyltWjoYvy6v/jLhorXdDWcjn07yky7MQ=="],
25
+
"@deno/experimental-route-config": ["@deno/experimental-route-config@0.0.5", "", { "dependencies": { "urlpattern-polyfill": "^10.0.0" } }, "sha512-0PN4qij3sC3Qm8WbiOBGlOQz8WtB0AENGkzsTHOYyPenf40iW7OGFid8QT3L8lGApnz3t6ufET0c2XgagV8Jjw=="],
56
26
57
-
"@atproto/jwk-jose": ["@atproto/jwk-jose@0.1.10", "", { "dependencies": { "@atproto/jwk": "0.5.0", "jose": "^5.2.0" } }, "sha512-Eiu/u4tZHz3IIhHZt0zneYEffSAO3Oqk/ToKwlu1TqKte6sjtPs/4uquSiAAGFYozqgo92JC/AQclWzzkHI5QQ=="],
58
-
59
-
"@atproto/jwk-webcrypto": ["@atproto/jwk-webcrypto@0.1.10", "", { "dependencies": { "@atproto/jwk": "0.5.0", "@atproto/jwk-jose": "0.1.10", "zod": "^3.23.8" } }, "sha512-JZsavs6JiSmw5rgcjkGDwzr1aCJGdybZOjVfYH+m9sXRU1BrUCA30uwNfZY7eFyWXyRAnCFiYiGVZgypXyKotw=="],
60
-
61
-
"@atproto/lexicon": ["@atproto/lexicon@0.5.1", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/syntax": "^0.4.1", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A=="],
62
-
63
-
"@atproto/oauth-client": ["@atproto/oauth-client@0.5.6", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.1", "@atproto-labs/fetch": "0.2.3", "@atproto-labs/handle-resolver": "0.3.1", "@atproto-labs/identity-resolver": "0.3.1", "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.0", "@atproto/jwk": "0.5.0", "@atproto/oauth-types": "0.4.1", "@atproto/xrpc": "0.7.5", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-O1S9lPptJxWPcNd2kODaLgWntz+A7PzskU2hP4IFa7hVLs4aEnEt9dKq5wJE97tDli8mgyh/ndPQhxUaCVQ5iQ=="],
64
-
65
-
"@atproto/oauth-client-node": ["@atproto/oauth-client-node@0.3.8", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.1", "@atproto-labs/handle-resolver-node": "0.1.19", "@atproto-labs/simple-store": "0.3.0", "@atproto/did": "0.2.0", "@atproto/jwk": "0.5.0", "@atproto/jwk-jose": "0.1.10", "@atproto/jwk-webcrypto": "0.1.10", "@atproto/oauth-client": "0.5.6", "@atproto/oauth-types": "0.4.1" } }, "sha512-HIBiYQERj04Xa0l8cJkqcZC0BbHH5uqDEvhqHWnJ5umSq/ms0+HZi3JKJXGv1XfYOvxUxx6NKgXJ8VhhYoQa5A=="],
66
-
67
-
"@atproto/oauth-types": ["@atproto/oauth-types@0.4.1", "", { "dependencies": { "@atproto/jwk": "0.5.0", "zod": "^3.23.8" } }, "sha512-c5ixf2ZOzcltOu1fDBnO/tok6Wj7JDDK66+Z0q/+bAr8LXgOnxP7zQfJ+DD4gTkB+saTqsqWtVv8qvx/IEtm1g=="],
68
-
69
-
"@atproto/syntax": ["@atproto/syntax@0.4.1", "", {}, "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw=="],
70
-
71
-
"@atproto/xrpc": ["@atproto/xrpc@0.7.5", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "zod": "^3.23.8" } }, "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA=="],
72
-
73
-
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="],
27
+
"@deno/svelte-adapter": ["@deno/svelte-adapter@0.1.0", "", { "dependencies": { "@deno/experimental-route-config": "^0.0.5" }, "peerDependencies": { "@sveltejs/kit": "2.x" } }, "sha512-fx4Kj1lSx1rJvjtPr3cXO7qKveI1vUyGW8jX+clJHQEqEeIDnEcBW0FpMZEVORPlay2SGydQWSGbwh4j2iENzg=="],
74
28
75
29
"@emnapi/core": ["@emnapi/core@0.45.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw=="],
76
30
77
31
"@emnapi/runtime": ["@emnapi/runtime@0.45.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w=="],
78
-
79
-
"@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="],
80
-
81
-
"@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="],
82
32
83
33
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
84
34
···
131
81
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
132
82
133
83
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
134
-
135
-
"@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="],
136
84
137
85
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
138
86
···
206
154
207
155
"@node-rs/bcrypt-win32-x64-msvc": ["@node-rs/bcrypt-win32-x64-msvc@1.9.0", "", { "os": "win32", "cpu": "x64" }, "sha512-2y0Tuo6ZAT2Cz8V7DHulSlv1Bip3zbzeXyeur+uR25IRNYXKvI/P99Zl85Fbuu/zzYAZRLLlGTRe6/9IHofe/w=="],
208
156
209
-
"@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
210
-
211
157
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
212
158
213
159
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.3", "", { "os": "android", "cpu": "arm" }, "sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw=="],
···
258
204
259
205
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="],
260
206
261
-
"@sveltejs/adapter-netlify": ["@sveltejs/adapter-netlify@5.2.4", "", { "dependencies": { "@iarna/toml": "^2.2.5", "esbuild": "^0.25.4", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-UtPcZq1HUA43hM8uLi+nsm5Q+YjHNj7/SMFoyeLZeY/VTloVWABEZ0tJ5WodTUmy/8j5QJ7oLZjj28aQxi8y3g=="],
262
-
263
-
"@sveltejs/kit": ["@sveltejs/kit@2.44.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-xU5qP7PiYmrSH70Whm/I+nf0j4xBnHyRQNkC1SEfaBOwCCkkeuL6WNxSb8q4Ib7+Z+sZ4JUTDYHfoyVm02EXVQ=="],
207
+
"@sveltejs/kit": ["@sveltejs/kit@2.43.5", "", { "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-44Mm5csR4mesKx2Eyhtk8UVrLJ4c04BT2wMTfYGKJMOkUqpHP5KLL2DPV0hXUA4t4+T3ZYe0aBygd42lVYv2cA=="],
264
208
265
209
"@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=="],
266
210
267
211
"@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=="],
268
212
269
-
"@tailwindcss/node": ["@tailwindcss/node@4.1.14", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.0", "lightningcss": "1.30.1", "magic-string": "^0.30.19", "source-map-js": "^1.2.1", "tailwindcss": "4.1.14" } }, "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw=="],
213
+
"@tailwindcss/node": ["@tailwindcss/node@4.1.13", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.5.1", "lightningcss": "1.30.1", "magic-string": "^0.30.18", "source-map-js": "^1.2.1", "tailwindcss": "4.1.13" } }, "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw=="],
270
214
271
-
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.14", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.5.1" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.14", "@tailwindcss/oxide-darwin-arm64": "4.1.14", "@tailwindcss/oxide-darwin-x64": "4.1.14", "@tailwindcss/oxide-freebsd-x64": "4.1.14", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", "@tailwindcss/oxide-linux-x64-musl": "4.1.14", "@tailwindcss/oxide-wasm32-wasi": "4.1.14", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" } }, "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw=="],
215
+
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.13", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.13", "@tailwindcss/oxide-darwin-arm64": "4.1.13", "@tailwindcss/oxide-darwin-x64": "4.1.13", "@tailwindcss/oxide-freebsd-x64": "4.1.13", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", "@tailwindcss/oxide-linux-x64-musl": "4.1.13", "@tailwindcss/oxide-wasm32-wasi": "4.1.13", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" } }, "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA=="],
272
216
273
-
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.14", "", { "os": "android", "cpu": "arm64" }, "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ=="],
217
+
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.13", "", { "os": "android", "cpu": "arm64" }, "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew=="],
274
218
275
-
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.14", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA=="],
219
+
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ=="],
276
220
277
-
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.14", "", { "os": "darwin", "cpu": "x64" }, "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw=="],
221
+
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw=="],
278
222
279
-
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.14", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw=="],
223
+
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ=="],
280
224
281
-
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14", "", { "os": "linux", "cpu": "arm" }, "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw=="],
225
+
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13", "", { "os": "linux", "cpu": "arm" }, "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw=="],
282
226
283
-
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w=="],
227
+
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ=="],
284
228
285
-
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.14", "", { "os": "linux", "cpu": "arm64" }, "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ=="],
229
+
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg=="],
286
230
287
-
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg=="],
231
+
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ=="],
288
232
289
-
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.14", "", { "os": "linux", "cpu": "x64" }, "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q=="],
233
+
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ=="],
290
234
291
-
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.14", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.5", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ=="],
235
+
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.13", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@emnapi/wasi-threads": "^1.0.4", "@napi-rs/wasm-runtime": "^0.2.12", "@tybys/wasm-util": "^0.10.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA=="],
292
236
293
-
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.14", "", { "os": "win32", "cpu": "arm64" }, "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA=="],
237
+
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg=="],
294
238
295
-
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.14", "", { "os": "win32", "cpu": "x64" }, "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA=="],
239
+
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.13", "", { "os": "win32", "cpu": "x64" }, "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw=="],
296
240
297
-
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.14", "", { "dependencies": { "@tailwindcss/node": "4.1.14", "@tailwindcss/oxide": "4.1.14", "tailwindcss": "4.1.14" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA=="],
241
+
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.13", "", { "dependencies": { "@tailwindcss/node": "4.1.13", "@tailwindcss/oxide": "4.1.13", "tailwindcss": "4.1.13" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ=="],
298
242
299
243
"@tybys/wasm-util": ["@tybys/wasm-util@0.8.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q=="],
300
244
···
306
250
307
251
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
308
252
309
-
"await-lock": ["await-lock@2.2.2", "", {}, "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="],
310
-
311
253
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
312
-
313
-
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
314
254
315
255
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
316
256
···
328
268
329
269
"devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="],
330
270
331
-
"drizzle-kit": ["drizzle-kit@0.31.5", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg=="],
332
-
333
-
"drizzle-orm": ["drizzle-orm@0.44.6", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-uy6uarrrEOc9K1u5/uhBFJbdF5VJ5xQ/Yzbecw3eAYOunv5FDeYkR2m8iitocdHBOHbvorviKOW5GVw0U1j4LQ=="],
334
-
335
271
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
336
272
337
273
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
338
-
339
-
"esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="],
340
274
341
275
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
342
276
···
348
282
349
283
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
350
284
351
-
"get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="],
352
-
353
285
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
354
286
355
-
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
356
-
357
-
"ipaddr.js": ["ipaddr.js@2.2.0", "", {}, "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA=="],
358
-
359
287
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
360
288
361
-
"iso-datestring-validator": ["iso-datestring-validator@2.2.2", "", {}, "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA=="],
362
-
363
289
"jiti": ["jiti@2.6.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ=="],
364
-
365
-
"jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="],
366
290
367
291
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
368
292
···
390
314
391
315
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
392
316
393
-
"lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
394
-
395
317
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
396
318
397
319
"memfs": ["memfs@3.5.3", "", { "dependencies": { "fs-monkey": "^1.0.4" } }, "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw=="],
···
407
329
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
408
330
409
331
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
410
-
411
-
"multiformats": ["multiformats@9.9.0", "", {}, "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="],
412
332
413
333
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
414
334
···
420
340
421
341
"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=="],
422
342
423
-
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
424
-
425
343
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
426
-
427
-
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
428
344
429
345
"rollup": ["rollup@4.52.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.3", "@rollup/rollup-android-arm64": "4.52.3", "@rollup/rollup-darwin-arm64": "4.52.3", "@rollup/rollup-darwin-x64": "4.52.3", "@rollup/rollup-freebsd-arm64": "4.52.3", "@rollup/rollup-freebsd-x64": "4.52.3", "@rollup/rollup-linux-arm-gnueabihf": "4.52.3", "@rollup/rollup-linux-arm-musleabihf": "4.52.3", "@rollup/rollup-linux-arm64-gnu": "4.52.3", "@rollup/rollup-linux-arm64-musl": "4.52.3", "@rollup/rollup-linux-loong64-gnu": "4.52.3", "@rollup/rollup-linux-ppc64-gnu": "4.52.3", "@rollup/rollup-linux-riscv64-gnu": "4.52.3", "@rollup/rollup-linux-riscv64-musl": "4.52.3", "@rollup/rollup-linux-s390x-gnu": "4.52.3", "@rollup/rollup-linux-x64-gnu": "4.52.3", "@rollup/rollup-linux-x64-musl": "4.52.3", "@rollup/rollup-openharmony-arm64": "4.52.3", "@rollup/rollup-win32-arm64-msvc": "4.52.3", "@rollup/rollup-win32-ia32-msvc": "4.52.3", "@rollup/rollup-win32-x64-gnu": "4.52.3", "@rollup/rollup-win32-x64-msvc": "4.52.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A=="],
430
346
···
433
349
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
434
350
435
351
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
436
-
437
-
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
438
352
439
353
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
440
354
441
-
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
442
-
443
-
"svelte": ["svelte@5.39.8", "", { "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-KfZ3hCITdxIXTOvrea4nFZX2o+47HPTChKeocgj9BwJQYqWrviVCcPj4boXHF5yf8+eBKqhHY8xii//XaakKXA=="],
355
+
"svelte": ["svelte@5.39.6", "", { "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-bOJXmuwLNaoqPCTWO8mPu/fwxI5peGE5Efe7oo6Cakpz/G60vsnVF6mxbGODaxMUFUKEnjm6XOwHEqOht6cbvw=="],
444
356
445
357
"svelte-check": ["svelte-check@4.3.2", "", { "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-71udP5w2kaSTcX8iV0hn3o2FWlabQHhJTJLIQrCqMsrcOeDUO2VhCQKKCA8AMVHSPwdxLEWkUWh9OKxns5PD9w=="],
446
358
···
448
360
449
361
"svelte-writable-derived": ["svelte-writable-derived@3.1.1", "", { "peerDependencies": { "svelte": "^3.2.1 || ^4.0.0-next.1 || ^5.0.0-next.94" } }, "sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw=="],
450
362
451
-
"tailwindcss": ["tailwindcss@4.1.14", "", {}, "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA=="],
363
+
"tailwindcss": ["tailwindcss@4.1.13", "", {}, "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w=="],
452
364
453
365
"tapable": ["tapable@2.2.3", "", {}, "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg=="],
454
366
···
456
368
457
369
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
458
370
459
-
"tlds": ["tlds@1.260.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ=="],
460
-
461
371
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
462
372
463
373
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
464
374
465
-
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
466
-
467
-
"uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="],
375
+
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
468
376
469
-
"undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="],
377
+
"urlpattern-polyfill": ["urlpattern-polyfill@10.1.0", "", {}, "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw=="],
470
378
471
-
"vite": ["vite@7.1.9", "", { "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-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="],
379
+
"vite": ["vite@7.1.7", "", { "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-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA=="],
472
380
473
381
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
474
382
475
383
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
476
384
477
385
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
478
-
479
-
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
480
-
481
-
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
482
386
483
387
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
484
388
···
486
390
487
391
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
488
392
489
-
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.6", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-DXj75ewm11LIWUk198QSKUTxjyRjsBwk09MuMk5DGK+GDUtyPhhEHOGP/Xwwj3DjQXXkivoBirmOnKrLfc0+9g=="],
393
+
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
490
394
491
395
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
492
396
493
397
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
494
-
495
-
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
496
-
497
-
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
498
-
499
-
"@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="],
500
-
501
-
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="],
502
-
503
-
"@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="],
504
-
505
-
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="],
506
-
507
-
"@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="],
508
-
509
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="],
510
-
511
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="],
512
-
513
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="],
514
-
515
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="],
516
-
517
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="],
518
-
519
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="],
520
-
521
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="],
522
-
523
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="],
524
-
525
-
"@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="],
526
-
527
-
"@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="],
528
-
529
-
"@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="],
530
-
531
-
"@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="],
532
-
533
-
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="],
534
-
535
-
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="],
536
-
537
-
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
538
398
}
539
399
}
-11
drizzle/0000_first_praxagora.sql
-11
drizzle/0000_first_praxagora.sql
···
1
-
CREATE TABLE "auth_session" (
2
-
"key" text PRIMARY KEY NOT NULL,
3
-
"session" json NOT NULL,
4
-
CONSTRAINT "auth_session_key_unique" UNIQUE("key")
5
-
);
6
-
--> statement-breakpoint
7
-
CREATE TABLE "auth_state" (
8
-
"key" text PRIMARY KEY NOT NULL,
9
-
"state" json NOT NULL,
10
-
CONSTRAINT "auth_state_key_unique" UNIQUE("key")
11
-
);
-85
drizzle/meta/0000_snapshot.json
-85
drizzle/meta/0000_snapshot.json
···
1
-
{
2
-
"id": "6e06677f-9a96-41ee-82f8-e0f6e1ea34e3",
3
-
"prevId": "00000000-0000-0000-0000-000000000000",
4
-
"version": "7",
5
-
"dialect": "postgresql",
6
-
"tables": {
7
-
"public.auth_session": {
8
-
"name": "auth_session",
9
-
"schema": "",
10
-
"columns": {
11
-
"key": {
12
-
"name": "key",
13
-
"type": "text",
14
-
"primaryKey": true,
15
-
"notNull": true
16
-
},
17
-
"session": {
18
-
"name": "session",
19
-
"type": "json",
20
-
"primaryKey": false,
21
-
"notNull": true
22
-
}
23
-
},
24
-
"indexes": {},
25
-
"foreignKeys": {},
26
-
"compositePrimaryKeys": {},
27
-
"uniqueConstraints": {
28
-
"auth_session_key_unique": {
29
-
"name": "auth_session_key_unique",
30
-
"nullsNotDistinct": false,
31
-
"columns": [
32
-
"key"
33
-
]
34
-
}
35
-
},
36
-
"policies": {},
37
-
"checkConstraints": {},
38
-
"isRLSEnabled": false
39
-
},
40
-
"public.auth_state": {
41
-
"name": "auth_state",
42
-
"schema": "",
43
-
"columns": {
44
-
"key": {
45
-
"name": "key",
46
-
"type": "text",
47
-
"primaryKey": true,
48
-
"notNull": true
49
-
},
50
-
"state": {
51
-
"name": "state",
52
-
"type": "json",
53
-
"primaryKey": false,
54
-
"notNull": true
55
-
}
56
-
},
57
-
"indexes": {},
58
-
"foreignKeys": {},
59
-
"compositePrimaryKeys": {},
60
-
"uniqueConstraints": {
61
-
"auth_state_key_unique": {
62
-
"name": "auth_state_key_unique",
63
-
"nullsNotDistinct": false,
64
-
"columns": [
65
-
"key"
66
-
]
67
-
}
68
-
},
69
-
"policies": {},
70
-
"checkConstraints": {},
71
-
"isRLSEnabled": false
72
-
}
73
-
},
74
-
"enums": {},
75
-
"schemas": {},
76
-
"sequences": {},
77
-
"roles": {},
78
-
"policies": {},
79
-
"views": {},
80
-
"_meta": {
81
-
"columns": {},
82
-
"schemas": {},
83
-
"tables": {}
84
-
}
85
-
}
-13
drizzle/meta/_journal.json
-13
drizzle/meta/_journal.json
-12
drizzle.config.ts
-12
drizzle.config.ts
···
1
-
import { defineConfig } from "drizzle-kit";
2
-
if (!process.env.DATABASE_URL) throw new Error("DATABASE_URL is not set");
3
-
4
-
export default defineConfig({
5
-
schema: "./src/lib/schema.ts",
6
-
dbCredentials: {
7
-
url: process.env.DATABASE_URL
8
-
},
9
-
verbose: true,
10
-
strict: true,
11
-
dialect: "postgresql"
12
-
});
-27
link/easytodo/tasks/list.json
-27
link/easytodo/tasks/list.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "link.easytodo.tasks.list",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"description": "A list of items to do.",
8
-
"key": "tid",
9
-
"record": {
10
-
"type": "object",
11
-
"required": ["id", "title", "createdAt"],
12
-
"properties": {
13
-
"id": { "type": "string" },
14
-
"title": { "type": "string" },
15
-
"createdAt": { "type": "string", "format": "datetime" },
16
-
"tasks": {
17
-
"type": "array",
18
-
"items": {
19
-
"type": "ref",
20
-
"ref": "link.easytodo.tasks.task"
21
-
}
22
-
}
23
-
}
24
-
}
25
-
}
26
-
}
27
-
}
-21
link/easytodo/tasks/task.json
-21
link/easytodo/tasks/task.json
···
1
-
{
2
-
"lexicon": 1,
3
-
"id": "link.easytodo.tasks.task",
4
-
"defs": {
5
-
"main": {
6
-
"type": "record",
7
-
"description": "An item to do.",
8
-
"key": "tid",
9
-
"record": {
10
-
"type": "object",
11
-
"required": ["id", "description", "is_completed"],
12
-
"properties": {
13
-
"id": { "type": "string" },
14
-
"description": { "type": "string" },
15
-
"is_completed": { "type": "boolean", "default": false },
16
-
"duration": { "type": "integer" }
17
-
}
18
-
}
19
-
}
20
-
}
21
-
}
+7
-17
package.json
+7
-17
package.json
···
7
7
"build": "vite build",
8
8
"preview": "vite preview",
9
9
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
10
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
11
-
"db:push": "drizzle-kit push",
12
-
"db:migrate": "drizzle-kit migrate",
13
-
"db:studio": "drizzle-kit studio"
10
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
14
11
},
15
12
"devDependencies": {
16
-
"@sveltejs/adapter-netlify": "^5.2.4",
17
-
"@sveltejs/kit": "^2.44.0",
13
+
"@sveltejs/kit": "^2.43.5",
18
14
"@sveltejs/vite-plugin-svelte": "^6.2.1",
19
-
"drizzle-kit": "^0.31.5",
20
-
"svelte": "^5.39.8",
15
+
"svelte": "^5.39.6",
21
16
"svelte-check": "^4.3.2",
22
17
"tslib": "^2.8.1",
23
-
"typescript": "^5.9.3",
24
-
"vite": "^7.1.9"
18
+
"typescript": "^5.9.2",
19
+
"vite": "^7.1.7"
25
20
},
26
21
"type": "module",
27
22
"dependencies": {
28
-
"@atproto/api": "^0.17.0",
29
-
"@atproto/oauth-client-node": "^0.3.8",
30
-
"@oslojs/encoding": "^1.1.0",
31
-
"@tailwindcss/vite": "^4.1.14",
32
-
"drizzle-orm": "^0.44.6",
23
+
"@tailwindcss/vite": "^4.1.13",
33
24
"oslo": "^1.2.1",
34
-
"postgres": "^3.4.7",
35
25
"svelte-french-toast": "^1.2.0",
36
-
"tailwindcss": "^4.1.14"
26
+
"tailwindcss": "^4.1.13"
37
27
}
38
28
}
+2
-12
src/app.d.ts
+2
-12
src/app.d.ts
···
1
-
// See https://svelte.dev/docs/kit/types#app.d.ts
2
-
3
-
import type { Agent } from "@atproto/api";
4
-
import type { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
5
-
1
+
// See https://kit.svelte.dev/docs/types#app
6
2
// for information about these interfaces
7
3
declare global {
8
4
namespace App {
9
5
// interface Error {}
10
-
11
-
// set on `hooks.server.ts`, available on server functions
12
-
interface Locals {
13
-
authedAgent: Agent | undefined;
14
-
user: ProfileViewDetailed | undefined;
15
-
}
16
-
6
+
// interface Locals {}
17
7
// interface PageData {}
18
8
// interface PageState {}
19
9
// interface Platform {}
-41
src/hooks.server.ts
-41
src/hooks.server.ts
···
1
-
import { Agent } from "@atproto/api";
2
-
import { atclient } from "$lib/atproto";
3
-
4
-
import { decryptToString } from "$lib/server/encryption";
5
-
import { decodeBase64, decodeBase64urlIgnorePadding } from "@oslojs/encoding";
6
-
7
-
import type { Handle } from "@sveltejs/kit";
8
-
import { ENCRYPTION_PASSWORD } from "$env/static/private";
9
-
10
-
// runs everytime there's a new request
11
-
export const handle: Handle = async ({ event, resolve }) => {
12
-
const sid = event.cookies.get("sid");
13
-
14
-
// if there is a session cookie
15
-
if (sid) {
16
-
// if a user is already authed, skip reauthing
17
-
if (event.locals.user) { return resolve(event); }
18
-
19
-
// decrypt session cookie
20
-
const decoded = decodeBase64urlIgnorePadding(sid);
21
-
const key = decodeBase64(ENCRYPTION_PASSWORD);
22
-
const decrypted = await decryptToString(key, decoded);
23
-
24
-
// get oauth session from client using decrypted cookie
25
-
const oauthSession = await atclient.restore(decrypted);
26
-
27
-
// set the authed agent
28
-
const authedAgent = new Agent(oauthSession);
29
-
if (!event.locals.authedAgent) {
30
-
event.locals.authedAgent = authedAgent;
31
-
}
32
-
33
-
// set the authed user with decrypted session DID
34
-
const user = await authedAgent.getProfile({ actor: decrypted });
35
-
event.locals.user = user.data;
36
-
}
37
-
38
-
return resolve(event);
39
-
}
40
-
41
-
-92
src/lib/atproto.ts
-92
src/lib/atproto.ts
···
1
-
import { eq } from "drizzle-orm";
2
-
import * as schema from "./schema";
3
-
import { db as database } from "./server/db";
4
-
import { NodeOAuthClient } from "@atproto/oauth-client-node";
5
-
import type { NodeSavedSession, NodeSavedSessionStore, NodeSavedState, NodeSavedStateStore } from "@atproto/oauth-client-node";
6
-
import { db } from "./server/db";
7
-
import { dev } from "$app/environment";
8
-
9
-
// can be implemented with your preferred DB and ORM
10
-
// both stores are the same, only different is 'state' and 'session'
11
-
12
-
export class AuthStateStore implements NodeSavedStateStore {
13
-
constructor(private db: typeof database) {}
14
-
15
-
async get(key: string): Promise<NodeSavedState | undefined> {
16
-
const result = await this.db.query.AuthState.findFirst({
17
-
where: eq(schema.AuthState.key, key)
18
-
});
19
-
20
-
if (!result) return;
21
-
22
-
return result.state as NodeSavedState;
23
-
}
24
-
25
-
async set(key: string, val: NodeSavedState) {
26
-
await this.db.insert(schema.AuthState)
27
-
.values({ key, state: val })
28
-
.onConflictDoUpdate({
29
-
target: schema.AuthState.key,
30
-
set: { state: val }
31
-
});
32
-
}
33
-
34
-
async del(key: string) {
35
-
await this.db.delete(schema.AuthState)
36
-
.where(eq(schema.AuthState.key, key));
37
-
}
38
-
}
39
-
40
-
export class AuthSessionStore implements NodeSavedSessionStore {
41
-
constructor(private db: typeof database) {}
42
-
43
-
async get(key: string): Promise<NodeSavedSession | undefined> {
44
-
const result = await this.db.query.AuthSession.findFirst({
45
-
where: eq(schema.AuthSession.key, key)
46
-
});
47
-
48
-
if (!result) return;
49
-
return result.session as NodeSavedSession;
50
-
}
51
-
52
-
async set(key: string, val: NodeSavedSession) {
53
-
await this.db.insert(schema.AuthSession)
54
-
.values({ key, session: val })
55
-
.onConflictDoUpdate({
56
-
target: schema.AuthSession.key,
57
-
set: { session: val }
58
-
});
59
-
}
60
-
61
-
async del(key: string) {
62
-
await this.db.delete(schema.AuthSession)
63
-
.where(eq(schema.AuthSession.key, key));
64
-
}
65
-
}
66
-
67
-
const publicUrl = "https://easytodo.link"
68
-
// localhost resolves to either 127.0.0.1 or [::1] (if ipv6)
69
-
const url = dev ? "http://[::1]:5173" : publicUrl;
70
-
71
-
export const atclient = new NodeOAuthClient({
72
-
stateStore: new AuthStateStore(db),
73
-
sessionStore: new AuthSessionStore(db),
74
-
clientMetadata: {
75
-
client_name: "easytodo.link",
76
-
client_id: !dev ? `${publicUrl}/client-metadata.json`
77
-
: `http://localhost?redirect_uri=${
78
-
encodeURIComponent(`${url}/oauth/callback`)
79
-
}&scope=${
80
-
encodeURIComponent(`atproto repo:link.easytodo.tasks.list repo:link.easytodo.tasks.task rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview`)
81
-
}`,
82
-
client_uri: url,
83
-
redirect_uris: [`${url}/oauth/callback`],
84
-
scope: "atproto repo:link.easytodo.tasks.list repo:link.easytodo.tasks.task rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview",
85
-
grant_types: ["authorization_code", "refresh_token"],
86
-
application_type: "web",
87
-
token_endpoint_auth_method: "none",
88
-
dpop_bound_access_tokens: true
89
-
}
90
-
});
91
-
92
-
-11
src/lib/schema.ts
-11
src/lib/schema.ts
···
1
-
import { pgTable, text, json } from 'drizzle-orm/pg-core';
2
-
3
-
export const AuthState = pgTable('auth_state', {
4
-
key: text('key').primaryKey().unique(),
5
-
state: json('state').notNull()
6
-
});
7
-
8
-
export const AuthSession = pgTable('auth_session', {
9
-
key: text('key').primaryKey().unique(),
10
-
session: json('session').notNull()
11
-
});
-10
src/lib/server/db.ts
-10
src/lib/server/db.ts
···
1
-
import { drizzle } from 'drizzle-orm/postgres-js';
2
-
import postgres from 'postgres';
3
-
import { env } from '$env/dynamic/private';
4
-
import * as schema from "../schema";
5
-
6
-
if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
7
-
const client = postgres(env.DATABASE_URL);
8
-
9
-
// add schema
10
-
export const db = drizzle(client, { schema });
-50
src/lib/server/encryption.ts
-50
src/lib/server/encryption.ts
···
1
-
// Code by @pilcrowonpaper on GitHub: https://gist.github.com/pilcrowonpaper/353318556029221c8e25f451b91e5f76
2
-
// AES128 with the Web Crypto API.
3
-
async function encrypt(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
4
-
const iv = new Uint8Array(16);
5
-
crypto.getRandomValues(iv);
6
-
const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["encrypt"]);
7
-
const cipher = await crypto.subtle.encrypt(
8
-
{
9
-
name: "AES-GCM",
10
-
iv,
11
-
tagLength: 128
12
-
},
13
-
cryptoKey,
14
-
data
15
-
);
16
-
const encrypted = new Uint8Array(iv.byteLength + cipher.byteLength);
17
-
encrypted.set(iv);
18
-
encrypted.set(new Uint8Array(cipher), iv.byteLength);
19
-
return encrypted;
20
-
}
21
-
22
-
export async function encryptString(key: Uint8Array, data: string): Promise<Uint8Array> {
23
-
const encoded = new TextEncoder().encode(data);
24
-
const encrypted = await encrypt(key, encoded);
25
-
return encrypted;
26
-
}
27
-
28
-
async function decrypt(key: Uint8Array, encrypted: Uint8Array): Promise<Uint8Array> {
29
-
if (encrypted.length < 16) {
30
-
throw new Error("Invalid data");
31
-
}
32
-
const cryptoKey = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["decrypt"]);
33
-
const decrypted = await crypto.subtle.decrypt(
34
-
{
35
-
name: "AES-GCM",
36
-
iv: encrypted.slice(0, 16),
37
-
tagLength: 128
38
-
},
39
-
cryptoKey,
40
-
encrypted.slice(16)
41
-
);
42
-
return new Uint8Array(decrypted);
43
-
}
44
-
45
-
export async function decryptToString(key: Uint8Array, data: Uint8Array): Promise<string> {
46
-
const decrypted = await decrypt(key, data);
47
-
const decoded = new TextDecoder().decode(decrypted);
48
-
return decoded;
49
-
}
50
-
-2
src/lib/stores.svelte.ts
-2
src/lib/stores.svelte.ts
···
38
38
// optional
39
39
duration?: number;
40
40
stopwatchInterval?: number;
41
-
rkey?: string;
42
41
}
43
42
44
43
export type List = {
45
44
id: string;
46
45
title: string;
47
46
tasks: Task[];
48
-
rkey?: string;
49
47
}
50
48
51
49
export const local_lists = persisted<List[]>("local_lists", [
-10
src/lib/utils.ts
-10
src/lib/utils.ts
···
4
4
return generateRandomString(10, alphabet("a-z", "0-9"));
5
5
}
6
6
7
-
export function parseAtUri(uri: string) {
8
-
const regex = /at:\/\/(?<did>did.*)\/(?<lexi>.*)\/(?<rkey>.*)/;
9
-
const groups = regex.exec(uri)?.groups;
10
-
return {
11
-
did: groups?.did,
12
-
lexi: groups?.lexi,
13
-
rkey: groups?.rkey
14
-
}
15
-
}
16
-
17
7
export function formatSecondsToDuration(seconds: number = 0) {
18
8
let hours = Math.floor(seconds / 3600);
19
9
let minutes = Math.floor((seconds - (hours * 3600)) / 60);
-10
src/routes/+layout.server.ts
-10
src/routes/+layout.server.ts
···
1
-
import type { LayoutServerLoadEvent } from "./$types";
2
-
3
-
export async function load({ locals }: LayoutServerLoadEvent) {
4
-
// have user available throughout the app via LayoutData
5
-
return !locals.user ? undefined : { user: {
6
-
did: locals.user.did,
7
-
handle: locals.user.handle,
8
-
avatar: locals.user.avatar
9
-
}};
10
-
}
+16
-54
src/routes/+layout.svelte
+16
-54
src/routes/+layout.svelte
···
1
1
<script lang="ts">
2
2
import "../app.css";
3
-
import { onMount } from "svelte";
3
+
import { onMount, type Snippet } from "svelte";
4
4
import { page } from "$app/state";
5
5
import { goto } from "$app/navigation";
6
6
import { fade } from "svelte/transition";
7
-
import type { LayoutProps } from "./$types";
8
7
import toast, { Toaster } from "svelte-french-toast";
9
8
import { persisted, pinned_list } from "$lib/stores.svelte";
10
9
11
-
let { data, children }: LayoutProps = $props();
12
-
let { user } = $derived(data);
10
+
interface Props {
11
+
children: Snippet
12
+
}
13
+
14
+
let { children }: Props = $props();
13
15
14
16
let theme = persisted<string>("theme", "dark");
15
17
let is_menu_open = $state(false);
16
-
let loginDialog = $state<HTMLDialogElement>();
17
-
let accountDialog = $state<HTMLDialogElement>();
18
18
let theme_style = $derived(theme.value === "dark"
19
19
? "text-white absolute top-0 z-[-2] h-screen w-screen bg-[#000000] bg-[radial-gradient(#ffffff33_1px,#00091d_1px)] bg-size-[20px_20px]"
20
20
: "text-black absolute inset-0 -z-10 h-full w-full bg-white bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] bg-size-[16px_16px]"
···
36
36
{@render children()}
37
37
</section>
38
38
39
-
<dialog bind:this={loginDialog} class="flex flex-col w-lg gap-4 bg-white top-1/2 left-1/2 -translate-1/2 p-4 rounded">
40
-
<span class="flex items-center gap-4 self-end w-full justify-between">
41
-
<h1 class="text-xl font-bold">Log into the Atmosphere</h1>
42
-
<button onclick={() => loginDialog?.close()} class="bg-gray-100 px-3 py-2 rounded self-end">Close</button>
43
-
</span>
44
-
<form method="POST" action="/?/login" class="flex flex-col gap-4">
45
-
<input name="handle" type="text" placeholder="zeu.dev" class="border rounded px-4 py-2" />
46
-
<button type="submit" class="border px-3 py-2 rounded">Login</button>
47
-
</form>
48
-
<details class="border border-gray-300 px-3 py-2 rounded">
49
-
<summary class="marker:hidden font-semibold cursor-pointer">
50
-
<span class="text-blue-500">@</span> Enter your internet handle
51
-
</summary>
52
-
<span class="flex flex-col gap-2 text-sm pt-1">
53
-
<p>
54
-
This would be a domain you control, most likely first created with Bluesky, Tangled, Gander,
55
-
or other Atmosphere applications.
56
-
</p>
57
-
<a href="" class="text-blue-500 underline">
58
-
Learn more about ATproto and controlling your social media data
59
-
</a>
60
-
</span>
61
-
</details>
62
-
</dialog>
63
-
64
-
<dialog bind:this={accountDialog} class="bg-white p-6 shadow top-1/2 left-1/2 -translate-1/2">
65
-
<h1>Account</h1>
66
-
<button onclick={() => accountDialog?.close()}>Close</button>
67
-
<form method="POST" action="/?/logout">
68
-
<button type="submit">Logout</button>
69
-
</form>
70
-
</dialog>
71
-
72
39
<aside class="z-50 fixed inset-x-0 bottom-0 text-black! flex w-full h-fit items-end justify-between p-8 pointer-events-none">
73
40
<div class="flex flex-col justify-start gap-4 pointer-events-auto">
74
41
{#if is_menu_open}
···
116
83
</button>
117
84
118
85
<!-- TODO: change to <a href='/login'> -->
119
-
{#if !user}
120
-
<button
121
-
onclick={() => loginDialog?.showModal()}
122
-
class="items-center h-fit w-full hover:bg-slate-500/10 rounded-full"
123
-
>
124
-
<img src="/login-line.svg" alt="Login" class="w-12 h-12"/>
125
-
</button>
126
-
{:else}
127
-
<button
128
-
onclick={() => accountDialog?.showModal()}
129
-
class="items-center h-fit w-full rounded-full"
130
-
>
131
-
<img src={user.avatar || "/user-line.svg"} alt="Login" class="w-10 h-10 rounded-full" />
132
-
</button>
133
-
{/if}
86
+
<button
87
+
onclick={comingSoon}
88
+
class="items-center h-fit w-full hover:bg-slate-500/10 rounded-full"
89
+
>
90
+
<img src="/login-line.svg" alt="Login" class="w-12 h-12"/>
91
+
</button>
134
92
</nav>
135
93
</div>
136
94
···
148
106
</aside>
149
107
<Toaster />
150
108
</div>
109
+
110
+
<style lang="postcss">
111
+
@reference "tailwindcss";
112
+
</style>
-116
src/routes/+page.server.ts
-116
src/routes/+page.server.ts
···
1
-
import { atclient } from "$lib/atproto";
2
-
import type { Task } from "$lib/stores.svelte";
3
-
import { parseAtUri } from "$lib/utils";
4
-
import type { $Typed } from "@atproto/api";
5
-
import type { Create, CreateResult } from "@atproto/api/dist/client/types/com/atproto/repo/applyWrites";
6
-
import { isValidHandle } from "@atproto/syntax";
7
-
import { error, fail, redirect, type Actions } from "@sveltejs/kit";
8
-
9
-
export const actions: Actions = {
10
-
login: async ({ request }) => {
11
-
// get handle from form
12
-
const formData = await request.formData();
13
-
const handle = formData.get("handle") as string;
14
-
15
-
// validate handle using ATProto SDK
16
-
if (!isValidHandle(handle)) {
17
-
error(400, { message: "Invalid handle" });
18
-
}
19
-
20
-
// get oauth authorizing url to redirect to
21
-
const redirectUrl = await atclient.authorize(handle, {
22
-
scope: "atproto repo:link.easytodo.tasks.list repo:link.easytodo.tasks.task rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app%23bsky_appview"
23
-
});
24
-
25
-
if (!redirectUrl) {
26
-
error(500, { message: "Unable to authorize" });
27
-
}
28
-
29
-
// redirect for user to authorize
30
-
redirect(301, redirectUrl.toString());
31
-
},
32
-
logout: async ({ cookies }) => {
33
-
cookies.delete("sid", { path: "/" });
34
-
redirect(301, "/");
35
-
},
36
-
37
-
38
-
// ATProto CRUD
39
-
saveListRecord: async ({ request, locals }) => {
40
-
const user = locals.user;
41
-
const agent = locals.authedAgent;
42
-
if (!user || !agent) { return fail(401); }
43
-
44
-
const formData = await request.formData();
45
-
const id = formData.get("id") as string;
46
-
const list_rkey = formData.get("rkey") as string;
47
-
const title = formData.get("title") as string;
48
-
const tasks = JSON.parse(formData.get("tasks") as string) as Task[];
49
-
50
-
const response = await agent.com.atproto.repo.applyWrites({
51
-
repo: user.did,
52
-
writes: tasks.map((t) => {
53
-
const { rkey: task_rkey, stopwatchInterval, ...rest } = t;
54
-
if (task_rkey) {
55
-
console.log("UPDATE TASK");
56
-
return {
57
-
$type: 'com.atproto.repo.applyWrites#update',
58
-
collection: "link.easytodo.tasks.task",
59
-
rkey: task_rkey,
60
-
value: {
61
-
$type: "link.easytodo.tasks.task",
62
-
...rest
63
-
}
64
-
}
65
-
}
66
-
else {
67
-
console.log("CREATE TASK");
68
-
return {
69
-
$type: 'com.atproto.repo.applyWrites#create',
70
-
collection: "link.easytodo.tasks.task",
71
-
value: {
72
-
$type: "link.easytodo.tasks.task",
73
-
...rest
74
-
},
75
-
}
76
-
}
77
-
})
78
-
});
79
-
80
-
if (response.success) {
81
-
console.log(response.data.results);
82
-
const list_record = {
83
-
$type: "link.easytodo.tasks.list",
84
-
createdAt: new Date().toISOString(),
85
-
id,
86
-
title,
87
-
tasks: response.data.results?.map((t) => {
88
-
// @ts-ignore
89
-
return { cid: t.cid, uri: t.uri }
90
-
})
91
-
};
92
-
93
-
if (list_rkey) {
94
-
const { success, data } = await agent.com.atproto.repo.putRecord({
95
-
rkey: list_rkey,
96
-
repo: user.did,
97
-
collection: "link.easytodo.tasks.list",
98
-
record: list_record
99
-
});
100
-
console.log("UPDATE LIST", { success, uri: data.uri });
101
-
return { saveListRecordResult: { success, rkey: list_rkey, uri: data.uri }};
102
-
}
103
-
else {
104
-
const { success, data } = await agent.com.atproto.repo.createRecord({
105
-
repo: user.did,
106
-
collection: "link.easytodo.tasks.list",
107
-
record: list_record
108
-
});
109
-
const { rkey } = parseAtUri(data.uri);
110
-
console.log("CREATE LIST", { success, rkey, uri: data.uri });
111
-
return { saveListRecordResult: { success, rkey, uri: data.uri }};
112
-
}
113
-
114
-
}
115
-
}
116
-
};
+7
-44
src/routes/[id]/+page.svelte
+7
-44
src/routes/[id]/+page.svelte
···
1
1
<script lang="ts">
2
2
import { onMount } from "svelte";
3
3
import { page } from "$app/state";
4
-
import { enhance } from "$app/forms";
5
4
import { goto } from "$app/navigation";
6
5
import toast from "svelte-french-toast";
7
-
import type { PageProps } from "../$types.js";
8
6
import { formatSecondsToDuration, generateId } from "$lib/utils";
9
7
import { local_lists, pinned_list, type List, type Task } from "$lib/stores.svelte";
10
8
11
-
let { data, form }: PageProps = $props();
12
-
let { user } = $derived(data);
13
-
let is_lists_menu_open = $state(false);
14
-
let is_cloud_menu_open = $state(false);
9
+
let is_menu_open = $state(false);
15
10
let list : List | undefined = $state(local_lists.value!.find((l) => l.id === page.params.id));
16
11
let task_input = $state("");
17
12
let user_lists = $derived(local_lists.value) as List[];
···
19
14
// since list points to something inside local_lists,
20
15
// it will run when list state changes
21
16
$effect(() => local_lists.update());
22
-
23
-
$effect(() => {
24
-
if (form?.saveListRecordResult.success) {
25
-
toast.success("Successfully saved to PDS!");
26
-
}
27
-
});
28
17
29
18
function addTask() {
30
19
if (task_input.length === 0) {
···
117
106
{#if list}
118
107
<section class="relative flex gap-4 w-full">
119
108
<div class="flex gap-4 border-black border w-fit h-fit p-2 bg-white rounded-xl">
120
-
<button onclick={() => is_lists_menu_open = !is_lists_menu_open}>
109
+
<button onclick={() => is_menu_open = !is_menu_open}>
121
110
<img
122
111
src="/list-box-line.svg"
123
-
alt="Lists menu button"
112
+
alt="Lists button"
124
113
class="w-12 h-12 hover:bg-slate-500/10 rounded-full"
125
114
/>
126
115
</button>
···
131
120
class="w-12 h-12 hover:bg-slate-500/10 rounded-full"
132
121
/>
133
122
</button>
134
-
{#if user}
135
-
<button onclick={() => is_cloud_menu_open = !is_cloud_menu_open}>
136
-
<img
137
-
src="/cloud.svg"
138
-
alt="Cloud menu button"
139
-
class="w-12 h-12 p-2 hover:bg-slate-500/10 rounded-full"
140
-
/>
141
-
</button>
142
-
{/if}
143
123
<button onclick={deleteList}>
144
124
<img
145
125
src="/trash-line.svg"
···
149
129
</button>
150
130
</div>
151
131
152
-
{#if is_lists_menu_open}
132
+
{#if is_menu_open}
153
133
<menu class="absolute flex flex-col gap-2 w-fit h-fit top-20 p-2 bg-white border border-black rounded-lg text-black! text-lg!">
154
134
{#each user_lists as user_list : List (user_list.id)}
155
135
<button
156
136
onclick={() => {
157
-
switchToList(user_list.id);
158
-
is_lists_menu_open = false;
137
+
switchToList(user_list.id)
138
+
is_menu_open = false;
159
139
}}
160
140
class="flex gap-2 justify-between text-start w-full h-full rounded-xl pl-2 pr-5 py-2 hover:bg-slate-500/10 transition-all duration-150 items-center"
161
141
>
···
168
148
<button
169
149
onclick={() => {
170
150
createList();
171
-
is_lists_menu_open = false;
151
+
is_menu_open = false;
172
152
}}
173
153
class="flex gap-2 justify-between text-start w-full h-full rounded-xl pl-2 pr-5 py-2 hover:bg-slate-500/10 transition-all duration-150 items-center"
174
154
>
175
155
Create new list
176
156
</button>
177
-
</menu>
178
-
{/if}
179
-
180
-
{#if is_cloud_menu_open}
181
-
<menu class="absolute flex flex-col gap-2 w-fit h-fit top-20 p-2 bg-white border border-black rounded-lg text-black! text-lg!">
182
-
<form method="POST" action="/?/saveListRecord" use:enhance>
183
-
<input name="id" type="hidden" value={list.id} />
184
-
<input name="title" type="hidden" value={list.title} />
185
-
<input name="tasks" type="hidden" value={JSON.stringify(list.tasks)} />
186
-
<button
187
-
type="submit"
188
-
class="flex gap-2 justify-between text-start w-full h-full rounded-xl pl-2 pr-5 py-2 hover:bg-slate-500/10 transition-all duration-150 items-center"
189
-
>
190
-
<img src="/save.svg" alt="Save to PDS button" class="w-8 h-8 p-2"/>
191
-
Save to PDS
192
-
</button>
193
-
</form>
194
157
</menu>
195
158
{/if}
196
159
</section>
-6
src/routes/client-metadata.json/+server.ts
-6
src/routes/client-metadata.json/+server.ts
-34
src/routes/oauth/callback/+server.ts
-34
src/routes/oauth/callback/+server.ts
···
1
-
import { atclient } from "$lib/atproto";
2
-
import { encryptString } from "$lib/server/encryption";
3
-
import { decodeBase64, encodeBase64urlNoPadding } from "@oslojs/encoding";
4
-
5
-
import { error, redirect } from "@sveltejs/kit";
6
-
import type { RequestEvent } from "@sveltejs/kit";
7
-
import { ENCRYPTION_PASSWORD } from "$env/static/private";
8
-
9
-
// called on after authorizing OAuth
10
-
export async function GET({ request, cookies }: RequestEvent) {
11
-
// get parameters set by the callback
12
-
const params = new URLSearchParams(request.url.split("?")[1]);
13
-
14
-
try {
15
-
const { session } = await atclient.callback(params);
16
-
const key = decodeBase64(ENCRYPTION_PASSWORD);
17
-
18
-
// encrypt the user DID
19
-
const encrypted = await encryptString(key, session.did);
20
-
const encoded = encodeBase64urlNoPadding(encrypted);
21
-
22
-
// set encoded session DID as cookies for auth
23
-
cookies.set("sid", encoded, {
24
-
path: "/",
25
-
maxAge: 60 * 60,
26
-
httpOnly: true,
27
-
sameSite: "lax"
28
-
});
29
-
} catch (err) {
30
-
error(500, { message: (err as Error).message });
31
-
}
32
-
33
-
redirect(301, "/");
34
-
}
-1
static/cloud.svg
-1
static/cloud.svg
···
1
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9"/></svg>
-1
static/save.svg
-1
static/save.svg
···
1
-
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/><path d="M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7M7 3v4a1 1 0 0 0 1 1h7"/></g></svg>
-1
static/user-line.svg
-1
static/user-line.svg
···
1
-
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="12" cy="8" r="5"/><path d="M20 21a8 8 0 1 0-16 0m16 0a8 8 0 1 0-16 0"/></g></svg>