@atproto/pds 0.5.12 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/api/app/bsky/notification/index.d.ts.map +1 -1
  3. package/dist/api/app/bsky/notification/index.js +2 -0
  4. package/dist/api/app/bsky/notification/index.js.map +1 -1
  5. package/dist/api/app/bsky/notification/unregisterPush.d.ts +4 -0
  6. package/dist/api/app/bsky/notification/unregisterPush.d.ts.map +1 -0
  7. package/dist/api/app/bsky/notification/unregisterPush.js +48 -0
  8. package/dist/api/app/bsky/notification/unregisterPush.js.map +1 -0
  9. package/package.json +42 -38
  10. package/build.templates.cjs +0 -22
  11. package/example.env +0 -42
  12. package/jest.config.cjs +0 -27
  13. package/src/account-manager/account-manager.ts +0 -916
  14. package/src/account-manager/db/index.ts +0 -21
  15. package/src/account-manager/db/migrations/001-init.ts +0 -115
  16. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  17. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  18. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  19. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  20. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  21. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  22. package/src/account-manager/db/migrations/index.ts +0 -17
  23. package/src/account-manager/db/schema/account-device.ts +0 -14
  24. package/src/account-manager/db/schema/account.ts +0 -16
  25. package/src/account-manager/db/schema/actor.ts +0 -17
  26. package/src/account-manager/db/schema/app-password.ts +0 -13
  27. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  28. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  29. package/src/account-manager/db/schema/device.ts +0 -18
  30. package/src/account-manager/db/schema/email-token.ts +0 -19
  31. package/src/account-manager/db/schema/index.ts +0 -43
  32. package/src/account-manager/db/schema/invite-code.ts +0 -24
  33. package/src/account-manager/db/schema/lexicon.ts +0 -15
  34. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  35. package/src/account-manager/db/schema/repo-root.ts +0 -12
  36. package/src/account-manager/db/schema/token.ts +0 -38
  37. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  38. package/src/account-manager/helpers/account-device.ts +0 -63
  39. package/src/account-manager/helpers/account.ts +0 -355
  40. package/src/account-manager/helpers/auth.ts +0 -222
  41. package/src/account-manager/helpers/authorization-request.ts +0 -90
  42. package/src/account-manager/helpers/authorized-client.ts +0 -75
  43. package/src/account-manager/helpers/device.ts +0 -47
  44. package/src/account-manager/helpers/email-token.ts +0 -87
  45. package/src/account-manager/helpers/invite.ts +0 -263
  46. package/src/account-manager/helpers/lexicon.ts +0 -67
  47. package/src/account-manager/helpers/password.ts +0 -136
  48. package/src/account-manager/helpers/repo.ts +0 -24
  49. package/src/account-manager/helpers/scrypt.ts +0 -53
  50. package/src/account-manager/helpers/token.ts +0 -158
  51. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  52. package/src/account-manager/oauth-store.ts +0 -880
  53. package/src/account-manager/scope-reference-getter.ts +0 -106
  54. package/src/actor-store/actor-store-reader.ts +0 -45
  55. package/src/actor-store/actor-store-resources.ts +0 -8
  56. package/src/actor-store/actor-store-transactor.ts +0 -31
  57. package/src/actor-store/actor-store-writer.ts +0 -17
  58. package/src/actor-store/actor-store.ts +0 -210
  59. package/src/actor-store/blob/reader.ts +0 -160
  60. package/src/actor-store/blob/transactor.ts +0 -383
  61. package/src/actor-store/db/index.ts +0 -20
  62. package/src/actor-store/db/migrations/001-init.ts +0 -105
  63. package/src/actor-store/db/migrations/index.ts +0 -5
  64. package/src/actor-store/db/schema/account-pref.ts +0 -11
  65. package/src/actor-store/db/schema/backlink.ts +0 -9
  66. package/src/actor-store/db/schema/blob.ts +0 -14
  67. package/src/actor-store/db/schema/index.ts +0 -23
  68. package/src/actor-store/db/schema/record-blob.ts +0 -8
  69. package/src/actor-store/db/schema/record.ts +0 -14
  70. package/src/actor-store/db/schema/repo-block.ts +0 -10
  71. package/src/actor-store/db/schema/repo-root.ts +0 -10
  72. package/src/actor-store/migrate.ts +0 -39
  73. package/src/actor-store/preference/reader.ts +0 -48
  74. package/src/actor-store/preference/transactor.ts +0 -55
  75. package/src/actor-store/preference/util.ts +0 -39
  76. package/src/actor-store/record/reader.ts +0 -374
  77. package/src/actor-store/record/transactor.ts +0 -111
  78. package/src/actor-store/repo/reader.ts +0 -31
  79. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  80. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  81. package/src/actor-store/repo/transactor.ts +0 -227
  82. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  83. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  84. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  85. package/src/api/app/bsky/actor/index.ts +0 -13
  86. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  87. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  88. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  89. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  90. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  91. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  92. package/src/api/app/bsky/feed/index.ts +0 -15
  93. package/src/api/app/bsky/index.ts +0 -11
  94. package/src/api/app/bsky/notification/index.ts +0 -7
  95. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  96. package/src/api/app/bsky/util/resolver.ts +0 -20
  97. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  98. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  99. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  100. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  101. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  102. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  103. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  104. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  105. package/src/api/com/atproto/admin/index.ts +0 -31
  106. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  107. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  108. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  109. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  110. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  111. package/src/api/com/atproto/admin/util.ts +0 -66
  112. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  113. package/src/api/com/atproto/identity/index.ts +0 -17
  114. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  115. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  116. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  117. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  118. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  119. package/src/api/com/atproto/index.ts +0 -19
  120. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  121. package/src/api/com/atproto/moderation/index.ts +0 -7
  122. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  123. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  124. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  125. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  126. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  127. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  128. package/src/api/com/atproto/repo/index.ts +0 -25
  129. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  130. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  131. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  132. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  133. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  134. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  135. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  136. package/src/api/com/atproto/server/createAccount.ts +0 -327
  137. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  138. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  139. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  140. package/src/api/com/atproto/server/createSession.ts +0 -97
  141. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  142. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  143. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  144. package/src/api/com/atproto/server/describeServer.ts +0 -29
  145. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  146. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  147. package/src/api/com/atproto/server/getSession.ts +0 -80
  148. package/src/api/com/atproto/server/index.ts +0 -55
  149. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  150. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  151. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  152. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  153. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  154. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  155. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  156. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  157. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  158. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  159. package/src/api/com/atproto/server/util.ts +0 -136
  160. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  161. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  162. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  163. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  164. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  165. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  166. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  167. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  168. package/src/api/com/atproto/sync/index.ts +0 -27
  169. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  170. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  171. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  172. package/src/api/com/atproto/sync/util.ts +0 -37
  173. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  174. package/src/api/com/atproto/temp/index.ts +0 -7
  175. package/src/api/index.ts +0 -10
  176. package/src/api/proxy.ts +0 -44
  177. package/src/app-view.ts +0 -24
  178. package/src/auth-output.ts +0 -52
  179. package/src/auth-routes.ts +0 -64
  180. package/src/auth-scope.ts +0 -40
  181. package/src/auth-verifier.ts +0 -668
  182. package/src/background.ts +0 -65
  183. package/src/basic-routes.ts +0 -52
  184. package/src/bsky-app-view.ts +0 -33
  185. package/src/config/config.ts +0 -553
  186. package/src/config/env.ts +0 -167
  187. package/src/config/index.ts +0 -3
  188. package/src/config/secrets.ts +0 -54
  189. package/src/context.ts +0 -523
  190. package/src/crawlers.ts +0 -46
  191. package/src/db/cast.ts +0 -52
  192. package/src/db/db.ts +0 -140
  193. package/src/db/index.ts +0 -4
  194. package/src/db/migrator.ts +0 -40
  195. package/src/db/pagination.ts +0 -132
  196. package/src/db/tables/moderation.ts +0 -80
  197. package/src/db/util.ts +0 -108
  198. package/src/did-cache/db/index.ts +0 -21
  199. package/src/did-cache/db/migrations.ts +0 -17
  200. package/src/did-cache/db/schema.ts +0 -9
  201. package/src/did-cache/index.ts +0 -131
  202. package/src/disk-blobstore.ts +0 -172
  203. package/src/error.ts +0 -19
  204. package/src/handle/explicit-slurs.ts +0 -22
  205. package/src/handle/index.ts +0 -49
  206. package/src/handle/reserved.ts +0 -1059
  207. package/src/image/image-url-builder.ts +0 -16
  208. package/src/index.ts +0 -189
  209. package/src/lexicons.ts +0 -4
  210. package/src/logger.ts +0 -35
  211. package/src/mailer/index.ts +0 -111
  212. package/src/mailer/moderation.ts +0 -33
  213. package/src/mailer/templates/confirm-email.d.ts +0 -4
  214. package/src/mailer/templates/confirm-email.hbs +0 -158
  215. package/src/mailer/templates/delete-account.d.ts +0 -4
  216. package/src/mailer/templates/delete-account.hbs +0 -156
  217. package/src/mailer/templates/plc-operation.d.ts +0 -4
  218. package/src/mailer/templates/plc-operation.hbs +0 -153
  219. package/src/mailer/templates/reset-password.d.ts +0 -4
  220. package/src/mailer/templates/reset-password.hbs +0 -154
  221. package/src/mailer/templates/update-email.d.ts +0 -4
  222. package/src/mailer/templates/update-email.hbs +0 -153
  223. package/src/mailer/templates.ts +0 -17
  224. package/src/pipethrough.ts +0 -716
  225. package/src/rate-limits.ts +0 -59
  226. package/src/read-after-write/index.ts +0 -3
  227. package/src/read-after-write/types.ts +0 -35
  228. package/src/read-after-write/util.ts +0 -101
  229. package/src/read-after-write/viewer.ts +0 -290
  230. package/src/redis.ts +0 -25
  231. package/src/repo/index.ts +0 -2
  232. package/src/repo/prepare.ts +0 -266
  233. package/src/repo/types.ts +0 -65
  234. package/src/scripts/README.md +0 -40
  235. package/src/scripts/index.ts +0 -20
  236. package/src/scripts/publish-identity.ts +0 -60
  237. package/src/scripts/rebuild-repo.ts +0 -119
  238. package/src/scripts/rotate-keys.ts +0 -146
  239. package/src/scripts/sequencer-recovery/index.ts +0 -23
  240. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  241. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  242. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  243. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  244. package/src/scripts/util.ts +0 -7
  245. package/src/sequencer/db/index.ts +0 -21
  246. package/src/sequencer/db/migrations/001-init.ts +0 -35
  247. package/src/sequencer/db/migrations/index.ts +0 -5
  248. package/src/sequencer/db/schema.ts +0 -19
  249. package/src/sequencer/events.ts +0 -199
  250. package/src/sequencer/index.ts +0 -3
  251. package/src/sequencer/outbox.ts +0 -123
  252. package/src/sequencer/sequencer.ts +0 -290
  253. package/src/util/compression.ts +0 -16
  254. package/src/util/debug.ts +0 -10
  255. package/src/util/http.ts +0 -31
  256. package/src/util/types.ts +0 -7
  257. package/src/well-known.ts +0 -30
  258. package/test.env +0 -2
  259. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  260. package/tests/_oauth_client_assets_middleware.ts +0 -23
  261. package/tests/_puppeteer.ts +0 -147
  262. package/tests/_types.d.ts +0 -16
  263. package/tests/_util.ts +0 -191
  264. package/tests/account-deactivation.test.ts +0 -204
  265. package/tests/account-deletion.test.ts +0 -300
  266. package/tests/account-manager.test.ts +0 -462
  267. package/tests/account-migration.test.ts +0 -221
  268. package/tests/account-status.test.ts +0 -206
  269. package/tests/account.test.ts +0 -595
  270. package/tests/app-passwords.test.ts +0 -262
  271. package/tests/auth.test.ts +0 -405
  272. package/tests/blob-deletes.test.ts +0 -204
  273. package/tests/create-post.test.ts +0 -79
  274. package/tests/crud.test.ts +0 -1595
  275. package/tests/db.test.ts +0 -170
  276. package/tests/email-confirmation.test.ts +0 -227
  277. package/tests/entryway-mock.ts +0 -323
  278. package/tests/entryway.test.ts +0 -145
  279. package/tests/file-uploads.test.ts +0 -301
  280. package/tests/get-service-auth.test.ts +0 -81
  281. package/tests/handle-validation.test.ts +0 -56
  282. package/tests/handles.test.ts +0 -274
  283. package/tests/invite-codes.test.ts +0 -367
  284. package/tests/invites-admin.test.ts +0 -252
  285. package/tests/moderation.test.ts +0 -280
  286. package/tests/moderator-auth.test.ts +0 -177
  287. package/tests/oauth.test.ts +0 -334
  288. package/tests/plc-operations.test.ts +0 -239
  289. package/tests/preferences.test.ts +0 -352
  290. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  291. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  292. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  293. package/tests/proxied/admin.test.ts +0 -340
  294. package/tests/proxied/feedgen.test.ts +0 -66
  295. package/tests/proxied/notif.test.ts +0 -85
  296. package/tests/proxied/procedures.test.ts +0 -175
  297. package/tests/proxied/proxy-catchall.test.ts +0 -256
  298. package/tests/proxied/proxy-header.test.ts +0 -239
  299. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  300. package/tests/proxied/read-after-write.test.ts +0 -382
  301. package/tests/proxied/views.test.ts +0 -608
  302. package/tests/races.test.ts +0 -89
  303. package/tests/rate-limits.test.ts +0 -70
  304. package/tests/recovery.test.ts +0 -180
  305. package/tests/seeds/basic.ts +0 -165
  306. package/tests/seeds/follows.ts +0 -57
  307. package/tests/seeds/likes.ts +0 -14
  308. package/tests/seeds/reposts.ts +0 -18
  309. package/tests/seeds/thread.ts +0 -40
  310. package/tests/seeds/users-bulk.ts +0 -246
  311. package/tests/seeds/users.ts +0 -67
  312. package/tests/sequencer.test.ts +0 -251
  313. package/tests/server.test.ts +0 -151
  314. package/tests/sync/invertible-ops.test.ts +0 -99
  315. package/tests/sync/list.test.ts +0 -43
  316. package/tests/sync/subscribe-repos.test.ts +0 -672
  317. package/tests/sync/sync.test.ts +0 -316
  318. package/tests/takedown-appeal.test.ts +0 -166
  319. package/tsconfig.build.json +0 -9
  320. package/tsconfig.build.tsbuildinfo +0 -1
  321. package/tsconfig.json +0 -7
  322. package/tsconfig.tests.json +0 -8
package/src/db/db.ts DELETED
@@ -1,140 +0,0 @@
1
- import assert from 'node:assert'
2
- import SqliteDB from 'better-sqlite3'
3
- import {
4
- Kysely,
5
- KyselyPlugin,
6
- PluginTransformQueryArgs,
7
- PluginTransformResultArgs,
8
- QueryResult,
9
- RootOperationNode,
10
- SqliteDialect,
11
- UnknownRow,
12
- sql,
13
- } from 'kysely'
14
- import { dbLogger } from '../logger.js'
15
- import { retrySqlite } from './util.js'
16
-
17
- const DEFAULT_PRAGMAS = {
18
- // strict: 'ON', // @TODO strictness should live on table defs instead
19
- }
20
-
21
- export class Database<Schema> {
22
- destroyed = false
23
- commitHooks: CommitHook[] = []
24
-
25
- constructor(public db: Kysely<Schema>) {}
26
-
27
- static sqlite<T>(
28
- location: string,
29
- opts?: { pragmas?: Record<string, string> },
30
- ): Database<T> {
31
- const sqliteDb = new SqliteDB(location, {
32
- timeout: 0, // handled by application
33
- })
34
- const pragmas = {
35
- ...DEFAULT_PRAGMAS,
36
- ...(opts?.pragmas ?? {}),
37
- }
38
- for (const pragma of Object.keys(pragmas)) {
39
- sqliteDb.pragma(`${pragma} = ${pragmas[pragma]}`)
40
- }
41
- const db = new Kysely<T>({
42
- dialect: new SqliteDialect({
43
- database: sqliteDb,
44
- }),
45
- })
46
- return new Database(db)
47
- }
48
-
49
- async ensureWal() {
50
- await sql`PRAGMA journal_mode = WAL`.execute(this.db)
51
- }
52
-
53
- async transactionNoRetry<T>(
54
- fn: (db: Database<Schema>) => T | PromiseLike<T>,
55
- ): Promise<T> {
56
- this.assertNotTransaction()
57
- const leakyTxPlugin = new LeakyTxPlugin()
58
- const { hooks, txRes } = await this.db
59
- .withPlugin(leakyTxPlugin)
60
- .transaction()
61
- .execute(async (txn) => {
62
- const dbTxn = new Database(txn)
63
- try {
64
- const txRes = await fn(dbTxn)
65
- leakyTxPlugin.endTx()
66
- const hooks = dbTxn.commitHooks
67
- return { hooks, txRes }
68
- } catch (err) {
69
- leakyTxPlugin.endTx()
70
- // ensure that all in-flight queries are flushed & the connection is open
71
- await txn.getExecutor().provideConnection(async () => {})
72
- throw err
73
- }
74
- })
75
- hooks.map((hook) => hook())
76
- return txRes
77
- }
78
-
79
- async transaction<T>(
80
- fn: (db: Database<Schema>) => T | PromiseLike<T>,
81
- ): Promise<T> {
82
- return retrySqlite(() => this.transactionNoRetry(fn))
83
- }
84
-
85
- async executeWithRetry<T>(query: { execute: () => Promise<T> }) {
86
- if (this.isTransaction) {
87
- // transaction() ensures retry on entire transaction, no need to retry individual statements.
88
- return query.execute()
89
- }
90
- return retrySqlite(() => query.execute())
91
- }
92
-
93
- onCommit(fn: () => void) {
94
- this.assertTransaction()
95
- this.commitHooks.push(fn)
96
- }
97
-
98
- get isTransaction() {
99
- return this.db.isTransaction
100
- }
101
-
102
- assertTransaction() {
103
- assert(this.isTransaction, 'Transaction required')
104
- }
105
-
106
- assertNotTransaction() {
107
- assert(!this.isTransaction, 'Cannot be in a transaction')
108
- }
109
-
110
- close(): void {
111
- if (this.destroyed) return
112
- this.db
113
- .destroy()
114
- .then(() => (this.destroyed = true))
115
- .catch((err) => dbLogger.error({ err }, 'error closing db'))
116
- }
117
- }
118
-
119
- type CommitHook = () => void
120
-
121
- class LeakyTxPlugin implements KyselyPlugin {
122
- private txOver = false
123
-
124
- endTx() {
125
- this.txOver = true
126
- }
127
-
128
- transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
129
- if (this.txOver) {
130
- throw new Error('tx already failed')
131
- }
132
- return args.node
133
- }
134
-
135
- async transformResult(
136
- args: PluginTransformResultArgs,
137
- ): Promise<QueryResult<UnknownRow>> {
138
- return args.result
139
- }
140
- }
package/src/db/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './db.js'
2
- export * from './cast.js'
3
- export * from './migrator.js'
4
- export * from './util.js'
@@ -1,40 +0,0 @@
1
- import { Kysely } from 'kysely'
2
- import { Migration, Migrator as KyselyMigrator } from 'kysely/migration'
3
-
4
- export class Migrator<T> extends KyselyMigrator {
5
- constructor(
6
- public db: Kysely<T>,
7
- migrations: Record<string, Migration>,
8
- ) {
9
- super({
10
- db,
11
- provider: {
12
- async getMigrations() {
13
- return migrations
14
- },
15
- },
16
- })
17
- }
18
-
19
- async migrateToOrThrow(migration: string) {
20
- const { error, results } = await this.migrateTo(migration)
21
- if (error) {
22
- throw error
23
- }
24
- if (!results) {
25
- throw new Error('An unknown failure occurred while migrating')
26
- }
27
- return results
28
- }
29
-
30
- async migrateToLatestOrThrow() {
31
- const { error, results } = await this.migrateToLatest()
32
- if (error) {
33
- throw error
34
- }
35
- if (!results) {
36
- throw new Error('An unknown failure occurred while migrating')
37
- }
38
- return results
39
- }
40
- }
@@ -1,132 +0,0 @@
1
- import { SqlBool, sql } from 'kysely'
2
- import { InvalidRequestError } from '@atproto/xrpc-server'
3
- import { AnyQb, DbRef } from './util.js'
4
-
5
- export type Cursor = { primary: string; secondary: string }
6
- export type LabeledResult = {
7
- primary: string | number
8
- secondary: string | number
9
- }
10
-
11
- /**
12
- * The GenericKeyset is an abstract class that sets-up the interface and partial implementation
13
- * of a keyset-paginated cursor with two parts. There are three types involved:
14
- * - Result: a raw result (i.e. a row from the db) containing data that will make-up a cursor.
15
- * - E.g. { createdAt: '2022-01-01T12:00:00Z', cid: 'bafyx' }
16
- * - LabeledResult: a Result processed such that the "primary" and "secondary" parts of the cursor are labeled.
17
- * - E.g. { primary: '2022-01-01T12:00:00Z', secondary: 'bafyx' }
18
- * - Cursor: the two string parts that make-up the packed/string cursor.
19
- * - E.g. packed cursor '1641038400000::bafyx' in parts { primary: '1641038400000', secondary: 'bafyx' }
20
- *
21
- * These types relate as such. Implementers define the relations marked with a *:
22
- * Result -*-> LabeledResult <-*-> Cursor <--> packed/string cursor
23
- * ↳ SQL Condition
24
- */
25
- export abstract class GenericKeyset<R, LR extends LabeledResult> {
26
- constructor(
27
- public primary: DbRef,
28
- public secondary: DbRef,
29
- ) {}
30
- abstract labelResult(result: R): LR
31
- abstract labeledResultToCursor(labeled: LR): Cursor
32
- abstract cursorToLabeledResult(cursor: Cursor): LR
33
- packFromResult(results: R | R[]): string | undefined {
34
- const result = Array.isArray(results) ? results.at(-1) : results
35
- if (!result) return
36
- return this.pack(this.labelResult(result))
37
- }
38
- pack(labeled?: LR): string | undefined {
39
- if (!labeled) return
40
- const cursor = this.labeledResultToCursor(labeled)
41
- return this.packCursor(cursor)
42
- }
43
- unpack(cursorStr?: string): LR | undefined {
44
- const cursor = this.unpackCursor(cursorStr)
45
- if (!cursor) return
46
- return this.cursorToLabeledResult(cursor)
47
- }
48
- packCursor(cursor?: Cursor): string | undefined {
49
- if (!cursor) return
50
- return `${cursor.primary}::${cursor.secondary}`
51
- }
52
- unpackCursor(cursorStr?: string): Cursor | undefined {
53
- if (!cursorStr) return
54
- const result = cursorStr.split('::')
55
- const [primary, secondary, ...others] = result
56
- if (!primary || !secondary || others.length > 0) {
57
- throw new InvalidRequestError('Malformed cursor')
58
- }
59
- return {
60
- primary,
61
- secondary,
62
- }
63
- }
64
- getSql(labeled?: LR, direction?: 'asc' | 'desc', tryIndex?: boolean) {
65
- if (labeled === undefined) return
66
- if (tryIndex) {
67
- // The tryIndex param will likely disappear and become the default implementation: here for now for gradual rollout query-by-query.
68
- if (direction === 'asc') {
69
- return sql<SqlBool>`((${this.primary}, ${this.secondary}) > (${labeled.primary}, ${labeled.secondary}))`
70
- } else {
71
- return sql<SqlBool>`((${this.primary}, ${this.secondary}) < (${labeled.primary}, ${labeled.secondary}))`
72
- }
73
- } else {
74
- // @NOTE this implementation can struggle to use an index on (primary, secondary) for pagination due to the "or" usage.
75
- if (direction === 'asc') {
76
- return sql<SqlBool>`((${this.primary} > ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} > ${labeled.secondary}))`
77
- } else {
78
- return sql<SqlBool>`((${this.primary} < ${labeled.primary}) or (${this.primary} = ${labeled.primary} and ${this.secondary} < ${labeled.secondary}))`
79
- }
80
- }
81
- }
82
- }
83
-
84
- type CreatedAtCidResult = { createdAt: string; cid: string }
85
- type TimeCidLabeledResult = Cursor
86
-
87
- export class TimeCidKeyset<
88
- TimeCidResult = CreatedAtCidResult,
89
- > extends GenericKeyset<TimeCidResult, TimeCidLabeledResult> {
90
- labelResult(result: TimeCidResult): TimeCidLabeledResult
91
- labelResult<TimeCidResult extends CreatedAtCidResult>(result: TimeCidResult) {
92
- return { primary: result.createdAt, secondary: result.cid }
93
- }
94
- labeledResultToCursor(labeled: TimeCidLabeledResult) {
95
- return {
96
- primary: new Date(labeled.primary).getTime().toString(),
97
- secondary: labeled.secondary,
98
- }
99
- }
100
- cursorToLabeledResult(cursor: Cursor) {
101
- const primaryDate = new Date(parseInt(cursor.primary, 10))
102
- if (isNaN(primaryDate.getTime())) {
103
- throw new InvalidRequestError('Malformed cursor')
104
- }
105
- return {
106
- primary: primaryDate.toISOString(),
107
- secondary: cursor.secondary,
108
- }
109
- }
110
- }
111
-
112
- export const paginate = <
113
- QB extends AnyQb,
114
- K extends GenericKeyset<unknown, any>,
115
- >(
116
- qb: QB,
117
- opts: {
118
- limit?: number
119
- cursor?: string
120
- direction?: 'asc' | 'desc'
121
- keyset: K
122
- tryIndex?: boolean
123
- },
124
- ): QB => {
125
- const { limit, cursor, keyset, direction = 'desc', tryIndex } = opts
126
- const keysetSql = keyset.getSql(keyset.unpack(cursor), direction, tryIndex)
127
- return qb
128
- .$if(!!limit, (q) => q.limit(limit as number))
129
- .orderBy(keyset.primary, direction)
130
- .orderBy(keyset.secondary, direction)
131
- .$if(!!keysetSql, (qb) => (keysetSql ? qb.where(keysetSql) : qb)) as QB
132
- }
@@ -1,80 +0,0 @@
1
- import { Generated } from 'kysely'
2
- import { com } from '../../lexicons/index.js'
3
-
4
- export const actionTableName = 'moderation_action'
5
- export const actionSubjectBlobTableName = 'moderation_action_subject_blob'
6
- export const reportTableName = 'moderation_report'
7
- export const reportResolutionTableName = 'moderation_report_resolution'
8
-
9
- export interface ModerationAction {
10
- id: Generated<number>
11
- action:
12
- | 'tools.ozone.moderation.defs#modEventTakedown'
13
- | 'tools.ozone.moderation.defs#modEventAcknowledge'
14
- | 'tools.ozone.moderation.defs#modEventEscalate'
15
- | 'tools.ozone.moderation.defs#modEventComment'
16
- | 'tools.ozone.moderation.defs#modEventLabel'
17
- | 'tools.ozone.moderation.defs#modEventReport'
18
- | 'tools.ozone.moderation.defs#modEventMute'
19
- | 'tools.ozone.moderation.defs#modEventUnmute'
20
- | 'tools.ozone.moderation.defs#modEventMuteReporter'
21
- | 'tools.ozone.moderation.defs#modEventUnmuteReporter'
22
- | 'tools.ozone.moderation.defs#modEventReverseTakedown'
23
- | 'tools.ozone.moderation.defs#modEventEmail'
24
- | 'tools.ozone.moderation.defs#modEventResolveAppeal'
25
- | 'tools.ozone.moderation.defs#modEventDivert'
26
- | 'tools.ozone.moderation.defs#accountEvent'
27
- | 'tools.ozone.moderation.defs#identityEvent'
28
- | 'tools.ozone.moderation.defs#recordEvent'
29
- | 'tools.ozone.moderation.defs#modEventPriorityScore'
30
- subjectType: 'com.atproto.admin.defs#repoRef' | 'com.atproto.repo.strongRef'
31
- subjectDid: string
32
- subjectUri: string | null
33
- subjectCid: string | null
34
- createLabelVals: string | null
35
- negateLabelVals: string | null
36
- comment: string | null
37
- createdAt: string
38
- createdBy: string
39
- durationInHours: number | null
40
- expiresAt: string | null
41
- meta: Record<string, string | boolean> | null
42
- }
43
-
44
- export interface ModerationActionSubjectBlob {
45
- actionId: number
46
- cid: string
47
- recordUri: string
48
- }
49
-
50
- export interface ModerationReport {
51
- id: Generated<number>
52
- subjectType: 'com.atproto.admin.defs#repoRef' | 'com.atproto.repo.strongRef'
53
- subjectDid: string
54
- subjectUri: string | null
55
- subjectCid: string | null
56
- reasonType:
57
- | com.atproto.moderation.defs.ReasonSpam
58
- | com.atproto.moderation.defs.ReasonOther
59
- | com.atproto.moderation.defs.ReasonMisleading
60
- | com.atproto.moderation.defs.ReasonRude
61
- | com.atproto.moderation.defs.ReasonSexual
62
- | com.atproto.moderation.defs.ReasonViolation
63
- reason: string | null
64
- reportedByDid: string
65
- createdAt: string
66
- }
67
-
68
- export interface ModerationReportResolution {
69
- reportId: number
70
- actionId: number
71
- createdAt: string
72
- createdBy: string
73
- }
74
-
75
- export type PartialDB = {
76
- [actionTableName]: ModerationAction
77
- [actionSubjectBlobTableName]: ModerationActionSubjectBlob
78
- [reportTableName]: ModerationReport
79
- [reportResolutionTableName]: ModerationReportResolution
80
- }
package/src/db/util.ts DELETED
@@ -1,108 +0,0 @@
1
- import {
2
- DummyDriver,
3
- DynamicModule,
4
- Kysely,
5
- RawBuilder,
6
- ReferenceExpression,
7
- SelectQueryBuilder,
8
- SqlBool,
9
- SqliteAdapter,
10
- SqliteIntrospector,
11
- SqliteQueryCompiler,
12
- sql,
13
- } from 'kysely'
14
- import { retry } from '@atproto/common'
15
-
16
- // Applies to repo_root or record table
17
- export const notSoftDeletedClause = (alias: DbRef) => {
18
- return sql<SqlBool>`${alias}."takedownRef" is null`
19
- }
20
-
21
- export const softDeleted = (repoOrRecord: { takedownRef: string | null }) => {
22
- return repoOrRecord.takedownRef !== null
23
- }
24
-
25
- export const countAll = sql<number>`count(*)`
26
- export const countDistinct = (ref: DbRef) => sql<number>`count(distinct ${ref})`
27
-
28
- // For use with doUpdateSet()
29
- export const excluded = <T, S>(db: Kysely<S>, col) => {
30
- return sql<T>`${db.dynamic.ref(`excluded.${col}`)}`
31
- }
32
-
33
- // Can be useful for large where-in clauses, to get the db to use a hash lookup on the list
34
- export const valuesList = (vals: unknown[]) => {
35
- return sql`(values (${sql.join(vals, sql`), (`)}))`
36
- }
37
-
38
- export const dummyDialect = {
39
- createAdapter() {
40
- return new SqliteAdapter()
41
- },
42
- createDriver() {
43
- return new DummyDriver()
44
- },
45
- createIntrospector(db) {
46
- return new SqliteIntrospector(db)
47
- },
48
- createQueryCompiler() {
49
- return new SqliteQueryCompiler()
50
- },
51
- }
52
-
53
- export const retrySqlite = <T>(fn: () => Promise<T>): Promise<T> => {
54
- return retry(fn, {
55
- retryable: retryableSqlite,
56
- getWaitMs: getWaitMsSqlite,
57
- maxRetries: 60, // a safety measure: getWaitMsSqlite() times out before this after 5000ms of waiting.
58
- })
59
- }
60
-
61
- const retryableSqlite = (err: unknown) => {
62
- return typeof err?.['code'] === 'string' && RETRY_ERRORS.has(err['code'])
63
- }
64
-
65
- // based on sqlite's backoff strategy https://github.com/sqlite/sqlite/blob/91c8e65dd4bf17d21fbf8f7073565fe1a71c8948/src/main.c#L1704-L1713
66
- const getWaitMsSqlite = (n: number, timeout = 5000) => {
67
- if (n < 0) return null
68
- let delay: number
69
- let prior: number
70
- if (n < DELAYS.length) {
71
- delay = DELAYS[n]
72
- prior = TOTALS[n]
73
- } else {
74
- delay = last(DELAYS)
75
- prior = last(TOTALS) + delay * (n - (DELAYS.length - 1))
76
- }
77
- if (prior + delay > timeout) {
78
- delay = timeout - prior
79
- if (delay <= 0) return null
80
- }
81
- return delay
82
- }
83
-
84
- const last = <T>(arr: T[]) => arr[arr.length - 1]
85
- const DELAYS = [1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100]
86
- const TOTALS = [0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228]
87
- const RETRY_ERRORS = new Set([
88
- 'SQLITE_BUSY',
89
- 'SQLITE_BUSY_SNAPSHOT',
90
- 'SQLITE_BUSY_RECOVERY',
91
- 'SQLITE_BUSY_TIMEOUT',
92
- ])
93
-
94
- export type Ref = ReferenceExpression<any, any>
95
-
96
- export type DbRef =
97
- | RawBuilder<unknown>
98
- | ReturnType<DynamicModule<unknown>['ref']>
99
-
100
- export type AnyQb = SelectQueryBuilder<any, any, any>
101
-
102
- export const isErrUniqueViolation = (err: unknown) => {
103
- const code = err?.['code']
104
- return (
105
- code === '23505' || // postgres, see https://www.postgresql.org/docs/current/errcodes-appendix.html
106
- code === 'SQLITE_CONSTRAINT_UNIQUE' // sqlite, see https://www.sqlite.org/rescode.html#constraint_unique
107
- )
108
- }
@@ -1,21 +0,0 @@
1
- import { Database, Migrator } from '../../db/index.js'
2
- import migrations from './migrations.js'
3
- import { DidCacheSchema } from './schema.js'
4
-
5
- export * from './schema.js'
6
-
7
- export type DidCacheDb = Database<DidCacheSchema>
8
-
9
- export const getDb = (
10
- location: string,
11
- disableWalAutoCheckpoint = false,
12
- ): DidCacheDb => {
13
- const pragmas: Record<string, string> = disableWalAutoCheckpoint
14
- ? { wal_autocheckpoint: '0', synchronous: 'NORMAL' }
15
- : { synchronous: 'NORMAL' }
16
- return Database.sqlite(location, { pragmas })
17
- }
18
-
19
- export const getMigrator = (db: DidCacheDb) => {
20
- return new Migrator(db.db, migrations)
21
- }
@@ -1,17 +0,0 @@
1
- import { Kysely } from 'kysely'
2
-
3
- export default {
4
- '001': {
5
- up: async (db: Kysely<unknown>) => {
6
- await db.schema
7
- .createTable('did_doc')
8
- .addColumn('did', 'varchar', (col) => col.primaryKey())
9
- .addColumn('doc', 'text', (col) => col.notNull())
10
- .addColumn('updatedAt', 'bigint', (col) => col.notNull())
11
- .execute()
12
- },
13
- down: async (db: Kysely<unknown>) => {
14
- await db.schema.dropTable('did_doc').execute()
15
- },
16
- },
17
- }
@@ -1,9 +0,0 @@
1
- export interface DidDoc {
2
- did: string
3
- doc: string // json representation of DidDocument
4
- updatedAt: number
5
- }
6
-
7
- export type DidCacheSchema = {
8
- did_doc: DidDoc
9
- }
@@ -1,131 +0,0 @@
1
- import PQueue from 'p-queue'
2
- import { CacheResult, DidCache, DidDocument } from '@atproto/identity'
3
- import { excluded } from '../db/util.js'
4
- import { didCacheLogger } from '../logger.js'
5
- import { DidCacheDb, getDb, getMigrator } from './db/index.js'
6
-
7
- export class DidSqliteCache implements DidCache {
8
- db: DidCacheDb
9
- public pQueue: PQueue | null //null during teardown
10
-
11
- constructor(
12
- dbLocation: string,
13
- public staleTTL: number,
14
- public maxTTL: number,
15
- disableWalAutoCheckpoint = false,
16
- ) {
17
- this.db = getDb(dbLocation, disableWalAutoCheckpoint)
18
- this.pQueue = new PQueue()
19
- }
20
-
21
- async cacheDid(
22
- did: string,
23
- doc: DidDocument,
24
- prevResult?: CacheResult,
25
- ): Promise<void> {
26
- try {
27
- if (prevResult) {
28
- await this.db.executeWithRetry(
29
- this.db.db
30
- .updateTable('did_doc')
31
- .set({ doc: JSON.stringify(doc), updatedAt: Date.now() })
32
- .where('did', '=', did)
33
- .where('updatedAt', '=', prevResult.updatedAt),
34
- )
35
- } else {
36
- await this.db.executeWithRetry(
37
- this.db.db
38
- .insertInto('did_doc')
39
- .values({ did, doc: JSON.stringify(doc), updatedAt: Date.now() })
40
- .onConflict((oc) =>
41
- oc.column('did').doUpdateSet({
42
- doc: excluded(this.db.db, 'doc'),
43
- updatedAt: excluded(this.db.db, 'updatedAt'),
44
- }),
45
- ),
46
- )
47
- }
48
- } catch (err) {
49
- didCacheLogger.error({ did, doc, err }, 'failed to cache did')
50
- }
51
- }
52
-
53
- async refreshCache(
54
- did: string,
55
- getDoc: () => Promise<DidDocument | null>,
56
- prevResult?: CacheResult,
57
- ): Promise<void> {
58
- this.pQueue?.add(async () => {
59
- try {
60
- const doc = await getDoc()
61
- if (doc) {
62
- await this.cacheDid(did, doc, prevResult)
63
- } else {
64
- await this.clearEntry(did)
65
- }
66
- } catch (err) {
67
- didCacheLogger.error({ did, err }, 'refreshing did cache failed')
68
- }
69
- })
70
- }
71
-
72
- async checkCache(did: string): Promise<CacheResult | null> {
73
- try {
74
- return await this.checkCacheInternal(did)
75
- } catch (err) {
76
- didCacheLogger.error({ did, err }, 'failed to check did cache')
77
- return null
78
- }
79
- }
80
-
81
- async checkCacheInternal(did: string): Promise<CacheResult | null> {
82
- const res = await this.db.db
83
- .selectFrom('did_doc')
84
- .where('did', '=', did)
85
- .selectAll()
86
- .executeTakeFirst()
87
- if (!res) return null
88
- const now = Date.now()
89
- const updatedAt = new Date(res.updatedAt).getTime()
90
- const expired = now > updatedAt + this.maxTTL
91
- const stale = now > updatedAt + this.staleTTL
92
- return {
93
- doc: JSON.parse(res.doc) as DidDocument,
94
- updatedAt,
95
- did,
96
- stale,
97
- expired,
98
- }
99
- }
100
-
101
- async clearEntry(did: string): Promise<void> {
102
- try {
103
- await this.db.executeWithRetry(
104
- this.db.db.deleteFrom('did_doc').where('did', '=', did),
105
- )
106
- } catch (err) {
107
- didCacheLogger.error({ did, err }, 'clearing did cache entry failed')
108
- }
109
- }
110
-
111
- async clear(): Promise<void> {
112
- await this.db.db.deleteFrom('did_doc').execute()
113
- }
114
-
115
- async processAll() {
116
- await this.pQueue?.onIdle()
117
- }
118
-
119
- async migrateOrThrow() {
120
- await this.db.ensureWal()
121
- await getMigrator(this.db).migrateToLatestOrThrow()
122
- }
123
-
124
- async destroy() {
125
- const pQueue = this.pQueue
126
- this.pQueue = null
127
- pQueue?.pause()
128
- pQueue?.clear()
129
- await pQueue?.onIdle()
130
- }
131
- }