Compare changes

Choose any two refs to compare.

+6 -1
.gitignore
··· 23 23 vite.config.ts.timestamp-* 24 24 25 25 .idea 26 - local.db 26 + local.db 27 + 28 + #tap 29 + tap.db 30 + tap.db-shm 31 + tap.db-wal
+14
dev.compose.yml
··· 26 26 timeout: 5s 27 27 networks: 28 28 - services-network 29 + tap: 30 + image: ghcr.io/bluesky-social/indigo/tap:latest 31 + platform: linux/amd64 32 + depends_on: 33 + - postgres 34 + - valkey 35 + ports: 36 + - '2480:2480' 37 + env_file: 38 + - .env 39 + extra_hosts: 40 + - "host.docker.internal:host-gateway" 41 + network_mode: "host" 42 + 29 43 volumes: 30 44 valkey_data: 31 45 postgres_data:
+35
drizzle/0000_breezy_menace.sql
··· 1 + CREATE TABLE "record_pokes" ( 2 + "id" serial PRIMARY KEY NOT NULL, 3 + "recordId" integer, 4 + "pokersRepo" text NOT NULL, 5 + "atUri" text NOT NULL, 6 + "indexedAt" time DEFAULT now() NOT NULL 7 + ); 8 + --> statement-breakpoint 9 + CREATE TABLE "records" ( 10 + "id" serial PRIMARY KEY NOT NULL, 11 + "rkey" varchar NOT NULL, 12 + "collection" varchar NOT NULL, 13 + "repo" varchar NOT NULL, 14 + "atUri" text NOT NULL, 15 + "data" jsonb NOT NULL, 16 + "indexedAt" timestamp DEFAULT now() NOT NULL 17 + ); 18 + --> statement-breakpoint 19 + CREATE TABLE "user_pokes" ( 20 + "id" serial PRIMARY KEY NOT NULL, 21 + "subject" text NOT NULL, 22 + "poker" text NOT NULL, 23 + "at_uri" text NOT NULL, 24 + "indexedAt" time DEFAULT now() NOT NULL 25 + ); 26 + --> statement-breakpoint 27 + ALTER TABLE "record_pokes" ADD CONSTRAINT "record_pokes_recordId_records_id_fk" FOREIGN KEY ("recordId") REFERENCES "public"."records"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint 28 + CREATE INDEX "record_pokes_pokersRepo_index" ON "record_pokes" USING btree ("pokersRepo");--> statement-breakpoint 29 + CREATE INDEX "record_pokes_atUri_index" ON "record_pokes" USING btree ("atUri");--> statement-breakpoint 30 + CREATE INDEX "records_rkey_index" ON "records" USING btree ("rkey");--> statement-breakpoint 31 + CREATE INDEX "records_collection_index" ON "records" USING btree ("collection");--> statement-breakpoint 32 + CREATE INDEX "records_repo_index" ON "records" USING btree ("repo");--> statement-breakpoint 33 + CREATE UNIQUE INDEX "records_atUri_index" ON "records" USING btree ("atUri");--> statement-breakpoint 34 + CREATE INDEX "user_pokes_subject_index" ON "user_pokes" USING btree ("subject");--> statement-breakpoint 35 + CREATE INDEX "user_pokes_poker_index" ON "user_pokes" USING btree ("poker");
-14
drizzle/0000_cultured_thor_girl.sql
··· 1 - CREATE TABLE `key_value_store` ( 2 - `key` text PRIMARY KEY NOT NULL, 3 - `value` text, 4 - `storeName` text, 5 - `createdAt` integer 6 - ); 7 - --> statement-breakpoint 8 - CREATE TABLE `session_store` ( 9 - `id` text PRIMARY KEY NOT NULL, 10 - `did` text NOT NULL, 11 - `handle` text NOT NULL, 12 - `createdAt` integer NOT NULL, 13 - `expiresAt` integer NOT NULL 14 - );
+254 -55
drizzle/meta/0000_snapshot.json
··· 1 1 { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "a1fafe21-58d6-4360-80a9-ab14cdefb1d6", 2 + "id": "b5b063c6-2451-42ca-8bef-0119b8202cb3", 5 3 "prevId": "00000000-0000-0000-0000-000000000000", 4 + "version": "7", 5 + "dialect": "postgresql", 6 6 "tables": { 7 - "key_value_store": { 8 - "name": "key_value_store", 7 + "public.record_pokes": { 8 + "name": "record_pokes", 9 + "schema": "", 9 10 "columns": { 10 - "key": { 11 - "name": "key", 11 + "id": { 12 + "name": "id", 13 + "type": "serial", 14 + "primaryKey": true, 15 + "notNull": true 16 + }, 17 + "recordId": { 18 + "name": "recordId", 19 + "type": "integer", 20 + "primaryKey": false, 21 + "notNull": false 22 + }, 23 + "pokersRepo": { 24 + "name": "pokersRepo", 25 + "type": "text", 26 + "primaryKey": false, 27 + "notNull": true 28 + }, 29 + "atUri": { 30 + "name": "atUri", 12 31 "type": "text", 32 + "primaryKey": false, 33 + "notNull": true 34 + }, 35 + "indexedAt": { 36 + "name": "indexedAt", 37 + "type": "time", 38 + "primaryKey": false, 39 + "notNull": true, 40 + "default": "now()" 41 + } 42 + }, 43 + "indexes": { 44 + "record_pokes_pokersRepo_index": { 45 + "name": "record_pokes_pokersRepo_index", 46 + "columns": [ 47 + { 48 + "expression": "pokersRepo", 49 + "isExpression": false, 50 + "asc": true, 51 + "nulls": "last" 52 + } 53 + ], 54 + "isUnique": false, 55 + "concurrently": false, 56 + "method": "btree", 57 + "with": {} 58 + }, 59 + "record_pokes_atUri_index": { 60 + "name": "record_pokes_atUri_index", 61 + "columns": [ 62 + { 63 + "expression": "atUri", 64 + "isExpression": false, 65 + "asc": true, 66 + "nulls": "last" 67 + } 68 + ], 69 + "isUnique": false, 70 + "concurrently": false, 71 + "method": "btree", 72 + "with": {} 73 + } 74 + }, 75 + "foreignKeys": { 76 + "record_pokes_recordId_records_id_fk": { 77 + "name": "record_pokes_recordId_records_id_fk", 78 + "tableFrom": "record_pokes", 79 + "tableTo": "records", 80 + "columnsFrom": [ 81 + "recordId" 82 + ], 83 + "columnsTo": [ 84 + "id" 85 + ], 86 + "onDelete": "no action", 87 + "onUpdate": "no action" 88 + } 89 + }, 90 + "compositePrimaryKeys": {}, 91 + "uniqueConstraints": {}, 92 + "policies": {}, 93 + "checkConstraints": {}, 94 + "isRLSEnabled": false 95 + }, 96 + "public.records": { 97 + "name": "records", 98 + "schema": "", 99 + "columns": { 100 + "id": { 101 + "name": "id", 102 + "type": "serial", 13 103 "primaryKey": true, 14 - "notNull": true, 15 - "autoincrement": false 104 + "notNull": true 105 + }, 106 + "rkey": { 107 + "name": "rkey", 108 + "type": "varchar", 109 + "primaryKey": false, 110 + "notNull": true 111 + }, 112 + "collection": { 113 + "name": "collection", 114 + "type": "varchar", 115 + "primaryKey": false, 116 + "notNull": true 16 117 }, 17 - "value": { 18 - "name": "value", 19 - "type": "text", 118 + "repo": { 119 + "name": "repo", 120 + "type": "varchar", 20 121 "primaryKey": false, 21 - "notNull": false, 22 - "autoincrement": false 122 + "notNull": true 23 123 }, 24 - "storeName": { 25 - "name": "storeName", 124 + "atUri": { 125 + "name": "atUri", 26 126 "type": "text", 27 127 "primaryKey": false, 28 - "notNull": false, 29 - "autoincrement": false 128 + "notNull": true 30 129 }, 31 - "createdAt": { 32 - "name": "createdAt", 33 - "type": "integer", 130 + "data": { 131 + "name": "data", 132 + "type": "jsonb", 133 + "primaryKey": false, 134 + "notNull": true 135 + }, 136 + "indexedAt": { 137 + "name": "indexedAt", 138 + "type": "timestamp", 34 139 "primaryKey": false, 35 - "notNull": false, 36 - "autoincrement": false 140 + "notNull": true, 141 + "default": "now()" 142 + } 143 + }, 144 + "indexes": { 145 + "records_rkey_index": { 146 + "name": "records_rkey_index", 147 + "columns": [ 148 + { 149 + "expression": "rkey", 150 + "isExpression": false, 151 + "asc": true, 152 + "nulls": "last" 153 + } 154 + ], 155 + "isUnique": false, 156 + "concurrently": false, 157 + "method": "btree", 158 + "with": {} 159 + }, 160 + "records_collection_index": { 161 + "name": "records_collection_index", 162 + "columns": [ 163 + { 164 + "expression": "collection", 165 + "isExpression": false, 166 + "asc": true, 167 + "nulls": "last" 168 + } 169 + ], 170 + "isUnique": false, 171 + "concurrently": false, 172 + "method": "btree", 173 + "with": {} 174 + }, 175 + "records_repo_index": { 176 + "name": "records_repo_index", 177 + "columns": [ 178 + { 179 + "expression": "repo", 180 + "isExpression": false, 181 + "asc": true, 182 + "nulls": "last" 183 + } 184 + ], 185 + "isUnique": false, 186 + "concurrently": false, 187 + "method": "btree", 188 + "with": {} 189 + }, 190 + "records_atUri_index": { 191 + "name": "records_atUri_index", 192 + "columns": [ 193 + { 194 + "expression": "atUri", 195 + "isExpression": false, 196 + "asc": true, 197 + "nulls": "last" 198 + } 199 + ], 200 + "isUnique": true, 201 + "concurrently": false, 202 + "method": "btree", 203 + "with": {} 37 204 } 38 205 }, 39 - "indexes": {}, 40 206 "foreignKeys": {}, 41 207 "compositePrimaryKeys": {}, 42 208 "uniqueConstraints": {}, 43 - "checkConstraints": {} 209 + "policies": {}, 210 + "checkConstraints": {}, 211 + "isRLSEnabled": false 44 212 }, 45 - "session_store": { 46 - "name": "session_store", 213 + "public.user_pokes": { 214 + "name": "user_pokes", 215 + "schema": "", 47 216 "columns": { 48 217 "id": { 49 218 "name": "id", 50 - "type": "text", 219 + "type": "serial", 51 220 "primaryKey": true, 52 - "notNull": true, 53 - "autoincrement": false 221 + "notNull": true 54 222 }, 55 - "did": { 56 - "name": "did", 223 + "subject": { 224 + "name": "subject", 57 225 "type": "text", 58 226 "primaryKey": false, 59 - "notNull": true, 60 - "autoincrement": false 227 + "notNull": true 61 228 }, 62 - "handle": { 63 - "name": "handle", 229 + "poker": { 230 + "name": "poker", 64 231 "type": "text", 65 232 "primaryKey": false, 66 - "notNull": true, 67 - "autoincrement": false 233 + "notNull": true 68 234 }, 69 - "createdAt": { 70 - "name": "createdAt", 71 - "type": "integer", 235 + "at_uri": { 236 + "name": "at_uri", 237 + "type": "text", 72 238 "primaryKey": false, 73 - "notNull": true, 74 - "autoincrement": false 239 + "notNull": true 75 240 }, 76 - "expiresAt": { 77 - "name": "expiresAt", 78 - "type": "integer", 241 + "indexedAt": { 242 + "name": "indexedAt", 243 + "type": "time", 79 244 "primaryKey": false, 80 245 "notNull": true, 81 - "autoincrement": false 246 + "default": "now()" 247 + } 248 + }, 249 + "indexes": { 250 + "user_pokes_subject_index": { 251 + "name": "user_pokes_subject_index", 252 + "columns": [ 253 + { 254 + "expression": "subject", 255 + "isExpression": false, 256 + "asc": true, 257 + "nulls": "last" 258 + } 259 + ], 260 + "isUnique": false, 261 + "concurrently": false, 262 + "method": "btree", 263 + "with": {} 264 + }, 265 + "user_pokes_poker_index": { 266 + "name": "user_pokes_poker_index", 267 + "columns": [ 268 + { 269 + "expression": "poker", 270 + "isExpression": false, 271 + "asc": true, 272 + "nulls": "last" 273 + } 274 + ], 275 + "isUnique": false, 276 + "concurrently": false, 277 + "method": "btree", 278 + "with": {} 82 279 } 83 280 }, 84 - "indexes": {}, 85 281 "foreignKeys": {}, 86 282 "compositePrimaryKeys": {}, 87 283 "uniqueConstraints": {}, 88 - "checkConstraints": {} 284 + "policies": {}, 285 + "checkConstraints": {}, 286 + "isRLSEnabled": false 89 287 } 90 288 }, 289 + "enums": {}, 290 + "schemas": {}, 291 + "sequences": {}, 292 + "roles": {}, 293 + "policies": {}, 91 294 "views": {}, 92 - "enums": {}, 93 295 "_meta": { 296 + "columns": {}, 94 297 "schemas": {}, 95 - "tables": {}, 96 - "columns": {} 97 - }, 98 - "internal": { 99 - "indexes": {} 298 + "tables": {} 100 299 } 101 300 }
+4 -4
drizzle/meta/_journal.json
··· 1 1 { 2 2 "version": "7", 3 - "dialect": "sqlite", 3 + "dialect": "postgresql", 4 4 "entries": [ 5 5 { 6 6 "idx": 0, 7 - "version": "6", 8 - "when": 1765476251050, 9 - "tag": "0000_cultured_thor_girl", 7 + "version": "7", 8 + "when": 1766121859810, 9 + "tag": "0000_breezy_menace", 10 10 "breakpoints": true 11 11 } 12 12 ]
+1 -1
drizzle.config.ts
··· 4 4 5 5 export default defineConfig({ 6 6 schema: './src/lib/server/db/schema.ts', 7 - dialect: 'sqlite', 7 + dialect: 'postgresql', 8 8 dbCredentials: { url: process.env.DATABASE_URL }, 9 9 verbose: true, 10 10 strict: true
+8 -3
package.json
··· 24 24 "@sveltejs/adapter-auto": "^7.0.0", 25 25 "@sveltejs/kit": "^2.48.5", 26 26 "@sveltejs/vite-plugin-svelte": "^6.2.1", 27 - "@types/better-sqlite3": "^7.6.13", 28 27 "@types/node": "^24", 28 + "@types/pg": "^8.16.0", 29 29 "dotenv": "^17.2.3", 30 30 "drizzle-kit": "^0.31.7", 31 31 "drizzle-orm": "^0.44.7", ··· 34 34 "globals": "^16.5.0", 35 35 "svelte": "^5.43.8", 36 36 "svelte-check": "^4.3.4", 37 + "tsx": "^4.21.0", 37 38 "typescript": "^5.9.3", 38 39 "typescript-eslint": "^8.47.0", 39 40 "vite": "^7.2.2" ··· 47 48 "@atproto/jwk-jose": "^0.1.11", 48 49 "@atproto/oauth-client-node": "^0.3.13", 49 50 "@atproto/oauth-types": "^0.5.2", 51 + "@atproto/tap": "^0.0.2", 50 52 "@oslojs/crypto": "^1.0.1", 51 53 "@oslojs/encoding": "^1.1.0", 52 54 "@sveltejs/adapter-node": "^5.4.0", 55 + "@tailwindcss/vite": "^4.1.18", 53 56 "@valkey/valkey-glide": "^2.2.1", 54 - "better-sqlite3": "12.4.1", 57 + "daisyui": "^5.5.14", 55 58 "node-schedule": "^2.1.1", 56 - "pino": "^10.1.0" 59 + "pg": "^8.16.3", 60 + "pino": "^10.1.0", 61 + "tailwindcss": "^4.1.18" 57 62 }, 58 63 "optionalDependencies": { 59 64 "@rollup/rollup-linux-x64-musl": "^4.52.5"
+874 -76
pnpm-lock.yaml
··· 32 32 '@atproto/oauth-types': 33 33 specifier: ^0.5.2 34 34 version: 0.5.2 35 + '@atproto/tap': 36 + specifier: ^0.0.2 37 + version: 0.0.2 35 38 '@oslojs/crypto': 36 39 specifier: ^1.0.1 37 40 version: 1.0.1 ··· 40 43 version: 1.1.0 41 44 '@sveltejs/adapter-node': 42 45 specifier: ^5.4.0 43 - version: 5.4.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2))) 46 + version: 5.4.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))) 47 + '@tailwindcss/vite': 48 + specifier: ^4.1.18 49 + version: 4.1.18(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 44 50 '@valkey/valkey-glide': 45 51 specifier: ^2.2.1 46 52 version: 2.2.1 47 - better-sqlite3: 48 - specifier: 12.4.1 49 - version: 12.4.1 53 + daisyui: 54 + specifier: ^5.5.14 55 + version: 5.5.14 50 56 node-schedule: 51 57 specifier: ^2.1.1 52 58 version: 2.1.1 59 + pg: 60 + specifier: ^8.16.3 61 + version: 8.16.3 53 62 pino: 54 63 specifier: ^10.1.0 55 64 version: 10.1.0 65 + tailwindcss: 66 + specifier: ^4.1.18 67 + version: 4.1.18 56 68 devDependencies: 57 69 '@eslint/compat': 58 70 specifier: ^1.4.0 59 - version: 1.4.1(eslint@9.39.1) 71 + version: 1.4.1(eslint@9.39.1(jiti@2.6.1)) 60 72 '@eslint/js': 61 73 specifier: ^9.39.1 62 74 version: 9.39.1 63 75 '@sveltejs/adapter-auto': 64 76 specifier: ^7.0.0 65 - version: 7.0.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2))) 77 + version: 7.0.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))) 66 78 '@sveltejs/kit': 67 79 specifier: ^2.48.5 68 - version: 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 80 + version: 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 69 81 '@sveltejs/vite-plugin-svelte': 70 82 specifier: ^6.2.1 71 - version: 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 72 - '@types/better-sqlite3': 73 - specifier: ^7.6.13 74 - version: 7.6.13 83 + version: 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 75 84 '@types/node': 76 85 specifier: ^24 77 86 version: 24.10.2 87 + '@types/pg': 88 + specifier: ^8.16.0 89 + version: 8.16.0 78 90 dotenv: 79 91 specifier: ^17.2.3 80 92 version: 17.2.3 ··· 83 95 version: 0.31.8 84 96 drizzle-orm: 85 97 specifier: ^0.44.7 86 - version: 0.44.7(@types/better-sqlite3@7.6.13)(better-sqlite3@12.4.1) 98 + version: 0.44.7(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(better-sqlite3@12.4.1)(pg@8.16.3) 87 99 eslint: 88 100 specifier: ^9.39.1 89 - version: 9.39.1 101 + version: 9.39.1(jiti@2.6.1) 90 102 eslint-plugin-svelte: 91 103 specifier: ^3.13.0 92 - version: 3.13.1(eslint@9.39.1)(svelte@5.45.8) 104 + version: 3.13.1(eslint@9.39.1(jiti@2.6.1))(svelte@5.45.8) 93 105 globals: 94 106 specifier: ^16.5.0 95 107 version: 16.5.0 ··· 99 111 svelte-check: 100 112 specifier: ^4.3.4 101 113 version: 4.3.4(picomatch@4.0.3)(svelte@5.45.8)(typescript@5.9.3) 114 + tsx: 115 + specifier: ^4.21.0 116 + version: 4.21.0 102 117 typescript: 103 118 specifier: ^5.9.3 104 119 version: 5.9.3 105 120 typescript-eslint: 106 121 specifier: ^8.47.0 107 - version: 8.49.0(eslint@9.39.1)(typescript@5.9.3) 122 + version: 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 108 123 vite: 109 124 specifier: ^7.2.2 110 - version: 7.2.7(@types/node@24.10.2) 125 + version: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 111 126 optionalDependencies: 112 127 '@rollup/rollup-linux-x64-musl': 113 128 specifier: ^4.52.5 ··· 207 222 '@atproto/syntax@0.4.2': 208 223 resolution: {integrity: sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA==} 209 224 225 + '@atproto/tap@0.0.2': 226 + resolution: {integrity: sha512-CrfJWrvozuSIokOQLMeSFcF5ZpstpxIZ9PnBpgIkbLQQKb3wO+0dn90xZN5jlLjczPHvT4PrF1z8uYgVlujTlg==} 227 + engines: {node: '>=18.7.0'} 228 + 229 + '@atproto/ws-client@0.0.4': 230 + resolution: {integrity: sha512-dox1XIymuC7/ZRhUqKezIGgooZS45C6vHCfu0PnWjfvsLCK2kAlnvX4IBkA/WpcoijDhQ9ejChnFbo/sLmgvAg==} 231 + engines: {node: '>=18.7.0'} 232 + 210 233 '@atproto/xrpc@0.7.7': 211 234 resolution: {integrity: sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA==} 212 235 ··· 231 254 cpu: [ppc64] 232 255 os: [aix] 233 256 257 + '@esbuild/aix-ppc64@0.27.1': 258 + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} 259 + engines: {node: '>=18'} 260 + cpu: [ppc64] 261 + os: [aix] 262 + 234 263 '@esbuild/android-arm64@0.18.20': 235 264 resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} 236 265 engines: {node: '>=12'} ··· 239 268 240 269 '@esbuild/android-arm64@0.25.12': 241 270 resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} 271 + engines: {node: '>=18'} 272 + cpu: [arm64] 273 + os: [android] 274 + 275 + '@esbuild/android-arm64@0.27.1': 276 + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} 242 277 engines: {node: '>=18'} 243 278 cpu: [arm64] 244 279 os: [android] ··· 255 290 cpu: [arm] 256 291 os: [android] 257 292 293 + '@esbuild/android-arm@0.27.1': 294 + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} 295 + engines: {node: '>=18'} 296 + cpu: [arm] 297 + os: [android] 298 + 258 299 '@esbuild/android-x64@0.18.20': 259 300 resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} 260 301 engines: {node: '>=12'} ··· 267 308 cpu: [x64] 268 309 os: [android] 269 310 311 + '@esbuild/android-x64@0.27.1': 312 + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} 313 + engines: {node: '>=18'} 314 + cpu: [x64] 315 + os: [android] 316 + 270 317 '@esbuild/darwin-arm64@0.18.20': 271 318 resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} 272 319 engines: {node: '>=12'} ··· 279 326 cpu: [arm64] 280 327 os: [darwin] 281 328 329 + '@esbuild/darwin-arm64@0.27.1': 330 + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} 331 + engines: {node: '>=18'} 332 + cpu: [arm64] 333 + os: [darwin] 334 + 282 335 '@esbuild/darwin-x64@0.18.20': 283 336 resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} 284 337 engines: {node: '>=12'} ··· 291 344 cpu: [x64] 292 345 os: [darwin] 293 346 347 + '@esbuild/darwin-x64@0.27.1': 348 + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} 349 + engines: {node: '>=18'} 350 + cpu: [x64] 351 + os: [darwin] 352 + 294 353 '@esbuild/freebsd-arm64@0.18.20': 295 354 resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} 296 355 engines: {node: '>=12'} ··· 299 358 300 359 '@esbuild/freebsd-arm64@0.25.12': 301 360 resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} 361 + engines: {node: '>=18'} 362 + cpu: [arm64] 363 + os: [freebsd] 364 + 365 + '@esbuild/freebsd-arm64@0.27.1': 366 + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} 302 367 engines: {node: '>=18'} 303 368 cpu: [arm64] 304 369 os: [freebsd] ··· 315 380 cpu: [x64] 316 381 os: [freebsd] 317 382 383 + '@esbuild/freebsd-x64@0.27.1': 384 + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} 385 + engines: {node: '>=18'} 386 + cpu: [x64] 387 + os: [freebsd] 388 + 318 389 '@esbuild/linux-arm64@0.18.20': 319 390 resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} 320 391 engines: {node: '>=12'} ··· 327 398 cpu: [arm64] 328 399 os: [linux] 329 400 401 + '@esbuild/linux-arm64@0.27.1': 402 + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} 403 + engines: {node: '>=18'} 404 + cpu: [arm64] 405 + os: [linux] 406 + 330 407 '@esbuild/linux-arm@0.18.20': 331 408 resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} 332 409 engines: {node: '>=12'} ··· 339 416 cpu: [arm] 340 417 os: [linux] 341 418 419 + '@esbuild/linux-arm@0.27.1': 420 + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} 421 + engines: {node: '>=18'} 422 + cpu: [arm] 423 + os: [linux] 424 + 342 425 '@esbuild/linux-ia32@0.18.20': 343 426 resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} 344 427 engines: {node: '>=12'} ··· 351 434 cpu: [ia32] 352 435 os: [linux] 353 436 437 + '@esbuild/linux-ia32@0.27.1': 438 + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} 439 + engines: {node: '>=18'} 440 + cpu: [ia32] 441 + os: [linux] 442 + 354 443 '@esbuild/linux-loong64@0.18.20': 355 444 resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} 356 445 engines: {node: '>=12'} ··· 363 452 cpu: [loong64] 364 453 os: [linux] 365 454 455 + '@esbuild/linux-loong64@0.27.1': 456 + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} 457 + engines: {node: '>=18'} 458 + cpu: [loong64] 459 + os: [linux] 460 + 366 461 '@esbuild/linux-mips64el@0.18.20': 367 462 resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} 368 463 engines: {node: '>=12'} ··· 375 470 cpu: [mips64el] 376 471 os: [linux] 377 472 473 + '@esbuild/linux-mips64el@0.27.1': 474 + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} 475 + engines: {node: '>=18'} 476 + cpu: [mips64el] 477 + os: [linux] 478 + 378 479 '@esbuild/linux-ppc64@0.18.20': 379 480 resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} 380 481 engines: {node: '>=12'} ··· 387 488 cpu: [ppc64] 388 489 os: [linux] 389 490 491 + '@esbuild/linux-ppc64@0.27.1': 492 + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} 493 + engines: {node: '>=18'} 494 + cpu: [ppc64] 495 + os: [linux] 496 + 390 497 '@esbuild/linux-riscv64@0.18.20': 391 498 resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} 392 499 engines: {node: '>=12'} ··· 399 506 cpu: [riscv64] 400 507 os: [linux] 401 508 509 + '@esbuild/linux-riscv64@0.27.1': 510 + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} 511 + engines: {node: '>=18'} 512 + cpu: [riscv64] 513 + os: [linux] 514 + 402 515 '@esbuild/linux-s390x@0.18.20': 403 516 resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} 404 517 engines: {node: '>=12'} ··· 411 524 cpu: [s390x] 412 525 os: [linux] 413 526 527 + '@esbuild/linux-s390x@0.27.1': 528 + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} 529 + engines: {node: '>=18'} 530 + cpu: [s390x] 531 + os: [linux] 532 + 414 533 '@esbuild/linux-x64@0.18.20': 415 534 resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} 416 535 engines: {node: '>=12'} ··· 423 542 cpu: [x64] 424 543 os: [linux] 425 544 545 + '@esbuild/linux-x64@0.27.1': 546 + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} 547 + engines: {node: '>=18'} 548 + cpu: [x64] 549 + os: [linux] 550 + 426 551 '@esbuild/netbsd-arm64@0.25.12': 427 552 resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} 553 + engines: {node: '>=18'} 554 + cpu: [arm64] 555 + os: [netbsd] 556 + 557 + '@esbuild/netbsd-arm64@0.27.1': 558 + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} 428 559 engines: {node: '>=18'} 429 560 cpu: [arm64] 430 561 os: [netbsd] ··· 441 572 cpu: [x64] 442 573 os: [netbsd] 443 574 575 + '@esbuild/netbsd-x64@0.27.1': 576 + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} 577 + engines: {node: '>=18'} 578 + cpu: [x64] 579 + os: [netbsd] 580 + 444 581 '@esbuild/openbsd-arm64@0.25.12': 445 582 resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} 583 + engines: {node: '>=18'} 584 + cpu: [arm64] 585 + os: [openbsd] 586 + 587 + '@esbuild/openbsd-arm64@0.27.1': 588 + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} 446 589 engines: {node: '>=18'} 447 590 cpu: [arm64] 448 591 os: [openbsd] ··· 459 602 cpu: [x64] 460 603 os: [openbsd] 461 604 605 + '@esbuild/openbsd-x64@0.27.1': 606 + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} 607 + engines: {node: '>=18'} 608 + cpu: [x64] 609 + os: [openbsd] 610 + 462 611 '@esbuild/openharmony-arm64@0.25.12': 463 612 resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} 613 + engines: {node: '>=18'} 614 + cpu: [arm64] 615 + os: [openharmony] 616 + 617 + '@esbuild/openharmony-arm64@0.27.1': 618 + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} 464 619 engines: {node: '>=18'} 465 620 cpu: [arm64] 466 621 os: [openharmony] ··· 477 632 cpu: [x64] 478 633 os: [sunos] 479 634 635 + '@esbuild/sunos-x64@0.27.1': 636 + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} 637 + engines: {node: '>=18'} 638 + cpu: [x64] 639 + os: [sunos] 640 + 480 641 '@esbuild/win32-arm64@0.18.20': 481 642 resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} 482 643 engines: {node: '>=12'} ··· 489 650 cpu: [arm64] 490 651 os: [win32] 491 652 653 + '@esbuild/win32-arm64@0.27.1': 654 + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} 655 + engines: {node: '>=18'} 656 + cpu: [arm64] 657 + os: [win32] 658 + 492 659 '@esbuild/win32-ia32@0.18.20': 493 660 resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} 494 661 engines: {node: '>=12'} ··· 501 668 cpu: [ia32] 502 669 os: [win32] 503 670 671 + '@esbuild/win32-ia32@0.27.1': 672 + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} 673 + engines: {node: '>=18'} 674 + cpu: [ia32] 675 + os: [win32] 676 + 504 677 '@esbuild/win32-x64@0.18.20': 505 678 resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} 506 679 engines: {node: '>=12'} ··· 509 682 510 683 '@esbuild/win32-x64@0.25.12': 511 684 resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} 685 + engines: {node: '>=18'} 686 + cpu: [x64] 687 + os: [win32] 688 + 689 + '@esbuild/win32-x64@0.27.1': 690 + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} 512 691 engines: {node: '>=18'} 513 692 cpu: [x64] 514 693 os: [win32] ··· 840 1019 svelte: ^5.0.0 841 1020 vite: ^6.3.0 || ^7.0.0 842 1021 1022 + '@tailwindcss/node@4.1.18': 1023 + resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} 1024 + 1025 + '@tailwindcss/oxide-android-arm64@4.1.18': 1026 + resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} 1027 + engines: {node: '>= 10'} 1028 + cpu: [arm64] 1029 + os: [android] 1030 + 1031 + '@tailwindcss/oxide-darwin-arm64@4.1.18': 1032 + resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} 1033 + engines: {node: '>= 10'} 1034 + cpu: [arm64] 1035 + os: [darwin] 1036 + 1037 + '@tailwindcss/oxide-darwin-x64@4.1.18': 1038 + resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} 1039 + engines: {node: '>= 10'} 1040 + cpu: [x64] 1041 + os: [darwin] 1042 + 1043 + '@tailwindcss/oxide-freebsd-x64@4.1.18': 1044 + resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} 1045 + engines: {node: '>= 10'} 1046 + cpu: [x64] 1047 + os: [freebsd] 1048 + 1049 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': 1050 + resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} 1051 + engines: {node: '>= 10'} 1052 + cpu: [arm] 1053 + os: [linux] 1054 + 1055 + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': 1056 + resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} 1057 + engines: {node: '>= 10'} 1058 + cpu: [arm64] 1059 + os: [linux] 1060 + 1061 + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': 1062 + resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} 1063 + engines: {node: '>= 10'} 1064 + cpu: [arm64] 1065 + os: [linux] 1066 + 1067 + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': 1068 + resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} 1069 + engines: {node: '>= 10'} 1070 + cpu: [x64] 1071 + os: [linux] 1072 + 1073 + '@tailwindcss/oxide-linux-x64-musl@4.1.18': 1074 + resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} 1075 + engines: {node: '>= 10'} 1076 + cpu: [x64] 1077 + os: [linux] 1078 + 1079 + '@tailwindcss/oxide-wasm32-wasi@4.1.18': 1080 + resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} 1081 + engines: {node: '>=14.0.0'} 1082 + cpu: [wasm32] 1083 + bundledDependencies: 1084 + - '@napi-rs/wasm-runtime' 1085 + - '@emnapi/core' 1086 + - '@emnapi/runtime' 1087 + - '@tybys/wasm-util' 1088 + - '@emnapi/wasi-threads' 1089 + - tslib 1090 + 1091 + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': 1092 + resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} 1093 + engines: {node: '>= 10'} 1094 + cpu: [arm64] 1095 + os: [win32] 1096 + 1097 + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': 1098 + resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} 1099 + engines: {node: '>= 10'} 1100 + cpu: [x64] 1101 + os: [win32] 1102 + 1103 + '@tailwindcss/oxide@4.1.18': 1104 + resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} 1105 + engines: {node: '>= 10'} 1106 + 1107 + '@tailwindcss/vite@4.1.18': 1108 + resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==} 1109 + peerDependencies: 1110 + vite: ^5.2.0 || ^6 || ^7 1111 + 843 1112 '@types/better-sqlite3@7.6.13': 844 1113 resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} 845 1114 ··· 854 1123 855 1124 '@types/node@24.10.2': 856 1125 resolution: {integrity: sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==} 1126 + 1127 + '@types/pg@8.16.0': 1128 + resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==} 857 1129 858 1130 '@types/resolve@1.20.2': 859 1131 resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} ··· 1073 1345 engines: {node: '>=4'} 1074 1346 hasBin: true 1075 1347 1348 + daisyui@5.5.14: 1349 + resolution: {integrity: sha512-L47rvw7I7hK68TA97VB8Ee0woHew+/ohR6Lx6Ah/krfISOqcG4My7poNpX5Mo5/ytMxiR40fEaz6njzDi7cuSg==} 1350 + 1076 1351 debug@4.4.3: 1077 1352 resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} 1078 1353 engines: {node: '>=6.0'} ··· 1207 1482 end-of-stream@1.4.5: 1208 1483 resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} 1209 1484 1485 + enhanced-resolve@5.18.4: 1486 + resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} 1487 + engines: {node: '>=10.13.0'} 1488 + 1210 1489 esbuild-register@3.6.0: 1211 1490 resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} 1212 1491 peerDependencies: ··· 1222 1501 engines: {node: '>=18'} 1223 1502 hasBin: true 1224 1503 1504 + esbuild@0.27.1: 1505 + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} 1506 + engines: {node: '>=18'} 1507 + hasBin: true 1508 + 1225 1509 escape-string-regexp@4.0.0: 1226 1510 resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 1227 1511 engines: {node: '>=10'} ··· 1368 1652 resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} 1369 1653 engines: {node: '>=18'} 1370 1654 1655 + graceful-fs@4.2.11: 1656 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 1657 + 1371 1658 has-flag@4.0.0: 1372 1659 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1373 1660 engines: {node: '>=8'} ··· 1432 1719 iso-datestring-validator@2.2.2: 1433 1720 resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} 1434 1721 1722 + jiti@2.6.1: 1723 + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} 1724 + hasBin: true 1725 + 1435 1726 jose@5.10.0: 1436 1727 resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} 1437 1728 ··· 1462 1753 resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1463 1754 engines: {node: '>= 0.8.0'} 1464 1755 1756 + lightningcss-android-arm64@1.30.2: 1757 + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} 1758 + engines: {node: '>= 12.0.0'} 1759 + cpu: [arm64] 1760 + os: [android] 1761 + 1762 + lightningcss-darwin-arm64@1.30.2: 1763 + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} 1764 + engines: {node: '>= 12.0.0'} 1765 + cpu: [arm64] 1766 + os: [darwin] 1767 + 1768 + lightningcss-darwin-x64@1.30.2: 1769 + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} 1770 + engines: {node: '>= 12.0.0'} 1771 + cpu: [x64] 1772 + os: [darwin] 1773 + 1774 + lightningcss-freebsd-x64@1.30.2: 1775 + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} 1776 + engines: {node: '>= 12.0.0'} 1777 + cpu: [x64] 1778 + os: [freebsd] 1779 + 1780 + lightningcss-linux-arm-gnueabihf@1.30.2: 1781 + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} 1782 + engines: {node: '>= 12.0.0'} 1783 + cpu: [arm] 1784 + os: [linux] 1785 + 1786 + lightningcss-linux-arm64-gnu@1.30.2: 1787 + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} 1788 + engines: {node: '>= 12.0.0'} 1789 + cpu: [arm64] 1790 + os: [linux] 1791 + 1792 + lightningcss-linux-arm64-musl@1.30.2: 1793 + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} 1794 + engines: {node: '>= 12.0.0'} 1795 + cpu: [arm64] 1796 + os: [linux] 1797 + 1798 + lightningcss-linux-x64-gnu@1.30.2: 1799 + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} 1800 + engines: {node: '>= 12.0.0'} 1801 + cpu: [x64] 1802 + os: [linux] 1803 + 1804 + lightningcss-linux-x64-musl@1.30.2: 1805 + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} 1806 + engines: {node: '>= 12.0.0'} 1807 + cpu: [x64] 1808 + os: [linux] 1809 + 1810 + lightningcss-win32-arm64-msvc@1.30.2: 1811 + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} 1812 + engines: {node: '>= 12.0.0'} 1813 + cpu: [arm64] 1814 + os: [win32] 1815 + 1816 + lightningcss-win32-x64-msvc@1.30.2: 1817 + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} 1818 + engines: {node: '>= 12.0.0'} 1819 + cpu: [x64] 1820 + os: [win32] 1821 + 1822 + lightningcss@1.30.2: 1823 + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} 1824 + engines: {node: '>= 12.0.0'} 1825 + 1465 1826 lilconfig@2.1.0: 1466 1827 resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} 1467 1828 engines: {node: '>=10'} ··· 1576 1937 path-parse@1.0.7: 1577 1938 resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1578 1939 1940 + pg-cloudflare@1.2.7: 1941 + resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==} 1942 + 1943 + pg-connection-string@2.9.1: 1944 + resolution: {integrity: sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==} 1945 + 1946 + pg-int8@1.0.1: 1947 + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} 1948 + engines: {node: '>=4.0.0'} 1949 + 1950 + pg-pool@3.10.1: 1951 + resolution: {integrity: sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==} 1952 + peerDependencies: 1953 + pg: '>=8.0' 1954 + 1955 + pg-protocol@1.10.3: 1956 + resolution: {integrity: sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==} 1957 + 1958 + pg-types@2.2.0: 1959 + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} 1960 + engines: {node: '>=4'} 1961 + 1962 + pg@8.16.3: 1963 + resolution: {integrity: sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==} 1964 + engines: {node: '>= 16.0.0'} 1965 + peerDependencies: 1966 + pg-native: '>=3.0.1' 1967 + peerDependenciesMeta: 1968 + pg-native: 1969 + optional: true 1970 + 1971 + pgpass@1.0.5: 1972 + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} 1973 + 1579 1974 picocolors@1.1.1: 1580 1975 resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1581 1976 ··· 1634 2029 postcss@8.5.6: 1635 2030 resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 1636 2031 engines: {node: ^10 || ^12 || >=14} 2032 + 2033 + postgres-array@2.0.0: 2034 + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} 2035 + engines: {node: '>=4'} 2036 + 2037 + postgres-bytea@1.0.0: 2038 + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} 2039 + engines: {node: '>=0.10.0'} 2040 + 2041 + postgres-date@1.0.7: 2042 + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} 2043 + engines: {node: '>=0.10.0'} 2044 + 2045 + postgres-interval@1.2.0: 2046 + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} 2047 + engines: {node: '>=0.10.0'} 1637 2048 1638 2049 prebuild-install@7.1.3: 1639 2050 resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} ··· 1806 2217 resolution: {integrity: sha512-1Jh7FwVh/2Uxg0T7SeE1qFKMhwYH45b2v53bcZpW7qHa6O8iU1ByEj56PF0IQ6dU4HE5gRkic6h+vx+tclHeiw==} 1807 2218 engines: {node: '>=18'} 1808 2219 2220 + tailwindcss@4.1.18: 2221 + resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} 2222 + 2223 + tapable@2.3.0: 2224 + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} 2225 + engines: {node: '>=6'} 2226 + 1809 2227 tar-fs@2.1.4: 1810 2228 resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} 1811 2229 ··· 1839 2257 1840 2258 tslib@2.8.1: 1841 2259 resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 2260 + 2261 + tsx@4.21.0: 2262 + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} 2263 + engines: {node: '>=18.0.0'} 2264 + hasBin: true 1842 2265 1843 2266 tunnel-agent@0.6.0: 1844 2267 resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} ··· 1937 2360 1938 2361 wrappy@1.0.2: 1939 2362 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 2363 + 2364 + ws@8.18.3: 2365 + resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} 2366 + engines: {node: '>=10.0.0'} 2367 + peerDependencies: 2368 + bufferutil: ^4.0.1 2369 + utf-8-validate: '>=5.0.2' 2370 + peerDependenciesMeta: 2371 + bufferutil: 2372 + optional: true 2373 + utf-8-validate: 2374 + optional: true 2375 + 2376 + xtend@4.0.2: 2377 + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 2378 + engines: {node: '>=0.4'} 1940 2379 1941 2380 yaml@1.10.2: 1942 2381 resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} ··· 2135 2574 2136 2575 '@atproto/syntax@0.4.2': {} 2137 2576 2577 + '@atproto/tap@0.0.2': 2578 + dependencies: 2579 + '@atproto/common': 0.5.3 2580 + '@atproto/syntax': 0.4.2 2581 + '@atproto/ws-client': 0.0.4 2582 + ws: 8.18.3 2583 + zod: 3.25.76 2584 + transitivePeerDependencies: 2585 + - bufferutil 2586 + - utf-8-validate 2587 + 2588 + '@atproto/ws-client@0.0.4': 2589 + dependencies: 2590 + '@atproto/common': 0.5.3 2591 + ws: 8.18.3 2592 + transitivePeerDependencies: 2593 + - bufferutil 2594 + - utf-8-validate 2595 + 2138 2596 '@atproto/xrpc@0.7.7': 2139 2597 dependencies: 2140 2598 '@atproto/lexicon': 0.6.0 ··· 2157 2615 '@esbuild/aix-ppc64@0.25.12': 2158 2616 optional: true 2159 2617 2618 + '@esbuild/aix-ppc64@0.27.1': 2619 + optional: true 2620 + 2160 2621 '@esbuild/android-arm64@0.18.20': 2161 2622 optional: true 2162 2623 2163 2624 '@esbuild/android-arm64@0.25.12': 2164 2625 optional: true 2165 2626 2627 + '@esbuild/android-arm64@0.27.1': 2628 + optional: true 2629 + 2166 2630 '@esbuild/android-arm@0.18.20': 2167 2631 optional: true 2168 2632 2169 2633 '@esbuild/android-arm@0.25.12': 2170 2634 optional: true 2171 2635 2636 + '@esbuild/android-arm@0.27.1': 2637 + optional: true 2638 + 2172 2639 '@esbuild/android-x64@0.18.20': 2173 2640 optional: true 2174 2641 2175 2642 '@esbuild/android-x64@0.25.12': 2643 + optional: true 2644 + 2645 + '@esbuild/android-x64@0.27.1': 2176 2646 optional: true 2177 2647 2178 2648 '@esbuild/darwin-arm64@0.18.20': 2179 2649 optional: true 2180 2650 2181 2651 '@esbuild/darwin-arm64@0.25.12': 2652 + optional: true 2653 + 2654 + '@esbuild/darwin-arm64@0.27.1': 2182 2655 optional: true 2183 2656 2184 2657 '@esbuild/darwin-x64@0.18.20': ··· 2187 2660 '@esbuild/darwin-x64@0.25.12': 2188 2661 optional: true 2189 2662 2663 + '@esbuild/darwin-x64@0.27.1': 2664 + optional: true 2665 + 2190 2666 '@esbuild/freebsd-arm64@0.18.20': 2191 2667 optional: true 2192 2668 2193 2669 '@esbuild/freebsd-arm64@0.25.12': 2194 2670 optional: true 2195 2671 2672 + '@esbuild/freebsd-arm64@0.27.1': 2673 + optional: true 2674 + 2196 2675 '@esbuild/freebsd-x64@0.18.20': 2197 2676 optional: true 2198 2677 2199 2678 '@esbuild/freebsd-x64@0.25.12': 2200 2679 optional: true 2201 2680 2681 + '@esbuild/freebsd-x64@0.27.1': 2682 + optional: true 2683 + 2202 2684 '@esbuild/linux-arm64@0.18.20': 2203 2685 optional: true 2204 2686 2205 2687 '@esbuild/linux-arm64@0.25.12': 2688 + optional: true 2689 + 2690 + '@esbuild/linux-arm64@0.27.1': 2206 2691 optional: true 2207 2692 2208 2693 '@esbuild/linux-arm@0.18.20': 2209 2694 optional: true 2210 2695 2211 2696 '@esbuild/linux-arm@0.25.12': 2697 + optional: true 2698 + 2699 + '@esbuild/linux-arm@0.27.1': 2212 2700 optional: true 2213 2701 2214 2702 '@esbuild/linux-ia32@0.18.20': ··· 2217 2705 '@esbuild/linux-ia32@0.25.12': 2218 2706 optional: true 2219 2707 2708 + '@esbuild/linux-ia32@0.27.1': 2709 + optional: true 2710 + 2220 2711 '@esbuild/linux-loong64@0.18.20': 2221 2712 optional: true 2222 2713 2223 2714 '@esbuild/linux-loong64@0.25.12': 2224 2715 optional: true 2225 2716 2717 + '@esbuild/linux-loong64@0.27.1': 2718 + optional: true 2719 + 2226 2720 '@esbuild/linux-mips64el@0.18.20': 2227 2721 optional: true 2228 2722 2229 2723 '@esbuild/linux-mips64el@0.25.12': 2230 2724 optional: true 2231 2725 2726 + '@esbuild/linux-mips64el@0.27.1': 2727 + optional: true 2728 + 2232 2729 '@esbuild/linux-ppc64@0.18.20': 2233 2730 optional: true 2234 2731 2235 2732 '@esbuild/linux-ppc64@0.25.12': 2733 + optional: true 2734 + 2735 + '@esbuild/linux-ppc64@0.27.1': 2236 2736 optional: true 2237 2737 2238 2738 '@esbuild/linux-riscv64@0.18.20': 2239 2739 optional: true 2240 2740 2241 2741 '@esbuild/linux-riscv64@0.25.12': 2742 + optional: true 2743 + 2744 + '@esbuild/linux-riscv64@0.27.1': 2242 2745 optional: true 2243 2746 2244 2747 '@esbuild/linux-s390x@0.18.20': ··· 2247 2750 '@esbuild/linux-s390x@0.25.12': 2248 2751 optional: true 2249 2752 2753 + '@esbuild/linux-s390x@0.27.1': 2754 + optional: true 2755 + 2250 2756 '@esbuild/linux-x64@0.18.20': 2251 2757 optional: true 2252 2758 2253 2759 '@esbuild/linux-x64@0.25.12': 2760 + optional: true 2761 + 2762 + '@esbuild/linux-x64@0.27.1': 2254 2763 optional: true 2255 2764 2256 2765 '@esbuild/netbsd-arm64@0.25.12': 2257 2766 optional: true 2258 2767 2768 + '@esbuild/netbsd-arm64@0.27.1': 2769 + optional: true 2770 + 2259 2771 '@esbuild/netbsd-x64@0.18.20': 2260 2772 optional: true 2261 2773 2262 2774 '@esbuild/netbsd-x64@0.25.12': 2263 2775 optional: true 2264 2776 2777 + '@esbuild/netbsd-x64@0.27.1': 2778 + optional: true 2779 + 2265 2780 '@esbuild/openbsd-arm64@0.25.12': 2781 + optional: true 2782 + 2783 + '@esbuild/openbsd-arm64@0.27.1': 2266 2784 optional: true 2267 2785 2268 2786 '@esbuild/openbsd-x64@0.18.20': ··· 2271 2789 '@esbuild/openbsd-x64@0.25.12': 2272 2790 optional: true 2273 2791 2792 + '@esbuild/openbsd-x64@0.27.1': 2793 + optional: true 2794 + 2274 2795 '@esbuild/openharmony-arm64@0.25.12': 2796 + optional: true 2797 + 2798 + '@esbuild/openharmony-arm64@0.27.1': 2275 2799 optional: true 2276 2800 2277 2801 '@esbuild/sunos-x64@0.18.20': ··· 2280 2804 '@esbuild/sunos-x64@0.25.12': 2281 2805 optional: true 2282 2806 2807 + '@esbuild/sunos-x64@0.27.1': 2808 + optional: true 2809 + 2283 2810 '@esbuild/win32-arm64@0.18.20': 2284 2811 optional: true 2285 2812 2286 2813 '@esbuild/win32-arm64@0.25.12': 2287 2814 optional: true 2288 2815 2816 + '@esbuild/win32-arm64@0.27.1': 2817 + optional: true 2818 + 2289 2819 '@esbuild/win32-ia32@0.18.20': 2290 2820 optional: true 2291 2821 2292 2822 '@esbuild/win32-ia32@0.25.12': 2823 + optional: true 2824 + 2825 + '@esbuild/win32-ia32@0.27.1': 2293 2826 optional: true 2294 2827 2295 2828 '@esbuild/win32-x64@0.18.20': ··· 2298 2831 '@esbuild/win32-x64@0.25.12': 2299 2832 optional: true 2300 2833 2301 - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': 2834 + '@esbuild/win32-x64@0.27.1': 2835 + optional: true 2836 + 2837 + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': 2302 2838 dependencies: 2303 - eslint: 9.39.1 2839 + eslint: 9.39.1(jiti@2.6.1) 2304 2840 eslint-visitor-keys: 3.4.3 2305 2841 2306 2842 '@eslint-community/regexpp@4.12.2': {} 2307 2843 2308 - '@eslint/compat@1.4.1(eslint@9.39.1)': 2844 + '@eslint/compat@1.4.1(eslint@9.39.1(jiti@2.6.1))': 2309 2845 dependencies: 2310 2846 '@eslint/core': 0.17.0 2311 2847 optionalDependencies: 2312 - eslint: 9.39.1 2848 + eslint: 9.39.1(jiti@2.6.1) 2313 2849 2314 2850 '@eslint/config-array@0.21.1': 2315 2851 dependencies: ··· 2534 3070 dependencies: 2535 3071 acorn: 8.15.0 2536 3072 2537 - '@sveltejs/adapter-auto@7.0.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))': 3073 + '@sveltejs/adapter-auto@7.0.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))': 2538 3074 dependencies: 2539 - '@sveltejs/kit': 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 3075 + '@sveltejs/kit': 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2540 3076 2541 - '@sveltejs/adapter-node@5.4.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))': 3077 + '@sveltejs/adapter-node@5.4.0(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))': 2542 3078 dependencies: 2543 3079 '@rollup/plugin-commonjs': 28.0.9(rollup@4.53.3) 2544 3080 '@rollup/plugin-json': 6.1.0(rollup@4.53.3) 2545 3081 '@rollup/plugin-node-resolve': 16.0.3(rollup@4.53.3) 2546 - '@sveltejs/kit': 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 3082 + '@sveltejs/kit': 2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2547 3083 rollup: 4.53.3 2548 3084 2549 - '@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2))': 3085 + '@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))': 2550 3086 dependencies: 2551 3087 '@standard-schema/spec': 1.0.0 2552 3088 '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) 2553 - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 3089 + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2554 3090 '@types/cookie': 0.6.0 2555 3091 acorn: 8.15.0 2556 3092 cookie: 0.6.0 ··· 2563 3099 set-cookie-parser: 2.7.2 2564 3100 sirv: 3.0.2 2565 3101 svelte: 5.45.8 2566 - vite: 7.2.7(@types/node@24.10.2) 3102 + vite: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 2567 3103 2568 - '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2))': 3104 + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))': 2569 3105 dependencies: 2570 - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 3106 + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2571 3107 debug: 4.4.3 2572 3108 svelte: 5.45.8 2573 - vite: 7.2.7(@types/node@24.10.2) 3109 + vite: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 2574 3110 transitivePeerDependencies: 2575 3111 - supports-color 2576 3112 2577 - '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2))': 3113 + '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))': 2578 3114 dependencies: 2579 - '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)) 3115 + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)))(svelte@5.45.8)(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2580 3116 debug: 4.4.3 2581 3117 deepmerge: 4.3.1 2582 3118 magic-string: 0.30.21 2583 3119 svelte: 5.45.8 2584 - vite: 7.2.7(@types/node@24.10.2) 2585 - vitefu: 1.1.1(vite@7.2.7(@types/node@24.10.2)) 3120 + vite: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 3121 + vitefu: 1.1.1(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)) 2586 3122 transitivePeerDependencies: 2587 3123 - supports-color 2588 3124 3125 + '@tailwindcss/node@4.1.18': 3126 + dependencies: 3127 + '@jridgewell/remapping': 2.3.5 3128 + enhanced-resolve: 5.18.4 3129 + jiti: 2.6.1 3130 + lightningcss: 1.30.2 3131 + magic-string: 0.30.21 3132 + source-map-js: 1.2.1 3133 + tailwindcss: 4.1.18 3134 + 3135 + '@tailwindcss/oxide-android-arm64@4.1.18': 3136 + optional: true 3137 + 3138 + '@tailwindcss/oxide-darwin-arm64@4.1.18': 3139 + optional: true 3140 + 3141 + '@tailwindcss/oxide-darwin-x64@4.1.18': 3142 + optional: true 3143 + 3144 + '@tailwindcss/oxide-freebsd-x64@4.1.18': 3145 + optional: true 3146 + 3147 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': 3148 + optional: true 3149 + 3150 + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': 3151 + optional: true 3152 + 3153 + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': 3154 + optional: true 3155 + 3156 + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': 3157 + optional: true 3158 + 3159 + '@tailwindcss/oxide-linux-x64-musl@4.1.18': 3160 + optional: true 3161 + 3162 + '@tailwindcss/oxide-wasm32-wasi@4.1.18': 3163 + optional: true 3164 + 3165 + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': 3166 + optional: true 3167 + 3168 + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': 3169 + optional: true 3170 + 3171 + '@tailwindcss/oxide@4.1.18': 3172 + optionalDependencies: 3173 + '@tailwindcss/oxide-android-arm64': 4.1.18 3174 + '@tailwindcss/oxide-darwin-arm64': 4.1.18 3175 + '@tailwindcss/oxide-darwin-x64': 4.1.18 3176 + '@tailwindcss/oxide-freebsd-x64': 4.1.18 3177 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 3178 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 3179 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 3180 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 3181 + '@tailwindcss/oxide-linux-x64-musl': 4.1.18 3182 + '@tailwindcss/oxide-wasm32-wasi': 4.1.18 3183 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 3184 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 3185 + 3186 + '@tailwindcss/vite@4.1.18(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))': 3187 + dependencies: 3188 + '@tailwindcss/node': 4.1.18 3189 + '@tailwindcss/oxide': 4.1.18 3190 + tailwindcss: 4.1.18 3191 + vite: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 3192 + 2589 3193 '@types/better-sqlite3@7.6.13': 2590 3194 dependencies: 2591 3195 '@types/node': 24.10.2 3196 + optional: true 2592 3197 2593 3198 '@types/cookie@0.6.0': {} 2594 3199 ··· 2600 3205 dependencies: 2601 3206 undici-types: 7.16.0 2602 3207 3208 + '@types/pg@8.16.0': 3209 + dependencies: 3210 + '@types/node': 24.10.2 3211 + pg-protocol: 1.10.3 3212 + pg-types: 2.2.0 3213 + 2603 3214 '@types/resolve@1.20.2': {} 2604 3215 2605 - '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': 3216 + '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': 2606 3217 dependencies: 2607 3218 '@eslint-community/regexpp': 4.12.2 2608 - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 3219 + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 2609 3220 '@typescript-eslint/scope-manager': 8.49.0 2610 - '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 2611 - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 3221 + '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 3222 + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 2612 3223 '@typescript-eslint/visitor-keys': 8.49.0 2613 - eslint: 9.39.1 3224 + eslint: 9.39.1(jiti@2.6.1) 2614 3225 ignore: 7.0.5 2615 3226 natural-compare: 1.4.0 2616 3227 ts-api-utils: 2.1.0(typescript@5.9.3) ··· 2618 3229 transitivePeerDependencies: 2619 3230 - supports-color 2620 3231 2621 - '@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3)': 3232 + '@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': 2622 3233 dependencies: 2623 3234 '@typescript-eslint/scope-manager': 8.49.0 2624 3235 '@typescript-eslint/types': 8.49.0 2625 3236 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) 2626 3237 '@typescript-eslint/visitor-keys': 8.49.0 2627 3238 debug: 4.4.3 2628 - eslint: 9.39.1 3239 + eslint: 9.39.1(jiti@2.6.1) 2629 3240 typescript: 5.9.3 2630 3241 transitivePeerDependencies: 2631 3242 - supports-color ··· 2648 3259 dependencies: 2649 3260 typescript: 5.9.3 2650 3261 2651 - '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': 3262 + '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': 2652 3263 dependencies: 2653 3264 '@typescript-eslint/types': 8.49.0 2654 3265 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) 2655 - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 3266 + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 2656 3267 debug: 4.4.3 2657 - eslint: 9.39.1 3268 + eslint: 9.39.1(jiti@2.6.1) 2658 3269 ts-api-utils: 2.1.0(typescript@5.9.3) 2659 3270 typescript: 5.9.3 2660 3271 transitivePeerDependencies: ··· 2677 3288 transitivePeerDependencies: 2678 3289 - supports-color 2679 3290 2680 - '@typescript-eslint/utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': 3291 + '@typescript-eslint/utils@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': 2681 3292 dependencies: 2682 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) 3293 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) 2683 3294 '@typescript-eslint/scope-manager': 8.49.0 2684 3295 '@typescript-eslint/types': 8.49.0 2685 3296 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) 2686 - eslint: 9.39.1 3297 + eslint: 9.39.1(jiti@2.6.1) 2687 3298 typescript: 5.9.3 2688 3299 transitivePeerDependencies: 2689 3300 - supports-color ··· 2762 3373 dependencies: 2763 3374 bindings: 1.5.0 2764 3375 prebuild-install: 7.1.3 3376 + optional: true 2765 3377 2766 3378 bindings@1.5.0: 2767 3379 dependencies: 2768 3380 file-uri-to-path: 1.0.0 3381 + optional: true 2769 3382 2770 3383 bl@4.1.0: 2771 3384 dependencies: 2772 3385 buffer: 5.7.1 2773 3386 inherits: 2.0.4 2774 3387 readable-stream: 3.6.2 3388 + optional: true 2775 3389 2776 3390 brace-expansion@1.1.12: 2777 3391 dependencies: ··· 2788 3402 dependencies: 2789 3403 base64-js: 1.5.1 2790 3404 ieee754: 1.2.1 3405 + optional: true 2791 3406 2792 3407 buffer@6.0.3: 2793 3408 dependencies: ··· 2805 3420 dependencies: 2806 3421 readdirp: 4.1.2 2807 3422 2808 - chownr@1.1.4: {} 3423 + chownr@1.1.4: 3424 + optional: true 2809 3425 2810 3426 clsx@2.1.1: {} 2811 3427 ··· 2835 3451 2836 3452 cssesc@3.0.0: {} 2837 3453 3454 + daisyui@5.5.14: {} 3455 + 2838 3456 debug@4.4.3: 2839 3457 dependencies: 2840 3458 ms: 2.1.3 ··· 2842 3460 decompress-response@6.0.0: 2843 3461 dependencies: 2844 3462 mimic-response: 3.1.0 3463 + optional: true 2845 3464 2846 - deep-extend@0.6.0: {} 3465 + deep-extend@0.6.0: 3466 + optional: true 2847 3467 2848 3468 deep-is@0.1.4: {} 2849 3469 ··· 2864 3484 transitivePeerDependencies: 2865 3485 - supports-color 2866 3486 2867 - drizzle-orm@0.44.7(@types/better-sqlite3@7.6.13)(better-sqlite3@12.4.1): 3487 + drizzle-orm@0.44.7(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(better-sqlite3@12.4.1)(pg@8.16.3): 2868 3488 optionalDependencies: 2869 3489 '@types/better-sqlite3': 7.6.13 3490 + '@types/pg': 8.16.0 2870 3491 better-sqlite3: 12.4.1 3492 + pg: 8.16.3 2871 3493 2872 3494 end-of-stream@1.4.5: 2873 3495 dependencies: 2874 3496 once: 1.4.0 3497 + optional: true 3498 + 3499 + enhanced-resolve@5.18.4: 3500 + dependencies: 3501 + graceful-fs: 4.2.11 3502 + tapable: 2.3.0 2875 3503 2876 3504 esbuild-register@3.6.0(esbuild@0.25.12): 2877 3505 dependencies: ··· 2934 3562 '@esbuild/win32-ia32': 0.25.12 2935 3563 '@esbuild/win32-x64': 0.25.12 2936 3564 3565 + esbuild@0.27.1: 3566 + optionalDependencies: 3567 + '@esbuild/aix-ppc64': 0.27.1 3568 + '@esbuild/android-arm': 0.27.1 3569 + '@esbuild/android-arm64': 0.27.1 3570 + '@esbuild/android-x64': 0.27.1 3571 + '@esbuild/darwin-arm64': 0.27.1 3572 + '@esbuild/darwin-x64': 0.27.1 3573 + '@esbuild/freebsd-arm64': 0.27.1 3574 + '@esbuild/freebsd-x64': 0.27.1 3575 + '@esbuild/linux-arm': 0.27.1 3576 + '@esbuild/linux-arm64': 0.27.1 3577 + '@esbuild/linux-ia32': 0.27.1 3578 + '@esbuild/linux-loong64': 0.27.1 3579 + '@esbuild/linux-mips64el': 0.27.1 3580 + '@esbuild/linux-ppc64': 0.27.1 3581 + '@esbuild/linux-riscv64': 0.27.1 3582 + '@esbuild/linux-s390x': 0.27.1 3583 + '@esbuild/linux-x64': 0.27.1 3584 + '@esbuild/netbsd-arm64': 0.27.1 3585 + '@esbuild/netbsd-x64': 0.27.1 3586 + '@esbuild/openbsd-arm64': 0.27.1 3587 + '@esbuild/openbsd-x64': 0.27.1 3588 + '@esbuild/openharmony-arm64': 0.27.1 3589 + '@esbuild/sunos-x64': 0.27.1 3590 + '@esbuild/win32-arm64': 0.27.1 3591 + '@esbuild/win32-ia32': 0.27.1 3592 + '@esbuild/win32-x64': 0.27.1 3593 + 2937 3594 escape-string-regexp@4.0.0: {} 2938 3595 2939 - eslint-plugin-svelte@3.13.1(eslint@9.39.1)(svelte@5.45.8): 3596 + eslint-plugin-svelte@3.13.1(eslint@9.39.1(jiti@2.6.1))(svelte@5.45.8): 2940 3597 dependencies: 2941 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) 3598 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) 2942 3599 '@jridgewell/sourcemap-codec': 1.5.5 2943 - eslint: 9.39.1 3600 + eslint: 9.39.1(jiti@2.6.1) 2944 3601 esutils: 2.0.3 2945 3602 globals: 16.5.0 2946 3603 known-css-properties: 0.37.0 ··· 2963 3620 2964 3621 eslint-visitor-keys@4.2.1: {} 2965 3622 2966 - eslint@9.39.1: 3623 + eslint@9.39.1(jiti@2.6.1): 2967 3624 dependencies: 2968 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) 3625 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) 2969 3626 '@eslint-community/regexpp': 4.12.2 2970 3627 '@eslint/config-array': 0.21.1 2971 3628 '@eslint/config-helpers': 0.4.2 ··· 2999 3656 minimatch: 3.1.2 3000 3657 natural-compare: 1.4.0 3001 3658 optionator: 0.9.4 3659 + optionalDependencies: 3660 + jiti: 2.6.1 3002 3661 transitivePeerDependencies: 3003 3662 - supports-color 3004 3663 ··· 3032 3691 3033 3692 events@3.3.0: {} 3034 3693 3035 - expand-template@2.0.3: {} 3694 + expand-template@2.0.3: 3695 + optional: true 3036 3696 3037 3697 fast-deep-equal@3.1.3: {} 3038 3698 ··· 3050 3710 dependencies: 3051 3711 flat-cache: 4.0.1 3052 3712 3053 - file-uri-to-path@1.0.0: {} 3713 + file-uri-to-path@1.0.0: 3714 + optional: true 3054 3715 3055 3716 find-up@5.0.0: 3056 3717 dependencies: ··· 3064 3725 3065 3726 flatted@3.3.3: {} 3066 3727 3067 - fs-constants@1.0.0: {} 3728 + fs-constants@1.0.0: 3729 + optional: true 3068 3730 3069 3731 fsevents@2.3.3: 3070 3732 optional: true ··· 3075 3737 dependencies: 3076 3738 resolve-pkg-maps: 1.0.0 3077 3739 3078 - github-from-package@0.0.0: {} 3740 + github-from-package@0.0.0: 3741 + optional: true 3079 3742 3080 3743 glob-parent@6.0.2: 3081 3744 dependencies: ··· 3085 3748 3086 3749 globals@16.5.0: {} 3087 3750 3751 + graceful-fs@4.2.11: {} 3752 + 3088 3753 has-flag@4.0.0: {} 3089 3754 3090 3755 hasown@2.0.2: ··· 3104 3769 3105 3770 imurmurhash@0.1.4: {} 3106 3771 3107 - inherits@2.0.4: {} 3772 + inherits@2.0.4: 3773 + optional: true 3108 3774 3109 - ini@1.3.8: {} 3775 + ini@1.3.8: 3776 + optional: true 3110 3777 3111 3778 ipaddr.js@2.3.0: {} 3112 3779 ··· 3134 3801 3135 3802 iso-datestring-validator@2.2.2: {} 3136 3803 3804 + jiti@2.6.1: {} 3805 + 3137 3806 jose@5.10.0: {} 3138 3807 3139 3808 js-yaml@4.1.1: ··· 3159 3828 prelude-ls: 1.2.1 3160 3829 type-check: 0.4.0 3161 3830 3831 + lightningcss-android-arm64@1.30.2: 3832 + optional: true 3833 + 3834 + lightningcss-darwin-arm64@1.30.2: 3835 + optional: true 3836 + 3837 + lightningcss-darwin-x64@1.30.2: 3838 + optional: true 3839 + 3840 + lightningcss-freebsd-x64@1.30.2: 3841 + optional: true 3842 + 3843 + lightningcss-linux-arm-gnueabihf@1.30.2: 3844 + optional: true 3845 + 3846 + lightningcss-linux-arm64-gnu@1.30.2: 3847 + optional: true 3848 + 3849 + lightningcss-linux-arm64-musl@1.30.2: 3850 + optional: true 3851 + 3852 + lightningcss-linux-x64-gnu@1.30.2: 3853 + optional: true 3854 + 3855 + lightningcss-linux-x64-musl@1.30.2: 3856 + optional: true 3857 + 3858 + lightningcss-win32-arm64-msvc@1.30.2: 3859 + optional: true 3860 + 3861 + lightningcss-win32-x64-msvc@1.30.2: 3862 + optional: true 3863 + 3864 + lightningcss@1.30.2: 3865 + dependencies: 3866 + detect-libc: 2.1.2 3867 + optionalDependencies: 3868 + lightningcss-android-arm64: 1.30.2 3869 + lightningcss-darwin-arm64: 1.30.2 3870 + lightningcss-darwin-x64: 1.30.2 3871 + lightningcss-freebsd-x64: 1.30.2 3872 + lightningcss-linux-arm-gnueabihf: 1.30.2 3873 + lightningcss-linux-arm64-gnu: 1.30.2 3874 + lightningcss-linux-arm64-musl: 1.30.2 3875 + lightningcss-linux-x64-gnu: 1.30.2 3876 + lightningcss-linux-x64-musl: 1.30.2 3877 + lightningcss-win32-arm64-msvc: 1.30.2 3878 + lightningcss-win32-x64-msvc: 1.30.2 3879 + 3162 3880 lilconfig@2.1.0: {} 3163 3881 3164 3882 locate-character@3.0.0: {} ··· 3181 3899 dependencies: 3182 3900 '@jridgewell/sourcemap-codec': 1.5.5 3183 3901 3184 - mimic-response@3.1.0: {} 3902 + mimic-response@3.1.0: 3903 + optional: true 3185 3904 3186 3905 minimatch@3.1.2: 3187 3906 dependencies: ··· 3191 3910 dependencies: 3192 3911 brace-expansion: 2.0.2 3193 3912 3194 - minimist@1.2.8: {} 3913 + minimist@1.2.8: 3914 + optional: true 3195 3915 3196 - mkdirp-classic@0.5.3: {} 3916 + mkdirp-classic@0.5.3: 3917 + optional: true 3197 3918 3198 3919 mri@1.2.0: {} 3199 3920 ··· 3205 3926 3206 3927 nanoid@3.3.11: {} 3207 3928 3208 - napi-build-utils@2.0.0: {} 3929 + napi-build-utils@2.0.0: 3930 + optional: true 3209 3931 3210 3932 natural-compare@1.4.0: {} 3211 3933 3212 3934 node-abi@3.85.0: 3213 3935 dependencies: 3214 3936 semver: 7.7.3 3937 + optional: true 3215 3938 3216 3939 node-schedule@2.1.1: 3217 3940 dependencies: ··· 3224 3947 once@1.4.0: 3225 3948 dependencies: 3226 3949 wrappy: 1.0.2 3950 + optional: true 3227 3951 3228 3952 optionator@0.9.4: 3229 3953 dependencies: ··· 3252 3976 3253 3977 path-parse@1.0.7: {} 3254 3978 3979 + pg-cloudflare@1.2.7: 3980 + optional: true 3981 + 3982 + pg-connection-string@2.9.1: {} 3983 + 3984 + pg-int8@1.0.1: {} 3985 + 3986 + pg-pool@3.10.1(pg@8.16.3): 3987 + dependencies: 3988 + pg: 8.16.3 3989 + 3990 + pg-protocol@1.10.3: {} 3991 + 3992 + pg-types@2.2.0: 3993 + dependencies: 3994 + pg-int8: 1.0.1 3995 + postgres-array: 2.0.0 3996 + postgres-bytea: 1.0.0 3997 + postgres-date: 1.0.7 3998 + postgres-interval: 1.2.0 3999 + 4000 + pg@8.16.3: 4001 + dependencies: 4002 + pg-connection-string: 2.9.1 4003 + pg-pool: 3.10.1(pg@8.16.3) 4004 + pg-protocol: 1.10.3 4005 + pg-types: 2.2.0 4006 + pgpass: 1.0.5 4007 + optionalDependencies: 4008 + pg-cloudflare: 1.2.7 4009 + 4010 + pgpass@1.0.5: 4011 + dependencies: 4012 + split2: 4.2.0 4013 + 3255 4014 picocolors@1.1.1: {} 3256 4015 3257 4016 picomatch@4.0.3: {} ··· 3323 4082 picocolors: 1.1.1 3324 4083 source-map-js: 1.2.1 3325 4084 4085 + postgres-array@2.0.0: {} 4086 + 4087 + postgres-bytea@1.0.0: {} 4088 + 4089 + postgres-date@1.0.7: {} 4090 + 4091 + postgres-interval@1.2.0: 4092 + dependencies: 4093 + xtend: 4.0.2 4094 + 3326 4095 prebuild-install@7.1.3: 3327 4096 dependencies: 3328 4097 detect-libc: 2.1.2 ··· 3337 4106 simple-get: 4.0.1 3338 4107 tar-fs: 2.1.4 3339 4108 tunnel-agent: 0.6.0 4109 + optional: true 3340 4110 3341 4111 prelude-ls@1.2.1: {} 3342 4112 ··· 3365 4135 dependencies: 3366 4136 end-of-stream: 1.4.5 3367 4137 once: 1.4.0 4138 + optional: true 3368 4139 3369 4140 punycode@2.3.1: {} 3370 4141 ··· 3376 4147 ini: 1.3.8 3377 4148 minimist: 1.2.8 3378 4149 strip-json-comments: 2.0.1 4150 + optional: true 3379 4151 3380 4152 readable-stream@3.6.2: 3381 4153 dependencies: 3382 4154 inherits: 2.0.4 3383 4155 string_decoder: 1.3.0 3384 4156 util-deprecate: 1.0.2 4157 + optional: true 3385 4158 3386 4159 readable-stream@4.7.0: 3387 4160 dependencies: ··· 3451 4224 3452 4225 shebang-regex@3.0.0: {} 3453 4226 3454 - simple-concat@1.0.1: {} 4227 + simple-concat@1.0.1: 4228 + optional: true 3455 4229 3456 4230 simple-get@4.0.1: 3457 4231 dependencies: 3458 4232 decompress-response: 6.0.0 3459 4233 once: 1.4.0 3460 4234 simple-concat: 1.0.1 4235 + optional: true 3461 4236 3462 4237 sirv@3.0.2: 3463 4238 dependencies: ··· 3490 4265 dependencies: 3491 4266 safe-buffer: 5.2.1 3492 4267 3493 - strip-json-comments@2.0.1: {} 4268 + strip-json-comments@2.0.1: 4269 + optional: true 3494 4270 3495 4271 strip-json-comments@3.1.1: {} 3496 4272 ··· 3540 4316 locate-character: 3.0.0 3541 4317 magic-string: 0.30.21 3542 4318 zimmerframe: 1.1.4 4319 + 4320 + tailwindcss@4.1.18: {} 4321 + 4322 + tapable@2.3.0: {} 3543 4323 3544 4324 tar-fs@2.1.4: 3545 4325 dependencies: ··· 3547 4327 mkdirp-classic: 0.5.3 3548 4328 pump: 3.0.3 3549 4329 tar-stream: 2.2.0 4330 + optional: true 3550 4331 3551 4332 tar-stream@2.2.0: 3552 4333 dependencies: ··· 3555 4336 fs-constants: 1.0.0 3556 4337 inherits: 2.0.4 3557 4338 readable-stream: 3.6.2 4339 + optional: true 3558 4340 3559 4341 thread-stream@2.7.0: 3560 4342 dependencies: ··· 3579 4361 3580 4362 tslib@2.8.1: {} 3581 4363 4364 + tsx@4.21.0: 4365 + dependencies: 4366 + esbuild: 0.27.1 4367 + get-tsconfig: 4.13.0 4368 + optionalDependencies: 4369 + fsevents: 2.3.3 4370 + 3582 4371 tunnel-agent@0.6.0: 3583 4372 dependencies: 3584 4373 safe-buffer: 5.2.1 4374 + optional: true 3585 4375 3586 4376 type-check@0.4.0: 3587 4377 dependencies: 3588 4378 prelude-ls: 1.2.1 3589 4379 3590 - typescript-eslint@8.49.0(eslint@9.39.1)(typescript@5.9.3): 4380 + typescript-eslint@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): 3591 4381 dependencies: 3592 - '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) 3593 - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 4382 + '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 4383 + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 3594 4384 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) 3595 - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) 3596 - eslint: 9.39.1 4385 + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) 4386 + eslint: 9.39.1(jiti@2.6.1) 3597 4387 typescript: 5.9.3 3598 4388 transitivePeerDependencies: 3599 4389 - supports-color ··· 3616 4406 3617 4407 util-deprecate@1.0.2: {} 3618 4408 3619 - vite@7.2.7(@types/node@24.10.2): 4409 + vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0): 3620 4410 dependencies: 3621 4411 esbuild: 0.25.12 3622 4412 fdir: 6.5.0(picomatch@4.0.3) ··· 3627 4417 optionalDependencies: 3628 4418 '@types/node': 24.10.2 3629 4419 fsevents: 2.3.3 4420 + jiti: 2.6.1 4421 + lightningcss: 1.30.2 4422 + tsx: 4.21.0 3630 4423 3631 - vitefu@1.1.1(vite@7.2.7(@types/node@24.10.2)): 4424 + vitefu@1.1.1(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)): 3632 4425 optionalDependencies: 3633 - vite: 7.2.7(@types/node@24.10.2) 4426 + vite: 7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0) 3634 4427 3635 4428 which@2.0.2: 3636 4429 dependencies: ··· 3638 4431 3639 4432 word-wrap@1.2.5: {} 3640 4433 3641 - wrappy@1.0.2: {} 4434 + wrappy@1.0.2: 4435 + optional: true 4436 + 4437 + ws@8.18.3: {} 4438 + 4439 + xtend@4.0.2: {} 3642 4440 3643 4441 yaml@1.10.2: {} 3644 4442
+2
src/app.css
··· 1 + @import "tailwindcss"; 2 + @plugin "daisyui";
+3 -27
src/hooks.server.ts
··· 1 1 import { db } from '$lib/server/db'; 2 2 import type { Handle, ServerInit } from '@sveltejs/kit'; 3 - import { migrate } from 'drizzle-orm/better-sqlite3/migrator'; 3 + import { migrate } from 'drizzle-orm/node-postgres/migrator'; 4 4 import { env } from '$env/dynamic/private'; 5 - import { keyValueStore } from '$lib/server/db/schema'; 6 - import { and, eq, lt } from 'drizzle-orm'; 7 - import { STATE_STORE } from '$lib/server/cache'; 8 - import { logger } from '$lib/server/logger'; 5 + 9 6 import { HOUR } from '@atproto/common'; 10 7 import { getSessionManager, SessionRestorationError } from '$lib/server/session'; 11 8 12 - const clearExpiredStates = async () => { 13 - try { 14 - logger.info('Running cleanup of the state store'); 15 - const oneHourAgo = new Date(Date.now() - HOUR); 16 - const result = await db 17 - .delete(keyValueStore) 18 - .where( 19 - and( 20 - eq(keyValueStore.storeName, STATE_STORE), 21 - lt(keyValueStore.createdAt, oneHourAgo)) 22 - ); 23 - 24 - if (result.changes > 0) { 25 - logger.info(`Cleaned up ${result.changes} expired key(s) from keyValueStore`); 26 - } 27 - } catch (err) { 28 - logger.error(`${(err as Error).message}`); 29 - } 30 - }; 31 9 32 10 33 11 export const init: ServerInit = async () => { 34 12 // Run Drizzle migrations on server startup 35 - migrate(db, { migrationsFolder: env.MIGRATIONS_FOLDER ?? 'drizzle' }); 13 + await migrate(db, { migrationsFolder: env.MIGRATIONS_FOLDER ?? 'drizzle' }); 36 14 37 - await clearExpiredStates(); 38 15 39 16 // Start a background job to clean up state every hour, which is recommended in the oauth docs 40 17 setInterval(async () => { 41 - await clearExpiredStates(); 42 18 //TODO prob should do one for the session store as well for expired sessions 43 19 }, HOUR); // Run every hour 44 20 };
+91
src/lib/components/InteractionBar.svelte
··· 1 + <script lang="ts"> 2 + let { 3 + likeCount = 0, 4 + repostCount = 0, 5 + commentCount = 0, 6 + onlike, 7 + onrepost, 8 + oncomment 9 + }: { 10 + likeCount?: number; 11 + repostCount?: number; 12 + commentCount?: number; 13 + onlike?: () => void; 14 + onrepost?: () => void; 15 + oncomment?: () => void; 16 + } = $props(); 17 + </script> 18 + 19 + <div class="flex gap-4 mt-4"> 20 + <button 21 + class="btn btn-ghost btn-sm gap-2" 22 + onclick={onlike} 23 + aria-label="Like" 24 + > 25 + <svg 26 + xmlns="http://www.w3.org/2000/svg" 27 + class="h-5 w-5" 28 + fill="none" 29 + viewBox="0 0 24 24" 30 + stroke="currentColor" 31 + > 32 + <path 33 + stroke-linecap="round" 34 + stroke-linejoin="round" 35 + stroke-width="2" 36 + d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" 37 + /> 38 + </svg> 39 + {#if likeCount > 0} 40 + <span class="text-sm">{likeCount}</span> 41 + {/if} 42 + </button> 43 + 44 + <button 45 + class="btn btn-ghost btn-sm gap-2" 46 + onclick={onrepost} 47 + aria-label="Repost" 48 + > 49 + <svg 50 + xmlns="http://www.w3.org/2000/svg" 51 + class="h-5 w-5" 52 + fill="none" 53 + viewBox="0 0 24 24" 54 + stroke="currentColor" 55 + > 56 + <path 57 + stroke-linecap="round" 58 + stroke-linejoin="round" 59 + stroke-width="2" 60 + d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" 61 + /> 62 + </svg> 63 + {#if repostCount > 0} 64 + <span class="text-sm">{repostCount}</span> 65 + {/if} 66 + </button> 67 + 68 + <button 69 + class="btn btn-ghost btn-sm gap-2" 70 + onclick={oncomment} 71 + aria-label="Comment" 72 + > 73 + <svg 74 + xmlns="http://www.w3.org/2000/svg" 75 + class="h-5 w-5" 76 + fill="none" 77 + viewBox="0 0 24 24" 78 + stroke="currentColor" 79 + > 80 + <path 81 + stroke-linecap="round" 82 + stroke-linejoin="round" 83 + stroke-width="2" 84 + d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" 85 + /> 86 + </svg> 87 + {#if commentCount > 0} 88 + <span class="text-sm">{commentCount}</span> 89 + {/if} 90 + </button> 91 + </div>
+118
src/lib/components/LeafletDocumentCard.svelte
··· 1 + <script lang="ts"> 2 + import InteractionBar from './InteractionBar.svelte'; 3 + 4 + let { 5 + record, 6 + profile 7 + }: { 8 + record: any; 9 + profile?: { handle: string; avatar?: string; displayName?: string }; 10 + } = $props(); 11 + 12 + const data = $derived(record.data as { 13 + title?: string; 14 + description?: string; 15 + tags?: string[]; 16 + author?: string; 17 + publishedAt?: string; 18 + pages?: Array<{ 19 + blocks: Array<{ 20 + block: { 21 + $type: string; 22 + plaintext?: string; 23 + }; 24 + }>; 25 + }>; 26 + }); 27 + 28 + function formatDate(dateString: string): string { 29 + const date = new Date(dateString); 30 + return new Intl.DateTimeFormat('en-US', { 31 + month: 'short', 32 + day: 'numeric', 33 + year: 'numeric' 34 + }).format(date); 35 + } 36 + 37 + function getPreviewText(): string { 38 + if (!data.pages || data.pages.length === 0) return ''; 39 + 40 + for (const page of data.pages) { 41 + for (const blockItem of page.blocks) { 42 + if ( 43 + blockItem.block.$type === 'pub.leaflet.blocks.text' && 44 + blockItem.block.plaintext && 45 + blockItem.block.plaintext.trim().length > 0 46 + ) { 47 + const text = blockItem.block.plaintext; 48 + return text.length > 200 ? text.slice(0, 200) + '...' : text; 49 + } 50 + } 51 + } 52 + return ''; 53 + } 54 + 55 + const previewText = getPreviewText(); 56 + </script> 57 + 58 + <div class="card bg-base-100 border-b border-base-300"> 59 + <div class="card-body"> 60 + <div class="flex items-start gap-4"> 61 + <div class="flex-shrink-0"> 62 + <div class="avatar"> 63 + <div class="w-12 h-12 rounded-full"> 64 + {#if profile?.avatar} 65 + <img src={profile.avatar} alt={profile.handle} /> 66 + {:else} 67 + <div class="bg-accent text-accent-content rounded-full w-12 h-12 flex items-center justify-center"> 68 + <span class="text-xl">{profile?.handle?.[0]?.toUpperCase() || '?'}</span> 69 + </div> 70 + {/if} 71 + </div> 72 + </div> 73 + </div> 74 + 75 + <div class="flex-grow"> 76 + {#if profile} 77 + <div class="text-sm text-base-content/60 mb-2"> 78 + <a href="https://bsky.app/profile/{profile.handle}" target="_blank" rel="noopener noreferrer" class="link link-hover"> 79 + @{profile.handle} 80 + </a> 81 + {#if profile.displayName} 82 + <span class="ml-1">ยท {profile.displayName}</span> 83 + {/if} 84 + </div> 85 + {/if} 86 + <h3 class="card-title text-lg mb-2">{data.title || 'Untitled Document'}</h3> 87 + 88 + {#if data.description} 89 + <p class="text-base-content/80 mb-2">{data.description}</p> 90 + {/if} 91 + 92 + {#if previewText} 93 + <p class="text-sm text-base-content/70 mb-3 line-clamp-3">{previewText}</p> 94 + {/if} 95 + 96 + {#if data.tags && data.tags.length > 0} 97 + <div class="flex flex-wrap gap-2 mb-3"> 98 + {#each data.tags as tag} 99 + <div class="badge badge-primary badge-sm">#{tag}</div> 100 + {/each} 101 + </div> 102 + {/if} 103 + 104 + {#if data.publishedAt} 105 + <div class="flex items-center gap-2 text-sm text-base-content/60"> 106 + <span>Published {formatDate(data.publishedAt)}</span> 107 + </div> 108 + {/if} 109 + 110 + <InteractionBar 111 + onlike={() => console.log('Liked document')} 112 + onrepost={() => console.log('Reposted document')} 113 + oncomment={() => console.log('Commented on document')} 114 + /> 115 + </div> 116 + </div> 117 + </div> 118 + </div>
+110
src/lib/components/MusicPlayCard.svelte
··· 1 + <script lang="ts"> 2 + import InteractionBar from './InteractionBar.svelte'; 3 + 4 + let { 5 + record, 6 + profile 7 + }: { 8 + record: any; 9 + profile?: { handle: string; avatar?: string; displayName?: string }; 10 + } = $props(); 11 + 12 + const data = $derived(record.data as { 13 + trackName?: string; 14 + artists?: Array<{ artistName: string; artistMbId: string }>; 15 + releaseName?: string; 16 + playedTime?: string; 17 + duration?: number; 18 + originUrl?: string; 19 + musicServiceBaseDomain?: string; 20 + }); 21 + 22 + function formatDuration(seconds: number): string { 23 + const mins = Math.floor(seconds / 60); 24 + const secs = seconds % 60; 25 + return `${mins}:${secs.toString().padStart(2, '0')}`; 26 + } 27 + 28 + function formatDate(dateString: string): string { 29 + const date = new Date(dateString); 30 + return new Intl.DateTimeFormat('en-US', { 31 + month: 'short', 32 + day: 'numeric', 33 + hour: 'numeric', 34 + minute: '2-digit' 35 + }).format(date); 36 + } 37 + </script> 38 + 39 + <div class="card bg-base-100 border-b border-base-300"> 40 + <div class="card-body"> 41 + <div class="flex items-start gap-4"> 42 + <div class="flex-shrink-0"> 43 + <div class="avatar"> 44 + <div class="w-12 h-12 rounded-full"> 45 + {#if profile?.avatar} 46 + <img src={profile.avatar} alt={profile.handle} /> 47 + {:else} 48 + <div class="bg-primary text-primary-content rounded-full w-12 h-12 flex items-center justify-center"> 49 + <span class="text-xl">{profile?.handle?.[0]?.toUpperCase() || '?'}</span> 50 + </div> 51 + {/if} 52 + </div> 53 + </div> 54 + </div> 55 + 56 + <div class="flex-grow"> 57 + {#if profile} 58 + <div class="text-sm text-base-content/60 mb-2"> 59 + <a href="https://bsky.app/profile/{profile.handle}" target="_blank" rel="noopener noreferrer" class="link link-hover"> 60 + @{profile.handle} 61 + </a> 62 + {#if profile.displayName} 63 + <span class="ml-1">ยท {profile.displayName}</span> 64 + {/if} 65 + </div> 66 + {/if} 67 + <h3 class="card-title text-lg">{data.trackName || 'Unknown Track'}</h3> 68 + {#if data.artists && data.artists.length > 0} 69 + <p class="text-base-content/70"> 70 + {data.artists.map((a) => a.artistName).join(', ')} 71 + </p> 72 + {/if} 73 + {#if data.releaseName} 74 + <p class="text-sm text-base-content/60 mt-1">{data.releaseName}</p> 75 + {/if} 76 + 77 + <div class="flex items-center gap-4 mt-2 text-sm text-base-content/60"> 78 + {#if data.duration} 79 + <span>{formatDuration(data.duration)}</span> 80 + <span>โ€ข</span> 81 + {/if} 82 + {#if data.playedTime} 83 + <span>{formatDate(data.playedTime)}</span> 84 + {/if} 85 + {#if data.musicServiceBaseDomain} 86 + <span>โ€ข</span> 87 + <span class="capitalize">{data.musicServiceBaseDomain.split('.')[0]}</span> 88 + {/if} 89 + </div> 90 + 91 + {#if data.originUrl} 92 + <a 93 + href={data.originUrl} 94 + target="_blank" 95 + rel="noopener noreferrer" 96 + class="link link-primary text-sm mt-2 inline-block" 97 + > 98 + Listen on {data.musicServiceBaseDomain?.split('.')[0] || 'platform'} 99 + </a> 100 + {/if} 101 + 102 + <InteractionBar 103 + onlike={() => console.log('Liked music play')} 104 + onrepost={() => console.log('Reposted music play')} 105 + oncomment={() => console.log('Commented on music play')} 106 + /> 107 + </div> 108 + </div> 109 + </div> 110 + </div>
+110
src/lib/components/TangledRepoCard.svelte
··· 1 + <script lang="ts"> 2 + import InteractionBar from './InteractionBar.svelte'; 3 + 4 + let { 5 + record, 6 + profile 7 + }: { 8 + record: any; 9 + profile?: { handle: string; avatar?: string; displayName?: string }; 10 + } = $props(); 11 + 12 + const data = $derived(record.data as { 13 + name?: string; 14 + description?: string; 15 + knot?: string; 16 + labels?: string[]; 17 + source?: string; 18 + createdAt?: string; 19 + }); 20 + 21 + function formatDate(dateString: string): string { 22 + const date = new Date(dateString); 23 + return new Intl.DateTimeFormat('en-US', { 24 + month: 'short', 25 + day: 'numeric', 26 + year: 'numeric' 27 + }).format(date); 28 + } 29 + 30 + function extractLabelName(atUri: string): string { 31 + const parts = atUri.split('/'); 32 + return parts[parts.length - 1] || atUri; 33 + } 34 + </script> 35 + 36 + <div class="card bg-base-100 border-b border-base-300"> 37 + <div class="card-body"> 38 + <div class="flex items-start gap-4"> 39 + <div class="flex-shrink-0"> 40 + <div class="avatar"> 41 + <div class="w-12 h-12 rounded-full"> 42 + {#if profile?.avatar} 43 + <img src={profile.avatar} alt={profile.handle} /> 44 + {:else} 45 + <div class="bg-secondary text-secondary-content rounded-full w-12 h-12 flex items-center justify-center"> 46 + <span class="text-xl">{profile?.handle?.[0]?.toUpperCase() || '?'}</span> 47 + </div> 48 + {/if} 49 + </div> 50 + </div> 51 + </div> 52 + 53 + <div class="flex-grow"> 54 + {#if profile} 55 + <div class="text-sm text-base-content/60 mb-2"> 56 + <a href="https://bsky.app/profile/{profile.handle}" target="_blank" rel="noopener noreferrer" class="link link-hover"> 57 + @{profile.handle} 58 + </a> 59 + {#if profile.displayName} 60 + <span class="ml-1">ยท {profile.displayName}</span> 61 + {/if} 62 + </div> 63 + {/if} 64 + <div class="flex items-center gap-2"> 65 + <h3 class="card-title text-lg">{data.name || 'Unknown Repository'}</h3> 66 + {#if data.knot} 67 + <div class="badge badge-outline badge-sm">{data.knot}</div> 68 + {/if} 69 + </div> 70 + 71 + {#if data.description} 72 + <p class="text-base-content/80 mt-2">{data.description}</p> 73 + {/if} 74 + 75 + {#if data.labels && data.labels.length > 0} 76 + <div class="flex flex-wrap gap-2 mt-3"> 77 + {#each data.labels as label} 78 + <div class="badge badge-ghost badge-sm"> 79 + {extractLabelName(label)} 80 + </div> 81 + {/each} 82 + </div> 83 + {/if} 84 + 85 + {#if data.createdAt} 86 + <div class="flex items-center gap-2 mt-3 text-sm text-base-content/60"> 87 + <span>Created {formatDate(data.createdAt)}</span> 88 + </div> 89 + {/if} 90 + 91 + {#if data.source} 92 + <a 93 + href={data.source} 94 + target="_blank" 95 + rel="noopener noreferrer" 96 + class="link link-primary text-sm mt-2 inline-block" 97 + > 98 + View source 99 + </a> 100 + {/if} 101 + 102 + <InteractionBar 103 + onlike={() => console.log('Liked repo')} 104 + onrepost={() => console.log('Reposted repo')} 105 + oncomment={() => console.log('Commented on repo')} 106 + /> 107 + </div> 108 + </div> 109 + </div> 110 + </div>
+2 -4
src/lib/server/db/index.ts
··· 1 - import { drizzle } from 'drizzle-orm/better-sqlite3'; 2 - import Database from 'better-sqlite3'; 1 + import { drizzle } from 'drizzle-orm/node-postgres'; 3 2 import * as schema from './schema'; 4 3 import { env } from '$env/dynamic/private'; 5 4 import { logger } from '$lib/server/logger'; 6 5 7 6 if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); 8 7 9 - const client = new Database(env.DATABASE_URL); 10 8 logger.info('Connected to database'); 11 - export const db = drizzle(client, { schema }); 9 + export const db = drizzle(env.DATABASE_URL!,{ schema });
+52 -15
src/lib/server/db/schema.ts
··· 1 - import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; 1 + import { index, text, integer, jsonb, pgTable, serial, time, varchar, uniqueIndex, timestamp } from 'drizzle-orm/pg-core'; 2 2 3 - export const keyValueStore = sqliteTable('key_value_store', { 4 - key: text('key').primaryKey(), 5 - value: text('value'), 6 - storeName: text('storeName'), 7 - createdAt: integer({ mode: 'timestamp' }) // Date 8 - }); 3 + /** 4 + * Holds collected records from firehose, backfilled, or manually entered 5 + */ 6 + export const recordsTable = pgTable('records', { 7 + id: serial().primaryKey(), 8 + rkey: varchar().notNull(), 9 + collection: varchar().notNull(), 10 + repo: varchar().notNull(), 11 + atUri: text().notNull(), 12 + data: jsonb().notNull(), 13 + indexedAt: timestamp({ mode: 'date' }).notNull().defaultNow() 14 + }, (table) => [ 15 + index().on(table.rkey), 16 + index().on(table.collection), 17 + index().on(table.repo), 18 + uniqueIndex().on(table.atUri), 19 + ]); 9 20 10 21 11 - export const sessionStore = sqliteTable('session_store', { 12 - id: text('id').primaryKey(), 13 - //Not leaving unique since it could be multiple logins from the same user across browsers 14 - did: text('did').notNull(), 15 - handle: text('handle').notNull(), 16 - createdAt: integer({ mode: 'timestamp' }).notNull(), // Date 17 - expiresAt: integer({ mode: 'timestamp' }).notNull() // Date 22 + /** 23 + * Holds pokes toward a record. Current thinking is when a user pokes a record it adds it to the "feeds" 24 + * Maybe have a "catch all feed" that shows all lexicons that the user wants to see 25 + * 26 + * these are the xyz.atpoke.feed.poke records 27 + */ 28 + export const recordPokesTable = pgTable('record_pokes',{ 29 + id: serial().primaryKey(), 30 + recordId: integer().references(() => recordsTable.id), 31 + pokersRepo: text().notNull(), 32 + atUri: text().notNull(), 33 + indexedAt: time().notNull().defaultNow() 34 + },(table) => [ 35 + index().on(table.pokersRepo), 36 + index().on(table.atUri) 37 + ]); 38 + 39 + /** 40 + * These are the traditional pokes. Like "I just poked user xyz". These will make it to the feed via recordsTable 41 + * 42 + * xyz.atpoke.graph.poke 43 + */ 44 + export const userPokes = pgTable('user_pokes', { 45 + id: serial().primaryKey(), 46 + //This is who you poked 47 + subject: text().notNull(), 48 + //Who is doing the poking 49 + poker: text().notNull(), 50 + at_uri: text().notNull(), 51 + indexedAt: time().notNull().defaultNow() 52 + }, (table) => [ 53 + index().on(table.subject), 54 + index().on(table.poker) 55 + ]); 18 56 19 - });
+4 -1
src/routes/+layout.svelte
··· 1 1 <script lang="ts"> 2 2 import favicon from '$lib/assets/favicon.svg'; 3 + import '../app.css'; 3 4 let { children, data } = $props(); 4 5 import { enhance } from '$app/forms'; 5 6 </script> ··· 55 56 <li> 56 57 <a href="/">Home</a> 57 58 </li> 58 - 59 + <li> 60 + <a href="/feed">Feed</a> 61 + </li> 59 62 <li> 60 63 <a href="/demo">Demo</a> 61 64 </li>
+76
src/routes/feed/+page.server.ts
··· 1 + import type { PageServerLoad } from './$types'; 2 + import { redirect } from '@sveltejs/kit'; 3 + import { db } from '$lib/server/db'; 4 + import { recordsTable } from '$lib/server/db/schema'; 5 + import { desc, eq, ne } from 'drizzle-orm'; 6 + 7 + interface ProfileData { 8 + handle: string; 9 + avatar?: string; 10 + displayName?: string; 11 + } 12 + 13 + async function fetchProfile(repo: string): Promise<ProfileData | null> { 14 + try { 15 + const response = await fetch( 16 + `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${repo}` 17 + ); 18 + if (!response.ok) return null; 19 + const data = await response.json(); 20 + return { 21 + handle: data.handle, 22 + avatar: data.avatar, 23 + displayName: data.displayName 24 + }; 25 + } catch { 26 + return null; 27 + } 28 + } 29 + 30 + export const load: PageServerLoad = async (event) => { 31 + if (!event.locals.session) { 32 + return redirect(302, '/login'); 33 + } 34 + 35 + // Fetch one music play record 36 + const musicRecords = await db 37 + .select() 38 + .from(recordsTable) 39 + .where(eq(recordsTable.collection, 'fm.teal.alpha.feed.play')) 40 + .orderBy(desc(recordsTable.indexedAt)) 41 + .limit(1); 42 + 43 + // Fetch other records (non-music) 44 + const otherRecords = await db 45 + .select() 46 + .from(recordsTable) 47 + .where(ne(recordsTable.collection, 'fm.teal.alpha.feed.play')) 48 + .orderBy(desc(recordsTable.indexedAt)) 49 + .limit(49); 50 + 51 + // Combine and sort by indexedAt 52 + const records = [...musicRecords, ...otherRecords].sort( 53 + (a, b) => b.indexedAt.getTime() - a.indexedAt.getTime() 54 + ); 55 + 56 + // Fetch profile data for all unique repos 57 + const uniqueRepos = [...new Set(records.map((r) => r.repo))]; 58 + const profilePromises = uniqueRepos.map(async (repo) => { 59 + const profile = await fetchProfile(repo); 60 + return { repo, profile }; 61 + }); 62 + 63 + const profileResults = await Promise.all(profilePromises); 64 + const profiles: Record<string, ProfileData> = {}; 65 + for (const { repo, profile } of profileResults) { 66 + if (profile) { 67 + profiles[repo] = profile; 68 + } 69 + } 70 + 71 + return { 72 + records, 73 + profiles, 74 + usersDid: event.locals.session.did 75 + }; 76 + };
+58
src/routes/feed/+page.svelte
··· 1 + <script lang="ts"> 2 + import type { PageData } from './$types'; 3 + import MusicPlayCard from '$lib/components/MusicPlayCard.svelte'; 4 + import TangledRepoCard from '$lib/components/TangledRepoCard.svelte'; 5 + import LeafletDocumentCard from '$lib/components/LeafletDocumentCard.svelte'; 6 + 7 + let { data }: { data: PageData } = $props(); 8 + </script> 9 + 10 + <svelte:head> 11 + <title>Feed - atpoke.xyz</title> 12 + </svelte:head> 13 + 14 + <div class="container mx-auto px-4 py-8 max-w-3xl"> 15 + <div class="mb-8"> 16 + <h1 class="text-4xl font-bold mb-2">Feed</h1> 17 + <p class="text-base-content/70">Discover the latest from the ATProto ecosystem</p> 18 + </div> 19 + 20 + {#if data.records.length === 0} 21 + <div class="alert"> 22 + <svg 23 + xmlns="http://www.w3.org/2000/svg" 24 + fill="none" 25 + viewBox="0 0 24 24" 26 + class="stroke-info shrink-0 w-6 h-6" 27 + > 28 + <path 29 + stroke-linecap="round" 30 + stroke-linejoin="round" 31 + stroke-width="2" 32 + d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" 33 + ></path> 34 + </svg> 35 + <span>No records found. The feed is empty.</span> 36 + </div> 37 + {:else} 38 + <div> 39 + {#each data.records as record (record.id)} 40 + {#if record.collection === 'fm.teal.alpha.feed.play'} 41 + <MusicPlayCard {record} profile={data.profiles[record.repo]} /> 42 + {:else if record.collection === 'sh.tangled.repo'} 43 + <TangledRepoCard {record} profile={data.profiles[record.repo]} /> 44 + {:else if record.collection === 'pub.leaflet.document'} 45 + <LeafletDocumentCard {record} profile={data.profiles[record.repo]} /> 46 + {:else} 47 + <div class="card bg-base-100 border-b border-base-300"> 48 + <div class="card-body"> 49 + <h3 class="card-title text-sm opacity-60">Unknown Collection Type</h3> 50 + <p class="text-sm">{record.collection}</p> 51 + <pre class="text-xs overflow-auto">{JSON.stringify(record.data, null, 2)}</pre> 52 + </div> 53 + </div> 54 + {/if} 55 + {/each} 56 + </div> 57 + {/if} 58 + </div>
+81
src/routes/webhooks/tap/+server.ts
··· 1 + import { json } from '@sveltejs/kit'; 2 + import { env } from '$env/dynamic/private'; 3 + import type { RequestHandler } from './$types'; 4 + import { logger } from '$lib/server/logger'; 5 + import { assureAdminAuth, type RecordEvent, type TapEvent } from '@atproto/tap'; 6 + import { db } from '$lib/server/db'; 7 + import { recordsTable } from '$lib/server/db/schema'; 8 + import { eq } from 'drizzle-orm'; 9 + 10 + export const POST: RequestHandler = async ({ request }) => { 11 + const auth = request.headers.get('Authorization'); 12 + 13 + if (auth === null) { 14 + logger.error('Missing Authorization header'); 15 + return json({ error: 'Missing Authorization header' }, { status: 401 }); 16 + } 17 + 18 + try{ 19 + if(env.TAP_ADMIN_PASSWORD === undefined) throw new Error('TAP_ADMIN_PASSWORD is not set'); 20 + assureAdminAuth(env.TAP_ADMIN_PASSWORD, auth); 21 + }catch (err){ 22 + const errorMessage = (err as Error).message; 23 + logger.error('Tap webhook auth error: ' + errorMessage + ''); 24 + return json({ error: 'Not authenticated' }, { status: 401 }); 25 + } 26 + 27 + try { 28 + const body = await request.json(); 29 + await parseAndProcessTapEvent(body); 30 + 31 + 32 + //This should just respond with 200 OK. comment out to not ack 33 + return json({ }); 34 + } catch (err) { 35 + console.error('Failed to process event:', err); 36 + return json({ error: 'Failed to process event' }, { status: 500 }); 37 + } 38 + 39 + }; 40 + 41 + const parseAndProcessTapEvent = async (event: TapEvent) => { 42 + switch (event.type) { 43 + case 'identity': 44 + logger.info(event); 45 + break; 46 + case 'record': 47 + await saveRecord(event.record as RecordEvent); 48 + break; 49 + default: 50 + throw new Error(`Unsupported event type: ${JSON.stringify(event)}`); 51 + } 52 + }; 53 + 54 + 55 + const saveRecord = async (event: RecordEvent) => { 56 + const atUri = `${event.did}/${event.collection}/${event.rkey}`; 57 + logger.info(`Processing record event: ${atUri}`); 58 + if (event.action === 'create' || event.action === 'update') { 59 + if (!event.record) { 60 + logger.warn(`Record event with action ${event.action} missing record data: ${event.rkey}`); 61 + return; 62 + } 63 + 64 + await db.insert(recordsTable).values({ 65 + rkey: event.rkey, 66 + collection: event.collection, 67 + repo: event.did, 68 + atUri: atUri, 69 + data: event.record, 70 + }).onConflictDoUpdate({ 71 + target: recordsTable.atUri, 72 + set: { 73 + data: event.record, 74 + 75 + } 76 + }); 77 + logger.info(`Saved record: ${event.did}/${event.collection}/${event.rkey}`); 78 + } else if (event.action === 'delete') { 79 + await db.delete(recordsTable).where(eq(recordsTable.atUri, atUri)); 80 + } 81 + };
+2 -1
vite.config.ts
··· 1 + import tailwindcss from '@tailwindcss/vite'; 1 2 import { sveltekit } from '@sveltejs/kit/vite'; 2 3 import { defineConfig } from 'vite'; 3 4 import 'dotenv/config'; 4 5 5 6 export default defineConfig({ 6 - plugins: [sveltekit()], 7 + plugins: [tailwindcss(), sveltekit()], 7 8 server: { 8 9 host: '0.0.0.0', 9 10 allowedHosts: process.env.OAUTH_DOMAIN ? [process.env.OAUTH_DOMAIN] : []