@atproto/pds 0.5.12 → 0.5.15

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 (326) hide show
  1. package/CHANGELOG.md +53 -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/dist/lexicons/app/bsky/actor/defs.defs.d.ts +6 -0
  10. package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
  11. package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
  12. package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
  13. package/package.json +42 -38
  14. package/build.templates.cjs +0 -22
  15. package/example.env +0 -42
  16. package/jest.config.cjs +0 -27
  17. package/src/account-manager/account-manager.ts +0 -916
  18. package/src/account-manager/db/index.ts +0 -21
  19. package/src/account-manager/db/migrations/001-init.ts +0 -115
  20. package/src/account-manager/db/migrations/002-account-deactivation.ts +0 -17
  21. package/src/account-manager/db/migrations/003-privileged-app-passwords.ts +0 -12
  22. package/src/account-manager/db/migrations/004-oauth.ts +0 -122
  23. package/src/account-manager/db/migrations/005-oauth-account-management.ts +0 -136
  24. package/src/account-manager/db/migrations/006-oauth-permission-sets.ts +0 -20
  25. package/src/account-manager/db/migrations/007-lexicon-failures-index.ts +0 -14
  26. package/src/account-manager/db/migrations/index.ts +0 -17
  27. package/src/account-manager/db/schema/account-device.ts +0 -14
  28. package/src/account-manager/db/schema/account.ts +0 -16
  29. package/src/account-manager/db/schema/actor.ts +0 -17
  30. package/src/account-manager/db/schema/app-password.ts +0 -13
  31. package/src/account-manager/db/schema/authorization-request.ts +0 -30
  32. package/src/account-manager/db/schema/authorized-client.ts +0 -23
  33. package/src/account-manager/db/schema/device.ts +0 -18
  34. package/src/account-manager/db/schema/email-token.ts +0 -19
  35. package/src/account-manager/db/schema/index.ts +0 -43
  36. package/src/account-manager/db/schema/invite-code.ts +0 -24
  37. package/src/account-manager/db/schema/lexicon.ts +0 -15
  38. package/src/account-manager/db/schema/refresh-token.ts +0 -11
  39. package/src/account-manager/db/schema/repo-root.ts +0 -12
  40. package/src/account-manager/db/schema/token.ts +0 -38
  41. package/src/account-manager/db/schema/used-refresh-token.ts +0 -13
  42. package/src/account-manager/helpers/account-device.ts +0 -63
  43. package/src/account-manager/helpers/account.ts +0 -355
  44. package/src/account-manager/helpers/auth.ts +0 -222
  45. package/src/account-manager/helpers/authorization-request.ts +0 -90
  46. package/src/account-manager/helpers/authorized-client.ts +0 -75
  47. package/src/account-manager/helpers/device.ts +0 -47
  48. package/src/account-manager/helpers/email-token.ts +0 -87
  49. package/src/account-manager/helpers/invite.ts +0 -263
  50. package/src/account-manager/helpers/lexicon.ts +0 -67
  51. package/src/account-manager/helpers/password.ts +0 -136
  52. package/src/account-manager/helpers/repo.ts +0 -24
  53. package/src/account-manager/helpers/scrypt.ts +0 -53
  54. package/src/account-manager/helpers/token.ts +0 -158
  55. package/src/account-manager/helpers/used-refresh-token.ts +0 -30
  56. package/src/account-manager/oauth-store.ts +0 -880
  57. package/src/account-manager/scope-reference-getter.ts +0 -106
  58. package/src/actor-store/actor-store-reader.ts +0 -45
  59. package/src/actor-store/actor-store-resources.ts +0 -8
  60. package/src/actor-store/actor-store-transactor.ts +0 -31
  61. package/src/actor-store/actor-store-writer.ts +0 -17
  62. package/src/actor-store/actor-store.ts +0 -210
  63. package/src/actor-store/blob/reader.ts +0 -160
  64. package/src/actor-store/blob/transactor.ts +0 -383
  65. package/src/actor-store/db/index.ts +0 -20
  66. package/src/actor-store/db/migrations/001-init.ts +0 -105
  67. package/src/actor-store/db/migrations/index.ts +0 -5
  68. package/src/actor-store/db/schema/account-pref.ts +0 -11
  69. package/src/actor-store/db/schema/backlink.ts +0 -9
  70. package/src/actor-store/db/schema/blob.ts +0 -14
  71. package/src/actor-store/db/schema/index.ts +0 -23
  72. package/src/actor-store/db/schema/record-blob.ts +0 -8
  73. package/src/actor-store/db/schema/record.ts +0 -14
  74. package/src/actor-store/db/schema/repo-block.ts +0 -10
  75. package/src/actor-store/db/schema/repo-root.ts +0 -10
  76. package/src/actor-store/migrate.ts +0 -39
  77. package/src/actor-store/preference/reader.ts +0 -48
  78. package/src/actor-store/preference/transactor.ts +0 -55
  79. package/src/actor-store/preference/util.ts +0 -39
  80. package/src/actor-store/record/reader.ts +0 -374
  81. package/src/actor-store/record/transactor.ts +0 -111
  82. package/src/actor-store/repo/reader.ts +0 -31
  83. package/src/actor-store/repo/sql-repo-reader.ts +0 -150
  84. package/src/actor-store/repo/sql-repo-transactor.ts +0 -105
  85. package/src/actor-store/repo/transactor.ts +0 -227
  86. package/src/api/app/bsky/actor/getPreferences.ts +0 -57
  87. package/src/api/app/bsky/actor/getProfile.ts +0 -41
  88. package/src/api/app/bsky/actor/getProfiles.ts +0 -51
  89. package/src/api/app/bsky/actor/index.ts +0 -13
  90. package/src/api/app/bsky/actor/putPreferences.ts +0 -62
  91. package/src/api/app/bsky/feed/getActorLikes.ts +0 -63
  92. package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -84
  93. package/src/api/app/bsky/feed/getFeed.ts +0 -47
  94. package/src/api/app/bsky/feed/getPostThread.ts +0 -251
  95. package/src/api/app/bsky/feed/getTimeline.ts +0 -50
  96. package/src/api/app/bsky/feed/index.ts +0 -15
  97. package/src/api/app/bsky/index.ts +0 -11
  98. package/src/api/app/bsky/notification/index.ts +0 -7
  99. package/src/api/app/bsky/notification/registerPush.ts +0 -71
  100. package/src/api/app/bsky/util/resolver.ts +0 -20
  101. package/src/api/com/atproto/admin/deleteAccount.ts +0 -22
  102. package/src/api/com/atproto/admin/disableAccountInvites.ts +0 -18
  103. package/src/api/com/atproto/admin/disableInviteCodes.ts +0 -21
  104. package/src/api/com/atproto/admin/enableAccountInvites.ts +0 -18
  105. package/src/api/com/atproto/admin/getAccountInfo.ts +0 -32
  106. package/src/api/com/atproto/admin/getAccountInfos.ts +0 -34
  107. package/src/api/com/atproto/admin/getInviteCodes.ts +0 -126
  108. package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -76
  109. package/src/api/com/atproto/admin/index.ts +0 -31
  110. package/src/api/com/atproto/admin/sendEmail.ts +0 -47
  111. package/src/api/com/atproto/admin/updateAccountEmail.ts +0 -32
  112. package/src/api/com/atproto/admin/updateAccountHandle.ts +0 -47
  113. package/src/api/com/atproto/admin/updateAccountPassword.ts +0 -34
  114. package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -68
  115. package/src/api/com/atproto/admin/util.ts +0 -66
  116. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +0 -50
  117. package/src/api/com/atproto/identity/index.ts +0 -17
  118. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +0 -59
  119. package/src/api/com/atproto/identity/resolveHandle.ts +0 -50
  120. package/src/api/com/atproto/identity/signPlcOperation.ts +0 -85
  121. package/src/api/com/atproto/identity/submitPlcOperation.ts +0 -65
  122. package/src/api/com/atproto/identity/updateHandle.ts +0 -66
  123. package/src/api/com/atproto/index.ts +0 -19
  124. package/src/api/com/atproto/moderation/createReport.ts +0 -41
  125. package/src/api/com/atproto/moderation/index.ts +0 -7
  126. package/src/api/com/atproto/repo/applyWrites.ts +0 -226
  127. package/src/api/com/atproto/repo/createRecord.ts +0 -143
  128. package/src/api/com/atproto/repo/deleteRecord.ts +0 -122
  129. package/src/api/com/atproto/repo/describeRepo.ts +0 -43
  130. package/src/api/com/atproto/repo/getRecord.ts +0 -40
  131. package/src/api/com/atproto/repo/importRepo.ts +0 -101
  132. package/src/api/com/atproto/repo/index.ts +0 -25
  133. package/src/api/com/atproto/repo/listMissingBlobs.ts +0 -29
  134. package/src/api/com/atproto/repo/listRecords.ts +0 -36
  135. package/src/api/com/atproto/repo/putRecord.ts +0 -211
  136. package/src/api/com/atproto/repo/uploadBlob.ts +0 -60
  137. package/src/api/com/atproto/server/activateAccount.ts +0 -37
  138. package/src/api/com/atproto/server/checkAccountStatus.ts +0 -51
  139. package/src/api/com/atproto/server/confirmEmail.ts +0 -39
  140. package/src/api/com/atproto/server/createAccount.ts +0 -327
  141. package/src/api/com/atproto/server/createAppPassword.ts +0 -53
  142. package/src/api/com/atproto/server/createInviteCode.ts +0 -38
  143. package/src/api/com/atproto/server/createInviteCodes.ts +0 -42
  144. package/src/api/com/atproto/server/createSession.ts +0 -97
  145. package/src/api/com/atproto/server/deactivateAccount.ts +0 -41
  146. package/src/api/com/atproto/server/deleteAccount.ts +0 -85
  147. package/src/api/com/atproto/server/deleteSession.ts +0 -23
  148. package/src/api/com/atproto/server/describeServer.ts +0 -29
  149. package/src/api/com/atproto/server/getAccountInviteCodes.ts +0 -142
  150. package/src/api/com/atproto/server/getServiceAuth.ts +0 -111
  151. package/src/api/com/atproto/server/getSession.ts +0 -80
  152. package/src/api/com/atproto/server/index.ts +0 -55
  153. package/src/api/com/atproto/server/listAppPasswords.ts +0 -45
  154. package/src/api/com/atproto/server/refreshSession.ts +0 -72
  155. package/src/api/com/atproto/server/requestAccountDelete.ts +0 -66
  156. package/src/api/com/atproto/server/requestEmailConfirmation.ts +0 -68
  157. package/src/api/com/atproto/server/requestEmailUpdate.ts +0 -86
  158. package/src/api/com/atproto/server/requestPasswordReset.ts +0 -52
  159. package/src/api/com/atproto/server/reserveSigningKey.ts +0 -15
  160. package/src/api/com/atproto/server/resetPassword.ts +0 -50
  161. package/src/api/com/atproto/server/revokeAppPassword.ts +0 -42
  162. package/src/api/com/atproto/server/updateEmail.ts +0 -52
  163. package/src/api/com/atproto/server/util.ts +0 -136
  164. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +0 -27
  165. package/src/api/com/atproto/sync/deprecated/getHead.ts +0 -33
  166. package/src/api/com/atproto/sync/getBlob.ts +0 -61
  167. package/src/api/com/atproto/sync/getBlocks.ts +0 -37
  168. package/src/api/com/atproto/sync/getLatestCommit.ts +0 -33
  169. package/src/api/com/atproto/sync/getRecord.ts +0 -49
  170. package/src/api/com/atproto/sync/getRepo.ts +0 -75
  171. package/src/api/com/atproto/sync/getRepoStatus.ts +0 -34
  172. package/src/api/com/atproto/sync/index.ts +0 -27
  173. package/src/api/com/atproto/sync/listBlobs.ts +0 -33
  174. package/src/api/com/atproto/sync/listRepos.ts +0 -74
  175. package/src/api/com/atproto/sync/subscribeRepos.ts +0 -73
  176. package/src/api/com/atproto/sync/util.ts +0 -37
  177. package/src/api/com/atproto/temp/checkSignupQueue.ts +0 -34
  178. package/src/api/com/atproto/temp/index.ts +0 -7
  179. package/src/api/index.ts +0 -10
  180. package/src/api/proxy.ts +0 -44
  181. package/src/app-view.ts +0 -24
  182. package/src/auth-output.ts +0 -52
  183. package/src/auth-routes.ts +0 -64
  184. package/src/auth-scope.ts +0 -40
  185. package/src/auth-verifier.ts +0 -668
  186. package/src/background.ts +0 -65
  187. package/src/basic-routes.ts +0 -52
  188. package/src/bsky-app-view.ts +0 -33
  189. package/src/config/config.ts +0 -553
  190. package/src/config/env.ts +0 -167
  191. package/src/config/index.ts +0 -3
  192. package/src/config/secrets.ts +0 -54
  193. package/src/context.ts +0 -523
  194. package/src/crawlers.ts +0 -46
  195. package/src/db/cast.ts +0 -52
  196. package/src/db/db.ts +0 -140
  197. package/src/db/index.ts +0 -4
  198. package/src/db/migrator.ts +0 -40
  199. package/src/db/pagination.ts +0 -132
  200. package/src/db/tables/moderation.ts +0 -80
  201. package/src/db/util.ts +0 -108
  202. package/src/did-cache/db/index.ts +0 -21
  203. package/src/did-cache/db/migrations.ts +0 -17
  204. package/src/did-cache/db/schema.ts +0 -9
  205. package/src/did-cache/index.ts +0 -131
  206. package/src/disk-blobstore.ts +0 -172
  207. package/src/error.ts +0 -19
  208. package/src/handle/explicit-slurs.ts +0 -22
  209. package/src/handle/index.ts +0 -49
  210. package/src/handle/reserved.ts +0 -1059
  211. package/src/image/image-url-builder.ts +0 -16
  212. package/src/index.ts +0 -189
  213. package/src/lexicons.ts +0 -4
  214. package/src/logger.ts +0 -35
  215. package/src/mailer/index.ts +0 -111
  216. package/src/mailer/moderation.ts +0 -33
  217. package/src/mailer/templates/confirm-email.d.ts +0 -4
  218. package/src/mailer/templates/confirm-email.hbs +0 -158
  219. package/src/mailer/templates/delete-account.d.ts +0 -4
  220. package/src/mailer/templates/delete-account.hbs +0 -156
  221. package/src/mailer/templates/plc-operation.d.ts +0 -4
  222. package/src/mailer/templates/plc-operation.hbs +0 -153
  223. package/src/mailer/templates/reset-password.d.ts +0 -4
  224. package/src/mailer/templates/reset-password.hbs +0 -154
  225. package/src/mailer/templates/update-email.d.ts +0 -4
  226. package/src/mailer/templates/update-email.hbs +0 -153
  227. package/src/mailer/templates.ts +0 -17
  228. package/src/pipethrough.ts +0 -716
  229. package/src/rate-limits.ts +0 -59
  230. package/src/read-after-write/index.ts +0 -3
  231. package/src/read-after-write/types.ts +0 -35
  232. package/src/read-after-write/util.ts +0 -101
  233. package/src/read-after-write/viewer.ts +0 -290
  234. package/src/redis.ts +0 -25
  235. package/src/repo/index.ts +0 -2
  236. package/src/repo/prepare.ts +0 -266
  237. package/src/repo/types.ts +0 -65
  238. package/src/scripts/README.md +0 -40
  239. package/src/scripts/index.ts +0 -20
  240. package/src/scripts/publish-identity.ts +0 -60
  241. package/src/scripts/rebuild-repo.ts +0 -119
  242. package/src/scripts/rotate-keys.ts +0 -146
  243. package/src/scripts/sequencer-recovery/index.ts +0 -23
  244. package/src/scripts/sequencer-recovery/recoverer.ts +0 -297
  245. package/src/scripts/sequencer-recovery/recovery-db.ts +0 -65
  246. package/src/scripts/sequencer-recovery/repair-repos.ts +0 -49
  247. package/src/scripts/sequencer-recovery/user-queues.ts +0 -44
  248. package/src/scripts/util.ts +0 -7
  249. package/src/sequencer/db/index.ts +0 -21
  250. package/src/sequencer/db/migrations/001-init.ts +0 -35
  251. package/src/sequencer/db/migrations/index.ts +0 -5
  252. package/src/sequencer/db/schema.ts +0 -19
  253. package/src/sequencer/events.ts +0 -199
  254. package/src/sequencer/index.ts +0 -3
  255. package/src/sequencer/outbox.ts +0 -123
  256. package/src/sequencer/sequencer.ts +0 -290
  257. package/src/util/compression.ts +0 -16
  258. package/src/util/debug.ts +0 -10
  259. package/src/util/http.ts +0 -31
  260. package/src/util/types.ts +0 -7
  261. package/src/well-known.ts +0 -30
  262. package/test.env +0 -2
  263. package/tests/__snapshots__/takedown-appeal.test.ts.snap +0 -43
  264. package/tests/_oauth_client_assets_middleware.ts +0 -23
  265. package/tests/_puppeteer.ts +0 -147
  266. package/tests/_types.d.ts +0 -16
  267. package/tests/_util.ts +0 -191
  268. package/tests/account-deactivation.test.ts +0 -204
  269. package/tests/account-deletion.test.ts +0 -300
  270. package/tests/account-manager.test.ts +0 -462
  271. package/tests/account-migration.test.ts +0 -221
  272. package/tests/account-status.test.ts +0 -206
  273. package/tests/account.test.ts +0 -595
  274. package/tests/app-passwords.test.ts +0 -262
  275. package/tests/auth.test.ts +0 -405
  276. package/tests/blob-deletes.test.ts +0 -204
  277. package/tests/create-post.test.ts +0 -79
  278. package/tests/crud.test.ts +0 -1595
  279. package/tests/db.test.ts +0 -170
  280. package/tests/email-confirmation.test.ts +0 -227
  281. package/tests/entryway-mock.ts +0 -323
  282. package/tests/entryway.test.ts +0 -145
  283. package/tests/file-uploads.test.ts +0 -301
  284. package/tests/get-service-auth.test.ts +0 -81
  285. package/tests/handle-validation.test.ts +0 -56
  286. package/tests/handles.test.ts +0 -274
  287. package/tests/invite-codes.test.ts +0 -367
  288. package/tests/invites-admin.test.ts +0 -252
  289. package/tests/moderation.test.ts +0 -280
  290. package/tests/moderator-auth.test.ts +0 -177
  291. package/tests/oauth.test.ts +0 -334
  292. package/tests/plc-operations.test.ts +0 -239
  293. package/tests/preferences.test.ts +0 -352
  294. package/tests/proxied/__snapshots__/admin.test.ts.snap +0 -516
  295. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +0 -215
  296. package/tests/proxied/__snapshots__/views.test.ts.snap +0 -4456
  297. package/tests/proxied/admin.test.ts +0 -340
  298. package/tests/proxied/feedgen.test.ts +0 -66
  299. package/tests/proxied/notif.test.ts +0 -85
  300. package/tests/proxied/procedures.test.ts +0 -175
  301. package/tests/proxied/proxy-catchall.test.ts +0 -256
  302. package/tests/proxied/proxy-header.test.ts +0 -239
  303. package/tests/proxied/proxy-oauth-aud.test.ts +0 -182
  304. package/tests/proxied/read-after-write.test.ts +0 -382
  305. package/tests/proxied/views.test.ts +0 -608
  306. package/tests/races.test.ts +0 -89
  307. package/tests/rate-limits.test.ts +0 -70
  308. package/tests/recovery.test.ts +0 -180
  309. package/tests/seeds/basic.ts +0 -165
  310. package/tests/seeds/follows.ts +0 -57
  311. package/tests/seeds/likes.ts +0 -14
  312. package/tests/seeds/reposts.ts +0 -18
  313. package/tests/seeds/thread.ts +0 -40
  314. package/tests/seeds/users-bulk.ts +0 -246
  315. package/tests/seeds/users.ts +0 -67
  316. package/tests/sequencer.test.ts +0 -251
  317. package/tests/server.test.ts +0 -151
  318. package/tests/sync/invertible-ops.test.ts +0 -99
  319. package/tests/sync/list.test.ts +0 -43
  320. package/tests/sync/subscribe-repos.test.ts +0 -672
  321. package/tests/sync/sync.test.ts +0 -316
  322. package/tests/takedown-appeal.test.ts +0 -166
  323. package/tsconfig.build.json +0 -9
  324. package/tsconfig.build.tsbuildinfo +0 -1
  325. package/tsconfig.json +0 -7
  326. 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
- }