the statusphere demo reworked into a vite/react app in a monorepo

Fix for OAuth localhost scopes (#16)

* fix oauth localhost usage

* misc fixes to profile validation and status view

authored by

devin ivy and committed by
GitHub
7077651a 9cd25e3c

+29 -106
+20 -98
package-lock.json
··· 12 12 "@atproto/api": "^0.13.4", 13 13 "@atproto/common": "^0.4.1", 14 14 "@atproto/identity": "^0.4.0", 15 - "@atproto/lexicon": "0.4.1-rc.0", 15 + "@atproto/lexicon": "^0.4.2", 16 16 "@atproto/oauth-client-node": "^0.1.0", 17 - "@atproto/repo": "0.4.2-rc.0", 18 17 "@atproto/sync": "^0.1.0", 19 18 "@atproto/syntax": "^0.3.0", 20 19 "@atproto/xrpc-server": "^0.6.3", ··· 148 147 "tlds": "^1.234.0" 149 148 } 150 149 }, 151 - "node_modules/@atproto/api/node_modules/@atproto/lexicon": { 152 - "version": "0.4.1", 153 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1.tgz", 154 - "integrity": "sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==", 155 - "dependencies": { 156 - "@atproto/common-web": "^0.3.0", 157 - "@atproto/syntax": "^0.3.0", 158 - "iso-datestring-validator": "^2.2.2", 159 - "multiformats": "^9.9.0", 160 - "zod": "^3.23.8" 161 - } 162 - }, 163 150 "node_modules/@atproto/common": { 164 - "version": "0.4.1", 165 - "resolved": "https://registry.npmjs.org/@atproto/common/-/common-0.4.1.tgz", 166 - "integrity": "sha512-uL7kQIcBTbvkBDNfxMXL6lBH4fO2DQpHd2BryJxMtbw/4iEPKe9xBYApwECHhEIk9+zhhpTRZ15FJ3gxTXN82Q==", 151 + "version": "0.4.4", 152 + "resolved": "https://registry.npmjs.org/@atproto/common/-/common-0.4.4.tgz", 153 + "integrity": "sha512-58tMbn6A1Zu296s/l3uIj8z9d7IRHpZvLOfsFRikaQaYrzhJpL2aPY4uFQ8GJcxnsxeUnxBCrQz9we5jVVJI5Q==", 167 154 "dependencies": { 168 - "@atproto/common-web": "^0.3.0", 155 + "@atproto/common-web": "^0.3.1", 169 156 "@ipld/dag-cbor": "^7.0.3", 170 157 "cbor-x": "^1.5.1", 171 158 "iso-datestring-validator": "^2.2.2", ··· 174 161 } 175 162 }, 176 163 "node_modules/@atproto/common-web": { 177 - "version": "0.3.0", 178 - "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.3.0.tgz", 179 - "integrity": "sha512-67VnV6JJyX+ZWyjV7xFQMypAgDmjVaR9ZCuU/QW+mqlqI7fex2uL4Fv+7/jHadgzhuJHVd6OHOvNn0wR5WZYtA==", 164 + "version": "0.3.1", 165 + "resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.3.1.tgz", 166 + "integrity": "sha512-N7wiTnus5vAr+lT//0y8m/FaHHLJ9LpGuEwkwDAeV3LCiPif4m/FS8x/QOYrx1PdZQwKso95RAPzCGWQBH5j6Q==", 180 167 "dependencies": { 181 168 "graphemer": "^1.4.0", 182 169 "multiformats": "^9.9.0", 183 170 "uint8arrays": "3.0.0", 184 - "zod": "^3.21.4" 171 + "zod": "^3.23.8" 185 172 } 186 173 }, 187 174 "node_modules/@atproto/common/node_modules/pino": { ··· 305 292 "lex": "dist/index.js" 306 293 } 307 294 }, 308 - "node_modules/@atproto/lex-cli/node_modules/@atproto/lexicon": { 309 - "version": "0.4.1", 310 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1.tgz", 311 - "integrity": "sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==", 312 - "dev": true, 313 - "dependencies": { 314 - "@atproto/common-web": "^0.3.0", 315 - "@atproto/syntax": "^0.3.0", 316 - "iso-datestring-validator": "^2.2.2", 317 - "multiformats": "^9.9.0", 318 - "zod": "^3.23.8" 319 - } 320 - }, 321 295 "node_modules/@atproto/lexicon": { 322 - "version": "0.4.1-rc.0", 323 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1-rc.0.tgz", 324 - "integrity": "sha512-CSYO8MWbxTXTLQMEJ1mTXD2pDxIXO2oCK/FVw9T/BeXLMcvwmeVgKAaytd1AGFkapX8IMAAtjBB3cnaltuHwbg==", 296 + "version": "0.4.2", 297 + "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.2.tgz", 298 + "integrity": "sha512-CXoOkhcdF3XVUnR2oNgCs2ljWfo/8zUjxL5RIhJW/UNLp/FSl+KpF8Jm5fbk8Y/XXVPGRAsv9OYfxyU/14N/pw==", 325 299 "dependencies": { 326 - "@atproto/common-web": "^0.3.0", 300 + "@atproto/common-web": "^0.3.1", 327 301 "@atproto/syntax": "^0.3.0", 328 302 "iso-datestring-validator": "^2.2.2", 329 303 "multiformats": "^9.9.0", ··· 375 349 } 376 350 }, 377 351 "node_modules/@atproto/repo": { 378 - "version": "0.4.2-rc.0", 379 - "resolved": "https://registry.npmjs.org/@atproto/repo/-/repo-0.4.2-rc.0.tgz", 380 - "integrity": "sha512-y8zXAR23r6qlsTmbzXaBEHYjvlgeNlAKj9eJ6V17JtT+4FVdW246alhsgSsglJ2Uv/e24RC1r90yNJNRxqDzXw==", 352 + "version": "0.5.3", 353 + "resolved": "https://registry.npmjs.org/@atproto/repo/-/repo-0.5.3.tgz", 354 + "integrity": "sha512-Lbp35SaK5149B9VnE6CVruo/iImNKQ49pPSR+5KuStHDCIyH0z/ynOrEJfpQjTzVu9kdio6bimo5zsl4F2fT2Q==", 381 355 "dependencies": { 382 - "@atproto/common": "^0.4.1", 383 - "@atproto/common-web": "^0.3.0", 384 - "@atproto/crypto": "^0.4.0", 385 - "@atproto/lexicon": "^0.4.1-rc.0", 356 + "@atproto/common": "^0.4.4", 357 + "@atproto/common-web": "^0.3.1", 358 + "@atproto/crypto": "^0.4.1", 359 + "@atproto/lexicon": "^0.4.2", 386 360 "@ipld/car": "^3.2.3", 387 361 "@ipld/dag-cbor": "^7.0.0", 388 362 "multiformats": "^9.9.0", ··· 405 379 "p-queue": "^6.6.2" 406 380 } 407 381 }, 408 - "node_modules/@atproto/sync/node_modules/@atproto/lexicon": { 409 - "version": "0.4.1", 410 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1.tgz", 411 - "integrity": "sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==", 412 - "dependencies": { 413 - "@atproto/common-web": "^0.3.0", 414 - "@atproto/syntax": "^0.3.0", 415 - "iso-datestring-validator": "^2.2.2", 416 - "multiformats": "^9.9.0", 417 - "zod": "^3.23.8" 418 - } 419 - }, 420 - "node_modules/@atproto/sync/node_modules/@atproto/repo": { 421 - "version": "0.5.0", 422 - "resolved": "https://registry.npmjs.org/@atproto/repo/-/repo-0.5.0.tgz", 423 - "integrity": "sha512-kZbj4wW5eFrDjkSTS9z+6bT4OTr5K4GrqWukWbfdBJtZPXsRDm75AV0C9ItoHDTdbBXn65TK6kqaJTrf89osCg==", 424 - "dependencies": { 425 - "@atproto/common": "^0.4.1", 426 - "@atproto/common-web": "^0.3.0", 427 - "@atproto/crypto": "^0.4.1", 428 - "@atproto/lexicon": "^0.4.1", 429 - "@ipld/car": "^3.2.3", 430 - "@ipld/dag-cbor": "^7.0.0", 431 - "multiformats": "^9.9.0", 432 - "uint8arrays": "3.0.0", 433 - "zod": "^3.23.8" 434 - } 435 - }, 436 382 "node_modules/@atproto/syntax": { 437 383 "version": "0.3.0", 438 384 "resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.3.0.tgz", ··· 463 409 "rate-limiter-flexible": "^2.4.1", 464 410 "uint8arrays": "3.0.0", 465 411 "ws": "^8.12.0", 466 - "zod": "^3.23.8" 467 - } 468 - }, 469 - "node_modules/@atproto/xrpc-server/node_modules/@atproto/lexicon": { 470 - "version": "0.4.1", 471 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1.tgz", 472 - "integrity": "sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==", 473 - "dependencies": { 474 - "@atproto/common-web": "^0.3.0", 475 - "@atproto/syntax": "^0.3.0", 476 - "iso-datestring-validator": "^2.2.2", 477 - "multiformats": "^9.9.0", 478 - "zod": "^3.23.8" 479 - } 480 - }, 481 - "node_modules/@atproto/xrpc/node_modules/@atproto/lexicon": { 482 - "version": "0.4.1", 483 - "resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.4.1.tgz", 484 - "integrity": "sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==", 485 - "dependencies": { 486 - "@atproto/common-web": "^0.3.0", 487 - "@atproto/syntax": "^0.3.0", 488 - "iso-datestring-validator": "^2.2.2", 489 - "multiformats": "^9.9.0", 490 412 "zod": "^3.23.8" 491 413 } 492 414 },
+1 -2
package.json
··· 17 17 "@atproto/common": "^0.4.1", 18 18 "@atproto/api": "^0.13.4", 19 19 "@atproto/identity": "^0.4.0", 20 - "@atproto/lexicon": "0.4.1-rc.0", 20 + "@atproto/lexicon": "^0.4.2", 21 21 "@atproto/oauth-client-node": "^0.1.0", 22 - "@atproto/repo": "0.4.2-rc.0", 23 22 "@atproto/sync": "^0.1.0", 24 23 "@atproto/syntax": "^0.3.0", 25 24 "@atproto/xrpc-server": "^0.6.3",
+2 -1
src/auth/client.ts
··· 6 6 export const createClient = async (db: Database) => { 7 7 const publicUrl = env.PUBLIC_URL 8 8 const url = publicUrl || `http://127.0.0.1:${env.PORT}` 9 + const enc = encodeURIComponent 9 10 return new NodeOAuthClient({ 10 11 clientMetadata: { 11 12 client_name: 'AT Protocol Express App', 12 13 client_id: publicUrl 13 14 ? `${url}/client-metadata.json` 14 - : `http://localhost?redirect_uri=${encodeURIComponent(`${url}/oauth/callback`)}`, 15 + : `http://localhost?redirect_uri=${enc(`${url}/oauth/callback`)}&scope=${enc('atproto transition:generic')}`, 15 16 client_uri: url, 16 17 redirect_uris: [`${url}/oauth/callback`], 17 18 scope: 'atproto transition:generic',
+4 -3
src/ingester.ts
··· 11 11 handleEvent: async (evt) => { 12 12 // Watch for write events 13 13 if (evt.event === 'create' || evt.event === 'update') { 14 + const now = new Date() 14 15 const record = evt.record 15 16 16 17 // If the write is a valid status update ··· 27 28 authorDid: evt.did, 28 29 status: record.status, 29 30 createdAt: record.createdAt, 30 - indexedAt: new Date().toISOString(), 31 + indexedAt: now.toISOString(), 31 32 }) 32 33 .onConflict((oc) => 33 34 oc.column('uri').doUpdateSet({ 34 35 status: record.status, 35 - indexedAt: new Date().toISOString(), 36 + indexedAt: now.toISOString(), 36 37 }) 37 38 ) 38 39 .execute() ··· 42 43 evt.collection === 'xyz.statusphere.status' 43 44 ) { 44 45 // Remove the status from our SQLite 45 - await db.deleteFrom('status').where({ uri: evt.uri.toString() }) 46 + await db.deleteFrom('status').where('uri', '=', evt.uri.toString()).execute() 46 47 } 47 48 }, 48 49 onError: (err) => {
+2 -2
src/pages/home.ts
··· 114 114 } 115 115 116 116 function ts(status: Status) { 117 + const createdAt = new Date(status.createdAt) 117 118 const indexedAt = new Date(status.indexedAt) 118 - const updatedAt = new Date(status.updatedAt) 119 - if (updatedAt > indexedAt) return updatedAt.toDateString() 119 + if (createdAt < indexedAt) return createdAt.toDateString() 120 120 return indexedAt.toDateString() 121 121 }