@atproto/pds 0.5.6 → 0.5.8

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 (243) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/background.d.ts +12 -6
  3. package/dist/background.d.ts.map +1 -1
  4. package/dist/background.js +32 -13
  5. package/dist/background.js.map +1 -1
  6. package/dist/context.d.ts.map +1 -1
  7. package/dist/context.js +4 -31
  8. package/dist/context.js.map +1 -1
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +33 -11
  12. package/dist/index.js.map +1 -1
  13. package/dist/lexicons/app/bsky/authFullApp.defs.d.ts.map +1 -1
  14. package/dist/lexicons/app/bsky/authFullApp.defs.js +1 -0
  15. package/dist/lexicons/app/bsky/authFullApp.defs.js.map +1 -1
  16. package/dist/lexicons/app/bsky/authViewAll.defs.d.ts.map +1 -1
  17. package/dist/lexicons/app/bsky/authViewAll.defs.js +1 -0
  18. package/dist/lexicons/app/bsky/authViewAll.defs.js.map +1 -1
  19. package/dist/lexicons/app/bsky/feed/searchPostsV2.d.ts +3 -0
  20. package/dist/lexicons/app/bsky/feed/searchPostsV2.d.ts.map +1 -0
  21. package/dist/lexicons/app/bsky/feed/searchPostsV2.defs.d.ts +158 -0
  22. package/dist/lexicons/app/bsky/feed/searchPostsV2.defs.d.ts.map +1 -0
  23. package/dist/lexicons/app/bsky/feed/searchPostsV2.defs.js +74 -0
  24. package/dist/lexicons/app/bsky/feed/searchPostsV2.defs.js.map +1 -0
  25. package/dist/lexicons/app/bsky/feed/searchPostsV2.js +6 -0
  26. package/dist/lexicons/app/bsky/feed/searchPostsV2.js.map +1 -0
  27. package/dist/lexicons/app/bsky/feed.d.ts +1 -0
  28. package/dist/lexicons/app/bsky/feed.d.ts.map +1 -1
  29. package/dist/lexicons/app/bsky/feed.js +1 -0
  30. package/dist/lexicons/app/bsky/feed.js.map +1 -1
  31. package/dist/lexicons/app/bsky/notification/defs.defs.d.ts +5 -0
  32. package/dist/lexicons/app/bsky/notification/defs.defs.d.ts.map +1 -1
  33. package/dist/lexicons/app/bsky/notification/defs.defs.js +1 -0
  34. package/dist/lexicons/app/bsky/notification/defs.defs.js.map +1 -1
  35. package/dist/lexicons/chat/bsky/actor/declaration.defs.d.ts +1 -1
  36. package/dist/lexicons/chat/bsky/actor/declaration.defs.js.map +1 -1
  37. package/dist/lexicons/chat/bsky/actor/defs.defs.d.ts +4 -6
  38. package/dist/lexicons/chat/bsky/actor/defs.defs.d.ts.map +1 -1
  39. package/dist/lexicons/chat/bsky/actor/defs.defs.js +2 -3
  40. package/dist/lexicons/chat/bsky/actor/defs.defs.js.map +1 -1
  41. package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts +64 -70
  42. package/dist/lexicons/chat/bsky/convo/defs.defs.d.ts.map +1 -1
  43. package/dist/lexicons/chat/bsky/convo/defs.defs.js +32 -35
  44. package/dist/lexicons/chat/bsky/convo/defs.defs.js.map +1 -1
  45. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.d.ts +1 -1
  46. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.d.ts.map +1 -1
  47. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.js +1 -1
  48. package/dist/lexicons/chat/bsky/convo/getUnreadCounts.defs.js.map +1 -1
  49. package/dist/lexicons/chat/bsky/convo/listConvoRequests.defs.d.ts +1 -1
  50. package/dist/lexicons/chat/bsky/convo/listConvoRequests.defs.d.ts.map +1 -1
  51. package/dist/lexicons/chat/bsky/convo/listConvoRequests.defs.js +1 -1
  52. package/dist/lexicons/chat/bsky/convo/listConvoRequests.defs.js.map +1 -1
  53. package/dist/lexicons/chat/bsky/convo/lockConvo.defs.d.ts +1 -1
  54. package/dist/lexicons/chat/bsky/convo/lockConvo.defs.d.ts.map +1 -1
  55. package/dist/lexicons/chat/bsky/convo/lockConvo.defs.js +1 -1
  56. package/dist/lexicons/chat/bsky/convo/lockConvo.defs.js.map +1 -1
  57. package/dist/lexicons/chat/bsky/convo/unlockConvo.defs.d.ts +1 -1
  58. package/dist/lexicons/chat/bsky/convo/unlockConvo.defs.d.ts.map +1 -1
  59. package/dist/lexicons/chat/bsky/convo/unlockConvo.defs.js +1 -1
  60. package/dist/lexicons/chat/bsky/convo/unlockConvo.defs.js.map +1 -1
  61. package/dist/lexicons/chat/bsky/group/addMembers.defs.d.ts +1 -1
  62. package/dist/lexicons/chat/bsky/group/addMembers.defs.d.ts.map +1 -1
  63. package/dist/lexicons/chat/bsky/group/addMembers.defs.js +1 -1
  64. package/dist/lexicons/chat/bsky/group/addMembers.defs.js.map +1 -1
  65. package/dist/lexicons/chat/bsky/group/approveJoinRequest.defs.d.ts +1 -1
  66. package/dist/lexicons/chat/bsky/group/approveJoinRequest.defs.d.ts.map +1 -1
  67. package/dist/lexicons/chat/bsky/group/approveJoinRequest.defs.js +1 -1
  68. package/dist/lexicons/chat/bsky/group/approveJoinRequest.defs.js.map +1 -1
  69. package/dist/lexicons/chat/bsky/group/createGroup.defs.d.ts +1 -1
  70. package/dist/lexicons/chat/bsky/group/createGroup.defs.d.ts.map +1 -1
  71. package/dist/lexicons/chat/bsky/group/createGroup.defs.js +1 -1
  72. package/dist/lexicons/chat/bsky/group/createGroup.defs.js.map +1 -1
  73. package/dist/lexicons/chat/bsky/group/createJoinLink.defs.d.ts +1 -1
  74. package/dist/lexicons/chat/bsky/group/createJoinLink.defs.d.ts.map +1 -1
  75. package/dist/lexicons/chat/bsky/group/createJoinLink.defs.js +1 -1
  76. package/dist/lexicons/chat/bsky/group/createJoinLink.defs.js.map +1 -1
  77. package/dist/lexicons/chat/bsky/group/disableJoinLink.defs.d.ts +1 -1
  78. package/dist/lexicons/chat/bsky/group/disableJoinLink.defs.d.ts.map +1 -1
  79. package/dist/lexicons/chat/bsky/group/disableJoinLink.defs.js +1 -1
  80. package/dist/lexicons/chat/bsky/group/disableJoinLink.defs.js.map +1 -1
  81. package/dist/lexicons/chat/bsky/group/editGroup.defs.d.ts +1 -1
  82. package/dist/lexicons/chat/bsky/group/editGroup.defs.d.ts.map +1 -1
  83. package/dist/lexicons/chat/bsky/group/editGroup.defs.js +1 -1
  84. package/dist/lexicons/chat/bsky/group/editGroup.defs.js.map +1 -1
  85. package/dist/lexicons/chat/bsky/group/editJoinLink.defs.d.ts +1 -1
  86. package/dist/lexicons/chat/bsky/group/editJoinLink.defs.d.ts.map +1 -1
  87. package/dist/lexicons/chat/bsky/group/editJoinLink.defs.js +1 -1
  88. package/dist/lexicons/chat/bsky/group/editJoinLink.defs.js.map +1 -1
  89. package/dist/lexicons/chat/bsky/group/enableJoinLink.defs.d.ts +1 -1
  90. package/dist/lexicons/chat/bsky/group/enableJoinLink.defs.d.ts.map +1 -1
  91. package/dist/lexicons/chat/bsky/group/enableJoinLink.defs.js +1 -1
  92. package/dist/lexicons/chat/bsky/group/enableJoinLink.defs.js.map +1 -1
  93. package/dist/lexicons/chat/bsky/group/getJoinLinkPreviews.defs.d.ts +1 -1
  94. package/dist/lexicons/chat/bsky/group/getJoinLinkPreviews.defs.d.ts.map +1 -1
  95. package/dist/lexicons/chat/bsky/group/getJoinLinkPreviews.defs.js +1 -1
  96. package/dist/lexicons/chat/bsky/group/getJoinLinkPreviews.defs.js.map +1 -1
  97. package/dist/lexicons/chat/bsky/group/listJoinRequests.defs.d.ts +1 -1
  98. package/dist/lexicons/chat/bsky/group/listJoinRequests.defs.d.ts.map +1 -1
  99. package/dist/lexicons/chat/bsky/group/listJoinRequests.defs.js +1 -1
  100. package/dist/lexicons/chat/bsky/group/listJoinRequests.defs.js.map +1 -1
  101. package/dist/lexicons/chat/bsky/group/listMutualGroups.defs.d.ts +1 -1
  102. package/dist/lexicons/chat/bsky/group/listMutualGroups.defs.d.ts.map +1 -1
  103. package/dist/lexicons/chat/bsky/group/listMutualGroups.defs.js +1 -1
  104. package/dist/lexicons/chat/bsky/group/listMutualGroups.defs.js.map +1 -1
  105. package/dist/lexicons/chat/bsky/group/rejectJoinRequest.defs.d.ts +1 -1
  106. package/dist/lexicons/chat/bsky/group/rejectJoinRequest.defs.d.ts.map +1 -1
  107. package/dist/lexicons/chat/bsky/group/rejectJoinRequest.defs.js +1 -1
  108. package/dist/lexicons/chat/bsky/group/rejectJoinRequest.defs.js.map +1 -1
  109. package/dist/lexicons/chat/bsky/group/removeMembers.defs.d.ts +1 -1
  110. package/dist/lexicons/chat/bsky/group/removeMembers.defs.d.ts.map +1 -1
  111. package/dist/lexicons/chat/bsky/group/removeMembers.defs.js +1 -1
  112. package/dist/lexicons/chat/bsky/group/removeMembers.defs.js.map +1 -1
  113. package/dist/lexicons/chat/bsky/group/requestJoin.defs.d.ts +1 -1
  114. package/dist/lexicons/chat/bsky/group/requestJoin.defs.d.ts.map +1 -1
  115. package/dist/lexicons/chat/bsky/group/requestJoin.defs.js +1 -1
  116. package/dist/lexicons/chat/bsky/group/requestJoin.defs.js.map +1 -1
  117. package/dist/lexicons/chat/bsky/group/updateJoinRequestsRead.defs.d.ts +1 -1
  118. package/dist/lexicons/chat/bsky/group/updateJoinRequestsRead.defs.d.ts.map +1 -1
  119. package/dist/lexicons/chat/bsky/group/updateJoinRequestsRead.defs.js +1 -1
  120. package/dist/lexicons/chat/bsky/group/updateJoinRequestsRead.defs.js.map +1 -1
  121. package/dist/lexicons/chat/bsky/group/withdrawJoinRequest.defs.d.ts +1 -1
  122. package/dist/lexicons/chat/bsky/group/withdrawJoinRequest.defs.d.ts.map +1 -1
  123. package/dist/lexicons/chat/bsky/group/withdrawJoinRequest.defs.js +1 -1
  124. package/dist/lexicons/chat/bsky/group/withdrawJoinRequest.defs.js.map +1 -1
  125. package/dist/lexicons/chat/bsky/moderation/defs.defs.d.ts +6 -6
  126. package/dist/lexicons/chat/bsky/moderation/defs.defs.d.ts.map +1 -1
  127. package/dist/lexicons/chat/bsky/moderation/defs.defs.js +3 -3
  128. package/dist/lexicons/chat/bsky/moderation/defs.defs.js.map +1 -1
  129. package/dist/lexicons/chat/bsky/moderation/getConvo.defs.d.ts +1 -1
  130. package/dist/lexicons/chat/bsky/moderation/getConvo.defs.d.ts.map +1 -1
  131. package/dist/lexicons/chat/bsky/moderation/getConvo.defs.js +1 -1
  132. package/dist/lexicons/chat/bsky/moderation/getConvo.defs.js.map +1 -1
  133. package/dist/lexicons/chat/bsky/moderation/getConvoMembers.defs.d.ts +1 -1
  134. package/dist/lexicons/chat/bsky/moderation/getConvoMembers.defs.d.ts.map +1 -1
  135. package/dist/lexicons/chat/bsky/moderation/getConvoMembers.defs.js +1 -1
  136. package/dist/lexicons/chat/bsky/moderation/getConvoMembers.defs.js.map +1 -1
  137. package/dist/lexicons/chat/bsky/moderation/getConvos.defs.d.ts +1 -1
  138. package/dist/lexicons/chat/bsky/moderation/getConvos.defs.d.ts.map +1 -1
  139. package/dist/lexicons/chat/bsky/moderation/getConvos.defs.js +1 -1
  140. package/dist/lexicons/chat/bsky/moderation/getConvos.defs.js.map +1 -1
  141. package/dist/lexicons/chat/bsky/notification/defs.d.ts +2 -0
  142. package/dist/lexicons/chat/bsky/notification/defs.d.ts.map +1 -0
  143. package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts +20 -0
  144. package/dist/lexicons/chat/bsky/notification/defs.defs.d.ts.map +1 -0
  145. package/dist/lexicons/chat/bsky/notification/defs.defs.js +19 -0
  146. package/dist/lexicons/chat/bsky/notification/defs.defs.js.map +1 -0
  147. package/dist/lexicons/chat/bsky/notification/defs.js +5 -0
  148. package/dist/lexicons/chat/bsky/notification/defs.js.map +1 -0
  149. package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts +3 -0
  150. package/dist/lexicons/chat/bsky/notification/getPreferences.d.ts.map +1 -0
  151. package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts +18 -0
  152. package/dist/lexicons/chat/bsky/notification/getPreferences.defs.d.ts.map +1 -0
  153. package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js +16 -0
  154. package/dist/lexicons/chat/bsky/notification/getPreferences.defs.js.map +1 -0
  155. package/dist/lexicons/chat/bsky/notification/getPreferences.js +6 -0
  156. package/dist/lexicons/chat/bsky/notification/getPreferences.js.map +1 -0
  157. package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts +3 -0
  158. package/dist/lexicons/chat/bsky/notification/putPreferences.d.ts.map +1 -0
  159. package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts +27 -0
  160. package/dist/lexicons/chat/bsky/notification/putPreferences.defs.d.ts.map +1 -0
  161. package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js +22 -0
  162. package/dist/lexicons/chat/bsky/notification/putPreferences.defs.js.map +1 -0
  163. package/dist/lexicons/chat/bsky/notification/putPreferences.js +6 -0
  164. package/dist/lexicons/chat/bsky/notification/putPreferences.js.map +1 -0
  165. package/dist/lexicons/chat/bsky/notification.d.ts +4 -0
  166. package/dist/lexicons/chat/bsky/notification.d.ts.map +1 -0
  167. package/dist/lexicons/chat/bsky/notification.js +7 -0
  168. package/dist/lexicons/chat/bsky/notification.js.map +1 -0
  169. package/dist/lexicons/chat/bsky.d.ts +1 -0
  170. package/dist/lexicons/chat/bsky.d.ts.map +1 -1
  171. package/dist/lexicons/chat/bsky.js +1 -0
  172. package/dist/lexicons/chat/bsky.js.map +1 -1
  173. package/dist/lexicons/tools/ozone/report/defs.defs.d.ts +4 -0
  174. package/dist/lexicons/tools/ozone/report/defs.defs.d.ts.map +1 -1
  175. package/dist/lexicons/tools/ozone/report/defs.defs.js +2 -0
  176. package/dist/lexicons/tools/ozone/report/defs.defs.js.map +1 -1
  177. package/dist/lexicons/tools/ozone/report/queryActivities.d.ts +3 -0
  178. package/dist/lexicons/tools/ozone/report/queryActivities.d.ts.map +1 -0
  179. package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts +42 -0
  180. package/dist/lexicons/tools/ozone/report/queryActivities.defs.d.ts.map +1 -0
  181. package/dist/lexicons/tools/ozone/report/queryActivities.defs.js +31 -0
  182. package/dist/lexicons/tools/ozone/report/queryActivities.defs.js.map +1 -0
  183. package/dist/lexicons/tools/ozone/report/queryActivities.js +6 -0
  184. package/dist/lexicons/tools/ozone/report/queryActivities.js.map +1 -0
  185. package/dist/lexicons/tools/ozone/report.d.ts +1 -0
  186. package/dist/lexicons/tools/ozone/report.d.ts.map +1 -1
  187. package/dist/lexicons/tools/ozone/report.js +1 -0
  188. package/dist/lexicons/tools/ozone/report.js.map +1 -1
  189. package/dist/pipethrough.d.ts +3 -0
  190. package/dist/pipethrough.d.ts.map +1 -1
  191. package/dist/pipethrough.js +32 -0
  192. package/dist/pipethrough.js.map +1 -1
  193. package/package.json +13 -13
  194. package/src/background.ts +49 -18
  195. package/src/context.ts +4 -37
  196. package/src/index.ts +31 -13
  197. package/src/pipethrough.ts +38 -1
  198. package/tests/_util.ts +8 -25
  199. package/tests/account-deactivation.test.ts +3 -2
  200. package/tests/account-deletion.test.ts +1 -1
  201. package/tests/account-migration.test.ts +2 -2
  202. package/tests/account-status.test.ts +1 -1
  203. package/tests/account.test.ts +1 -1
  204. package/tests/app-passwords.test.ts +1 -1
  205. package/tests/auth.test.ts +1 -1
  206. package/tests/blob-deletes.test.ts +5 -4
  207. package/tests/create-post.test.ts +1 -1
  208. package/tests/crud.test.ts +1 -1
  209. package/tests/db.test.ts +1 -1
  210. package/tests/email-confirmation.test.ts +1 -1
  211. package/tests/file-uploads.test.ts +2 -2
  212. package/tests/get-service-auth.test.ts +1 -1
  213. package/tests/handles.test.ts +1 -1
  214. package/tests/invite-codes.test.ts +1 -1
  215. package/tests/invites-admin.test.ts +5 -4
  216. package/tests/moderation.test.ts +1 -1
  217. package/tests/moderator-auth.test.ts +1 -1
  218. package/tests/plc-operations.test.ts +3 -2
  219. package/tests/preferences.test.ts +1 -1
  220. package/tests/proxied/admin.test.ts +3 -2
  221. package/tests/proxied/feedgen.test.ts +1 -1
  222. package/tests/proxied/notif.test.ts +6 -13
  223. package/tests/proxied/procedures.test.ts +5 -4
  224. package/tests/proxied/proxy-catchall.test.ts +9 -8
  225. package/tests/proxied/proxy-header.test.ts +14 -9
  226. package/tests/proxied/proxy-oauth-aud.test.ts +17 -10
  227. package/tests/proxied/read-after-write.test.ts +7 -7
  228. package/tests/proxied/views.test.ts +6 -5
  229. package/tests/races.test.ts +1 -1
  230. package/tests/rate-limits.test.ts +1 -1
  231. package/tests/recovery.test.ts +1 -1
  232. package/tests/seeds/basic.ts +2 -2
  233. package/tests/seeds/follows.ts +1 -1
  234. package/tests/seeds/users-bulk.ts +2 -1
  235. package/tests/seeds/users.ts +5 -2
  236. package/tests/sequencer.test.ts +6 -4
  237. package/tests/server.test.ts +11 -13
  238. package/tests/sync/invertible-ops.test.ts +4 -1
  239. package/tests/sync/list.test.ts +1 -1
  240. package/tests/sync/subscribe-repos.test.ts +7 -6
  241. package/tests/sync/sync.test.ts +2 -2
  242. package/tests/takedown-appeal.test.ts +3 -2
  243. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,7 +1,7 @@
1
1
  import { IncomingHttpHeaders, ServerResponse } from 'node:http'
2
2
  import { PassThrough, Readable, finished } from 'node:stream'
3
3
  import { Request } from 'express'
4
- import { Dispatcher } from 'undici'
4
+ import { Agent, Dispatcher, Pool, interceptors } from 'undici'
5
5
  import {
6
6
  decodeStream,
7
7
  getServiceEndpoint,
@@ -20,12 +20,49 @@ import {
20
20
  excludeErrorResult,
21
21
  parseReqNsid,
22
22
  } from '@atproto/xrpc-server'
23
+ import { isUnicastIp, unicastLookup } from '@atproto-labs/fetch-node'
23
24
  import { buildProxiedContentEncoding } from '@atproto-labs/xrpc-utils'
24
25
  import { isAccessPrivileged } from './auth-scope.js'
26
+ import { ProxyConfig } from './config/config.js'
25
27
  import { AppContext } from './context.js'
26
28
  import { chat, com, tools } from './lexicons/index.js'
27
29
  import { httpLogger } from './logger.js'
28
30
 
31
+ export function buildProxyAgent(cfg: ProxyConfig): Dispatcher {
32
+ const agent = new Agent({
33
+ allowH2: cfg.allowHTTP2,
34
+ headersTimeout: cfg.headersTimeout,
35
+ maxResponseSize: cfg.maxResponseSize,
36
+ bodyTimeout: cfg.bodyTimeout,
37
+ factory: cfg.disableSsrfProtection
38
+ ? undefined
39
+ : (origin, opts) => {
40
+ const { protocol, hostname } =
41
+ origin instanceof URL ? origin : new URL(origin)
42
+ if (protocol !== 'https:') {
43
+ throw new Error(`Forbidden protocol "${protocol}"`)
44
+ }
45
+ if (isUnicastIp(hostname) === false) {
46
+ throw new Error('Hostname resolved to non-unicast address')
47
+ }
48
+ return new Pool(origin, opts)
49
+ },
50
+ connect: {
51
+ lookup: cfg.disableSsrfProtection ? undefined : unicastLookup,
52
+ },
53
+ })
54
+
55
+ return agent.compose(
56
+ cfg.maxRetries > 0
57
+ ? interceptors.retry({
58
+ statusCodes: [], // Only retry on socket errors
59
+ methods: ['GET', 'HEAD'],
60
+ maxRetries: cfg.maxRetries,
61
+ })
62
+ : (dispatch) => dispatch,
63
+ )
64
+ }
65
+
29
66
  export const proxyHandler = (ctx: AppContext): CatchallHandler => {
30
67
  const performAuth = ctx.authVerifier.authorization<RpcPermissionMatch>({
31
68
  authorize: (permissions, { params }) => permissions.assertRpc(params),
package/tests/_util.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { Server } from 'node:http'
1
+ import { RequestListener, createServer } from 'node:http'
2
2
  import { AddressInfo } from 'node:net'
3
- import { type Express } from 'express'
3
+ // eslint-disable-next-line import/default
4
+ import httpTerminator from 'http-terminator'
4
5
  import { ToolsOzoneModerationDefs, lexToJson } from '@atproto/api'
5
6
  import { isCidString } from '@atproto/lex'
6
7
  import { isCid, isPlainObject } from '@atproto/lex-data'
@@ -146,19 +147,11 @@ export const paginateAll = async <T extends { cursor?: string }>(
146
147
  return results
147
148
  }
148
149
 
149
- export async function startServer(app: Express) {
150
- return new Promise<{
151
- origin: string
152
- server: Server
153
- stop: () => Promise<void>
154
- }>((resolve, reject) => {
150
+ export async function startServer(listener: RequestListener) {
151
+ return new Promise<AsyncDisposable & { port: number }>((resolve, reject) => {
155
152
  const onListen = () => {
156
153
  const port = (server.address() as AddressInfo).port
157
- resolve({
158
- server,
159
- origin: `http://localhost:${port}`,
160
- stop: () => stopServer(server),
161
- })
154
+ resolve({ port, [Symbol.asyncDispose]: () => terminator.terminate() })
162
155
  cleanup()
163
156
  }
164
157
  const onError = (err: Error) => {
@@ -170,22 +163,12 @@ export async function startServer(app: Express) {
170
163
  server.removeListener('error', onError)
171
164
  }
172
165
 
173
- const server = app
166
+ const server = createServer(listener)
174
167
  .listen(0)
175
168
  .once('listening', onListen)
176
169
  .once('error', onError)
177
- })
178
- }
179
170
 
180
- export async function stopServer(server: Server) {
181
- return new Promise<void>((resolve, reject) => {
182
- server.close((err) => {
183
- if (err) {
184
- reject(err)
185
- } else {
186
- resolve()
187
- }
188
- })
171
+ const terminator = httpTerminator.createHttpTerminator({ server })
189
172
  })
190
173
  }
191
174
 
@@ -5,6 +5,7 @@ import {
5
5
  TestNetworkNoAppView,
6
6
  basicSeed,
7
7
  } from '@atproto/dev-env'
8
+ import type { DidString } from '@atproto/syntax'
8
9
 
9
10
  describe('account deactivation', () => {
10
11
  let network: TestNetworkNoAppView
@@ -12,7 +13,7 @@ describe('account deactivation', () => {
12
13
  let sc: SeedClient
13
14
  let agent: AtpAgent
14
15
 
15
- let alice: string
16
+ let alice: DidString
16
17
  let aliceAvatar: ImageRef
17
18
 
18
19
  beforeAll(async () => {
@@ -39,7 +40,7 @@ describe('account deactivation', () => {
39
40
  })
40
41
 
41
42
  afterAll(async () => {
42
- await network.close()
43
+ await network?.close()
43
44
  })
44
45
 
45
46
  it('deactivates account', async () => {
@@ -57,7 +57,7 @@ describe('account deletion', () => {
57
57
 
58
58
  afterAll(async () => {
59
59
  mailer.transporter.sendMail = _origSendMail
60
- await network.close()
60
+ await network?.close()
61
61
  })
62
62
 
63
63
  const getMailFrom = async (promise): Promise<Mail.Options> => {
@@ -71,8 +71,8 @@ describe('account migration', () => {
71
71
  })
72
72
 
73
73
  afterAll(async () => {
74
- await newPds.close()
75
- await network.close()
74
+ await newPds?.close()
75
+ await network?.close()
76
76
  })
77
77
 
78
78
  it('migrates an account', async () => {
@@ -19,7 +19,7 @@ describe('account-status', () => {
19
19
  })
20
20
 
21
21
  afterAll(async () => {
22
- await network.close()
22
+ await network?.close()
23
23
  })
24
24
 
25
25
  it('takedown + activation triggers an error', async () => {
@@ -60,7 +60,7 @@ describe('account', () => {
60
60
 
61
61
  afterAll(async () => {
62
62
  mailer.transporter.sendMail = _origSendMail
63
- await network.close()
63
+ await network?.close()
64
64
  })
65
65
 
66
66
  it('serves the accounts system config', async () => {
@@ -24,7 +24,7 @@ describe('app_passwords', () => {
24
24
  })
25
25
 
26
26
  afterAll(async () => {
27
- await network.close()
27
+ await network?.close()
28
28
  })
29
29
 
30
30
  let appPass: string
@@ -16,7 +16,7 @@ describe('auth', () => {
16
16
  })
17
17
 
18
18
  afterAll(async () => {
19
- await network.close()
19
+ await network?.close()
20
20
  })
21
21
 
22
22
  const createAccount = async (info) => {
@@ -1,5 +1,6 @@
1
1
  import { AtpAgent, BlobRef } from '@atproto/api'
2
2
  import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env'
3
+ import type { DidString } from '@atproto/syntax'
3
4
  import { AppContext } from '../src/index.js'
4
5
 
5
6
  describe('blob deletes', () => {
@@ -9,8 +10,8 @@ describe('blob deletes', () => {
9
10
 
10
11
  let ctx: AppContext
11
12
 
12
- let alice: string
13
- let bob: string
13
+ let alice: DidString
14
+ let bob: DidString
14
15
 
15
16
  beforeAll(async () => {
16
17
  network = await TestNetworkNoAppView.create({
@@ -35,7 +36,7 @@ describe('blob deletes', () => {
35
36
  })
36
37
 
37
38
  afterAll(async () => {
38
- await network.close()
39
+ await network?.close()
39
40
  })
40
41
 
41
42
  const getDbBlobsForDid = (did: string) => {
@@ -184,7 +185,7 @@ describe('blob deletes', () => {
184
185
 
185
186
  async function updateProfile(
186
187
  sc: SeedClient,
187
- did: string,
188
+ did: DidString,
188
189
  avatar?: BlobRef,
189
190
  banner?: BlobRef,
190
191
  ) {
@@ -25,7 +25,7 @@ describe('pds posts record creation', () => {
25
25
  })
26
26
 
27
27
  afterAll(async () => {
28
- await network.close()
28
+ await network?.close()
29
29
  })
30
30
 
31
31
  it('allows for creating posts with tags', async () => {
@@ -47,7 +47,7 @@ describe('crud operations', () => {
47
47
  })
48
48
 
49
49
  afterAll(async () => {
50
- await network.close()
50
+ await network?.close()
51
51
  })
52
52
 
53
53
  it('registers users', async () => {
package/tests/db.test.ts CHANGED
@@ -14,7 +14,7 @@ describe('db', () => {
14
14
  })
15
15
 
16
16
  afterAll(async () => {
17
- await network.close()
17
+ await network?.close()
18
18
  })
19
19
 
20
20
  it('commits changes', async () => {
@@ -42,7 +42,7 @@ describe('email confirmation', () => {
42
42
 
43
43
  afterAll(async () => {
44
44
  mailer.transporter.sendMail = _origSendMail
45
- await network.close()
45
+ await network?.close()
46
46
  })
47
47
 
48
48
  const getMailFrom = async (promise): Promise<SendMailOptions> => {
@@ -41,8 +41,8 @@ describe('file uploads', () => {
41
41
  })
42
42
 
43
43
  afterAll(async () => {
44
- aliceDb.close()
45
- await network.close()
44
+ aliceDb?.close()
45
+ await network?.close()
46
46
  })
47
47
 
48
48
  let smallBlob: TypedBlobRef
@@ -23,7 +23,7 @@ describe('com.atproto.server.getServiceAuth', () => {
23
23
  })
24
24
 
25
25
  afterAll(async () => {
26
- await network.close()
26
+ await network?.close()
27
27
  })
28
28
 
29
29
  it('issues a token whose aud matches a bare-DID input', async () => {
@@ -60,7 +60,7 @@ describe('handles', () => {
60
60
  })
61
61
 
62
62
  afterAll(async () => {
63
- await network.close()
63
+ await network?.close()
64
64
  })
65
65
 
66
66
  const getHandleFromDb = async (
@@ -26,7 +26,7 @@ describe('account', () => {
26
26
  })
27
27
 
28
28
  afterAll(async () => {
29
- await network.close()
29
+ await network?.close()
30
30
  })
31
31
 
32
32
  it('describes the fact that invites are required', async () => {
@@ -1,6 +1,7 @@
1
1
  import { AtpAgent } from '@atproto/api'
2
2
  import { randomStr } from '@atproto/crypto'
3
3
  import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env'
4
+ import type { DidString } from '@atproto/syntax'
4
5
 
5
6
  describe('pds admin invite views', () => {
6
7
  let network: TestNetworkNoAppView
@@ -20,12 +21,12 @@ describe('pds admin invite views', () => {
20
21
  })
21
22
 
22
23
  afterAll(async () => {
23
- await network.close()
24
+ await network?.close()
24
25
  })
25
26
 
26
- let alice: string
27
- let bob: string
28
- let carol: string
27
+ let alice: DidString
28
+ let bob: DidString
29
+ let carol: DidString
29
30
 
30
31
  beforeAll(async () => {
31
32
  const adminCode = await agent.api.com.atproto.server.createInviteCode(
@@ -47,7 +47,7 @@ describe('moderation', () => {
47
47
  })
48
48
 
49
49
  afterAll(async () => {
50
- await network.close()
50
+ await network?.close()
51
51
  })
52
52
 
53
53
  it('takes down accounts', async () => {
@@ -71,7 +71,7 @@ describe('moderator auth', () => {
71
71
  }, 20_000) // @NOTE seeding can take a while
72
72
 
73
73
  afterAll(async () => {
74
- await network.close()
74
+ await network?.close()
75
75
  })
76
76
 
77
77
  it('allows service auth requests from the configured appview did', async () => {
@@ -6,6 +6,7 @@ import { AtpAgent } from '@atproto/api'
6
6
  import { check } from '@atproto/common'
7
7
  import { Secp256k1Keypair } from '@atproto/crypto'
8
8
  import { SeedClient, TestNetworkNoAppView, basicSeed } from '@atproto/dev-env'
9
+ import type { DidString } from '@atproto/syntax'
9
10
  import { AppContext } from '../src/index.js'
10
11
 
11
12
  describe('plc operations', () => {
@@ -17,7 +18,7 @@ describe('plc operations', () => {
17
18
  const mailCatcher = new EventEmitter()
18
19
  let _origSendMail
19
20
 
20
- let alice: string
21
+ let alice: DidString
21
22
 
22
23
  let sampleKey: string
23
24
 
@@ -48,7 +49,7 @@ describe('plc operations', () => {
48
49
  })
49
50
 
50
51
  afterAll(async () => {
51
- await network.close()
52
+ await network?.close()
52
53
  })
53
54
 
54
55
  const getMailFrom = async (promise): Promise<SendMailOptions> => {
@@ -29,7 +29,7 @@ describe('user preferences', () => {
29
29
  }, 20_000) // @NOTE seeding can take a while
30
30
 
31
31
  afterAll(async () => {
32
- await network.close()
32
+ await network?.close()
33
33
  })
34
34
 
35
35
  it('requires auth to set or put preferences.', async () => {
@@ -1,5 +1,6 @@
1
1
  import { AtpAgent } from '@atproto/api'
2
2
  import { SeedClient, TestNetwork } from '@atproto/dev-env'
3
+ import type { DidString } from '@atproto/syntax'
3
4
  import { forSnapshot } from '../_util.js'
4
5
  import basicSeed from '../seeds/basic.js'
5
6
 
@@ -8,7 +9,7 @@ describe('proxies admin requests', () => {
8
9
  let agent: AtpAgent
9
10
  let sc: SeedClient
10
11
 
11
- let moderator: string
12
+ let moderator: DidString
12
13
 
13
14
  beforeAll(async () => {
14
15
  network = await TestNetwork.create({
@@ -69,7 +70,7 @@ describe('proxies admin requests', () => {
69
70
  })
70
71
 
71
72
  afterAll(async () => {
72
- await network.close()
73
+ await network?.close()
73
74
  })
74
75
 
75
76
  it('creates reports of a repo.', async () => {
@@ -51,7 +51,7 @@ describe('feedgen proxy view', () => {
51
51
  })
52
52
 
53
53
  afterAll(async () => {
54
- await network.close()
54
+ await network?.close()
55
55
  })
56
56
 
57
57
  it('performs basic proxy of getFeed', async () => {
@@ -1,16 +1,13 @@
1
- import { once } from 'node:events'
2
- import http from 'node:http'
3
- import { AddressInfo } from 'node:net'
4
- import express from 'express'
5
1
  import { AtpAgent } from '@atproto/api'
6
2
  import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env'
7
3
  import { createServer, verifyJwt } from '@atproto/xrpc-server'
8
4
  import { app } from '../../src/lexicons/index.js'
5
+ import { startServer } from '../_util.js'
9
6
  import usersSeed from '../seeds/users.js'
10
7
 
11
8
  describe('notif service proxy', () => {
12
9
  let network: TestNetworkNoAppView
13
- let notifServer: http.Server
10
+ let notifServer: AsyncDisposable & { port: number }
14
11
  let notifDid: string
15
12
  let agent: AtpAgent
16
13
  let sc: SeedClient
@@ -29,10 +26,9 @@ describe('notif service proxy', () => {
29
26
  notifServer = await createMockNotifService(spy)
30
27
  notifDid = sc.dids.dan
31
28
  await plc.updateData(notifDid, network.pds.ctx.plcRotationKey, (x) => {
32
- const addr = notifServer.address() as AddressInfo
33
29
  x.services['bsky_notif'] = {
34
30
  type: 'BskyNotificationService',
35
- endpoint: `http://localhost:${addr.port}`,
31
+ endpoint: `http://localhost:${notifServer.port}`,
36
32
  }
37
33
  return x
38
34
  })
@@ -40,9 +36,8 @@ describe('notif service proxy', () => {
40
36
  }, 20_000) // @NOTE seeding can take a while
41
37
 
42
38
  afterAll(async () => {
43
- await network.close()
44
- notifServer.close()
45
- await once(notifServer, 'close')
39
+ await notifServer?.[Symbol.asyncDispose]()
40
+ await network?.close()
46
41
  })
47
42
 
48
43
  it('proxies to notif service.', async () => {
@@ -86,7 +81,5 @@ async function createMockNotifService(ref: { current: unknown }) {
86
81
  jwt: req.headers.authorization?.replace('Bearer ', ''),
87
82
  }
88
83
  })
89
- const server = express().use(svc.router).listen()
90
- await once(server, 'listening')
91
- return server
84
+ return startServer(svc.router)
92
85
  }
@@ -1,5 +1,6 @@
1
1
  import { AtpAgent } from '@atproto/api'
2
2
  import { SeedClient, TestNetwork } from '@atproto/dev-env'
3
+ import type { DidString } from '@atproto/syntax'
3
4
  import basicSeed from '../seeds/basic.js'
4
5
 
5
6
  describe('proxies appview procedures', () => {
@@ -7,9 +8,9 @@ describe('proxies appview procedures', () => {
7
8
  let agent: AtpAgent
8
9
  let sc: SeedClient
9
10
 
10
- let alice: string
11
- let bob: string
12
- let carol: string
11
+ let alice: DidString
12
+ let bob: DidString
13
+ let carol: DidString
13
14
 
14
15
  beforeAll(async () => {
15
16
  network = await TestNetwork.create({
@@ -25,7 +26,7 @@ describe('proxies appview procedures', () => {
25
26
  })
26
27
 
27
28
  afterAll(async () => {
28
- await network.close()
29
+ await network?.close()
29
30
  })
30
31
 
31
32
  it('maintains muted actors.', async () => {
@@ -4,6 +4,8 @@ import { AddressInfo } from 'node:net'
4
4
  import { setTimeout as sleep } from 'node:timers/promises'
5
5
  import * as plc from '@did-plc/lib'
6
6
  import express from 'express'
7
+ // eslint-disable-next-line import/default
8
+ import httpTerminator from 'http-terminator'
7
9
  import AtpAgent from '@atproto/api'
8
10
  import { Keypair } from '@atproto/crypto'
9
11
  import { TestNetworkNoAppView } from '@atproto/dev-env'
@@ -158,10 +160,14 @@ describe('proxy header', () => {
158
160
  })
159
161
 
160
162
  class ProxyServer {
163
+ private terminator: httpTerminator.HttpTerminator
164
+
161
165
  constructor(
162
- private server: http.Server,
166
+ server: http.Server,
163
167
  public did: string,
164
- ) {}
168
+ ) {
169
+ this.terminator = httpTerminator.createHttpTerminator({ server })
170
+ }
165
171
 
166
172
  static async create(
167
173
  plcClient: plc.Client,
@@ -245,11 +251,6 @@ class ProxyServer {
245
251
  }
246
252
 
247
253
  async close() {
248
- await new Promise<void>((resolve, reject) => {
249
- this.server.close((err) => {
250
- if (err) reject(err)
251
- else resolve()
252
- })
253
- })
254
+ await this.terminator.terminate()
254
255
  }
255
256
  }
@@ -4,8 +4,11 @@ import http from 'node:http'
4
4
  import { AddressInfo } from 'node:net'
5
5
  import * as plc from '@did-plc/lib'
6
6
  import express from 'express'
7
+ // eslint-disable-next-line import/default
8
+ import httpTerminator from 'http-terminator'
7
9
  import { Keypair } from '@atproto/crypto'
8
10
  import { SeedClient, TestNetworkNoAppView, usersSeed } from '@atproto/dev-env'
11
+ import type { DidString } from '@atproto/syntax'
9
12
  import { verifyJwt } from '@atproto/xrpc-server'
10
13
  import { parseProxyHeader } from '../../src/pipethrough.js'
11
14
 
@@ -13,7 +16,7 @@ describe('proxy header', () => {
13
16
  let network: TestNetworkNoAppView
14
17
  let sc: SeedClient
15
18
 
16
- let alice: string
19
+ let alice: DidString
17
20
 
18
21
  let proxyServer: ProxyServer
19
22
 
@@ -35,8 +38,8 @@ describe('proxy header', () => {
35
38
  }, 20_000) // @NOTE seeding can take a while
36
39
 
37
40
  afterAll(async () => {
38
- await proxyServer.close()
39
- await network.close()
41
+ await proxyServer?.close()
42
+ await network?.close()
40
43
  })
41
44
 
42
45
  it('parses proxy header', async () => {
@@ -171,12 +174,16 @@ type ProxyReq = {
171
174
  }
172
175
 
173
176
  class ProxyServer {
177
+ private terminator: httpTerminator.HttpTerminator
178
+
174
179
  constructor(
175
- public server: http.Server,
180
+ server: http.Server,
176
181
  public url: string,
177
182
  public did: string,
178
183
  public requests: ProxyReq[],
179
- ) {}
184
+ ) {
185
+ this.terminator = httpTerminator.createHttpTerminator({ server })
186
+ }
180
187
 
181
188
  static async create(
182
189
  plcClient: plc.Client,
@@ -226,9 +233,7 @@ class ProxyServer {
226
233
  return new ProxyServer(server, url, did, requests)
227
234
  }
228
235
 
229
- close(): Promise<void> {
230
- return new Promise<void>((resolve) => {
231
- this.server.close(() => resolve())
232
- })
236
+ async close(): Promise<void> {
237
+ await this.terminator.terminate()
233
238
  }
234
239
  }