An atproto based writing game loosely inspired by Fiasco!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

wip: sync lexicon test

+891 -18
+7
app.config.ts
··· 1 1 import { defineConfig } from "@solidjs/start/config"; 2 2 3 3 export default defineConfig({ 4 + server: { 5 + preset: "node-server", 6 + }, 4 7 vite: { 5 8 ssr: { external: ["drizzle-orm"] }, 9 + server: { 10 + host: "0.0.0.0", 11 + port: 3000, 12 + }, 6 13 }, 7 14 });
+4
drizzle/0003_elite_marvel_boy.sql
··· 1 + ALTER TABLE "post" ADD COLUMN "uri" varchar(512);--> statement-breakpoint 2 + ALTER TABLE "post" ADD COLUMN "authorDid" varchar(255);--> statement-breakpoint 3 + ALTER TABLE "post" ADD COLUMN "createdAt" timestamp;--> statement-breakpoint 4 + ALTER TABLE "post" ADD COLUMN "indexedAt" timestamp DEFAULT now();
+220
drizzle/meta/0003_snapshot.json
··· 1 + { 2 + "id": "f7adfcbb-9977-4b66-950b-8662b1ad3094", 3 + "prevId": "ed4e5fa6-c644-4498-81f2-2ab6e82937ce", 4 + "version": "7", 5 + "dialect": "postgresql", 6 + "tables": { 7 + "public.auth_session": { 8 + "name": "auth_session", 9 + "schema": "", 10 + "columns": { 11 + "key": { 12 + "name": "key", 13 + "type": "varchar(255)", 14 + "primaryKey": true, 15 + "notNull": true 16 + }, 17 + "session": { 18 + "name": "session", 19 + "type": "text", 20 + "primaryKey": false, 21 + "notNull": true 22 + } 23 + }, 24 + "indexes": {}, 25 + "foreignKeys": {}, 26 + "compositePrimaryKeys": {}, 27 + "uniqueConstraints": {}, 28 + "policies": {}, 29 + "checkConstraints": {}, 30 + "isRLSEnabled": false 31 + }, 32 + "public.auth_state": { 33 + "name": "auth_state", 34 + "schema": "", 35 + "columns": { 36 + "key": { 37 + "name": "key", 38 + "type": "varchar(255)", 39 + "primaryKey": true, 40 + "notNull": true 41 + }, 42 + "state": { 43 + "name": "state", 44 + "type": "text", 45 + "primaryKey": false, 46 + "notNull": true 47 + } 48 + }, 49 + "indexes": {}, 50 + "foreignKeys": {}, 51 + "compositePrimaryKeys": {}, 52 + "uniqueConstraints": {}, 53 + "policies": {}, 54 + "checkConstraints": {}, 55 + "isRLSEnabled": false 56 + }, 57 + "public.post": { 58 + "name": "post", 59 + "schema": "", 60 + "columns": { 61 + "id": { 62 + "name": "id", 63 + "type": "integer", 64 + "primaryKey": true, 65 + "notNull": true, 66 + "identity": { 67 + "type": "always", 68 + "name": "post_id_seq", 69 + "schema": "public", 70 + "increment": "1", 71 + "startWith": "1", 72 + "minValue": "1", 73 + "maxValue": "2147483647", 74 + "cache": "1", 75 + "cycle": false 76 + } 77 + }, 78 + "uri": { 79 + "name": "uri", 80 + "type": "varchar(512)", 81 + "primaryKey": false, 82 + "notNull": false 83 + }, 84 + "authorDid": { 85 + "name": "authorDid", 86 + "type": "varchar(255)", 87 + "primaryKey": false, 88 + "notNull": false 89 + }, 90 + "message": { 91 + "name": "message", 92 + "type": "varchar(255)", 93 + "primaryKey": false, 94 + "notNull": true 95 + }, 96 + "author": { 97 + "name": "author", 98 + "type": "varchar(255)", 99 + "primaryKey": false, 100 + "notNull": true 101 + }, 102 + "createdAt": { 103 + "name": "createdAt", 104 + "type": "timestamp", 105 + "primaryKey": false, 106 + "notNull": false 107 + }, 108 + "indexedAt": { 109 + "name": "indexedAt", 110 + "type": "timestamp", 111 + "primaryKey": false, 112 + "notNull": false, 113 + "default": "now()" 114 + } 115 + }, 116 + "indexes": {}, 117 + "foreignKeys": {}, 118 + "compositePrimaryKeys": {}, 119 + "uniqueConstraints": {}, 120 + "policies": {}, 121 + "checkConstraints": {}, 122 + "isRLSEnabled": false 123 + }, 124 + "public.user_session": { 125 + "name": "user_session", 126 + "schema": "", 127 + "columns": { 128 + "sessionId": { 129 + "name": "sessionId", 130 + "type": "varchar(255)", 131 + "primaryKey": true, 132 + "notNull": true 133 + }, 134 + "did": { 135 + "name": "did", 136 + "type": "varchar(255)", 137 + "primaryKey": false, 138 + "notNull": true 139 + }, 140 + "createdAt": { 141 + "name": "createdAt", 142 + "type": "timestamp", 143 + "primaryKey": false, 144 + "notNull": true, 145 + "default": "now()" 146 + }, 147 + "expiresAt": { 148 + "name": "expiresAt", 149 + "type": "timestamp", 150 + "primaryKey": false, 151 + "notNull": true 152 + } 153 + }, 154 + "indexes": {}, 155 + "foreignKeys": { 156 + "user_session_did_user_did_fk": { 157 + "name": "user_session_did_user_did_fk", 158 + "tableFrom": "user_session", 159 + "tableTo": "user", 160 + "columnsFrom": [ 161 + "did" 162 + ], 163 + "columnsTo": [ 164 + "did" 165 + ], 166 + "onDelete": "cascade", 167 + "onUpdate": "no action" 168 + } 169 + }, 170 + "compositePrimaryKeys": {}, 171 + "uniqueConstraints": {}, 172 + "policies": {}, 173 + "checkConstraints": {}, 174 + "isRLSEnabled": false 175 + }, 176 + "public.user": { 177 + "name": "user", 178 + "schema": "", 179 + "columns": { 180 + "did": { 181 + "name": "did", 182 + "type": "varchar(255)", 183 + "primaryKey": true, 184 + "notNull": true 185 + }, 186 + "handle": { 187 + "name": "handle", 188 + "type": "varchar(255)", 189 + "primaryKey": false, 190 + "notNull": true 191 + }, 192 + "createdAt": { 193 + "name": "createdAt", 194 + "type": "timestamp", 195 + "primaryKey": false, 196 + "notNull": true, 197 + "default": "now()" 198 + } 199 + }, 200 + "indexes": {}, 201 + "foreignKeys": {}, 202 + "compositePrimaryKeys": {}, 203 + "uniqueConstraints": {}, 204 + "policies": {}, 205 + "checkConstraints": {}, 206 + "isRLSEnabled": false 207 + } 208 + }, 209 + "enums": {}, 210 + "schemas": {}, 211 + "sequences": {}, 212 + "roles": {}, 213 + "policies": {}, 214 + "views": {}, 215 + "_meta": { 216 + "columns": {}, 217 + "schemas": {}, 218 + "tables": {} 219 + } 220 + }
+7
drizzle/meta/_journal.json
··· 22 22 "when": 1759612340624, 23 23 "tag": "0002_loose_meltdown", 24 24 "breakpoints": true 25 + }, 26 + { 27 + "idx": 3, 28 + "version": "7", 29 + "when": 1759696452331, 30 + "tag": "0003_elite_marvel_boy", 31 + "breakpoints": true 25 32 } 26 33 ] 27 34 }
+22
lexicons/message.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "xyz.protoshamble.message", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "key": "tid", 8 + "record": { 9 + "type": "object", 10 + "required": ["message", "createdAt"], 11 + "properties": { 12 + "message": { 13 + "type": "string", 14 + "minLength": 1, 15 + "maxLength": 255 16 + }, 17 + "createdAt": { "type": "string", "format": "datetime" } 18 + } 19 + } 20 + } 21 + } 22 + }
+9 -3
package.json
··· 1 1 { 2 - "name": "example-with-drizzle", 2 + "name": "protoshamble", 3 3 "type": "module", 4 4 "scripts": { 5 5 "dev": "vinxi dev", 6 6 "build": "vinxi build", 7 - "start": "vinxi start" 7 + "start": "vinxi start", 8 + "db:push": "drizzle-kit push", 9 + "db:generate": "drizzle-kit generate", 10 + "lexgen": "lex gen-server ./src/lexicon ./lexicons/*" 8 11 }, 9 12 "devDependencies": { 10 - "@types/better-sqlite3": "^7.6.10", 13 + "@atproto/lex-cli": "^0.9.5", 11 14 "@types/node": "^20.14.8", 12 15 "@types/pg": "^8.15.5", 13 16 "drizzle-kit": "^0.31.5", ··· 15 18 }, 16 19 "dependencies": { 17 20 "@atproto/api": "^0.17.0", 21 + "@atproto/common": "^0.4.12", 22 + "@atproto/lexicon": "^0.5.1", 18 23 "@atproto/oauth-client-node": "^0.3.8", 19 24 "@atproto/syntax": "^0.4.1", 20 25 "@solidjs/router": "^0.15.0", ··· 22 27 "better-sqlite3": "^11.0.0", 23 28 "dotenv": "^17.2.3", 24 29 "drizzle-orm": "^0.44.5", 30 + "multiformats": "^13.4.1", 25 31 "pg": "^8.16.3", 26 32 "solid-js": "^1.9.5", 27 33 "vinxi": "^0.5.7"
+294 -3
pnpm-lock.yaml
··· 11 11 '@atproto/api': 12 12 specifier: ^0.17.0 13 13 version: 0.17.0 14 + '@atproto/common': 15 + specifier: ^0.4.12 16 + version: 0.4.12 17 + '@atproto/lexicon': 18 + specifier: ^0.5.1 19 + version: 0.5.1 14 20 '@atproto/oauth-client-node': 15 21 specifier: ^0.3.8 16 22 version: 0.3.8 ··· 32 38 drizzle-orm: 33 39 specifier: ^0.44.5 34 40 version: 0.44.5(@types/better-sqlite3@7.6.13)(@types/pg@8.15.5)(better-sqlite3@11.10.0)(pg@8.16.3) 41 + multiformats: 42 + specifier: ^13.4.1 43 + version: 13.4.1 35 44 pg: 36 45 specifier: ^8.16.3 37 46 version: 8.16.3 ··· 42 51 specifier: ^0.5.7 43 52 version: 0.5.8(@types/node@20.19.19)(better-sqlite3@11.10.0)(db0@0.3.2(better-sqlite3@11.10.0)(drizzle-orm@0.44.5(@types/better-sqlite3@7.6.13)(@types/pg@8.15.5)(better-sqlite3@11.10.0)(pg@8.16.3)))(drizzle-orm@0.44.5(@types/better-sqlite3@7.6.13)(@types/pg@8.15.5)(better-sqlite3@11.10.0)(pg@8.16.3))(ioredis@5.8.0)(jiti@2.6.0)(terser@5.44.0)(tsx@4.20.6) 44 53 devDependencies: 45 - '@types/better-sqlite3': 46 - specifier: ^7.6.10 47 - version: 7.6.13 54 + '@atproto/lex-cli': 55 + specifier: ^0.9.5 56 + version: 0.9.5 48 57 '@types/node': 49 58 specifier: ^20.14.8 50 59 version: 20.19.19 ··· 95 104 '@atproto/common-web@0.4.3': 96 105 resolution: {integrity: sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==} 97 106 107 + '@atproto/common@0.4.12': 108 + resolution: {integrity: sha512-NC+TULLQiqs6MvNymhQS5WDms3SlbIKGLf4n33tpftRJcalh507rI+snbcUb7TLIkKw7VO17qMqxEXtIdd5auQ==} 109 + engines: {node: '>=18.7.0'} 110 + 98 111 '@atproto/did@0.2.0': 99 112 resolution: {integrity: sha512-BskT39KYbwY1DUsWekkHh47xS+wvJpFq5F9acsicNfYniinyAMnNTzGKQEhnjQuG7K0qQItg/SnmC+y0tJXV7Q==} 100 113 ··· 106 119 107 120 '@atproto/jwk@0.5.0': 108 121 resolution: {integrity: sha512-Qi2NtEqhkG+uz3CKia4+H05WMV/z//dz3ESo5+cyBKrOnxVTJ5ZubMyltWjoYvy6v/jLhorXdDWcjn07yky7MQ==} 122 + 123 + '@atproto/lex-cli@0.9.5': 124 + resolution: {integrity: sha512-zun4jhD1dbjD7IHtLIjh/1UsMx+6E8+OyOT2GXYAKIj9N6wmLKM/v2OeQBKxcyqUmtRi57lxWnGikWjjU7pplQ==} 125 + engines: {node: '>=18.7.0'} 126 + hasBin: true 109 127 110 128 '@atproto/lexicon@0.5.1': 111 129 resolution: {integrity: sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==} ··· 263 281 resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} 264 282 engines: {node: '>=6.9.0'} 265 283 284 + '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': 285 + resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==} 286 + cpu: [arm64] 287 + os: [darwin] 288 + 289 + '@cbor-extract/cbor-extract-darwin-x64@2.2.0': 290 + resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==} 291 + cpu: [x64] 292 + os: [darwin] 293 + 294 + '@cbor-extract/cbor-extract-linux-arm64@2.2.0': 295 + resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==} 296 + cpu: [arm64] 297 + os: [linux] 298 + 299 + '@cbor-extract/cbor-extract-linux-arm@2.2.0': 300 + resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==} 301 + cpu: [arm] 302 + os: [linux] 303 + 304 + '@cbor-extract/cbor-extract-linux-x64@2.2.0': 305 + resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==} 306 + cpu: [x64] 307 + os: [linux] 308 + 309 + '@cbor-extract/cbor-extract-win32-x64@2.2.0': 310 + resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==} 311 + cpu: [x64] 312 + os: [win32] 313 + 266 314 '@cloudflare/kv-asset-handler@0.4.0': 267 315 resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} 268 316 engines: {node: '>=18.0.0'} ··· 574 622 575 623 '@ioredis/commands@1.4.0': 576 624 resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} 625 + 626 + '@ipld/dag-cbor@7.0.3': 627 + resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==} 577 628 578 629 '@isaacs/cliui@8.0.2': 579 630 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} ··· 964 1015 resolution: {integrity: sha512-a05fzK+jBGacsSAc1vE8an7lpBh4H0PyIEcivtEyHLomgSeElAJxm9E2It/0nYRZ5Lh23m0okbhzJNaYWZpAOg==} 965 1016 engines: {node: '>=12'} 966 1017 1018 + '@ts-morph/common@0.25.0': 1019 + resolution: {integrity: sha512-kMnZz+vGGHi4GoHnLmMhGNjm44kGtKUXGnOvrKmMwAuvNjM/PgKVGfUnL7IDvK7Jb2QQ82jq3Zmp04Gy+r3Dkg==} 1020 + 967 1021 '@types/babel__core@7.20.5': 968 1022 resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} 969 1023 ··· 1113 1167 async@3.2.6: 1114 1168 resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} 1115 1169 1170 + atomic-sleep@1.0.0: 1171 + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} 1172 + engines: {node: '>=8.0.0'} 1173 + 1116 1174 await-lock@2.2.2: 1117 1175 resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} 1118 1176 ··· 1206 1264 1207 1265 caniuse-lite@1.0.30001746: 1208 1266 resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==} 1267 + 1268 + cbor-extract@2.2.0: 1269 + resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} 1270 + hasBin: true 1271 + 1272 + cbor-x@1.6.0: 1273 + resolution: {integrity: sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==} 1274 + 1275 + cborg@1.10.2: 1276 + resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} 1277 + hasBin: true 1209 1278 1210 1279 ccount@2.0.1: 1211 1280 resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} 1212 1281 1282 + chalk@4.1.2: 1283 + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 1284 + engines: {node: '>=10'} 1285 + 1213 1286 chalk@5.6.2: 1214 1287 resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} 1215 1288 engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} ··· 1250 1323 resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} 1251 1324 engines: {node: '>=0.10.0'} 1252 1325 1326 + code-block-writer@13.0.3: 1327 + resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} 1328 + 1253 1329 color-convert@2.0.1: 1254 1330 resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 1255 1331 engines: {node: '>=7.0.0'} ··· 1262 1338 1263 1339 commander@2.20.3: 1264 1340 resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 1341 + 1342 + commander@9.5.0: 1343 + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} 1344 + engines: {node: ^12.20.0 || >=14} 1265 1345 1266 1346 commondir@1.0.1: 1267 1347 resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} ··· 1644 1724 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 1645 1725 engines: {node: '>=8.6.0'} 1646 1726 1727 + fast-redact@3.5.0: 1728 + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} 1729 + engines: {node: '>=6'} 1730 + 1647 1731 fastq@1.19.1: 1648 1732 resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 1649 1733 ··· 1751 1835 1752 1836 h3@1.15.4: 1753 1837 resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} 1838 + 1839 + has-flag@4.0.0: 1840 + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1841 + engines: {node: '>=8'} 1754 1842 1755 1843 hasown@2.0.2: 1756 1844 resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} ··· 2071 2159 ms@2.1.3: 2072 2160 resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 2073 2161 2162 + multiformats@13.4.1: 2163 + resolution: {integrity: sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==} 2164 + 2074 2165 multiformats@9.9.0: 2075 2166 resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} 2076 2167 ··· 2115 2206 resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} 2116 2207 engines: {node: '>= 6.13.0'} 2117 2208 2209 + node-gyp-build-optional-packages@5.1.1: 2210 + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} 2211 + hasBin: true 2212 + 2118 2213 node-gyp-build@4.8.4: 2119 2214 resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} 2120 2215 hasBin: true ··· 2149 2244 ohash@2.0.11: 2150 2245 resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} 2151 2246 2247 + on-exit-leak-free@2.1.2: 2248 + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} 2249 + engines: {node: '>=14.0.0'} 2250 + 2152 2251 on-finished@2.4.1: 2153 2252 resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 2154 2253 engines: {node: '>= 0.8'} ··· 2176 2275 parseurl@1.3.3: 2177 2276 resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 2178 2277 engines: {node: '>= 0.8'} 2278 + 2279 + path-browserify@1.0.1: 2280 + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} 2179 2281 2180 2282 path-key@3.1.1: 2181 2283 resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} ··· 2253 2355 resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 2254 2356 engines: {node: '>=12'} 2255 2357 2358 + pino-abstract-transport@1.2.0: 2359 + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} 2360 + 2361 + pino-std-serializers@6.2.2: 2362 + resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} 2363 + 2364 + pino@8.21.0: 2365 + resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} 2366 + hasBin: true 2367 + 2256 2368 pkg-types@1.3.1: 2257 2369 resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} 2258 2370 ··· 2284 2396 engines: {node: '>=10'} 2285 2397 hasBin: true 2286 2398 2399 + prettier@3.6.2: 2400 + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} 2401 + engines: {node: '>=14'} 2402 + hasBin: true 2403 + 2287 2404 pretty-bytes@7.1.0: 2288 2405 resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==} 2289 2406 engines: {node: '>=20'} 2290 2407 2291 2408 process-nextick-args@2.0.1: 2292 2409 resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} 2410 + 2411 + process-warning@3.0.0: 2412 + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} 2293 2413 2294 2414 process@0.11.10: 2295 2415 resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} ··· 2306 2426 2307 2427 queue-microtask@1.2.3: 2308 2428 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 2429 + 2430 + quick-format-unescaped@4.0.4: 2431 + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} 2309 2432 2310 2433 radix3@1.1.2: 2311 2434 resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} ··· 2342 2465 resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 2343 2466 engines: {node: '>= 14.18.0'} 2344 2467 2468 + real-require@0.2.0: 2469 + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} 2470 + engines: {node: '>= 12.13.0'} 2471 + 2345 2472 recast@0.23.11: 2346 2473 resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} 2347 2474 engines: {node: '>= 4'} ··· 2412 2539 2413 2540 safe-buffer@5.2.1: 2414 2541 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 2542 + 2543 + safe-stable-stringify@2.5.0: 2544 + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} 2545 + engines: {node: '>=10'} 2415 2546 2416 2547 scule@1.3.0: 2417 2548 resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} ··· 2501 2632 engines: {node: '>=10'} 2502 2633 peerDependencies: 2503 2634 solid-js: ^1.7 2635 + 2636 + sonic-boom@3.8.1: 2637 + resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} 2504 2638 2505 2639 source-map-js@1.2.1: 2506 2640 resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} ··· 2588 2722 resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} 2589 2723 engines: {node: '>=18'} 2590 2724 2725 + supports-color@7.2.0: 2726 + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 2727 + engines: {node: '>=8'} 2728 + 2591 2729 supports-preserve-symlinks-flag@1.0.0: 2592 2730 resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 2593 2731 engines: {node: '>= 0.4'} ··· 2624 2762 text-decoder@1.2.3: 2625 2763 resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} 2626 2764 2765 + thread-stream@2.7.0: 2766 + resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} 2767 + 2627 2768 tiny-invariant@1.3.3: 2628 2769 resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} 2629 2770 ··· 2652 2793 trim-lines@3.0.1: 2653 2794 resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} 2654 2795 2796 + ts-morph@24.0.0: 2797 + resolution: {integrity: sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==} 2798 + 2655 2799 tslib@2.8.1: 2656 2800 resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 2657 2801 ··· 2946 3090 resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} 2947 3091 engines: {node: '>=12'} 2948 3092 3093 + yesno@0.4.0: 3094 + resolution: {integrity: sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==} 3095 + 2949 3096 youch-core@0.3.3: 2950 3097 resolution: {integrity: sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==} 2951 3098 ··· 3029 3176 uint8arrays: 3.0.0 3030 3177 zod: 3.25.76 3031 3178 3179 + '@atproto/common@0.4.12': 3180 + dependencies: 3181 + '@atproto/common-web': 0.4.3 3182 + '@ipld/dag-cbor': 7.0.3 3183 + cbor-x: 1.6.0 3184 + iso-datestring-validator: 2.2.2 3185 + multiformats: 9.9.0 3186 + pino: 8.21.0 3187 + 3032 3188 '@atproto/did@0.2.0': 3033 3189 dependencies: 3034 3190 zod: 3.25.76 ··· 3049 3205 multiformats: 9.9.0 3050 3206 zod: 3.25.76 3051 3207 3208 + '@atproto/lex-cli@0.9.5': 3209 + dependencies: 3210 + '@atproto/lexicon': 0.5.1 3211 + '@atproto/syntax': 0.4.1 3212 + chalk: 4.1.2 3213 + commander: 9.5.0 3214 + prettier: 3.6.2 3215 + ts-morph: 24.0.0 3216 + yesno: 0.4.0 3217 + zod: 3.25.76 3218 + 3052 3219 '@atproto/lexicon@0.5.1': 3053 3220 dependencies: 3054 3221 '@atproto/common-web': 0.4.3 ··· 3292 3459 '@babel/helper-string-parser': 7.27.1 3293 3460 '@babel/helper-validator-identifier': 7.27.1 3294 3461 3462 + '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': 3463 + optional: true 3464 + 3465 + '@cbor-extract/cbor-extract-darwin-x64@2.2.0': 3466 + optional: true 3467 + 3468 + '@cbor-extract/cbor-extract-linux-arm64@2.2.0': 3469 + optional: true 3470 + 3471 + '@cbor-extract/cbor-extract-linux-arm@2.2.0': 3472 + optional: true 3473 + 3474 + '@cbor-extract/cbor-extract-linux-x64@2.2.0': 3475 + optional: true 3476 + 3477 + '@cbor-extract/cbor-extract-win32-x64@2.2.0': 3478 + optional: true 3479 + 3295 3480 '@cloudflare/kv-asset-handler@0.4.0': 3296 3481 dependencies: 3297 3482 mime: 3.0.0 ··· 3460 3645 optional: true 3461 3646 3462 3647 '@ioredis/commands@1.4.0': {} 3648 + 3649 + '@ipld/dag-cbor@7.0.3': 3650 + dependencies: 3651 + cborg: 1.10.2 3652 + multiformats: 9.9.0 3463 3653 3464 3654 '@isaacs/cliui@8.0.2': 3465 3655 dependencies: ··· 3848 4038 - supports-color 3849 4039 - vite 3850 4040 4041 + '@ts-morph/common@0.25.0': 4042 + dependencies: 4043 + minimatch: 9.0.5 4044 + path-browserify: 1.0.1 4045 + tinyglobby: 0.2.15 4046 + 3851 4047 '@types/babel__core@7.20.5': 3852 4048 dependencies: 3853 4049 '@babel/parser': 7.28.4 ··· 3872 4068 '@types/better-sqlite3@7.6.13': 3873 4069 dependencies: 3874 4070 '@types/node': 20.19.19 4071 + optional: true 3875 4072 3876 4073 '@types/braces@3.0.5': {} 3877 4074 ··· 4046 4243 async-sema@3.1.1: {} 4047 4244 4048 4245 async@3.2.6: {} 4246 + 4247 + atomic-sleep@1.0.0: {} 4049 4248 4050 4249 await-lock@2.2.2: {} 4051 4250 ··· 4161 4360 camelcase@8.0.0: {} 4162 4361 4163 4362 caniuse-lite@1.0.30001746: {} 4363 + 4364 + cbor-extract@2.2.0: 4365 + dependencies: 4366 + node-gyp-build-optional-packages: 5.1.1 4367 + optionalDependencies: 4368 + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.0 4369 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.0 4370 + '@cbor-extract/cbor-extract-linux-arm': 2.2.0 4371 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.0 4372 + '@cbor-extract/cbor-extract-linux-x64': 2.2.0 4373 + '@cbor-extract/cbor-extract-win32-x64': 2.2.0 4374 + optional: true 4375 + 4376 + cbor-x@1.6.0: 4377 + optionalDependencies: 4378 + cbor-extract: 2.2.0 4379 + 4380 + cborg@1.10.2: {} 4164 4381 4165 4382 ccount@2.0.1: {} 4166 4383 4384 + chalk@4.1.2: 4385 + dependencies: 4386 + ansi-styles: 4.3.0 4387 + supports-color: 7.2.0 4388 + 4167 4389 chalk@5.6.2: {} 4168 4390 4169 4391 character-entities-html4@2.1.0: {} ··· 4198 4420 4199 4421 cluster-key-slot@1.1.2: {} 4200 4422 4423 + code-block-writer@13.0.3: {} 4424 + 4201 4425 color-convert@2.0.1: 4202 4426 dependencies: 4203 4427 color-name: 1.1.4 ··· 4207 4431 comma-separated-tokens@2.0.3: {} 4208 4432 4209 4433 commander@2.20.3: {} 4434 + 4435 + commander@9.5.0: {} 4210 4436 4211 4437 commondir@1.0.1: {} 4212 4438 ··· 4476 4702 merge2: 1.4.1 4477 4703 micromatch: 4.0.8 4478 4704 4705 + fast-redact@3.5.0: {} 4706 + 4479 4707 fastq@1.19.1: 4480 4708 dependencies: 4481 4709 reusify: 1.1.0 ··· 4586 4814 radix3: 1.1.2 4587 4815 ufo: 1.6.1 4588 4816 uncrypto: 0.1.3 4817 + 4818 + has-flag@4.0.0: {} 4589 4819 4590 4820 hasown@2.0.2: 4591 4821 dependencies: ··· 4898 5128 4899 5129 ms@2.1.3: {} 4900 5130 5131 + multiformats@13.4.1: {} 5132 + 4901 5133 multiformats@9.9.0: {} 4902 5134 4903 5135 nanoid@3.3.11: {} ··· 5019 5251 5020 5252 node-forge@1.3.1: {} 5021 5253 5254 + node-gyp-build-optional-packages@5.1.1: 5255 + dependencies: 5256 + detect-libc: 2.1.1 5257 + optional: true 5258 + 5022 5259 node-gyp-build@4.8.4: {} 5023 5260 5024 5261 node-mock-http@1.0.3: {} ··· 5050 5287 ufo: 1.6.1 5051 5288 5052 5289 ohash@2.0.11: {} 5290 + 5291 + on-exit-leak-free@2.1.2: {} 5053 5292 5054 5293 on-finished@2.4.1: 5055 5294 dependencies: ··· 5082 5321 entities: 6.0.1 5083 5322 5084 5323 parseurl@1.3.3: {} 5324 + 5325 + path-browserify@1.0.1: {} 5085 5326 5086 5327 path-key@3.1.1: {} 5087 5328 ··· 5145 5386 5146 5387 picomatch@4.0.3: {} 5147 5388 5389 + pino-abstract-transport@1.2.0: 5390 + dependencies: 5391 + readable-stream: 4.7.0 5392 + split2: 4.2.0 5393 + 5394 + pino-std-serializers@6.2.2: {} 5395 + 5396 + pino@8.21.0: 5397 + dependencies: 5398 + atomic-sleep: 1.0.0 5399 + fast-redact: 3.5.0 5400 + on-exit-leak-free: 2.1.2 5401 + pino-abstract-transport: 1.2.0 5402 + pino-std-serializers: 6.2.2 5403 + process-warning: 3.0.0 5404 + quick-format-unescaped: 4.0.4 5405 + real-require: 0.2.0 5406 + safe-stable-stringify: 2.5.0 5407 + sonic-boom: 3.8.1 5408 + thread-stream: 2.7.0 5409 + 5148 5410 pkg-types@1.3.1: 5149 5411 dependencies: 5150 5412 confbox: 0.1.8 ··· 5187 5449 simple-get: 4.0.1 5188 5450 tar-fs: 2.1.4 5189 5451 tunnel-agent: 0.6.0 5452 + 5453 + prettier@3.6.2: {} 5190 5454 5191 5455 pretty-bytes@7.1.0: {} 5192 5456 5193 5457 process-nextick-args@2.0.1: {} 5194 5458 5459 + process-warning@3.0.0: {} 5460 + 5195 5461 process@0.11.10: {} 5196 5462 5197 5463 property-information@7.1.0: {} ··· 5204 5470 quansync@0.2.11: {} 5205 5471 5206 5472 queue-microtask@1.2.3: {} 5473 + 5474 + quick-format-unescaped@4.0.4: {} 5207 5475 5208 5476 radix3@1.1.2: {} 5209 5477 ··· 5255 5523 5256 5524 readdirp@4.1.2: {} 5257 5525 5526 + real-require@0.2.0: {} 5527 + 5258 5528 recast@0.23.11: 5259 5529 dependencies: 5260 5530 ast-types: 0.16.1 ··· 5340 5610 safe-buffer@5.1.2: {} 5341 5611 5342 5612 safe-buffer@5.2.1: {} 5613 + 5614 + safe-stable-stringify@2.5.0: {} 5343 5615 5344 5616 scule@1.3.0: {} 5345 5617 ··· 5465 5737 dependencies: 5466 5738 solid-js: 1.9.9 5467 5739 5740 + sonic-boom@3.8.1: 5741 + dependencies: 5742 + atomic-sleep: 1.0.0 5743 + 5468 5744 source-map-js@1.2.1: {} 5469 5745 5470 5746 source-map-support@0.5.21: ··· 5547 5823 5548 5824 supports-color@10.2.2: {} 5549 5825 5826 + supports-color@7.2.0: 5827 + dependencies: 5828 + has-flag: 4.0.0 5829 + 5550 5830 supports-preserve-symlinks-flag@1.0.0: {} 5551 5831 5552 5832 system-architecture@0.1.0: {} ··· 5600 5880 transitivePeerDependencies: 5601 5881 - react-native-b4a 5602 5882 5883 + thread-stream@2.7.0: 5884 + dependencies: 5885 + real-require: 0.2.0 5886 + 5603 5887 tiny-invariant@1.3.3: {} 5604 5888 5605 5889 tinyexec@1.0.1: {} ··· 5620 5904 tr46@0.0.3: {} 5621 5905 5622 5906 trim-lines@3.0.1: {} 5907 + 5908 + ts-morph@24.0.0: 5909 + dependencies: 5910 + '@ts-morph/common': 0.25.0 5911 + code-block-writer: 13.0.3 5623 5912 5624 5913 tslib@2.8.1: {} 5625 5914 ··· 5960 6249 string-width: 4.2.3 5961 6250 y18n: 5.0.8 5962 6251 yargs-parser: 21.1.1 6252 + 6253 + yesno@0.4.0: {} 5963 6254 5964 6255 youch-core@0.3.3: 5965 6256 dependencies:
+2 -1
src/api/server.ts
··· 27 27 } catch (err) { 28 28 if (err instanceof Response) throw err 29 29 console.error('OAuth authorize failed:', err) 30 - return { error: 'Could not initiate login' } 30 + console.error('Error details:', JSON.stringify(err, Object.getOwnPropertyNames(err), 2)) 31 + return { error: `Could not initiate login: ${err instanceof Error ? err.message : String(err)}` } 31 32 } 32 33 } 33 34
+2 -2
src/auth/client.ts
··· 8 8 9 9 const publicUrl = process.env.PUBLIC_URL 10 10 const port = process.env.PORT || 3000 11 - const url = publicUrl || `http://localhost:${port}` 11 + const url = publicUrl || `http://127.0.0.1:${port}` 12 12 const enc = encodeURIComponent 13 13 14 14 oauthClient = new NodeOAuthClient({ ··· 16 16 client_name: 'Protoshamble', 17 17 client_id: publicUrl 18 18 ? `${url}/client-metadata.json` 19 - : `http://localhost?redirect_uri=${enc(`${url}/oauth/callback`)}&scope=${enc('atproto transition:generic')}`, 19 + : `http://127.0.0.1/app-info.json?redirect_uri=${enc(`${url}/oauth/callback`)}&scope=${enc('atproto transition:generic')}`, 20 20 client_uri: url, 21 21 redirect_uris: [`${url}/oauth/callback`], 22 22 scope: 'atproto transition:generic',
+19 -3
src/db/index.ts
··· 1 1 import 'dotenv/config'; 2 2 import { drizzle } from 'drizzle-orm/node-postgres'; 3 3 import { postTable } from './schema'; 4 - 4 + 5 5 const db = drizzle(process.env.DATABASE_URL!); 6 6 7 - export const insertPost = async (message: string) => { 8 - return db.insert(postTable).values({ message, author: 'Etienne'}) 7 + interface InsertPostParams { 8 + uri?: string; 9 + authorDid?: string; 10 + message: string; 11 + author: string; 12 + createdAt?: Date; 13 + indexedAt?: Date; 14 + } 15 + 16 + export const insertPost = async (params: InsertPostParams) => { 17 + return db.insert(postTable).values({ 18 + uri: params.uri, 19 + authorDid: params.authorDid, 20 + message: params.message, 21 + author: params.author, 22 + createdAt: params.createdAt, 23 + indexedAt: params.indexedAt 24 + }) 9 25 } 10 26 11 27 export const getPosts = async () => {
+5 -1
src/db/schema.ts
··· 2 2 3 3 export const postTable = pgTable("post", { 4 4 id: integer().primaryKey().generatedAlwaysAsIdentity(), 5 + uri: varchar({ length: 512 }), 6 + authorDid: varchar({ length: 255 }), 5 7 message: varchar({ length: 255 }).notNull(), 6 - author: varchar({ length: 255 }).notNull() 8 + author: varchar({ length: 255 }).notNull(), 9 + createdAt: timestamp(), 10 + indexedAt: timestamp().defaultNow() 7 11 }); 8 12 9 13 export const authSessionTable = pgTable("auth_session", {
+44
src/lexicon/index.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 3 + */ 4 + import { 5 + type Auth, 6 + type Options as XrpcOptions, 7 + Server as XrpcServer, 8 + type StreamConfigOrHandler, 9 + type MethodConfigOrHandler, 10 + createServer as createXrpcServer, 11 + } from '@atproto/xrpc-server' 12 + import { schemas } from './lexicons.js' 13 + 14 + export function createServer(options?: XrpcOptions): Server { 15 + return new Server(options) 16 + } 17 + 18 + export class Server { 19 + xrpc: XrpcServer 20 + xyz: XyzNS 21 + 22 + constructor(options?: XrpcOptions) { 23 + this.xrpc = createXrpcServer(schemas, options) 24 + this.xyz = new XyzNS(this) 25 + } 26 + } 27 + 28 + export class XyzNS { 29 + _server: Server 30 + protoshamble: XyzProtoshambleNS 31 + 32 + constructor(server: Server) { 33 + this._server = server 34 + this.protoshamble = new XyzProtoshambleNS(server) 35 + } 36 + } 37 + 38 + export class XyzProtoshambleNS { 39 + _server: Server 40 + 41 + constructor(server: Server) { 42 + this._server = server 43 + } 44 + }
+72
src/lexicon/lexicons.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 3 + */ 4 + import { 5 + type LexiconDoc, 6 + Lexicons, 7 + ValidationError, 8 + type ValidationResult, 9 + } from '@atproto/lexicon' 10 + import { type $Typed, is$typed, maybe$typed } from './util.js' 11 + 12 + export const schemaDict = { 13 + XyzProtoshambleMessage: { 14 + lexicon: 1, 15 + id: 'xyz.protoshamble.message', 16 + defs: { 17 + main: { 18 + type: 'record', 19 + key: 'tid', 20 + record: { 21 + type: 'object', 22 + required: ['message', 'createdAt'], 23 + properties: { 24 + message: { 25 + type: 'string', 26 + minLength: 1, 27 + maxLength: 255, 28 + }, 29 + createdAt: { 30 + type: 'string', 31 + format: 'datetime', 32 + }, 33 + }, 34 + }, 35 + }, 36 + }, 37 + }, 38 + } as const satisfies Record<string, LexiconDoc> 39 + export const schemas = Object.values(schemaDict) satisfies LexiconDoc[] 40 + export const lexicons: Lexicons = new Lexicons(schemas) 41 + 42 + export function validate<T extends { $type: string }>( 43 + v: unknown, 44 + id: string, 45 + hash: string, 46 + requiredType: true, 47 + ): ValidationResult<T> 48 + export function validate<T extends { $type?: string }>( 49 + v: unknown, 50 + id: string, 51 + hash: string, 52 + requiredType?: false, 53 + ): ValidationResult<T> 54 + export function validate( 55 + v: unknown, 56 + id: string, 57 + hash: string, 58 + requiredType?: boolean, 59 + ): ValidationResult { 60 + return (requiredType ? is$typed : maybe$typed)(v, id, hash) 61 + ? lexicons.validate(`${id}#${hash}`, v) 62 + : { 63 + success: false, 64 + error: new ValidationError( 65 + `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`, 66 + ), 67 + } 68 + } 69 + 70 + export const ids = { 71 + XyzProtoshambleMessage: 'xyz.protoshamble.message', 72 + } as const
+28
src/lexicon/types/xyz/protoshamble/message.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 3 + */ 4 + import { type ValidationResult, BlobRef } from '@atproto/lexicon' 5 + import { CID } from 'multiformats/cid' 6 + import { validate as _validate } from '../../../lexicons' 7 + import { type $Typed, is$typed as _is$typed, type OmitKey } from '../../../util' 8 + 9 + const is$typed = _is$typed, 10 + validate = _validate 11 + const id = 'xyz.protoshamble.message' 12 + 13 + export interface Record { 14 + $type: 'xyz.protoshamble.message' 15 + message: string 16 + createdAt: string 17 + [k: string]: unknown 18 + } 19 + 20 + const hashRecord = 'main' 21 + 22 + export function isRecord<V>(v: V) { 23 + return is$typed(v, id, hashRecord) 24 + } 25 + 26 + export function validateRecord<V>(v: V) { 27 + return validate<Record & V>(v, id, hashRecord, true) 28 + }
+82
src/lexicon/util.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 3 + */ 4 + 5 + import { type ValidationResult } from '@atproto/lexicon' 6 + 7 + export type OmitKey<T, K extends keyof T> = { 8 + [K2 in keyof T as K2 extends K ? never : K2]: T[K2] 9 + } 10 + 11 + export type $Typed<V, T extends string = string> = V & { $type: T } 12 + export type Un$Typed<V extends { $type?: string }> = OmitKey<V, '$type'> 13 + 14 + export type $Type<Id extends string, Hash extends string> = Hash extends 'main' 15 + ? Id 16 + : `${Id}#${Hash}` 17 + 18 + function isObject<V>(v: V): v is V & object { 19 + return v != null && typeof v === 'object' 20 + } 21 + 22 + function is$type<Id extends string, Hash extends string>( 23 + $type: unknown, 24 + id: Id, 25 + hash: Hash, 26 + ): $type is $Type<Id, Hash> { 27 + return hash === 'main' 28 + ? $type === id 29 + : // $type === `${id}#${hash}` 30 + typeof $type === 'string' && 31 + $type.length === id.length + 1 + hash.length && 32 + $type.charCodeAt(id.length) === 35 /* '#' */ && 33 + $type.startsWith(id) && 34 + $type.endsWith(hash) 35 + } 36 + 37 + export type $TypedObject< 38 + V, 39 + Id extends string, 40 + Hash extends string, 41 + > = V extends { 42 + $type: $Type<Id, Hash> 43 + } 44 + ? V 45 + : V extends { $type?: string } 46 + ? V extends { $type?: infer T extends $Type<Id, Hash> } 47 + ? V & { $type: T } 48 + : never 49 + : V & { $type: $Type<Id, Hash> } 50 + 51 + export function is$typed<V, Id extends string, Hash extends string>( 52 + v: V, 53 + id: Id, 54 + hash: Hash, 55 + ): v is $TypedObject<V, Id, Hash> { 56 + return isObject(v) && '$type' in v && is$type(v.$type, id, hash) 57 + } 58 + 59 + export function maybe$typed<V, Id extends string, Hash extends string>( 60 + v: V, 61 + id: Id, 62 + hash: Hash, 63 + ): v is V & object & { $type?: $Type<Id, Hash> } { 64 + return ( 65 + isObject(v) && 66 + ('$type' in v ? v.$type === undefined || is$type(v.$type, id, hash) : true) 67 + ) 68 + } 69 + 70 + export type Validator<R = unknown> = (v: unknown) => ValidationResult<R> 71 + export type ValidatorParam<V extends Validator> = 72 + V extends Validator<infer R> ? R : never 73 + 74 + /** 75 + * Utility function that allows to convert a "validate*" utility function into a 76 + * type predicate. 77 + */ 78 + export function asPredicate<V extends Validator>(validate: V) { 79 + return function <T>(v: T): v is T & ValidatorParam<V> { 80 + return validate(v).success 81 + } 82 + }
+2 -5
src/routes/index.tsx
··· 3 3 import { action } from "@solidjs/router"; 4 4 import { getPosts, insertPost } from "~/db"; 5 5 import { getUser, logout } from "~/api"; 6 + import { createPost } from "./post-action"; 6 7 7 8 export const route = { 8 9 preload() { ··· 13 14 } 14 15 } satisfies RouteDefinition; 15 16 16 - const post = action(async (formData: FormData) => { 17 - "use server"; 18 - const message = formData.get('message') as string; 19 - return await insertPost(message); 20 - }) 17 + const post = action(createPost) 21 18 22 19 export default function Home() { 23 20 const posts = createAsync(async () => (await getPosts()).map(post => post.message || ''), { deferStream: true });
+72
src/routes/post-action.ts
··· 1 + "use server"; 2 + 3 + import { TID } from '@atproto/common'; 4 + import { getAgent } from '~/api/server'; 5 + import { insertPost } from '~/db'; 6 + import * as Message from '~/lexicon/types/xyz/protoshamble/message'; 7 + 8 + export async function createPost(formData: FormData) { 9 + const message = formData.get('message') as string; 10 + 11 + if (!message || message.trim().length === 0) { 12 + return { error: 'Message is required' }; 13 + } 14 + 15 + // Get the authenticated agent 16 + const agent = await getAgent(); 17 + 18 + if (!agent) { 19 + // Not logged in - just save to database without writing to PDS 20 + await insertPost({ 21 + message, 22 + author: 'Anonymous', 23 + }); 24 + return { success: true }; 25 + } 26 + 27 + // Construct the record 28 + const rkey = TID.nextStr(); 29 + const record = { 30 + $type: 'xyz.protoshamble.message' as const, 31 + message, 32 + createdAt: new Date().toISOString(), 33 + }; 34 + 35 + // Validate the record 36 + const validation = Message.validateRecord(record); 37 + if (!validation.success) { 38 + console.error('Validation failed:', validation.error); 39 + return { error: 'Invalid message format' }; 40 + } 41 + 42 + try { 43 + // Write the record to the user's PDS 44 + const result = await agent.com.atproto.repo.putRecord({ 45 + repo: agent.assertDid, 46 + collection: 'xyz.protoshamble.message', 47 + rkey, 48 + record, 49 + validate: false, 50 + }); 51 + 52 + const uri = result.data.uri; 53 + 54 + // Get user handle for display 55 + const profile = await agent.getProfile({ actor: agent.assertDid }); 56 + 57 + // Save to local database with AT Protocol metadata 58 + await insertPost({ 59 + uri, 60 + authorDid: agent.assertDid, 61 + message, 62 + author: profile.data.handle, 63 + createdAt: new Date(record.createdAt), 64 + indexedAt: new Date(), 65 + }); 66 + 67 + return { success: true, uri }; 68 + } catch (err) { 69 + console.error('Failed to write record to PDS:', err); 70 + return { error: 'Failed to save message to PDS' }; 71 + } 72 + }