See the best posts from any Bluesky account
0
fork

Configure Feed

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

Add accounts and auth_states tables with models and tests

Install @adonisjs/auth and @atproto/oauth-client-node packages.
Create SQLite migrations for accounts (DID-keyed, stores OAuth
session data) and auth_states (temporary OAuth flow state storage).
Add corresponding Lucid models following existing conventions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+390
+22
app/models/account.ts
··· 1 + import { BaseModel, column } from '@adonisjs/lucid/orm' 2 + 3 + export default class Account extends BaseModel { 4 + static table = 'accounts' 5 + static primaryKey = 'did' 6 + static selfAssignPrimaryKey = true 7 + 8 + @column({ isPrimary: true }) 9 + declare did: string 10 + 11 + @column() 12 + declare handle: string 13 + 14 + @column() 15 + declare sessionData: string 16 + 17 + @column() 18 + declare createdAt: number 19 + 20 + @column() 21 + declare updatedAt: number 22 + }
+16
app/models/auth_state.ts
··· 1 + import { BaseModel, column } from '@adonisjs/lucid/orm' 2 + 3 + export default class AuthState extends BaseModel { 4 + static table = 'auth_states' 5 + static primaryKey = 'key' 6 + static selfAssignPrimaryKey = true 7 + 8 + @column({ isPrimary: true }) 9 + declare key: string 10 + 11 + @column() 12 + declare stateData: string 13 + 14 + @column() 15 + declare createdAt: number 16 + }
+17
database/migrations/1775991741242_create_accounts_table.ts
··· 1 + import { BaseSchema } from '@adonisjs/lucid/schema' 2 + 3 + export default class extends BaseSchema { 4 + async up() { 5 + this.schema.createTable('accounts', (table) => { 6 + table.text('did').primary().notNullable() 7 + table.text('handle').notNullable() 8 + table.text('session_data').notNullable() 9 + table.integer('created_at').notNullable() 10 + table.integer('updated_at').notNullable() 11 + }) 12 + } 13 + 14 + async down() { 15 + this.schema.dropTable('accounts') 16 + } 17 + }
+15
database/migrations/1775991741243_create_auth_states_table.ts
··· 1 + import { BaseSchema } from '@adonisjs/lucid/schema' 2 + 3 + export default class extends BaseSchema { 4 + async up() { 5 + this.schema.createTable('auth_states', (table) => { 6 + table.text('key').primary().notNullable() 7 + table.text('state_data').notNullable() 8 + table.integer('created_at').notNullable() 9 + }) 10 + } 11 + 12 + async down() { 13 + this.schema.dropTable('auth_states') 14 + } 15 + }
+2
package.json
··· 72 72 "youch": "^4.1.1" 73 73 }, 74 74 "dependencies": { 75 + "@adonisjs/auth": "^10.1.0", 75 76 "@adonisjs/core": "^7.3.0", 76 77 "@adonisjs/lucid": "^22.4.0", 77 78 "@adonisjs/queue": "^0.6.0", ··· 81 82 "@adonisjs/vite": "^5.1.0", 82 83 "@alpinejs/csp": "^3.15.11", 83 84 "@atproto/api": "^0.19.8", 85 + "@atproto/oauth-client-node": "^0.3.17", 84 86 "@clickhouse/client": "^1.18.2", 85 87 "@tailwindcss/vite": "^4.2.2", 86 88 "@vinejs/vine": "^4.3.0",
+239
pnpm-lock.yaml
··· 8 8 9 9 .: 10 10 dependencies: 11 + '@adonisjs/auth': 12 + specifier: ^10.1.0 13 + version: 10.1.0(8824ab621c81534275012d39ae9b10b6) 11 14 '@adonisjs/core': 12 15 specifier: ^7.3.0 13 16 version: 7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1) ··· 35 38 '@atproto/api': 36 39 specifier: ^0.19.8 37 40 version: 0.19.8 41 + '@atproto/oauth-client-node': 42 + specifier: ^0.3.17 43 + version: 0.3.17 38 44 '@clickhouse/client': 39 45 specifier: ^1.18.2 40 46 version: 1.18.2 ··· 157 163 engines: {node: '>=24.0.0'} 158 164 peerDependencies: 159 165 typescript: ^5.0.0 || ^6.0.0 166 + 167 + '@adonisjs/auth@10.1.0': 168 + resolution: {integrity: sha512-H92C4HLWBpvxtQrgnsdWdWfoGu2bM/j+nyk/tHmpxH9ETkNOH0z3dRfEebLJI63vtTDpRp5cwiI0bzn32gUQiA==} 169 + engines: {node: '>=24.0.0'} 170 + peerDependencies: 171 + '@adonisjs/assembler': ^8.0.0-next.26 || ^8.0.0 172 + '@adonisjs/core': ^7.0.0-next.16 || ^7.0.0 173 + '@adonisjs/i18n': ^3.0.0-next.2 || ^3.0.0 174 + '@adonisjs/lucid': ^22.0.0-next.1 || ^22.0.0 175 + '@adonisjs/session': ^8.0.0-next.1 || ^8.0.0 176 + '@japa/api-client': ^3.1.1 177 + '@japa/browser-client': ^2.2.0 178 + '@japa/plugin-adonisjs': ^5.1.0-next.0 || ^5.1.0 179 + peerDependenciesMeta: 180 + '@adonisjs/assembler': 181 + optional: true 182 + '@adonisjs/i18n': 183 + optional: true 184 + '@adonisjs/lucid': 185 + optional: true 186 + '@adonisjs/session': 187 + optional: true 188 + '@japa/api-client': 189 + optional: true 190 + '@japa/browser-client': 191 + optional: true 192 + '@japa/plugin-adonisjs': 193 + optional: true 160 194 161 195 '@adonisjs/bodyparser@11.0.1': 162 196 resolution: {integrity: sha512-RUpkRRSvCSMLmVJcYUyaAwC9Z1tWlThBvVGiIU5bkWwwe5CcbG2f9sifzod04B+hcgJ4xWSs+FF/WNdbwWFwhQ==} ··· 474 508 resolution: {integrity: sha512-+YEv9ElJi9azr8AYII79NxYXQRJsrUy1kUqZfxZfvPM7rhs3174mzB+qEE9Pl3sVKAJS5cevyT4lgLNV0AZK6A==} 475 509 engines: {node: '>= 10'} 476 510 511 + '@atproto-labs/did-resolver@0.2.6': 512 + resolution: {integrity: sha512-2K1bC04nI2fmgNcvof+yA28IhGlpWn2JKYlPa7To9JTKI45FINCGkQSGiL2nyXlyzDJJ34fZ1aq6/IRFIOIiqg==} 513 + 514 + '@atproto-labs/fetch-node@0.2.0': 515 + resolution: {integrity: sha512-Krq09nH/aeoiU2s9xdHA0FjTEFWG9B5FFenipv1iRixCcPc7V3DhTNDawxG9gI8Ny0k4dBVS9WTRN/IDzBx86Q==} 516 + engines: {node: '>=18.7.0'} 517 + 518 + '@atproto-labs/fetch@0.2.3': 519 + resolution: {integrity: sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==} 520 + 521 + '@atproto-labs/handle-resolver-node@0.1.25': 522 + resolution: {integrity: sha512-NY9WYM2VLd3IuMGRkkmvGBg8xqVEaK/fitv1vD8SMXqFTekdpjOLCCyv7EFtqVHouzmDcL83VOvWRfHVa8V9Yw==} 523 + engines: {node: '>=18.7.0'} 524 + 525 + '@atproto-labs/handle-resolver@0.3.6': 526 + resolution: {integrity: sha512-qnSTXvOBNj1EHhp2qTWSX8MS5q3AwYU5LKlt5fBvSbCjgmTr2j0URHCv+ydrwO55KvsojIkTMgeMOh4YuY4fCA==} 527 + 528 + '@atproto-labs/identity-resolver@0.3.6': 529 + resolution: {integrity: sha512-qoWqBDRobln0NR8L8dQjSp79E0chGkBhibEgxQa2f9WD+JbJdjQ0YvwwO5yeQn05pJoJmAwmI2wyJ45zjU7aWg==} 530 + 531 + '@atproto-labs/pipe@0.1.1': 532 + resolution: {integrity: sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==} 533 + 534 + '@atproto-labs/simple-store-memory@0.1.4': 535 + resolution: {integrity: sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw==} 536 + 537 + '@atproto-labs/simple-store@0.3.0': 538 + resolution: {integrity: sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ==} 539 + 477 540 '@atproto/api@0.19.8': 478 541 resolution: {integrity: sha512-b79kuI3AzEmpLLi9afRNq6T0KFEEVL4d+vHFAtWxeDwS7lfwUOIIngMjAVvwmwC5nJRZIrK8L9d4y7LD8zdvsg==} 479 542 480 543 '@atproto/common-web@0.4.20': 481 544 resolution: {integrity: sha512-RcsYT28yQgVi/Glb/hHPGpqpzIlKrbMLeldEd7PmmMLWDaJL2j3lb92qytvxjl1yhi2Ssq2TEuMZ2NlWaAbpow==} 482 545 546 + '@atproto/did@0.3.0': 547 + resolution: {integrity: sha512-raUPzUGegtW/6OxwCmM8bhZvuIMzxG5t9oWsth6Tp91Kb5fTnHV2h/KKNF1C82doeA4BdXCErTyg7ISwLbQkzA==} 548 + 549 + '@atproto/jwk-jose@0.1.11': 550 + resolution: {integrity: sha512-i4Fnr2sTBYmMmHXl7NJh8GrCH+tDQEVWrcDMDnV5DjJfkgT17wIqvojIw9SNbSL4Uf0OtfEv6AgG0A+mgh8b5Q==} 551 + 552 + '@atproto/jwk-webcrypto@0.2.0': 553 + resolution: {integrity: sha512-UmgRrrEAkWvxwhlwe30UmDOdTEFidlIzBC7C3cCbeJMcBN1x8B3KH+crXrsTqfWQBG58mXgt8wgSK3Kxs2LhFg==} 554 + 555 + '@atproto/jwk@0.6.0': 556 + resolution: {integrity: sha512-bDoJPvt7TrQVi/rBfBrSSpGykhtIriKxeYCYQTiPRKFfyRhbgpElF0wPXADjIswnbzZdOwbY63az4E/CFVT3Tw==} 557 + 483 558 '@atproto/lex-data@0.0.15': 484 559 resolution: {integrity: sha512-ZsbGiaM5S3CnGrcTMbDGON3bLZzCi/Mx9UvcMREKSRujnF68eHgMiXxJqvykP7+QpOX6tYCK93axZkuJVhtSEw==} 485 560 ··· 488 563 489 564 '@atproto/lexicon@0.6.2': 490 565 resolution: {integrity: sha512-p3Ly6hinVZW0ETuAXZMeUGwuMm3g8HvQMQ41yyEE6AL0hAkfeKFaZKos6BdBrr6CjkpbrDZqE8M+5+QOceysMw==} 566 + 567 + '@atproto/oauth-client-node@0.3.17': 568 + resolution: {integrity: sha512-67LNuKAlC35Exe7CB5S0QCAnEqr6fKV9Nvp64jAHFof1N+Vc9Ltt1K9oekE5Ctf7dvpGByrHRF0noUw9l9sWLA==} 569 + engines: {node: '>=18.7.0'} 570 + 571 + '@atproto/oauth-client@0.6.0': 572 + resolution: {integrity: sha512-F7ZTKzFptXgyihMkd7QTdRSkrh4XqrS+qTw+V81k5Q6Bh3MB1L3ypvfSJ6v7SSUJa6XxoZYJTCahHC1e+ndE6Q==} 573 + 574 + '@atproto/oauth-types@0.6.3': 575 + resolution: {integrity: sha512-jdKuoPknJuh/WjI+mYk7agSbx9mNVMbS6Dr3k1z2YMY2oRiCQjxYBuo4MLKATbxj05nMQaZRWlHRUazoAu5Cng==} 491 576 492 577 '@atproto/syntax@0.5.3': 493 578 resolution: {integrity: sha512-gzhlHOJHm5KXdCc17fXi1fXM81ccs5jJfNgCui84ay9JGvczxegpYHNqdMlv+iBuhtBzFIjgx6ChjRxN/kO8kQ==} ··· 1505 1590 engines: {node: '>=6.0.0'} 1506 1591 hasBin: true 1507 1592 1593 + basic-auth@2.0.1: 1594 + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} 1595 + engines: {node: '>= 0.8'} 1596 + 1508 1597 better-sqlite3@12.8.0: 1509 1598 resolution: {integrity: sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==} 1510 1599 engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x} ··· 1670 1759 core-js-compat@3.49.0: 1671 1760 resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} 1672 1761 1762 + core-js@3.49.0: 1763 + resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} 1764 + 1673 1765 cron-parser@5.5.0: 1674 1766 resolution: {integrity: sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww==} 1675 1767 engines: {node: '>=18'} ··· 2222 2314 resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 2223 2315 engines: {node: '>= 0.10'} 2224 2316 2317 + ipaddr.js@2.3.0: 2318 + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} 2319 + engines: {node: '>= 10'} 2320 + 2225 2321 is-builtin-module@5.0.0: 2226 2322 resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} 2227 2323 engines: {node: '>=18.20'} ··· 2294 2390 resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} 2295 2391 hasBin: true 2296 2392 2393 + jose@5.10.0: 2394 + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} 2395 + 2297 2396 joycon@3.1.1: 2298 2397 resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 2299 2398 engines: {node: '>=10'} ··· 2489 2588 log-update@7.2.0: 2490 2589 resolution: {integrity: sha512-iLs7dGSyjZiUgvrUvuD3FndAxVJk+TywBkkkwUSm9HdYoskJalWg5qVsEiXeufPvRVPbCUmNQewg798rx+sPXg==} 2491 2590 engines: {node: '>=20'} 2591 + 2592 + lru-cache@10.4.3: 2593 + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 2492 2594 2493 2595 lru-cache@11.3.3: 2494 2596 resolution: {integrity: sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==} ··· 2885 2987 2886 2988 rxjs@7.8.2: 2887 2989 resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} 2990 + 2991 + safe-buffer@5.1.2: 2992 + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 2888 2993 2889 2994 safe-buffer@5.2.1: 2890 2995 resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} ··· 3208 3313 undici-types@7.18.2: 3209 3314 resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} 3210 3315 3316 + undici@6.24.1: 3317 + resolution: {integrity: sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==} 3318 + engines: {node: '>=18.17'} 3319 + 3211 3320 unicode-segmenter@0.14.5: 3212 3321 resolution: {integrity: sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==} 3213 3322 ··· 3404 3513 transitivePeerDependencies: 3405 3514 - babel-plugin-macros 3406 3515 3516 + '@adonisjs/auth@10.1.0(8824ab621c81534275012d39ae9b10b6)': 3517 + dependencies: 3518 + '@adonisjs/core': 7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1) 3519 + '@adonisjs/presets': 3.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1)) 3520 + basic-auth: 2.0.1 3521 + optionalDependencies: 3522 + '@adonisjs/assembler': 8.4.0(typescript@6.0.2) 3523 + '@adonisjs/lucid': 22.4.2(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@vinejs/vine@4.3.1)(better-sqlite3@12.8.0)(luxon@3.7.2) 3524 + '@adonisjs/session': 8.1.0(6ec8878f6288127aeb8665fba21971dc) 3525 + '@japa/api-client': 3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0) 3526 + '@japa/browser-client': 2.3.0(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0)(playwright@1.59.1) 3527 + '@japa/plugin-adonisjs': 5.2.0(@adonisjs/core@7.3.1(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@vinejs/vine@4.3.1)(edge.js@6.5.0)(pino-pretty@13.1.3)(youch@4.1.1))(@japa/api-client@3.2.1(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0))(@japa/browser-client@2.3.0(@japa/assert@4.2.0(@japa/runner@5.3.0))(@japa/runner@5.3.0)(playwright@1.59.1))(@japa/runner@5.3.0)(playwright@1.59.1) 3528 + 3407 3529 '@adonisjs/bodyparser@11.0.1(@adonisjs/http-server@8.2.0(@adonisjs/application@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/config@6.1.0)(@adonisjs/fold@11.0.0))(@adonisjs/events@10.2.0(@adonisjs/application@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/config@6.1.0)(@adonisjs/fold@11.0.0))(@adonisjs/fold@11.0.0))(@adonisjs/fold@11.0.0)(@adonisjs/logger@7.1.1(pino-pretty@13.1.3))(@boringnode/encryption@1.0.0)(youch@4.1.1))': 3408 3530 dependencies: 3409 3531 '@adonisjs/http-server': 8.2.0(@adonisjs/application@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/config@6.1.0)(@adonisjs/fold@11.0.0))(@adonisjs/events@10.2.0(@adonisjs/application@9.0.0(@adonisjs/assembler@8.4.0(typescript@6.0.2))(@adonisjs/config@6.1.0)(@adonisjs/fold@11.0.0))(@adonisjs/fold@11.0.0))(@adonisjs/fold@11.0.0)(@adonisjs/logger@7.1.1(pino-pretty@13.1.3))(@boringnode/encryption@1.0.0)(youch@4.1.1) ··· 3713 3835 '@ast-grep/napi-win32-ia32-msvc': 0.42.1 3714 3836 '@ast-grep/napi-win32-x64-msvc': 0.42.1 3715 3837 3838 + '@atproto-labs/did-resolver@0.2.6': 3839 + dependencies: 3840 + '@atproto-labs/fetch': 0.2.3 3841 + '@atproto-labs/pipe': 0.1.1 3842 + '@atproto-labs/simple-store': 0.3.0 3843 + '@atproto-labs/simple-store-memory': 0.1.4 3844 + '@atproto/did': 0.3.0 3845 + zod: 3.25.76 3846 + 3847 + '@atproto-labs/fetch-node@0.2.0': 3848 + dependencies: 3849 + '@atproto-labs/fetch': 0.2.3 3850 + '@atproto-labs/pipe': 0.1.1 3851 + ipaddr.js: 2.3.0 3852 + undici: 6.24.1 3853 + 3854 + '@atproto-labs/fetch@0.2.3': 3855 + dependencies: 3856 + '@atproto-labs/pipe': 0.1.1 3857 + 3858 + '@atproto-labs/handle-resolver-node@0.1.25': 3859 + dependencies: 3860 + '@atproto-labs/fetch-node': 0.2.0 3861 + '@atproto-labs/handle-resolver': 0.3.6 3862 + '@atproto/did': 0.3.0 3863 + 3864 + '@atproto-labs/handle-resolver@0.3.6': 3865 + dependencies: 3866 + '@atproto-labs/simple-store': 0.3.0 3867 + '@atproto-labs/simple-store-memory': 0.1.4 3868 + '@atproto/did': 0.3.0 3869 + zod: 3.25.76 3870 + 3871 + '@atproto-labs/identity-resolver@0.3.6': 3872 + dependencies: 3873 + '@atproto-labs/did-resolver': 0.2.6 3874 + '@atproto-labs/handle-resolver': 0.3.6 3875 + 3876 + '@atproto-labs/pipe@0.1.1': {} 3877 + 3878 + '@atproto-labs/simple-store-memory@0.1.4': 3879 + dependencies: 3880 + '@atproto-labs/simple-store': 0.3.0 3881 + lru-cache: 10.4.3 3882 + 3883 + '@atproto-labs/simple-store@0.3.0': {} 3884 + 3716 3885 '@atproto/api@0.19.8': 3717 3886 dependencies: 3718 3887 '@atproto/common-web': 0.4.20 ··· 3731 3900 '@atproto/syntax': 0.5.3 3732 3901 zod: 3.25.76 3733 3902 3903 + '@atproto/did@0.3.0': 3904 + dependencies: 3905 + zod: 3.25.76 3906 + 3907 + '@atproto/jwk-jose@0.1.11': 3908 + dependencies: 3909 + '@atproto/jwk': 0.6.0 3910 + jose: 5.10.0 3911 + 3912 + '@atproto/jwk-webcrypto@0.2.0': 3913 + dependencies: 3914 + '@atproto/jwk': 0.6.0 3915 + '@atproto/jwk-jose': 0.1.11 3916 + zod: 3.25.76 3917 + 3918 + '@atproto/jwk@0.6.0': 3919 + dependencies: 3920 + multiformats: 9.9.0 3921 + zod: 3.25.76 3922 + 3734 3923 '@atproto/lex-data@0.0.15': 3735 3924 dependencies: 3736 3925 multiformats: 9.9.0 ··· 3751 3940 multiformats: 9.9.0 3752 3941 zod: 3.25.76 3753 3942 3943 + '@atproto/oauth-client-node@0.3.17': 3944 + dependencies: 3945 + '@atproto-labs/did-resolver': 0.2.6 3946 + '@atproto-labs/handle-resolver-node': 0.1.25 3947 + '@atproto-labs/simple-store': 0.3.0 3948 + '@atproto/did': 0.3.0 3949 + '@atproto/jwk': 0.6.0 3950 + '@atproto/jwk-jose': 0.1.11 3951 + '@atproto/jwk-webcrypto': 0.2.0 3952 + '@atproto/oauth-client': 0.6.0 3953 + '@atproto/oauth-types': 0.6.3 3954 + 3955 + '@atproto/oauth-client@0.6.0': 3956 + dependencies: 3957 + '@atproto-labs/did-resolver': 0.2.6 3958 + '@atproto-labs/fetch': 0.2.3 3959 + '@atproto-labs/handle-resolver': 0.3.6 3960 + '@atproto-labs/identity-resolver': 0.3.6 3961 + '@atproto-labs/simple-store': 0.3.0 3962 + '@atproto-labs/simple-store-memory': 0.1.4 3963 + '@atproto/did': 0.3.0 3964 + '@atproto/jwk': 0.6.0 3965 + '@atproto/oauth-types': 0.6.3 3966 + '@atproto/xrpc': 0.7.7 3967 + core-js: 3.49.0 3968 + multiformats: 9.9.0 3969 + zod: 3.25.76 3970 + 3971 + '@atproto/oauth-types@0.6.3': 3972 + dependencies: 3973 + '@atproto/did': 0.3.0 3974 + '@atproto/jwk': 0.6.0 3975 + zod: 3.25.76 3976 + 3754 3977 '@atproto/syntax@0.5.3': 3755 3978 dependencies: 3756 3979 tslib: 2.8.1 ··· 4583 4806 4584 4807 baseline-browser-mapping@2.10.17: {} 4585 4808 4809 + basic-auth@2.0.1: 4810 + dependencies: 4811 + safe-buffer: 5.1.2 4812 + 4586 4813 better-sqlite3@12.8.0: 4587 4814 dependencies: 4588 4815 bindings: 1.5.0 ··· 4742 4969 core-js-compat@3.49.0: 4743 4970 dependencies: 4744 4971 browserslist: 4.28.2 4972 + 4973 + core-js@3.49.0: {} 4745 4974 4746 4975 cron-parser@5.5.0: 4747 4976 dependencies: ··· 5282 5511 5283 5512 ipaddr.js@1.9.1: {} 5284 5513 5514 + ipaddr.js@2.3.0: {} 5515 + 5285 5516 is-builtin-module@5.0.0: 5286 5517 dependencies: 5287 5518 builtin-modules: 5.0.0 ··· 5335 5566 5336 5567 jiti@2.6.1: {} 5337 5568 5569 + jose@5.10.0: {} 5570 + 5338 5571 joycon@3.1.1: {} 5339 5572 5340 5573 js-stringify@1.0.2: {} ··· 5485 5718 slice-ansi: 8.0.0 5486 5719 strip-ansi: 7.2.0 5487 5720 wrap-ansi: 10.0.0 5721 + 5722 + lru-cache@10.4.3: {} 5488 5723 5489 5724 lru-cache@11.3.3: {} 5490 5725 ··· 5885 6120 dependencies: 5886 6121 tslib: 2.8.1 5887 6122 6123 + safe-buffer@5.1.2: {} 6124 + 5888 6125 safe-buffer@5.2.1: {} 5889 6126 5890 6127 safe-stable-stringify@2.5.0: {} ··· 6195 6432 multiformats: 9.9.0 6196 6433 6197 6434 undici-types@7.18.2: {} 6435 + 6436 + undici@6.24.1: {} 6198 6437 6199 6438 unicode-segmenter@0.14.5: {} 6200 6439
+79
tests/unit/auth_models.spec.ts
··· 1 + import { test } from '@japa/runner' 2 + import testUtils from '@adonisjs/core/services/test_utils' 3 + import Account from '#models/account' 4 + import AuthState from '#models/auth_state' 5 + 6 + test.group('Lucid schemas — Account', (group) => { 7 + group.each.setup(() => testUtils.db().withGlobalTransaction()) 8 + 9 + test('can create and read back an account', async ({ assert }) => { 10 + const now = Date.now() 11 + await Account.create({ 12 + did: 'did:plc:testaccount001', 13 + handle: 'testaccount.bsky.social', 14 + sessionData: '{"accessJwt":"abc","refreshJwt":"def"}', 15 + createdAt: now, 16 + updatedAt: now, 17 + }) 18 + 19 + const account = await Account.findOrFail('did:plc:testaccount001') 20 + 21 + assert.equal(account.did, 'did:plc:testaccount001') 22 + assert.equal(account.handle, 'testaccount.bsky.social') 23 + assert.equal(account.sessionData, '{"accessJwt":"abc","refreshJwt":"def"}') 24 + assert.equal(account.createdAt, now) 25 + assert.equal(account.updatedAt, now) 26 + }) 27 + 28 + test('can update session_data on an existing account', async ({ assert }) => { 29 + const now = Date.now() 30 + await Account.create({ 31 + did: 'did:plc:updatetest', 32 + handle: 'updatetest.bsky.social', 33 + sessionData: '{"old":"data"}', 34 + createdAt: now, 35 + updatedAt: now, 36 + }) 37 + 38 + const account = await Account.findOrFail('did:plc:updatetest') 39 + account.sessionData = '{"new":"data"}' 40 + account.updatedAt = Date.now() 41 + await account.save() 42 + 43 + const refreshed = await Account.findOrFail('did:plc:updatetest') 44 + assert.equal(refreshed.sessionData, '{"new":"data"}') 45 + }) 46 + }) 47 + 48 + test.group('Lucid schemas — AuthState', (group) => { 49 + group.each.setup(() => testUtils.db().withGlobalTransaction()) 50 + 51 + test('can create and read back an auth state', async ({ assert }) => { 52 + const now = Date.now() 53 + await AuthState.create({ 54 + key: 'state_abc123', 55 + stateData: '{"dpopKey":"xyz","iss":"https://bsky.social"}', 56 + createdAt: now, 57 + }) 58 + 59 + const state = await AuthState.findOrFail('state_abc123') 60 + 61 + assert.equal(state.key, 'state_abc123') 62 + assert.equal(state.stateData, '{"dpopKey":"xyz","iss":"https://bsky.social"}') 63 + assert.equal(state.createdAt, now) 64 + }) 65 + 66 + test('can delete an auth state after use', async ({ assert }) => { 67 + await AuthState.create({ 68 + key: 'state_deleteme', 69 + stateData: '{"temp":"data"}', 70 + createdAt: Date.now(), 71 + }) 72 + 73 + const state = await AuthState.findOrFail('state_deleteme') 74 + await state.delete() 75 + 76 + const deleted = await AuthState.find('state_deleteme') 77 + assert.isNull(deleted) 78 + }) 79 + })