[READ ONLY MIRROR] Spark Social AppView Server github.com/sprksocial/server
atproto deno hono lexicon
5
fork

Configure Feed

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

add dev env and infra from bsky/atproto

+10222
+1459
services/dev-env/CHANGELOG.md
··· 1 + # @atproto/dev-env 2 + 3 + ## 0.3.97 4 + 5 + ### Patch Changes 6 + 7 + - Updated dependencies [[`d4e14b7bd`](https://github.com/bluesky-social/atproto/commit/d4e14b7bdc7752476757ecfe96343d146411b784), [`99e2809ca`](https://github.com/bluesky-social/atproto/commit/99e2809ca2ebf70acaa10254f140a8dd0fad4305), [`11d8d21be`](https://github.com/bluesky-social/atproto/commit/11d8d21beac4b79ac44b930197761f9d08dbb492), [`27b0a7be1`](https://github.com/bluesky-social/atproto/commit/27b0a7be1ed1b6e098114791d84ec9dc844db552), [`11d8d21be`](https://github.com/bluesky-social/atproto/commit/11d8d21beac4b79ac44b930197761f9d08dbb492), [`5cce76670`](https://github.com/bluesky-social/atproto/commit/5cce7667058981561340107e0124093203e796e3)]: 8 + - @atproto/pds@0.4.104 9 + - @atproto/api@0.14.7 10 + - @atproto/bsky@0.0.124 11 + - @atproto/ozone@0.1.86 12 + 13 + ## 0.3.96 14 + 15 + ### Patch Changes 16 + 17 + - Updated dependencies [[`82d5a2d36`](https://github.com/bluesky-social/atproto/commit/82d5a2d3617c40caab7a18e46c709c4b3c48e7f8)]: 18 + - @atproto/pds@0.4.103 19 + - @atproto/bsky@0.0.123 20 + - @atproto/ozone@0.1.85 21 + 22 + ## 0.3.95 23 + 24 + ### Patch Changes 25 + 26 + - Updated dependencies [[`44f81f2eb`](https://github.com/bluesky-social/atproto/commit/44f81f2eb9229e21aec4472b3a05e855396dbec5)]: 27 + - @atproto/api@0.14.6 28 + - @atproto/bsky@0.0.123 29 + - @atproto/ozone@0.1.85 30 + - @atproto/pds@0.4.102 31 + 32 + ## 0.3.94 33 + 34 + ### Patch Changes 35 + 36 + - Updated dependencies [[`7e3678c08`](https://github.com/bluesky-social/atproto/commit/7e3678c089d2faa1a884a52a4fb80b8116c9854f), [`9b643fbec`](https://github.com/bluesky-social/atproto/commit/9b643fbecac30de5cfdb80d0671bfa55e9f4512a), [`6e382f67a`](https://github.com/bluesky-social/atproto/commit/6e382f67aa73532efadfea80ff96a27b526cb178)]: 37 + - @atproto/api@0.14.5 38 + - @atproto/pds@0.4.101 39 + - @atproto/ozone@0.1.84 40 + - @atproto/bsky@0.0.122 41 + - @atproto/sync@0.1.15 42 + 43 + ## 0.3.93 44 + 45 + ### Patch Changes 46 + 47 + - Updated dependencies [[`b9cb049d9`](https://github.com/bluesky-social/atproto/commit/b9cb049d940cc706681142ef498238f74e2f539c)]: 48 + - @atproto/ozone@0.1.83 49 + - @atproto/api@0.14.4 50 + - @atproto/pds@0.4.100 51 + - @atproto/bsky@0.0.121 52 + 53 + ## 0.3.92 54 + 55 + ### Patch Changes 56 + 57 + - Updated dependencies [[`22af31a89`](https://github.com/bluesky-social/atproto/commit/22af31a898476c5e317aea263af366bddda120d6), [`01874c4be`](https://github.com/bluesky-social/atproto/commit/01874c4be73a41ffb8fe28378f674949aa2c938f)]: 58 + - @atproto/api@0.14.3 59 + - @atproto/bsky@0.0.120 60 + - @atproto/ozone@0.1.82 61 + - @atproto/pds@0.4.99 62 + 63 + ## 0.3.91 64 + 65 + ### Patch Changes 66 + 67 + - Updated dependencies [[`7449f8607`](https://github.com/bluesky-social/atproto/commit/7449f8607c1be948a0b55611c21075757c3d7261)]: 68 + - @atproto/ozone@0.1.81 69 + 70 + ## 0.3.90 71 + 72 + ### Patch Changes 73 + 74 + - Updated dependencies [[`010f10c6f`](https://github.com/bluesky-social/atproto/commit/010f10c6f212f699ad42c0349a58bbcf2172e3cc), [`a9887f687`](https://github.com/bluesky-social/atproto/commit/a9887f68778c49932d92cfea98aadcfa4d5b62e9)]: 75 + - @atproto/api@0.14.2 76 + - @atproto/ozone@0.1.80 77 + - @atproto/pds@0.4.98 78 + - @atproto/bsky@0.0.119 79 + 80 + ## 0.3.89 81 + 82 + ### Patch Changes 83 + 84 + - Updated dependencies []: 85 + - @atproto/pds@0.4.97 86 + - @atproto/bsky@0.0.118 87 + - @atproto/ozone@0.1.79 88 + 89 + ## 0.3.88 90 + 91 + ### Patch Changes 92 + 93 + - Updated dependencies [[`3f58dd0e7`](https://github.com/bluesky-social/atproto/commit/3f58dd0e742cdfed9c3eae0118bc57f539de78f1), [`20e57bacf`](https://github.com/bluesky-social/atproto/commit/20e57bacf9bb2ae8a118eadbfc291f3213b8dc2f), [`ba5bb6e66`](https://github.com/bluesky-social/atproto/commit/ba5bb6e667fb58bbefd332844957de575e102ca3), [`6ea9c961a`](https://github.com/bluesky-social/atproto/commit/6ea9c961af964cd9b0d00b5073c695c5e0b3345a)]: 94 + - @atproto/bsky@0.0.118 95 + - @atproto/ozone@0.1.79 96 + - @atproto/api@0.14.1 97 + - @atproto/pds@0.4.96 98 + 99 + ## 0.3.87 100 + 101 + ### Patch Changes 102 + 103 + - Updated dependencies [[`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c), [`c53d943c8`](https://github.com/bluesky-social/atproto/commit/c53d943c8be5b8886254e020970a68c0f745b14c)]: 104 + - @atproto/api@0.14.0 105 + - @atproto/ozone@0.1.78 106 + - @atproto/bsky@0.0.117 107 + - @atproto/pds@0.4.95 108 + - @atproto/syntax@0.3.3 109 + - @atproto/lexicon@0.4.7 110 + - @atproto/bsync@0.0.14 111 + - @atproto/sync@0.1.14 112 + - @atproto/xrpc-server@0.7.11 113 + 114 + ## 0.3.86 115 + 116 + ### Patch Changes 117 + 118 + - Updated dependencies [[`709a85b0b`](https://github.com/bluesky-social/atproto/commit/709a85b0b633b5483b7161db64b429c746239153)]: 119 + - @atproto/ozone@0.1.77 120 + - @atproto/api@0.13.35 121 + - @atproto/pds@0.4.94 122 + - @atproto/bsky@0.0.116 123 + 124 + ## 0.3.85 125 + 126 + ### Patch Changes 127 + 128 + - Updated dependencies [[`dc8a7842e`](https://github.com/bluesky-social/atproto/commit/dc8a7842e67f5f3709e88310d2a60d384453b486), [`636951e47`](https://github.com/bluesky-social/atproto/commit/636951e4728cd52c2e5355eb93b47d7e869b67e9), [`dc8a7842e`](https://github.com/bluesky-social/atproto/commit/dc8a7842e67f5f3709e88310d2a60d384453b486)]: 129 + - @atproto/api@0.13.34 130 + - @atproto/bsky@0.0.115 131 + - @atproto/ozone@0.1.76 132 + - @atproto/pds@0.4.93 133 + 134 + ## 0.3.84 135 + 136 + ### Patch Changes 137 + 138 + - [#3220](https://github.com/bluesky-social/atproto/pull/3220) [`61dc0d60e`](https://github.com/bluesky-social/atproto/commit/61dc0d60e19b88c6427a54c6d95a391b5f4da7bd) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Apply new linting rules regarding import order 139 + 140 + - [#3220](https://github.com/bluesky-social/atproto/pull/3220) [`61dc0d60e`](https://github.com/bluesky-social/atproto/commit/61dc0d60e19b88c6427a54c6d95a391b5f4da7bd) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update NodeJS engine requirement to >=18.7.0 141 + 142 + - Updated dependencies [[`61dc0d60e`](https://github.com/bluesky-social/atproto/commit/61dc0d60e19b88c6427a54c6d95a391b5f4da7bd), [`8a30e0ed9`](https://github.com/bluesky-social/atproto/commit/8a30e0ed9239cb2037d54fb98e70e8b0cfbc3e39), [`61dc0d60e`](https://github.com/bluesky-social/atproto/commit/61dc0d60e19b88c6427a54c6d95a391b5f4da7bd), [`8a30e0ed9`](https://github.com/bluesky-social/atproto/commit/8a30e0ed9239cb2037d54fb98e70e8b0cfbc3e39), [`53a577fd4`](https://github.com/bluesky-social/atproto/commit/53a577fd4bfb1c7301e14db85b42f4758b053dee), [`87ed907a6`](https://github.com/bluesky-social/atproto/commit/87ed907a6b96b408c02c9af819cec8380a453254)]: 143 + - @atproto/xrpc-server@0.7.10 144 + - @atproto/common-web@0.4.0 145 + - @atproto/identity@0.4.6 146 + - @atproto/lexicon@0.4.6 147 + - @atproto/crypto@0.4.4 148 + - @atproto/syntax@0.3.2 149 + - @atproto/bsync@0.0.13 150 + - @atproto/ozone@0.1.75 151 + - @atproto/bsky@0.0.114 152 + - @atproto/sync@0.1.13 153 + - @atproto/api@0.13.33 154 + - @atproto/pds@0.4.92 155 + 156 + ## 0.3.83 157 + 158 + ### Patch Changes 159 + 160 + - Updated dependencies [[`4f2841efe`](https://github.com/bluesky-social/atproto/commit/4f2841efeb410e710e0c8da7c9204468f6256a75), [`da7a831a7`](https://github.com/bluesky-social/atproto/commit/da7a831a7318343ba1ee98de3811ba337c043dbd), [`7f52e6735`](https://github.com/bluesky-social/atproto/commit/7f52e67354906c3bf9830d7a2924ab58d6160905), [`8810885b8`](https://github.com/bluesky-social/atproto/commit/8810885b8e7fa0377e6c000c091eec1dd85ed261), [`4f2841efe`](https://github.com/bluesky-social/atproto/commit/4f2841efeb410e710e0c8da7c9204468f6256a75), [`8810885b8`](https://github.com/bluesky-social/atproto/commit/8810885b8e7fa0377e6c000c091eec1dd85ed261), [`4f2841efe`](https://github.com/bluesky-social/atproto/commit/4f2841efeb410e710e0c8da7c9204468f6256a75)]: 161 + - @atproto/xrpc-server@0.7.9 162 + - @atproto/ozone@0.1.74 163 + - @atproto/api@0.13.32 164 + - @atproto/pds@0.4.91 165 + - @atproto/bsky@0.0.113 166 + - @atproto/sync@0.1.12 167 + - @atproto/bsync@0.0.12 168 + - @atproto/crypto@0.4.3 169 + 170 + ## 0.3.82 171 + 172 + ### Patch Changes 173 + 174 + - Updated dependencies [[`8c6c7813a`](https://github.com/bluesky-social/atproto/commit/8c6c7813a9c2110c8fe21acdca8f09554a1983ce)]: 175 + - @atproto/api@0.13.31 176 + - @atproto/pds@0.4.90 177 + - @atproto/bsky@0.0.112 178 + - @atproto/ozone@0.1.73 179 + 180 + ## 0.3.81 181 + 182 + ### Patch Changes 183 + 184 + - Updated dependencies [[`1ada2d093`](https://github.com/bluesky-social/atproto/commit/1ada2d093427e45b6d59a16cf146bf5282560c7b), [`e6e6aea38`](https://github.com/bluesky-social/atproto/commit/e6e6aea3814e3d0bb42a537f80d77947e85fa73f), [`c0a75d310`](https://github.com/bluesky-social/atproto/commit/c0a75d310aa92c067799a97d1acc5bd0543114c5)]: 185 + - @atproto/ozone@0.1.72 186 + - @atproto/api@0.13.30 187 + - @atproto/bsky@0.0.111 188 + - @atproto/pds@0.4.89 189 + 190 + ## 0.3.80 191 + 192 + ### Patch Changes 193 + 194 + - Updated dependencies [[`1015d9692`](https://github.com/bluesky-social/atproto/commit/1015d96925898149cc60b434561e19730a1bea12)]: 195 + - @atproto/xrpc-server@0.7.8 196 + - @atproto/bsky@0.0.110 197 + - @atproto/ozone@0.1.71 198 + - @atproto/pds@0.4.88 199 + - @atproto/sync@0.1.11 200 + 201 + ## 0.3.79 202 + 203 + ### Patch Changes 204 + 205 + - Updated dependencies [[`50603b4f2`](https://github.com/bluesky-social/atproto/commit/50603b4f2ef08bd618730107ec164a57f27dcca6), [`50603b4f2`](https://github.com/bluesky-social/atproto/commit/50603b4f2ef08bd618730107ec164a57f27dcca6)]: 206 + - @atproto/ozone@0.1.70 207 + - @atproto/api@0.13.29 208 + - @atproto/pds@0.4.87 209 + - @atproto/bsky@0.0.109 210 + 211 + ## 0.3.78 212 + 213 + ### Patch Changes 214 + 215 + - Updated dependencies [[`cbf17066f`](https://github.com/bluesky-social/atproto/commit/cbf17066f314fbc7f2e943127ee4a9f589f8bec2)]: 216 + - @atproto/bsky@0.0.108 217 + - @atproto/api@0.13.28 218 + - @atproto/pds@0.4.86 219 + - @atproto/ozone@0.1.69 220 + 221 + ## 0.3.77 222 + 223 + ### Patch Changes 224 + 225 + - Updated dependencies [[`0832a377d`](https://github.com/bluesky-social/atproto/commit/0832a377d269584a906d5062ebb5e2e6307f9c61)]: 226 + - @atproto/xrpc-server@0.7.7 227 + - @atproto/bsky@0.0.107 228 + - @atproto/ozone@0.1.68 229 + - @atproto/pds@0.4.85 230 + - @atproto/sync@0.1.10 231 + 232 + ## 0.3.76 233 + 234 + ### Patch Changes 235 + 236 + - [#3344](https://github.com/bluesky-social/atproto/pull/3344) [`48a0e9d60`](https://github.com/bluesky-social/atproto/commit/48a0e9d6060c2dc93899f13f2fc7cc76c04fbcd9) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Properly dispose of unused http responses 237 + 238 + - Updated dependencies [[`48a0e9d60`](https://github.com/bluesky-social/atproto/commit/48a0e9d6060c2dc93899f13f2fc7cc76c04fbcd9), [`e277158f7`](https://github.com/bluesky-social/atproto/commit/e277158f70a831b04fde3ec84b3c1eaa6ce82e9d)]: 239 + - @atproto/ozone@0.1.67 240 + - @atproto/api@0.13.27 241 + - @atproto/bsky@0.0.106 242 + - @atproto/pds@0.4.84 243 + 244 + ## 0.3.75 245 + 246 + ### Patch Changes 247 + 248 + - Updated dependencies [[`1abfd74ec`](https://github.com/bluesky-social/atproto/commit/1abfd74ec7114e5d8e2411f7a4fa10bdce97e277)]: 249 + - @atproto/crypto@0.4.3 250 + - @atproto/bsky@0.0.105 251 + - @atproto/identity@0.4.5 252 + - @atproto/ozone@0.1.66 253 + - @atproto/pds@0.4.83 254 + - @atproto/xrpc-server@0.7.6 255 + - @atproto/sync@0.1.9 256 + 257 + ## 0.3.74 258 + 259 + ### Patch Changes 260 + 261 + - [#3177](https://github.com/bluesky-social/atproto/pull/3177) [`72eba67af`](https://github.com/bluesky-social/atproto/commit/72eba67af1af8320b5400bcb9319d5c3c8407d99) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Remove dependency on Axios 262 + 263 + - Updated dependencies [[`72eba67af`](https://github.com/bluesky-social/atproto/commit/72eba67af1af8320b5400bcb9319d5c3c8407d99), [`72eba67af`](https://github.com/bluesky-social/atproto/commit/72eba67af1af8320b5400bcb9319d5c3c8407d99), [`72eba67af`](https://github.com/bluesky-social/atproto/commit/72eba67af1af8320b5400bcb9319d5c3c8407d99), [`72eba67af`](https://github.com/bluesky-social/atproto/commit/72eba67af1af8320b5400bcb9319d5c3c8407d99)]: 264 + - @atproto/bsky@0.0.104 265 + - @atproto/common-web@0.3.2 266 + - @atproto/identity@0.4.4 267 + - @atproto/ozone@0.1.65 268 + - @atproto/pds@0.4.82 269 + - @atproto/api@0.13.26 270 + - @atproto/lexicon@0.4.5 271 + - @atproto/sync@0.1.8 272 + - @atproto/bsync@0.0.11 273 + - @atproto/crypto@0.4.2 274 + - @atproto/xrpc-server@0.7.5 275 + 276 + ## 0.3.73 277 + 278 + ### Patch Changes 279 + 280 + - [#3271](https://github.com/bluesky-social/atproto/pull/3271) [`53621f8e1`](https://github.com/bluesky-social/atproto/commit/53621f8e100a3aa3c1caff10a08d3f4ea919875a) Thanks [@foysalit](https://github.com/foysalit)! - Allow setting policy names with takedown actions and when querying events 281 + 282 + - Updated dependencies [[`53621f8e1`](https://github.com/bluesky-social/atproto/commit/53621f8e100a3aa3c1caff10a08d3f4ea919875a)]: 283 + - @atproto/ozone@0.1.64 284 + - @atproto/api@0.13.25 285 + - @atproto/bsky@0.0.103 286 + - @atproto/pds@0.4.81 287 + 288 + ## 0.3.72 289 + 290 + ### Patch Changes 291 + 292 + - Updated dependencies [[`d90d999de`](https://github.com/bluesky-social/atproto/commit/d90d999defda01a9b04dbce129e254990062c283), [`6d1ad3783`](https://github.com/bluesky-social/atproto/commit/6d1ad37836f275e03bc115e944a3195b82f3398d)]: 293 + - @atproto/ozone@0.1.63 294 + - @atproto/api@0.13.24 295 + - @atproto/bsky@0.0.102 296 + - @atproto/pds@0.4.80 297 + 298 + ## 0.3.71 299 + 300 + ### Patch Changes 301 + 302 + - Updated dependencies [[`6d308b857`](https://github.com/bluesky-social/atproto/commit/6d308b857ba2a514ee3c75ebdef7225e298ed7d7), [`6d308b857`](https://github.com/bluesky-social/atproto/commit/6d308b857ba2a514ee3c75ebdef7225e298ed7d7), [`9ea2cce9a`](https://github.com/bluesky-social/atproto/commit/9ea2cce9a4c0a08994a8cb5abc81dc4bc2221d0c), [`b4674a61a`](https://github.com/bluesky-social/atproto/commit/b4674a61a92ca96f89ac06e705e08c2e6af07e1b)]: 303 + - @atproto/pds@0.4.79 304 + - @atproto/api@0.13.23 305 + - @atproto/ozone@0.1.62 306 + - @atproto/bsky@0.0.101 307 + 308 + ## 0.3.70 309 + 310 + ### Patch Changes 311 + 312 + - Updated dependencies [[`f22383cee`](https://github.com/bluesky-social/atproto/commit/f22383cee8feb8b9f761c801ab6e07ad8dc019ed)]: 313 + - @atproto/api@0.13.22 314 + - @atproto/bsky@0.0.100 315 + - @atproto/ozone@0.1.61 316 + - @atproto/pds@0.4.78 317 + 318 + ## 0.3.69 319 + 320 + ### Patch Changes 321 + 322 + - [#3266](https://github.com/bluesky-social/atproto/pull/3266) [`638f5a831`](https://github.com/bluesky-social/atproto/commit/638f5a8312136e8666d9390a73cb273459ffe082) Thanks [@rafaelbsky](https://github.com/rafaelbsky)! - Fix avatar path resolution 323 + 324 + ## 0.3.68 325 + 326 + ### Patch Changes 327 + 328 + - Updated dependencies [[`dced566de`](https://github.com/bluesky-social/atproto/commit/dced566de5079ef4208801db476a7e7416f5e5aa)]: 329 + - @atproto/api@0.13.21 330 + - @atproto/bsky@0.0.99 331 + - @atproto/ozone@0.1.60 332 + - @atproto/pds@0.4.77 333 + 334 + ## 0.3.67 335 + 336 + ### Patch Changes 337 + 338 + - Updated dependencies [[`c9848edaf`](https://github.com/bluesky-social/atproto/commit/c9848edaf0947727aa5a60e3c67eecda3f48d46a), [`9fd65ba0f`](https://github.com/bluesky-social/atproto/commit/9fd65ba0fa4caca59fd0e6156145e4c2618e3a95), [`207728d2b`](https://github.com/bluesky-social/atproto/commit/207728d2b3b819af297ecb90e6373eb7721cbe34), [`0bec389a1`](https://github.com/bluesky-social/atproto/commit/0bec389a1c53adbcfab7b877df9b291d44d8ea33)]: 339 + - @atproto/pds@0.4.76 340 + - @atproto/lexicon@0.4.4 341 + - @atproto/ozone@0.1.59 342 + - @atproto/bsky@0.0.98 343 + - @atproto/api@0.13.20 344 + - @atproto/sync@0.1.7 345 + - @atproto/bsync@0.0.10 346 + - @atproto/crypto@0.4.2 347 + - @atproto/xrpc-server@0.7.4 348 + 349 + ## 0.3.66 350 + 351 + ### Patch Changes 352 + 353 + - Updated dependencies [[`ed2236220`](https://github.com/bluesky-social/atproto/commit/ed2236220900ab9a6132c525289cfdd959733a42)]: 354 + - @atproto/ozone@0.1.58 355 + - @atproto/api@0.13.19 356 + - @atproto/pds@0.4.75 357 + - @atproto/bsky@0.0.97 358 + 359 + ## 0.3.65 360 + 361 + ### Patch Changes 362 + 363 + - Updated dependencies [[`1e367cba2`](https://github.com/bluesky-social/atproto/commit/1e367cba2bd1ff5560c2ec5c2a5d348cd9342b65), [`5ddd51235`](https://github.com/bluesky-social/atproto/commit/5ddd51235c7e064bddcad2dd218df05d144d18d3), [`1e367cba2`](https://github.com/bluesky-social/atproto/commit/1e367cba2bd1ff5560c2ec5c2a5d348cd9342b65)]: 364 + - @atproto/pds@0.4.74 365 + - @atproto/bsky@0.0.96 366 + - @atproto/ozone@0.1.57 367 + 368 + ## 0.3.64 369 + 370 + ### Patch Changes 371 + 372 + - Updated dependencies [[`a3ce23c4c`](https://github.com/bluesky-social/atproto/commit/a3ce23c4ccf4f40998b9d1f5731e5c905390aedc)]: 373 + - @atproto/ozone@0.1.57 374 + - @atproto/bsky@0.0.96 375 + - @atproto/api@0.13.18 376 + - @atproto/pds@0.4.73 377 + 378 + ## 0.3.63 379 + 380 + ### Patch Changes 381 + 382 + - Updated dependencies [[`a4b528e5f`](https://github.com/bluesky-social/atproto/commit/a4b528e5f51c8bfca56b293b0059b88d138ec421), [`2e7aa211d`](https://github.com/bluesky-social/atproto/commit/2e7aa211d2cbc629899c7f87f1713b13b932750b), [`90399c859`](https://github.com/bluesky-social/atproto/commit/90399c85955301babc689c293bd3e7e1a94505a3)]: 383 + - @atproto/api@0.13.17 384 + - @atproto/pds@0.4.72 385 + - @atproto/bsky@0.0.95 386 + - @atproto/ozone@0.1.56 387 + 388 + ## 0.3.62 389 + 390 + ### Patch Changes 391 + 392 + - Updated dependencies [[`24423fc2d`](https://github.com/bluesky-social/atproto/commit/24423fc2dd394c99a29dbe4419b356090ef19546), [`bac9be2d3`](https://github.com/bluesky-social/atproto/commit/bac9be2d3ec904d1f984a871f43cf89aca17289d), [`48d08a469`](https://github.com/bluesky-social/atproto/commit/48d08a469f75837e3b7e879d286d12780440b8b8), [`bac9be2d3`](https://github.com/bluesky-social/atproto/commit/bac9be2d3ec904d1f984a871f43cf89aca17289d), [`bac9be2d3`](https://github.com/bluesky-social/atproto/commit/bac9be2d3ec904d1f984a871f43cf89aca17289d), [`561431fe4`](https://github.com/bluesky-social/atproto/commit/561431fe4897e81767dc768e9a31020d09bf86ff)]: 393 + - @atproto/pds@0.4.71 394 + - @atproto/syntax@0.3.1 395 + - @atproto/ozone@0.1.55 396 + - @atproto/api@0.13.16 397 + - @atproto/lexicon@0.4.3 398 + - @atproto/bsky@0.0.94 399 + - @atproto/bsync@0.0.9 400 + - @atproto/sync@0.1.6 401 + - @atproto/xrpc-server@0.7.3 402 + 403 + ## 0.3.61 404 + 405 + ### Patch Changes 406 + 407 + - Updated dependencies [[`d6f33b474`](https://github.com/bluesky-social/atproto/commit/d6f33b4742e0b94722a993efc7d18833d9416bb6), [`b6eeb81c6`](https://github.com/bluesky-social/atproto/commit/b6eeb81c6d454b5ae91b05a21fc1820274c1b429), [`9e18ab6a3`](https://github.com/bluesky-social/atproto/commit/9e18ab6a35f47e0a9cee76221bfa0817c8a624a1), [`1982693e3`](https://github.com/bluesky-social/atproto/commit/1982693e3ea1fef4db76ac9aca3db8dc5ebf3fe0), [`1982693e3`](https://github.com/bluesky-social/atproto/commit/1982693e3ea1fef4db76ac9aca3db8dc5ebf3fe0), [`9ffeb5216`](https://github.com/bluesky-social/atproto/commit/9ffeb5216ab29919a2c1f3cc18af26c21a077d4a), [`1982693e3`](https://github.com/bluesky-social/atproto/commit/1982693e3ea1fef4db76ac9aca3db8dc5ebf3fe0), [`839202a3d`](https://github.com/bluesky-social/atproto/commit/839202a3d2b01de25de900cec7540019545798c6), [`e680d55ca`](https://github.com/bluesky-social/atproto/commit/e680d55ca2d7f6b213e2a8693eba6be39163ba41), [`c4b5e5395`](https://github.com/bluesky-social/atproto/commit/c4b5e53957463c37dd16fdd1b897d4ab02ab8e84), [`9ffeb5216`](https://github.com/bluesky-social/atproto/commit/9ffeb5216ab29919a2c1f3cc18af26c21a077d4a)]: 408 + - @atproto/ozone@0.1.54 409 + - @atproto/api@0.13.15 410 + - @atproto/pds@0.4.70 411 + - @atproto/crypto@0.4.2 412 + - @atproto/xrpc-server@0.7.2 413 + - @atproto/bsky@0.0.93 414 + - @atproto/identity@0.4.3 415 + - @atproto/sync@0.1.5 416 + 417 + ## 0.3.60 418 + 419 + ### Patch Changes 420 + 421 + - Updated dependencies [[`209238769`](https://github.com/bluesky-social/atproto/commit/209238769c0bf38bf04f7fa9621eeb176b5c0ed8), [`73f40e63a`](https://github.com/bluesky-social/atproto/commit/73f40e63abe3283efc0a27eef781c00b497caad1)]: 422 + - @atproto/bsky@0.0.92 423 + - @atproto/api@0.13.14 424 + - @atproto/pds@0.4.69 425 + - @atproto/ozone@0.1.53 426 + 427 + ## 0.3.59 428 + 429 + ### Patch Changes 430 + 431 + - Updated dependencies [[`19e36afb2`](https://github.com/bluesky-social/atproto/commit/19e36afb2c13dbc7b1033eb3cab5e7fc6f496fdc)]: 432 + - @atproto/ozone@0.1.52 433 + - @atproto/api@0.13.13 434 + - @atproto/bsky@0.0.91 435 + - @atproto/pds@0.4.68 436 + 437 + ## 0.3.58 438 + 439 + ### Patch Changes 440 + 441 + - Updated dependencies [[`c1b0e176a`](https://github.com/bluesky-social/atproto/commit/c1b0e176adbc5108bff49d74fbae18de60e86732)]: 442 + - @atproto/pds@0.4.67 443 + - @atproto/bsky@0.0.90 444 + - @atproto/ozone@0.1.51 445 + 446 + ## 0.3.57 447 + 448 + ### Patch Changes 449 + 450 + - Updated dependencies [[`9d40ccbb6`](https://github.com/bluesky-social/atproto/commit/9d40ccbb69103fae9aae7e3cec31e9b3116f3ba2), [`d605577c2`](https://github.com/bluesky-social/atproto/commit/d605577c25d3e69c7cc0a1e858a4f009d1ea3096)]: 451 + - @atproto/pds@0.4.66 452 + - @atproto/sync@0.1.4 453 + - @atproto/bsky@0.0.90 454 + - @atproto/ozone@0.1.51 455 + 456 + ## 0.3.56 457 + 458 + ### Patch Changes 459 + 460 + - Updated dependencies [[`22d039a22`](https://github.com/bluesky-social/atproto/commit/22d039a229e3ef08a793e1c98b473b1b8e18ac5e)]: 461 + - @atproto/ozone@0.1.51 462 + - @atproto/api@0.13.12 463 + - @atproto/bsky@0.0.89 464 + - @atproto/pds@0.4.65 465 + 466 + ## 0.3.55 467 + 468 + ### Patch Changes 469 + 470 + - Updated dependencies [[`72549f442`](https://github.com/bluesky-social/atproto/commit/72549f442223c0c74594e111a9793e39b0c5ea2d), [`08ed0a5a9`](https://github.com/bluesky-social/atproto/commit/08ed0a5a916685b2aaea783706e6d6287a2aa287), [`08ed0a5a9`](https://github.com/bluesky-social/atproto/commit/08ed0a5a916685b2aaea783706e6d6287a2aa287)]: 471 + - @atproto/bsky@0.0.88 472 + - @atproto/ozone@0.1.50 473 + - @atproto/pds@0.4.64 474 + 475 + ## 0.3.54 476 + 477 + ### Patch Changes 478 + 479 + - Updated dependencies [[`a0531ce42`](https://github.com/bluesky-social/atproto/commit/a0531ce429f5139cb0e2cc19aa9b338599947e44)]: 480 + - @atproto/api@0.13.11 481 + - @atproto/bsky@0.0.87 482 + - @atproto/ozone@0.1.49 483 + - @atproto/pds@0.4.63 484 + 485 + ## 0.3.53 486 + 487 + ### Patch Changes 488 + 489 + - Updated dependencies [[`df14df522`](https://github.com/bluesky-social/atproto/commit/df14df522bb7986e56ee1f6a0f5d862e1ea6f4d5)]: 490 + - @atproto/ozone@0.1.48 491 + - @atproto/api@0.13.10 492 + - @atproto/bsky@0.0.86 493 + - @atproto/pds@0.4.62 494 + 495 + ## 0.3.52 496 + 497 + ### Patch Changes 498 + 499 + - Updated dependencies [[`4098d9890`](https://github.com/bluesky-social/atproto/commit/4098d9890173f4d6c6512f2d8994eebbf12b5e13), [`a2bad977a`](https://github.com/bluesky-social/atproto/commit/a2bad977a8d941b4075ea3ffee3d6f7a0c0f467c)]: 500 + - @atproto/pds@0.4.61 501 + - @atproto/ozone@0.1.47 502 + - @atproto/api@0.13.9 503 + - @atproto/bsky@0.0.85 504 + - @atproto/bsync@0.0.8 505 + - @atproto/crypto@0.4.1 506 + - @atproto/sync@0.1.3 507 + - @atproto/xrpc-server@0.7.1 508 + 509 + ## 0.3.51 510 + 511 + ### Patch Changes 512 + 513 + - Updated dependencies [[`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`2676206e4`](https://github.com/bluesky-social/atproto/commit/2676206e422233fefbf2d9d182e8d462f0957c93), [`922b94ce3`](https://github.com/bluesky-social/atproto/commit/922b94ce379d861faaa5cf8448b7a44f04e474d3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`eb20ff64a`](https://github.com/bluesky-social/atproto/commit/eb20ff64a2d8e3061c652e1e247bf9b0fe3c41a6), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`87a1f2426`](https://github.com/bluesky-social/atproto/commit/87a1f24262e0e644b6cf31cc7a0446d9127ffa94), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3), [`a06634ae5`](https://github.com/bluesky-social/atproto/commit/a06634ae576217d53ef7ea7f8cbfa9faa8662634), [`b298bfd28`](https://github.com/bluesky-social/atproto/commit/b298bfd280c5de8b38b843fd852e6d2739a776d8), [`a07b21151`](https://github.com/bluesky-social/atproto/commit/a07b21151f1850340c4b7797ebb11521b1a6cdf3)]: 514 + - @atproto/common-web@0.3.1 515 + - @atproto/api@0.13.8 516 + - @atproto/pds@0.4.60 517 + - @atproto/xrpc-server@0.7.0 518 + - @atproto/lexicon@0.4.2 519 + - @atproto/bsky@0.0.84 520 + - @atproto/ozone@0.1.46 521 + - @atproto/identity@0.4.2 522 + - @atproto/sync@0.1.2 523 + - @atproto/bsync@0.0.7 524 + - @atproto/crypto@0.4.1 525 + 526 + ## 0.3.50 527 + 528 + ### Patch Changes 529 + 530 + - Updated dependencies [[`e6bd5aecc`](https://github.com/bluesky-social/atproto/commit/e6bd5aecce7954d60e5fb263297e697ab7aab98e), [`98711a147`](https://github.com/bluesky-social/atproto/commit/98711a147a8674337f605c6368f39fc10c2fae93), [`33aa0c722`](https://github.com/bluesky-social/atproto/commit/33aa0c722226a18215af0ae1833c7c552fc7aaa7)]: 531 + - @atproto/api@0.13.7 532 + - @atproto/ozone@0.1.45 533 + - @atproto/xrpc-server@0.6.4 534 + - @atproto/bsky@0.0.83 535 + - @atproto/pds@0.4.59 536 + - @atproto/bsync@0.0.6 537 + - @atproto/crypto@0.4.1 538 + - @atproto/sync@0.1.1 539 + 540 + ## 0.3.49 541 + 542 + ### Patch Changes 543 + 544 + - Updated dependencies [[`b15dec2f4`](https://github.com/bluesky-social/atproto/commit/b15dec2f4feb25ac91b169c83ccff1adbb5a9442), [`642c7ae96`](https://github.com/bluesky-social/atproto/commit/642c7ae968b0dd2bfb448aa6eba0c1fd9312d909)]: 545 + - @atproto/sync@0.1.0 546 + - @atproto/ozone@0.1.44 547 + - @atproto/bsky@0.0.82 548 + - @atproto/pds@0.4.58 549 + 550 + ## 0.3.48 551 + 552 + ### Patch Changes 553 + 554 + - Updated dependencies [[`325859b8b`](https://github.com/bluesky-social/atproto/commit/325859b8bff8dcfdd1eb8cabd51bffedb03aad87), [`e4d41d66f`](https://github.com/bluesky-social/atproto/commit/e4d41d66fa4757a696363f39903562458967b63d)]: 555 + - @atproto/ozone@0.1.43 556 + - @atproto/api@0.13.6 557 + - @atproto/bsky@0.0.81 558 + - @atproto/pds@0.4.57 559 + 560 + ## 0.3.47 561 + 562 + ### Patch Changes 563 + 564 + - Updated dependencies [[`80ada8f47`](https://github.com/bluesky-social/atproto/commit/80ada8f47628f55f3074cd16a52857e98d117e14)]: 565 + - @atproto/bsky@0.0.80 566 + - @atproto/api@0.13.5 567 + - @atproto/pds@0.4.56 568 + - @atproto/ozone@0.1.42 569 + 570 + ## 0.3.46 571 + 572 + ### Patch Changes 573 + 574 + - Updated dependencies []: 575 + - @atproto/pds@0.4.55 576 + - @atproto/bsky@0.0.79 577 + - @atproto/ozone@0.1.41 578 + 579 + ## 0.3.45 580 + 581 + ### Patch Changes 582 + 583 + - Updated dependencies [[`ebb318325`](https://github.com/bluesky-social/atproto/commit/ebb318325b6e80c4ea1a93a617569da2698afe31), [`dee817b6e`](https://github.com/bluesky-social/atproto/commit/dee817b6e0fc02351d51ce310b5e65239b7c5ed7), [`ebb318325`](https://github.com/bluesky-social/atproto/commit/ebb318325b6e80c4ea1a93a617569da2698afe31), [`dee817b6e`](https://github.com/bluesky-social/atproto/commit/dee817b6e0fc02351d51ce310b5e65239b7c5ed7), [`dee817b6e`](https://github.com/bluesky-social/atproto/commit/dee817b6e0fc02351d51ce310b5e65239b7c5ed7), [`ebb318325`](https://github.com/bluesky-social/atproto/commit/ebb318325b6e80c4ea1a93a617569da2698afe31), [`d9ffa3c46`](https://github.com/bluesky-social/atproto/commit/d9ffa3c460924010d7002b616cb7a0c66111cc6c), [`d9ffa3c46`](https://github.com/bluesky-social/atproto/commit/d9ffa3c460924010d7002b616cb7a0c66111cc6c), [`bbca17bc5`](https://github.com/bluesky-social/atproto/commit/bbca17bc5388e0b2af26fb107347c8ab507ee42f), [`a8e1f9000`](https://github.com/bluesky-social/atproto/commit/a8e1f9000d9617c4df9d9f0e74ae0e0b73fcfd66), [`ebb318325`](https://github.com/bluesky-social/atproto/commit/ebb318325b6e80c4ea1a93a617569da2698afe31), [`d9ffa3c46`](https://github.com/bluesky-social/atproto/commit/d9ffa3c460924010d7002b616cb7a0c66111cc6c), [`dee817b6e`](https://github.com/bluesky-social/atproto/commit/dee817b6e0fc02351d51ce310b5e65239b7c5ed7)]: 584 + - @atproto/xrpc-server@0.6.3 585 + - @atproto/pds@0.4.54 586 + - @atproto/api@0.13.4 587 + - @atproto/bsky@0.0.79 588 + - @atproto/crypto@0.4.1 589 + - @atproto/ozone@0.1.41 590 + - @atproto/identity@0.4.1 591 + 592 + ## 0.3.44 593 + 594 + ### Patch Changes 595 + 596 + - Updated dependencies [[`4ab248354`](https://github.com/bluesky-social/atproto/commit/4ab2483547d5dabfba88ed4419a4f374bbd7cae7)]: 597 + - @atproto/bsky@0.0.78 598 + - @atproto/api@0.13.3 599 + - @atproto/pds@0.4.53 600 + - @atproto/ozone@0.1.40 601 + 602 + ## 0.3.43 603 + 604 + ### Patch Changes 605 + 606 + - Updated dependencies [[`2a0c088cc`](https://github.com/bluesky-social/atproto/commit/2a0c088cc5d502ca70da9612a261186aa2f2e1fb), [`aba664fbd`](https://github.com/bluesky-social/atproto/commit/aba664fbdfbaddba321e96db2478e0bc8fc72d27)]: 607 + - @atproto/bsky@0.0.77 608 + - @atproto/api@0.13.2 609 + - @atproto/pds@0.4.52 610 + - @atproto/ozone@0.1.39 611 + 612 + ## 0.3.42 613 + 614 + ### Patch Changes 615 + 616 + - Updated dependencies [[`f9a2f3ed1`](https://github.com/bluesky-social/atproto/commit/f9a2f3ed172ae1a8dc1cca0e893e13eac2e4955d)]: 617 + - @atproto/pds@0.4.51 618 + - @atproto/bsky@0.0.76 619 + - @atproto/ozone@0.1.38 620 + 621 + ## 0.3.41 622 + 623 + ### Patch Changes 624 + 625 + - Updated dependencies [[`acbacbbd5`](https://github.com/bluesky-social/atproto/commit/acbacbbd5621473b14ee7a6a3132f675806d23b1), [`acbacbbd5`](https://github.com/bluesky-social/atproto/commit/acbacbbd5621473b14ee7a6a3132f675806d23b1), [`50c0ec176`](https://github.com/bluesky-social/atproto/commit/50c0ec176c223c90e7c86e1e0c059455fecfa9ae), [`50c0ec176`](https://github.com/bluesky-social/atproto/commit/50c0ec176c223c90e7c86e1e0c059455fecfa9ae), [`50c0ec176`](https://github.com/bluesky-social/atproto/commit/50c0ec176c223c90e7c86e1e0c059455fecfa9ae), [`50c0ec176`](https://github.com/bluesky-social/atproto/commit/50c0ec176c223c90e7c86e1e0c059455fecfa9ae)]: 626 + - @atproto/xrpc-server@0.6.2 627 + - @atproto/pds@0.4.50 628 + - @atproto/ozone@0.1.38 629 + - @atproto/bsky@0.0.76 630 + 631 + ## 0.3.40 632 + 633 + ### Patch Changes 634 + 635 + - Updated dependencies [[`22af354a5`](https://github.com/bluesky-social/atproto/commit/22af354a5db595d7cbc0e65f02601de3565337e1)]: 636 + - @atproto/api@0.13.1 637 + - @atproto/bsky@0.0.75 638 + - @atproto/ozone@0.1.37 639 + - @atproto/pds@0.4.49 640 + 641 + ## 0.3.39 642 + 643 + ### Patch Changes 644 + 645 + - Updated dependencies [[`b934b396b`](https://github.com/bluesky-social/atproto/commit/b934b396b13ba32bf2bf7e75ecdf6871e5f310dd), [`2bdf75d7a`](https://github.com/bluesky-social/atproto/commit/2bdf75d7a63924c10e7a311f16cb447d595b933e), [`b934b396b`](https://github.com/bluesky-social/atproto/commit/b934b396b13ba32bf2bf7e75ecdf6871e5f310dd), [`b934b396b`](https://github.com/bluesky-social/atproto/commit/b934b396b13ba32bf2bf7e75ecdf6871e5f310dd)]: 646 + - @atproto/lexicon@0.4.1 647 + - @atproto/api@0.13.0 648 + - @atproto/bsky@0.0.74 649 + - @atproto/ozone@0.1.36 650 + - @atproto/pds@0.4.48 651 + - @atproto/xrpc-server@0.6.1 652 + 653 + ## 0.3.38 654 + 655 + ### Patch Changes 656 + 657 + - Updated dependencies [[`269cbc87c`](https://github.com/bluesky-social/atproto/commit/269cbc87c5ec9d65d1d479269ac5e91dffbb186c)]: 658 + - @atproto/pds@0.4.47 659 + - @atproto/bsky@0.0.73 660 + - @atproto/ozone@0.1.35 661 + 662 + ## 0.3.37 663 + 664 + ### Patch Changes 665 + 666 + - Updated dependencies [[`dc471da26`](https://github.com/bluesky-social/atproto/commit/dc471da267955d0962a8affaf983df60d962d97c), [`dc471da26`](https://github.com/bluesky-social/atproto/commit/dc471da267955d0962a8affaf983df60d962d97c)]: 667 + - @atproto/api@0.12.29 668 + - @atproto/xrpc-server@0.6.0 669 + - @atproto/pds@0.4.46 670 + - @atproto/bsky@0.0.73 671 + - @atproto/ozone@0.1.35 672 + 673 + ## 0.3.36 674 + 675 + ### Patch Changes 676 + 677 + - Updated dependencies [[`951a3df15`](https://github.com/bluesky-social/atproto/commit/951a3df15aa9c1f5b0a2b66cfb0e2eaf6198fe41)]: 678 + - @atproto/ozone@0.1.34 679 + - @atproto/bsky@0.0.72 680 + - @atproto/api@0.12.28 681 + - @atproto/pds@0.4.45 682 + 683 + ## 0.3.35 684 + 685 + ### Patch Changes 686 + 687 + - Updated dependencies [[`ff803fd2b`](https://github.com/bluesky-social/atproto/commit/ff803fd2bfad92eec5f88ee9b347c174731ef4ec)]: 688 + - @atproto/ozone@0.1.33 689 + - @atproto/bsky@0.0.71 690 + - @atproto/api@0.12.27 691 + - @atproto/pds@0.4.44 692 + 693 + ## 0.3.34 694 + 695 + ### Patch Changes 696 + 697 + - Updated dependencies [[`77c5306d2`](https://github.com/bluesky-social/atproto/commit/77c5306d2a40d7edd20def73163b8f93f3a30ee7)]: 698 + - @atproto/ozone@0.1.32 699 + - @atproto/bsky@0.0.70 700 + - @atproto/api@0.12.26 701 + - @atproto/pds@0.4.43 702 + 703 + ## 0.3.33 704 + 705 + ### Patch Changes 706 + 707 + - Updated dependencies [[`12dcdb668`](https://github.com/bluesky-social/atproto/commit/12dcdb668c8ec0f8a89689c326ab3e9dbc6d2f3c), [`76c91f832`](https://github.com/bluesky-social/atproto/commit/76c91f8325363c95e25349e8e236aa2f70e63d5b)]: 708 + - @atproto/api@0.12.25 709 + - @atproto/bsync@0.0.5 710 + - @atproto/bsky@0.0.69 711 + - @atproto/ozone@0.1.31 712 + - @atproto/pds@0.4.42 713 + 714 + ## 0.3.32 715 + 716 + ### Patch Changes 717 + 718 + - [#2633](https://github.com/bluesky-social/atproto/pull/2633) [`acc9093d2`](https://github.com/bluesky-social/atproto/commit/acc9093d2845eba02b68fb2f9db33e4f1b59bb10) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Adapt to changes from @atproto/oauth-provider 719 + 720 + - Updated dependencies [[`acc9093d2`](https://github.com/bluesky-social/atproto/commit/acc9093d2845eba02b68fb2f9db33e4f1b59bb10), [`acc9093d2`](https://github.com/bluesky-social/atproto/commit/acc9093d2845eba02b68fb2f9db33e4f1b59bb10), [`acc9093d2`](https://github.com/bluesky-social/atproto/commit/acc9093d2845eba02b68fb2f9db33e4f1b59bb10)]: 721 + - @atproto/pds@0.4.41 722 + - @atproto/ozone@0.1.30 723 + - @atproto/bsync@0.0.4 724 + - @atproto/bsky@0.0.68 725 + - @atproto/crypto@0.4.0 726 + - @atproto/xrpc-server@0.5.3 727 + 728 + ## 0.3.31 729 + 730 + ### Patch Changes 731 + 732 + - Updated dependencies [[`ed5810179`](https://github.com/bluesky-social/atproto/commit/ed5810179006f254f2035fe1f0e3c4798080cfe0), [`0529bec99`](https://github.com/bluesky-social/atproto/commit/0529bec99183439829a3553f45ac7203763144c3), [`2f40203fb`](https://github.com/bluesky-social/atproto/commit/2f40203fb453934aaf5d353b680d89b8a1febd0f)]: 733 + - @atproto/api@0.12.24 734 + - @atproto/ozone@0.1.29 735 + - @atproto/bsky@0.0.67 736 + - @atproto/pds@0.4.40 737 + 738 + ## 0.3.30 739 + 740 + ### Patch Changes 741 + 742 + - Updated dependencies [[`bc861a2c2`](https://github.com/bluesky-social/atproto/commit/bc861a2c25b4151fb7e070dc20d5e1e07da21863)]: 743 + - @atproto/ozone@0.1.28 744 + - @atproto/bsky@0.0.66 745 + - @atproto/api@0.12.23 746 + - @atproto/pds@0.4.39 747 + 748 + ## 0.3.29 749 + 750 + ### Patch Changes 751 + 752 + - [#2553](https://github.com/bluesky-social/atproto/pull/2553) [`af7d3912a`](https://github.com/bluesky-social/atproto/commit/af7d3912a3b304a752ed72947eaa8cf28b35ec02) Thanks [@devinivy](https://github.com/devinivy)! - Support for starter packs (app.bsky.graph.starterpack) 753 + 754 + - Updated dependencies [[`af7d3912a`](https://github.com/bluesky-social/atproto/commit/af7d3912a3b304a752ed72947eaa8cf28b35ec02), [`615a96ddc`](https://github.com/bluesky-social/atproto/commit/615a96ddc2965251cfab060dfc43fc1a51ef4bff)]: 755 + - @atproto/ozone@0.1.27 756 + - @atproto/bsky@0.0.65 757 + - @atproto/api@0.12.22 758 + - @atproto/pds@0.4.38 759 + - @atproto/xrpc-server@0.5.2 760 + 761 + ## 0.3.28 762 + 763 + ### Patch Changes 764 + 765 + - [#2460](https://github.com/bluesky-social/atproto/pull/2460) [`3ad051996`](https://github.com/bluesky-social/atproto/commit/3ad0519961e2437aa4870bf1358e6c275dcdee24) Thanks [@foysalit](https://github.com/foysalit)! - Add DB backed team member management for ozone 766 + 767 + - Updated dependencies [[`3ad051996`](https://github.com/bluesky-social/atproto/commit/3ad0519961e2437aa4870bf1358e6c275dcdee24)]: 768 + - @atproto/ozone@0.1.26 769 + - @atproto/api@0.12.21 770 + - @atproto/pds@0.4.37 771 + - @atproto/bsky@0.0.64 772 + 773 + ## 0.3.27 774 + 775 + ### Patch Changes 776 + 777 + - Updated dependencies [[`ea0f10b5d`](https://github.com/bluesky-social/atproto/commit/ea0f10b5d0d334eb587032c54d5ace9ea811cf26)]: 778 + - @atproto/api@0.12.20 779 + - @atproto/bsky@0.0.63 780 + - @atproto/ozone@0.1.25 781 + - @atproto/pds@0.4.36 782 + 783 + ## 0.3.26 784 + 785 + ### Patch Changes 786 + 787 + - Updated dependencies [[`a8d6c1123`](https://github.com/bluesky-social/atproto/commit/a8d6c112359f5c4c0cfbe2df63443ed275f2a646)]: 788 + - @atproto/pds@0.4.35 789 + - @atproto/bsky@0.0.62 790 + - @atproto/ozone@0.1.24 791 + 792 + ## 0.3.25 793 + 794 + ### Patch Changes 795 + 796 + - Updated dependencies [[`7c1973841`](https://github.com/bluesky-social/atproto/commit/7c1973841dab416ae19435d37853aeea1f579d39)]: 797 + - @atproto/api@0.12.19 798 + - @atproto/bsky@0.0.62 799 + - @atproto/ozone@0.1.24 800 + - @atproto/pds@0.4.34 801 + 802 + ## 0.3.24 803 + 804 + ### Patch Changes 805 + 806 + - Updated dependencies [[`58abcbd8b`](https://github.com/bluesky-social/atproto/commit/58abcbd8b6e42a1f66bda6acc3ee6a2c0894e546)]: 807 + - @atproto/api@0.12.18 808 + - @atproto/bsky@0.0.61 809 + - @atproto/ozone@0.1.23 810 + - @atproto/pds@0.4.33 811 + 812 + ## 0.3.23 813 + 814 + ### Patch Changes 815 + 816 + - Updated dependencies [[`2b21b5be2`](https://github.com/bluesky-social/atproto/commit/2b21b5be293d32c5eb5ae971c39703bc7d2224fd), [`d8e2fefa9`](https://github.com/bluesky-social/atproto/commit/d8e2fefa98581edb3837e567657aa41a1cdb21f6)]: 817 + - @atproto/ozone@0.1.22 818 + - @atproto/bsky@0.0.60 819 + - @atproto/api@0.12.17 820 + - @atproto/pds@0.4.32 821 + 822 + ## 0.3.22 823 + 824 + ### Patch Changes 825 + 826 + - [#2539](https://github.com/bluesky-social/atproto/pull/2539) [`9495af23b`](https://github.com/bluesky-social/atproto/commit/9495af23bdb328cfc71182ac80e6eb61863d7a46) Thanks [@dholms](https://github.com/dholms)! - Allow updating deactivation state through admin.updateSubjectStatus 827 + 828 + - Updated dependencies [[`9495af23b`](https://github.com/bluesky-social/atproto/commit/9495af23bdb328cfc71182ac80e6eb61863d7a46)]: 829 + - @atproto/api@0.12.16 830 + - @atproto/pds@0.4.31 831 + - @atproto/bsky@0.0.59 832 + - @atproto/ozone@0.1.21 833 + 834 + ## 0.3.21 835 + 836 + ### Patch Changes 837 + 838 + - Updated dependencies [[`255d5ea1f`](https://github.com/bluesky-social/atproto/commit/255d5ea1f06726547cdbe59c83bd18f2d4746912)]: 839 + - @atproto/api@0.12.15 840 + - @atproto/pds@0.4.30 841 + - @atproto/bsky@0.0.58 842 + - @atproto/ozone@0.1.20 843 + 844 + ## 0.3.20 845 + 846 + ### Patch Changes 847 + 848 + - Updated dependencies [[`c4af6a409`](https://github.com/bluesky-social/atproto/commit/c4af6a409ea2171c3cf1d0e7c8ed496794a3f049)]: 849 + - @atproto/api@0.12.14 850 + - @atproto/bsky@0.0.57 851 + - @atproto/ozone@0.1.19 852 + - @atproto/pds@0.4.29 853 + 854 + ## 0.3.19 855 + 856 + ### Patch Changes 857 + 858 + - Updated dependencies [[`53551be6c`](https://github.com/bluesky-social/atproto/commit/53551be6cf092a9b4d2e132788b94ac0d4ffcecc)]: 859 + - @atproto/ozone@0.1.18 860 + - @atproto/bsky@0.0.56 861 + - @atproto/pds@0.4.28 862 + 863 + ## 0.3.18 864 + 865 + ### Patch Changes 866 + 867 + - Updated dependencies [[`1d4ab5d04`](https://github.com/bluesky-social/atproto/commit/1d4ab5d046aac4539658ee6d7e61882c54d5beb9), [`1d4ab5d04`](https://github.com/bluesky-social/atproto/commit/1d4ab5d046aac4539658ee6d7e61882c54d5beb9)]: 868 + - @atproto/pds@0.4.27 869 + - @atproto/api@0.12.13 870 + - @atproto/bsky@0.0.55 871 + - @atproto/ozone@0.1.17 872 + 873 + ## 0.3.17 874 + 875 + ### Patch Changes 876 + 877 + - Updated dependencies [[`0cc5ef70f`](https://github.com/bluesky-social/atproto/commit/0cc5ef70f4e5a8e24983051d5f5ad8ee27be8684)]: 878 + - @atproto/pds@0.4.26 879 + - @atproto/bsky@0.0.54 880 + - @atproto/ozone@0.1.16 881 + 882 + ## 0.3.16 883 + 884 + ### Patch Changes 885 + 886 + - Updated dependencies [[`0e8acb9fb`](https://github.com/bluesky-social/atproto/commit/0e8acb9fbaf3edcebd8e4f8fe4a381ede0206895)]: 887 + - @atproto/pds@0.4.25 888 + - @atproto/bsky@0.0.54 889 + - @atproto/ozone@0.1.16 890 + 891 + ## 0.3.15 892 + 893 + ### Patch Changes 894 + 895 + - Updated dependencies [[`cf25a60e2`](https://github.com/bluesky-social/atproto/commit/cf25a60e25b7531a359f0849729209a55193f7d6), [`1f560f021`](https://github.com/bluesky-social/atproto/commit/1f560f021c07eb9e8d76577e67fd2d7ac39cdee4)]: 896 + - @atproto/pds@0.4.24 897 + - @atproto/api@0.12.12 898 + - @atproto/ozone@0.1.16 899 + - @atproto/bsky@0.0.54 900 + 901 + ## 0.3.14 902 + 903 + ### Patch Changes 904 + 905 + - Updated dependencies [[`06d2328ee`](https://github.com/bluesky-social/atproto/commit/06d2328eeb8d706018dbdf7cc7b9862dd65b96cb)]: 906 + - @atproto/api@0.12.11 907 + - @atproto/bsky@0.0.53 908 + - @atproto/ozone@0.1.15 909 + - @atproto/pds@0.4.23 910 + 911 + ## 0.3.13 912 + 913 + ### Patch Changes 914 + 915 + - Updated dependencies [[`d32f7215f`](https://github.com/bluesky-social/atproto/commit/d32f7215f69bc87f50890d9cfdb09840c2fbaa41)]: 916 + - @atproto/api@0.12.10 917 + - @atproto/pds@0.4.22 918 + - @atproto/bsky@0.0.52 919 + - @atproto/ozone@0.1.14 920 + 921 + ## 0.3.12 922 + 923 + ### Patch Changes 924 + 925 + - Updated dependencies [[`f36585013`](https://github.com/bluesky-social/atproto/commit/f365850139ffb2b5e63facfd95eedf0b87d01ee7)]: 926 + - @atproto/pds@0.4.21 927 + - @atproto/bsky@0.0.51 928 + - @atproto/ozone@0.1.13 929 + 930 + ## 0.3.11 931 + 932 + ### Patch Changes 933 + 934 + - Updated dependencies [[`f83b4c8ca`](https://github.com/bluesky-social/atproto/commit/f83b4c8cad01cebc1b67caa6c7ebe45f07b2f318)]: 935 + - @atproto/api@0.12.9 936 + - @atproto/bsky@0.0.51 937 + - @atproto/ozone@0.1.13 938 + - @atproto/pds@0.4.20 939 + 940 + ## 0.3.10 941 + 942 + ### Patch Changes 943 + 944 + - Updated dependencies [[`58f719cc1`](https://github.com/bluesky-social/atproto/commit/58f719cc1c8d0ebd5ad7cf11221372b671cd7857)]: 945 + - @atproto/api@0.12.8 946 + - @atproto/bsky@0.0.50 947 + - @atproto/ozone@0.1.12 948 + - @atproto/pds@0.4.19 949 + 950 + ## 0.3.9 951 + 952 + ### Patch Changes 953 + 954 + - Updated dependencies [[`58551bbe0`](https://github.com/bluesky-social/atproto/commit/58551bbe0595462c44fc3b6ab5b83e520f141933)]: 955 + - @atproto/ozone@0.1.11 956 + - @atproto/api@0.12.7 957 + - @atproto/pds@0.4.18 958 + - @atproto/bsky@0.0.49 959 + 960 + ## 0.3.8 961 + 962 + ### Patch Changes 963 + 964 + - Updated dependencies [[`b9b7c5821`](https://github.com/bluesky-social/atproto/commit/b9b7c582199d57d2fe0af8af5c8c411ed34f5b9d)]: 965 + - @atproto/api@0.12.6 966 + - @atproto/bsky@0.0.48 967 + - @atproto/ozone@0.1.10 968 + - @atproto/pds@0.4.17 969 + 970 + ## 0.3.7 971 + 972 + ### Patch Changes 973 + 974 + - Updated dependencies [[`3424a1770`](https://github.com/bluesky-social/atproto/commit/3424a17703891f5678ec76ef97e696afb3288b22)]: 975 + - @atproto/api@0.12.5 976 + - @atproto/bsky@0.0.47 977 + - @atproto/ozone@0.1.9 978 + - @atproto/pds@0.4.16 979 + 980 + ## 0.3.6 981 + 982 + ### Patch Changes 983 + 984 + - Updated dependencies [[`93a4a4df9`](https://github.com/bluesky-social/atproto/commit/93a4a4df9ce38f89a5d05e300d247b85fb007e05)]: 985 + - @atproto/api@0.12.4 986 + - @atproto/pds@0.4.15 987 + - @atproto/bsky@0.0.46 988 + - @atproto/ozone@0.1.8 989 + 990 + ## 0.3.5 991 + 992 + ### Patch Changes 993 + 994 + - Updated dependencies [[`0edef0ec0`](https://github.com/bluesky-social/atproto/commit/0edef0ec01403fd6097a4d2875b68313f2f1261f), [`c6d758b8b`](https://github.com/bluesky-social/atproto/commit/c6d758b8b63f4ef50b2ab9afc62164e92a53e7f0)]: 995 + - @atproto/api@0.12.3 996 + - @atproto/bsky@0.0.45 997 + - @atproto/ozone@0.1.7 998 + - @atproto/pds@0.4.14 999 + 1000 + ## 0.3.4 1001 + 1002 + ### Patch Changes 1003 + 1004 + - Updated dependencies [[`cd4fcc709`](https://github.com/bluesky-social/atproto/commit/cd4fcc709fe8d725a4af769ce21f53711fe5622a)]: 1005 + - @atproto/xrpc-server@0.5.1 1006 + - @atproto/bsky@0.0.44 1007 + - @atproto/ozone@0.1.6 1008 + - @atproto/pds@0.4.13 1009 + 1010 + ## 0.3.3 1011 + 1012 + ### Patch Changes 1013 + 1014 + - Updated dependencies [[`d77ac35d4`](https://github.com/bluesky-social/atproto/commit/d77ac35d484925d90169e6a1047cddfbe90923bc)]: 1015 + - @atproto/pds@0.4.12 1016 + - @atproto/bsky@0.0.43 1017 + - @atproto/ozone@0.1.5 1018 + 1019 + ## 0.3.2 1020 + 1021 + ### Patch Changes 1022 + 1023 + - Updated dependencies [[`abc6f82da`](https://github.com/bluesky-social/atproto/commit/abc6f82da38abef2b1bbe8d9e41a0534a5418c9e)]: 1024 + - @atproto/api@0.12.2 1025 + - @atproto/bsky@0.0.43 1026 + - @atproto/ozone@0.1.5 1027 + - @atproto/pds@0.4.11 1028 + 1029 + ## 0.3.1 1030 + 1031 + ### Patch Changes 1032 + 1033 + - [#2342](https://github.com/bluesky-social/atproto/pull/2342) [`eb7668c07`](https://github.com/bluesky-social/atproto/commit/eb7668c07d44f4b42ea2cc28143c64f4ba3312f5) Thanks [@estrattonbailey](https://github.com/estrattonbailey)! - Adds the `associated` property to `profile` and `profile-basic` views, bringing them in line with `profile-detailed` views. 1034 + 1035 + - Updated dependencies [[`eb7668c07`](https://github.com/bluesky-social/atproto/commit/eb7668c07d44f4b42ea2cc28143c64f4ba3312f5)]: 1036 + - @atproto/ozone@0.1.4 1037 + - @atproto/bsky@0.0.42 1038 + - @atproto/api@0.12.1 1039 + - @atproto/pds@0.4.10 1040 + 1041 + ## 0.3.0 1042 + 1043 + ### Minor Changes 1044 + 1045 + - [#2169](https://github.com/bluesky-social/atproto/pull/2169) [`f689bd51a`](https://github.com/bluesky-social/atproto/commit/f689bd51a2f4e02d4eca40eb2568a1fcb95494e9) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Build system rework, stop bundling dependencies. 1046 + 1047 + ### Patch Changes 1048 + 1049 + - Updated dependencies [[`f689bd51a`](https://github.com/bluesky-social/atproto/commit/f689bd51a2f4e02d4eca40eb2568a1fcb95494e9), [`36f2e966c`](https://github.com/bluesky-social/atproto/commit/36f2e966cba6cc90ba4320520da5c7381cfb8086)]: 1050 + - @atproto/xrpc-server@0.5.0 1051 + - @atproto/common-web@0.3.0 1052 + - @atproto/identity@0.4.0 1053 + - @atproto/lexicon@0.4.0 1054 + - @atproto/crypto@0.4.0 1055 + - @atproto/syntax@0.3.0 1056 + - @atproto/api@0.12.0 1057 + - @atproto/bsync@0.0.3 1058 + - @atproto/ozone@0.1.3 1059 + - @atproto/bsky@0.0.41 1060 + - @atproto/pds@0.4.9 1061 + 1062 + ## 0.2.41 1063 + 1064 + ### Patch Changes 1065 + 1066 + - Updated dependencies [[`7dd9941b7`](https://github.com/bluesky-social/atproto/commit/7dd9941b73dbbd82601740e021cc87d765af60ca)]: 1067 + - @atproto/api@0.11.2 1068 + - @atproto/bsky@0.0.40 1069 + - @atproto/ozone@0.1.2 1070 + - @atproto/pds@0.4.8 1071 + 1072 + ## 0.2.40 1073 + 1074 + ### Patch Changes 1075 + 1076 + - Updated dependencies [[`b95c3955d`](https://github.com/bluesky-social/atproto/commit/b95c3955d0b8263a44a3d2a46b35b1831d9e504a)]: 1077 + - @atproto/ozone@0.1.1 1078 + - @atproto/api@0.11.1 1079 + - @atproto/bsky@0.0.39 1080 + - @atproto/pds@0.4.7 1081 + 1082 + ## 0.2.39 1083 + 1084 + ### Patch Changes 1085 + 1086 + - Updated dependencies [[`971d3e4c2`](https://github.com/bluesky-social/atproto/commit/971d3e4c26ecfda746e83d458391715752ea7064), [`219480764`](https://github.com/bluesky-social/atproto/commit/2194807644cbdb0021e867437693300c1b0e55f5), [`971d3e4c2`](https://github.com/bluesky-social/atproto/commit/971d3e4c26ecfda746e83d458391715752ea7064)]: 1087 + - @atproto/ozone@0.1.0 1088 + - @atproto/api@0.11.1 1089 + - @atproto/pds@0.4.7 1090 + - @atproto/bsky@0.0.39 1091 + 1092 + ## 0.2.38 1093 + 1094 + ### Patch Changes 1095 + 1096 + - Updated dependencies [[`4eaadc0ac`](https://github.com/bluesky-social/atproto/commit/4eaadc0acb6b73b9745dd7a2b929d02e58083ab0), [`4eaadc0ac`](https://github.com/bluesky-social/atproto/commit/4eaadc0acb6b73b9745dd7a2b929d02e58083ab0)]: 1097 + - @atproto/common-web@0.2.4 1098 + - @atproto/identity@0.3.3 1099 + - @atproto/api@0.11.0 1100 + - @atproto/lexicon@0.3.3 1101 + - @atproto/syntax@0.2.1 1102 + - @atproto/bsky@0.0.38 1103 + - @atproto/ozone@0.0.17 1104 + - @atproto/pds@0.4.6 1105 + - @atproto/bsync@0.0.2 1106 + - @atproto/crypto@0.3.0 1107 + - @atproto/xrpc-server@0.4.4 1108 + 1109 + ## 0.2.37 1110 + 1111 + ### Patch Changes 1112 + 1113 + - Updated dependencies [[`192223f12`](https://github.com/bluesky-social/atproto/commit/192223f127c0b226287df1ecfcd953636db08655)]: 1114 + - @atproto/ozone@0.0.16 1115 + - @atproto/bsky@0.0.37 1116 + - @atproto/api@0.10.5 1117 + - @atproto/pds@0.4.5 1118 + 1119 + ## 0.2.36 1120 + 1121 + ### Patch Changes 1122 + 1123 + - Updated dependencies [[`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f), [`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f), [`6ec885992`](https://github.com/bluesky-social/atproto/commit/6ec8859929a16f9725319cc398b716acf913b01f)]: 1124 + - @atproto/api@0.10.4 1125 + - @atproto/bsky@0.0.36 1126 + - @atproto/ozone@0.0.15 1127 + - @atproto/pds@0.4.4 1128 + 1129 + ## 0.2.35 1130 + 1131 + ### Patch Changes 1132 + 1133 + - Updated dependencies [[`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed), [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed), [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed), [`2a0ceb818`](https://github.com/bluesky-social/atproto/commit/2a0ceb8180faa17de8061d4fa6c361b57a2005ed)]: 1134 + - @atproto/api@0.10.3 1135 + - @atproto/bsky@0.0.35 1136 + - @atproto/ozone@0.0.14 1137 + - @atproto/pds@0.4.3 1138 + 1139 + ## 0.2.34 1140 + 1141 + ### Patch Changes 1142 + 1143 + - Updated dependencies [[`0c815b964`](https://github.com/bluesky-social/atproto/commit/0c815b964c030aa0f277c40bf9786f130dc320f4), [`61b3d2525`](https://github.com/bluesky-social/atproto/commit/61b3d25253353db2da1336004f94e7dc5adb0410), [`43531905c`](https://github.com/bluesky-social/atproto/commit/43531905ce1aec6d36d9be5943782811ecca6e6d), [`61b3d2525`](https://github.com/bluesky-social/atproto/commit/61b3d25253353db2da1336004f94e7dc5adb0410)]: 1144 + - @atproto/syntax@0.2.0 1145 + - @atproto/api@0.10.2 1146 + - @atproto/bsky@0.0.34 1147 + - @atproto/bsync@0.0.1 1148 + - @atproto/lexicon@0.3.2 1149 + - @atproto/ozone@0.0.13 1150 + - @atproto/pds@0.4.2 1151 + - @atproto/xrpc-server@0.4.3 1152 + 1153 + ## 0.2.33 1154 + 1155 + ### Patch Changes 1156 + 1157 + - Updated dependencies [[`514aab92d`](https://github.com/bluesky-social/atproto/commit/514aab92d26acd43859285f46318e386846522b1)]: 1158 + - @atproto/api@0.10.1 1159 + - @atproto/bsky@0.0.33 1160 + - @atproto/ozone@0.0.12 1161 + - @atproto/pds@0.4.1 1162 + 1163 + ## 0.2.32 1164 + 1165 + ### Patch Changes 1166 + 1167 + - Updated dependencies [[`b60719480`](https://github.com/bluesky-social/atproto/commit/b60719480f5f00bffd074a40e8ddc03aa93d137d), [`4c511b3d9`](https://github.com/bluesky-social/atproto/commit/4c511b3d9de41ffeae3fc11db941e7df04f4468a)]: 1168 + - @atproto/api@0.10.0 1169 + - @atproto/bsky@0.0.32 1170 + - @atproto/ozone@0.0.11 1171 + - @atproto/pds@0.4.0 1172 + 1173 + ## 0.2.31 1174 + 1175 + ### Patch Changes 1176 + 1177 + - Updated dependencies [[`f79cc6339`](https://github.com/bluesky-social/atproto/commit/f79cc63390ae9dbd47a4ff5d694eec25b78b788e)]: 1178 + - @atproto/api@0.9.8 1179 + - @atproto/ozone@0.0.10 1180 + - @atproto/bsky@0.0.31 1181 + - @atproto/pds@0.3.19 1182 + 1183 + ## 0.2.30 1184 + 1185 + ### Patch Changes 1186 + 1187 + - Updated dependencies [[`8c94979f7`](https://github.com/bluesky-social/atproto/commit/8c94979f73fc5057449e24e66ef2e09b0e17e55b)]: 1188 + - @atproto/api@0.9.7 1189 + - @atproto/bsky@0.0.30 1190 + - @atproto/pds@0.3.18 1191 + - @atproto/ozone@0.0.9 1192 + 1193 + ## 0.2.29 1194 + 1195 + ### Patch Changes 1196 + 1197 + - Updated dependencies [[`e4ec7af03`](https://github.com/bluesky-social/atproto/commit/e4ec7af03608949fc3b00a845f547a77599b5ad0)]: 1198 + - @atproto/api@0.9.6 1199 + - @atproto/bsky@0.0.29 1200 + - @atproto/ozone@0.0.8 1201 + - @atproto/pds@0.3.17 1202 + 1203 + ## 0.2.28 1204 + 1205 + ### Patch Changes 1206 + 1207 + - Updated dependencies [[`8994d363`](https://github.com/bluesky-social/atproto/commit/8994d3633adad1c02569d6d44ae896e18195e8e2)]: 1208 + - @atproto/api@0.9.5 1209 + - @atproto/bsky@0.0.28 1210 + - @atproto/ozone@0.0.7 1211 + - @atproto/pds@0.3.16 1212 + 1213 + ## 0.2.27 1214 + 1215 + ### Patch Changes 1216 + 1217 + - Updated dependencies [[`4171c04a`](https://github.com/bluesky-social/atproto/commit/4171c04ad81c5734a4558bc41fa1c4f3a1aba18c)]: 1218 + - @atproto/api@0.9.4 1219 + - @atproto/bsky@0.0.27 1220 + - @atproto/ozone@0.0.6 1221 + - @atproto/pds@0.3.15 1222 + 1223 + ## 0.2.26 1224 + 1225 + ### Patch Changes 1226 + 1227 + - Updated dependencies [[`5368245a`](https://github.com/bluesky-social/atproto/commit/5368245a6ef7095c86ad166fb04ff9bef27c3c3e)]: 1228 + - @atproto/api@0.9.3 1229 + - @atproto/bsky@0.0.26 1230 + - @atproto/ozone@0.0.5 1231 + - @atproto/pds@0.3.14 1232 + 1233 + ## 0.2.25 1234 + 1235 + ### Patch Changes 1236 + 1237 + - Updated dependencies [[`15f38560`](https://github.com/bluesky-social/atproto/commit/15f38560b9e2dc3af8cf860826e7477234fe6a2d)]: 1238 + - @atproto/api@0.9.2 1239 + - @atproto/bsky@0.0.25 1240 + - @atproto/ozone@0.0.4 1241 + - @atproto/pds@0.3.13 1242 + 1243 + ## 0.2.24 1244 + 1245 + ### Patch Changes 1246 + 1247 + - Updated dependencies [[`c6fc73ae`](https://github.com/bluesky-social/atproto/commit/c6fc73aee6c245d12f876abd11889b8dbd0ce2ed)]: 1248 + - @atproto/api@0.9.1 1249 + - @atproto/bsky@0.0.24 1250 + - @atproto/ozone@0.0.3 1251 + - @atproto/pds@0.3.12 1252 + 1253 + ## 0.2.23 1254 + 1255 + ### Patch Changes 1256 + 1257 + - Updated dependencies [[`e43396af`](https://github.com/bluesky-social/atproto/commit/e43396af0973748dd2d034e88d35cf7ae8b4df2c), [`bf8d718c`](https://github.com/bluesky-social/atproto/commit/bf8d718cf918ac8d8a2cb1f57fde80535284642d), [`51fcba7a`](https://github.com/bluesky-social/atproto/commit/51fcba7a7945c604fc50e9545850a12ef0ee6da6)]: 1258 + - @atproto/api@0.9.0 1259 + - @atproto/bsky@0.0.23 1260 + - @atproto/pds@0.3.11 1261 + - @atproto/ozone@0.0.2 1262 + 1263 + ## 0.2.22 1264 + 1265 + ### Patch Changes 1266 + 1267 + - Updated dependencies [[`14067733`](https://github.com/bluesky-social/atproto/commit/140677335f76b99129c1f593d9e11d64624386c6)]: 1268 + - @atproto/api@0.8.0 1269 + - @atproto/bsky@0.0.22 1270 + - @atproto/pds@0.3.10 1271 + 1272 + ## 0.2.21 1273 + 1274 + ### Patch Changes 1275 + 1276 + - Updated dependencies [[`8f3f43cb`](https://github.com/bluesky-social/atproto/commit/8f3f43cb40f79ff7c52f81290daec55cfb000093)]: 1277 + - @atproto/api@0.7.4 1278 + - @atproto/bsky@0.0.21 1279 + - @atproto/pds@0.3.9 1280 + 1281 + ## 0.2.20 1282 + 1283 + ### Patch Changes 1284 + 1285 + - Updated dependencies [[`7dec9df3`](https://github.com/bluesky-social/atproto/commit/7dec9df3b583ee8c06c0c6a7e32c259820dc84a5)]: 1286 + - @atproto/api@0.7.3 1287 + - @atproto/bsky@0.0.20 1288 + - @atproto/pds@0.3.8 1289 + 1290 + ## 0.2.19 1291 + 1292 + ### Patch Changes 1293 + 1294 + - Updated dependencies [[`ffe39aae`](https://github.com/bluesky-social/atproto/commit/ffe39aae8394394f73bbfaa9047a8b5818aa053a), [`ffe39aae`](https://github.com/bluesky-social/atproto/commit/ffe39aae8394394f73bbfaa9047a8b5818aa053a)]: 1295 + - @atproto/bsky@0.0.19 1296 + - @atproto/api@0.7.2 1297 + - @atproto/pds@0.3.7 1298 + 1299 + ## 0.2.18 1300 + 1301 + ### Patch Changes 1302 + 1303 + - Updated dependencies [[`60deea17`](https://github.com/bluesky-social/atproto/commit/60deea17622f7c574c18432a55ced4e1cdc1b3a1)]: 1304 + - @atproto/api@0.7.1 1305 + - @atproto/bsky@0.0.18 1306 + - @atproto/pds@0.3.6 1307 + 1308 + ## 0.2.17 1309 + 1310 + ### Patch Changes 1311 + 1312 + - Updated dependencies [[`45352f9b`](https://github.com/bluesky-social/atproto/commit/45352f9b6d02aa405be94e9102424d983912ca5d)]: 1313 + - @atproto/api@0.7.0 1314 + - @atproto/bsky@0.0.17 1315 + - @atproto/pds@0.3.5 1316 + 1317 + ## 0.2.16 1318 + 1319 + ### Patch Changes 1320 + 1321 + - Updated dependencies [[`3c0ef382`](https://github.com/bluesky-social/atproto/commit/3c0ef382c12a413cc971ae47ffb341236c545f60), [`378fc613`](https://github.com/bluesky-social/atproto/commit/378fc6132f621ca517897c9467ed5bba134b3776)]: 1322 + - @atproto/syntax@0.1.5 1323 + - @atproto/api@0.6.24 1324 + - @atproto/bsky@0.0.16 1325 + - @atproto/lexicon@0.3.1 1326 + - @atproto/pds@0.3.4 1327 + - @atproto/xrpc-server@0.4.2 1328 + 1329 + ## 0.2.15 1330 + 1331 + ### Patch Changes 1332 + 1333 + - Updated dependencies [[`e1b5f253`](https://github.com/bluesky-social/atproto/commit/e1b5f2537a5ba4d8b951a741269b604856028ae5)]: 1334 + - @atproto/crypto@0.3.0 1335 + - @atproto/xrpc-server@0.4.1 1336 + - @atproto/bsky@0.0.15 1337 + - @atproto/identity@0.3.2 1338 + - @atproto/pds@0.3.3 1339 + - @atproto/api@0.6.23 1340 + 1341 + ## 0.2.14 1342 + 1343 + ### Patch Changes 1344 + 1345 + - Updated dependencies [[`772736a0`](https://github.com/bluesky-social/atproto/commit/772736a01081f39504e1b19a1b3687783bb78f07)]: 1346 + - @atproto/api@0.6.23 1347 + - @atproto/bsky@0.0.14 1348 + - @atproto/pds@0.3.2 1349 + 1350 + ## 0.2.13 1351 + 1352 + ### Patch Changes 1353 + 1354 + - [#1788](https://github.com/bluesky-social/atproto/pull/1788) [`84e2d4d2`](https://github.com/bluesky-social/atproto/commit/84e2d4d2b6694f344d80c18672c78b650189d423) Thanks [@bnewbold](https://github.com/bnewbold)! - update license to "MIT or Apache2" 1355 + 1356 + - Updated dependencies [[`ce49743d`](https://github.com/bluesky-social/atproto/commit/ce49743d7f8800d33116b88001d7b512553c2c89), [`84e2d4d2`](https://github.com/bluesky-social/atproto/commit/84e2d4d2b6694f344d80c18672c78b650189d423)]: 1357 + - @atproto/lexicon@0.3.0 1358 + - @atproto/xrpc-server@0.4.0 1359 + - @atproto/common-web@0.2.3 1360 + - @atproto/identity@0.3.1 1361 + - @atproto/crypto@0.2.3 1362 + - @atproto/syntax@0.1.4 1363 + - @atproto/bsky@0.0.13 1364 + - @atproto/api@0.6.22 1365 + - @atproto/pds@0.3.1 1366 + 1367 + ## 0.2.12 1368 + 1369 + ### Patch Changes 1370 + 1371 + - Updated dependencies [[`9c98a5ba`](https://github.com/bluesky-social/atproto/commit/9c98a5baaf503b02238a6afe4f6e2b79c5181693), [`bb039d8e`](https://github.com/bluesky-social/atproto/commit/bb039d8e4ce5b7f70c4f3e86d1327e210ef24dc3), [`35d108ce`](https://github.com/bluesky-social/atproto/commit/35d108ce94866ce1b3d147cd0620a0ba1c4ebcd7)]: 1372 + - @atproto/api@0.6.21 1373 + - @atproto/identity@0.3.0 1374 + - @atproto/common-web@0.2.2 1375 + - @atproto/bsky@0.0.12 1376 + - @atproto/pds@0.3.0 1377 + - @atproto/lexicon@0.2.3 1378 + - @atproto/syntax@0.1.3 1379 + - @atproto/xrpc-server@0.3.3 1380 + 1381 + ## 0.2.11 1382 + 1383 + ### Patch Changes 1384 + 1385 + - [#1568](https://github.com/bluesky-social/atproto/pull/1568) [`41ee177f`](https://github.com/bluesky-social/atproto/commit/41ee177f5a440490280d17acd8a89bcddaffb23b) Thanks [@dholms](https://github.com/dholms)! - Added email verification and update flows 1386 + 1387 + - Updated dependencies [[`41ee177f`](https://github.com/bluesky-social/atproto/commit/41ee177f5a440490280d17acd8a89bcddaffb23b), [`41ee177f`](https://github.com/bluesky-social/atproto/commit/41ee177f5a440490280d17acd8a89bcddaffb23b)]: 1388 + - @atproto/api@0.6.20 1389 + - @atproto/pds@0.1.20 1390 + - @atproto/common-web@0.2.1 1391 + - @atproto/bsky@0.0.11 1392 + - @atproto/identity@0.2.1 1393 + - @atproto/syntax@0.1.2 1394 + - @atproto/xrpc-server@0.3.2 1395 + 1396 + ## 0.2.10 1397 + 1398 + ### Patch Changes 1399 + 1400 + - Updated dependencies [[`35b616cd`](https://github.com/bluesky-social/atproto/commit/35b616cd82232879937afc88d3f77d20c6395276)]: 1401 + - @atproto/api@0.6.19 1402 + - @atproto/bsky@0.0.10 1403 + - @atproto/pds@0.1.19 1404 + 1405 + ## 0.2.9 1406 + 1407 + ### Patch Changes 1408 + 1409 + - Updated dependencies [[`2ce8a11b`](https://github.com/bluesky-social/atproto/commit/2ce8a11b8daf5d39027488c5dde8c47b0eb937bf)]: 1410 + - @atproto/api@0.6.18 1411 + - @atproto/bsky@0.0.9 1412 + - @atproto/pds@0.1.18 1413 + 1414 + ## 0.2.8 1415 + 1416 + ### Patch Changes 1417 + 1418 + - Updated dependencies [[`d96f7d9b`](https://github.com/bluesky-social/atproto/commit/d96f7d9b84c6fbab9711059c8584a77d892dcedd)]: 1419 + - @atproto/bsky@0.0.8 1420 + - @atproto/api@0.6.17 1421 + - @atproto/pds@0.1.17 1422 + 1423 + ## 0.2.7 1424 + 1425 + ### Patch Changes 1426 + 1427 + - Updated dependencies [[`56e2cf89`](https://github.com/bluesky-social/atproto/commit/56e2cf8999f6d7522529a9be8652c47545f82242)]: 1428 + - @atproto/api@0.6.16 1429 + - @atproto/bsky@0.0.7 1430 + - @atproto/pds@0.1.16 1431 + 1432 + ## 0.2.6 1433 + 1434 + ### Patch Changes 1435 + 1436 + - Updated dependencies [[`2cc329f2`](https://github.com/bluesky-social/atproto/commit/2cc329f26547217dd94b6bb11ee590d707cbd14f)]: 1437 + - @atproto/api@0.6.15 1438 + - @atproto/bsky@0.0.6 1439 + - @atproto/pds@0.1.15 1440 + 1441 + ## 0.2.5 1442 + 1443 + ### Patch Changes 1444 + 1445 + - Updated dependencies [[`b1dc3555`](https://github.com/bluesky-social/atproto/commit/b1dc355504f9f2e047093dc56682b8034518cf80)]: 1446 + - @atproto/syntax@0.1.1 1447 + - @atproto/api@0.6.14 1448 + - @atproto/bsky@0.0.5 1449 + - @atproto/pds@0.1.14 1450 + - @atproto/xrpc-server@0.3.1 1451 + 1452 + ## 0.2.4 1453 + 1454 + ### Patch Changes 1455 + 1456 + - Updated dependencies [[`3877210e`](https://github.com/bluesky-social/atproto/commit/3877210e7fb3c76dfb1a11eb9ba3f18426301d9f)]: 1457 + - @atproto/api@0.6.13 1458 + - @atproto/bsky@0.0.4 1459 + - @atproto/pds@0.1.13
+39
services/dev-env/README.md
··· 1 + # @atproto/dev-env: Local Developer Environment 2 + 3 + A command-line application for developers to construct and manage development environments. 4 + 5 + [![NPM](https://img.shields.io/npm/v/@atproto/dev-env)](https://www.npmjs.com/package/@atproto/dev-env) 6 + [![Github CI Status](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml/badge.svg)](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml) 7 + 8 + ## REPL API 9 + 10 + The following methods are available in the REPL. 11 + 12 + ### `status()` 13 + 14 + List the currently active servers. 15 + 16 + ### `startPds(port?: number)` 17 + 18 + Create a new PDS instance. Data is stored in memory. 19 + 20 + ### `stop(port: number)` 21 + 22 + Stop the server at the given port. 23 + 24 + ### `mkuser(handle: string, pdsPort?: number)` 25 + 26 + Create a new user. 27 + 28 + ### `user(handle: string): ServiceClient` 29 + 30 + Get the `ServiceClient` for the given user. 31 + 32 + ## License 33 + 34 + This project is dual-licensed under MIT and Apache 2.0 terms: 35 + 36 + - MIT license ([LICENSE-MIT.txt](https://github.com/bluesky-social/atproto/blob/main/LICENSE-MIT.txt) or http://opensource.org/licenses/MIT) 37 + - Apache License, Version 2.0, ([LICENSE-APACHE.txt](https://github.com/bluesky-social/atproto/blob/main/LICENSE-APACHE.txt) or http://www.apache.org/licenses/LICENSE-2.0) 38 + 39 + Downstream projects and end users may chose either license individually, or both together, at their discretion. The motivation for this dual-licensing is the additional software patent assurance provided by Apache 2.0.
services/dev-env/assets/at.png

This is a binary file and will not be displayed.

services/dev-env/assets/hd-key.jpg

This is a binary file and will not be displayed.

services/dev-env/assets/key-alt.jpg

This is a binary file and will not be displayed.

services/dev-env/assets/key-landscape-large.jpg

This is a binary file and will not be displayed.

services/dev-env/assets/key-landscape-small.jpg

This is a binary file and will not be displayed.

services/dev-env/assets/key-portrait-large.jpg

This is a binary file and will not be displayed.

services/dev-env/assets/key-portrait-small.jpg

This is a binary file and will not be displayed.

+60
services/dev-env/package.json
··· 1 + { 2 + "name": "@atproto/dev-env", 3 + "version": "0.3.97", 4 + "license": "MIT", 5 + "description": "Local development environment helper for atproto development", 6 + "keywords": [ 7 + "atproto" 8 + ], 9 + "homepage": "https://atproto.com", 10 + "repository": { 11 + "type": "git", 12 + "url": "https://github.com/bluesky-social/atproto", 13 + "directory": "packages/dev-env" 14 + }, 15 + "main": "dist/index.js", 16 + "types": "dist/index.d.ts", 17 + "bin": "dist/bin.js", 18 + "scripts": { 19 + "build": "tsc --build tsconfig.build.json", 20 + "start": "../dev-infra/with-test-redis-and-db.sh node dist/bin.js", 21 + "dev": "../dev-infra/with-test-redis-and-db.sh node --watch dist/bin.js" 22 + }, 23 + "engines": { 24 + "node": ">=18.7.0" 25 + }, 26 + "dependencies": { 27 + "@atproto/api": "0.14.7", 28 + "@atproto/bsky": "0.0.124", 29 + "@atproto/bsync": "0.0.14", 30 + "@atproto/common-web": "0.4.0", 31 + "@atproto/crypto": "0.4.4", 32 + "@atproto/identity": "0.4.6", 33 + "@atproto/lexicon": "0.4.7", 34 + "@atproto/ozone": "0.1.86", 35 + "@atproto/pds": "0.4.104", 36 + "@atproto/sync": "0.1.15", 37 + "@atproto/syntax": "0.3.3", 38 + "@atproto/xrpc-server": "0.7.11", 39 + "@did-plc/lib": "^0.0.1", 40 + "@did-plc/server": "^0.0.1", 41 + "dotenv": "^16.0.3", 42 + "express": "^4.18.2", 43 + "get-port": "^5.1.1", 44 + "multiformats": "^9.9.0", 45 + "uint8arrays": "3.0.0", 46 + "undici": "^6.14.1" 47 + }, 48 + "devDependencies": { 49 + "@types/express": "^4.17.13", 50 + "@types/node": "^22.13.5", 51 + "typescript": "^5.6.3" 52 + }, 53 + "pnpm": { 54 + "onlyBuiltDependencies": [ 55 + "better-sqlite3", 56 + "cbor-extract", 57 + "sharp" 58 + ] 59 + } 60 + }
+4600
services/dev-env/pnpm-lock.yaml
··· 1 + lockfileVersion: '9.0' 2 + 3 + settings: 4 + autoInstallPeers: true 5 + excludeLinksFromLockfile: false 6 + 7 + importers: 8 + 9 + .: 10 + dependencies: 11 + '@atproto/api': 12 + specifier: 0.14.7 13 + version: 0.14.7 14 + '@atproto/bsky': 15 + specifier: 0.0.124 16 + version: 0.0.124 17 + '@atproto/bsync': 18 + specifier: 0.0.14 19 + version: 0.0.14 20 + '@atproto/common-web': 21 + specifier: 0.4.0 22 + version: 0.4.0 23 + '@atproto/crypto': 24 + specifier: 0.4.4 25 + version: 0.4.4 26 + '@atproto/identity': 27 + specifier: 0.4.6 28 + version: 0.4.6 29 + '@atproto/lexicon': 30 + specifier: 0.4.7 31 + version: 0.4.7 32 + '@atproto/ozone': 33 + specifier: 0.1.86 34 + version: 0.1.86 35 + '@atproto/pds': 36 + specifier: 0.4.104 37 + version: 0.4.104 38 + '@atproto/sync': 39 + specifier: 0.1.15 40 + version: 0.1.15 41 + '@atproto/syntax': 42 + specifier: 0.3.3 43 + version: 0.3.3 44 + '@atproto/xrpc-server': 45 + specifier: 0.7.11 46 + version: 0.7.11 47 + '@did-plc/lib': 48 + specifier: ^0.0.1 49 + version: 0.0.1 50 + '@did-plc/server': 51 + specifier: ^0.0.1 52 + version: 0.0.1 53 + dotenv: 54 + specifier: ^16.0.3 55 + version: 16.4.7 56 + express: 57 + specifier: ^4.18.2 58 + version: 4.21.2 59 + get-port: 60 + specifier: ^5.1.1 61 + version: 5.1.1 62 + multiformats: 63 + specifier: ^9.9.0 64 + version: 9.9.0 65 + uint8arrays: 66 + specifier: 3.0.0 67 + version: 3.0.0 68 + undici: 69 + specifier: ^6.14.1 70 + version: 6.21.1 71 + devDependencies: 72 + '@types/express': 73 + specifier: ^4.17.13 74 + version: 4.17.21 75 + '@types/node': 76 + specifier: ^22.13.5 77 + version: 22.13.5 78 + typescript: 79 + specifier: ^5.6.3 80 + version: 5.7.3 81 + 82 + packages: 83 + 84 + '@atproto-labs/fetch-node@0.1.7': 85 + resolution: {integrity: sha512-vZ627PQqVGiBmPxulnviIGvvBPpTdzOcnfU1WcLeES3E0WjNxRGQqFaodBl5Zc4cj3QSPG/KC6wPcj/rjhbDrQ==} 86 + engines: {node: '>=18.7.0'} 87 + 88 + '@atproto-labs/fetch@0.2.1': 89 + resolution: {integrity: sha512-V22/7C7r+FfIDZA/BVn5UeuK5JccDp7nOiRfp5JITpVw2OXQbVfd8kywN7voWvPXw4sjd4cHoIPgQa0wvQGenQ==} 90 + 91 + '@atproto-labs/pipe@0.1.0': 92 + resolution: {integrity: sha512-ghOqHFyJlQVFPESzlVHjKroP0tPzbmG5Jms0dNI9yLDEfL8xp4OFPWLX4f6T8mRq69wWs4nIDM3sSsFbFqLa1w==} 93 + 94 + '@atproto-labs/simple-store-memory@0.1.2': 95 + resolution: {integrity: sha512-q6wawjKKXuhUzr2MnkSlgr6zU6VimYkL8eNvLQvkroLnIDyMkoCKO4+EJ885ZD8lGwBo4pX9Lhrg9JJ+ncJI8g==} 96 + 97 + '@atproto-labs/simple-store@0.1.2': 98 + resolution: {integrity: sha512-9vTNvyPPBs44tKVFht16wGlilW8u4wpEtKwLkWbuNEh3h9TTQ8zjVhEoGZh/v73G4Otr9JUOSIq+/5+8OZD2mQ==} 99 + 100 + '@atproto-labs/xrpc-utils@0.0.7': 101 + resolution: {integrity: sha512-mNev88mtNo79h4bkEQYuLoTlejc1zMl9lLwKbpKYfFaaU0IS9VdhiPdRTEcQ6JGYK915OZ5Lv7OJQNF0g9qq9w==} 102 + 103 + '@atproto/api@0.14.7': 104 + resolution: {integrity: sha512-YG2kvAtsgtajLlLrorYuHcxGgepG0c/RUB2/iJyBnwKjGqDLG8joOETf38JSNiGzs6NJbNKa9NHG6BQKourxBA==} 105 + 106 + '@atproto/aws@0.2.16': 107 + resolution: {integrity: sha512-NXWEBybqiVErKGbcKLrevFaUTMCazb6XtM/HX7EYgyQdtyl4MwzGr93aZcwoSkOFBhJr3t7sNQHC3Tpyh5l+hg==} 108 + engines: {node: '>=18.7.0'} 109 + 110 + '@atproto/bsky@0.0.124': 111 + resolution: {integrity: sha512-yar3reXczoEMV3ImoKMo+L2UhQApUrVvVtQAiVjc38+HHEVl4ikopiLtwBmY+lB71wikxSOI3bc8APzR3kyitw==} 112 + engines: {node: '>=18.7.0'} 113 + hasBin: true 114 + 115 + '@atproto/bsync@0.0.14': 116 + resolution: {integrity: sha512-y6ioCJxmqnwQUc/MqBDCrNciJqrPanqSMjMneEU7mRSdbxXW27b1TblADSJeavkn8vbUGJUEmMWcqgWOrRClpw==} 117 + engines: {node: '>=18.7.0'} 118 + 119 + '@atproto/common-web@0.4.0': 120 + resolution: {integrity: sha512-ZYL0P9myHybNgwh/hBY0HaBzqiLR1B5/ie5bJpLQAg0whRzNA28t8/nU2vh99tbsWcAF0LOD29M8++LyENJLNQ==} 121 + 122 + '@atproto/common@0.1.0': 123 + resolution: {integrity: sha512-OB5tWE2R19jwiMIs2IjQieH5KTUuMb98XGCn9h3xuu6NanwjlmbCYMv08fMYwIp3UQ6jcq//84cDT3Bu6fJD+A==} 124 + 125 + '@atproto/common@0.1.1': 126 + resolution: {integrity: sha512-GYwot5wF/z8iYGSPjrLHuratLc0CVgovmwfJss7+BUOB6y2/Vw8+1Vw0n9DDI0gb5vmx3UI8z0uJgC8aa8yuJg==} 127 + 128 + '@atproto/common@0.4.8': 129 + resolution: {integrity: sha512-/etCtnWQGLcfiGhIPwxAWrzgzoGB22nMWMeQcU6xZgRT4Cqrfg3A08jAMIHqve/AQpL+6D82lHYp36CG7a5G0w==} 130 + engines: {node: '>=18.7.0'} 131 + 132 + '@atproto/crypto@0.1.0': 133 + resolution: {integrity: sha512-9xgFEPtsCiJEPt9o3HtJT30IdFTGw5cQRSJVIy5CFhqBA4vDLcdXiRDLCjkzHEVbtNCsHUW6CrlfOgbeLPcmcg==} 134 + 135 + '@atproto/crypto@0.4.4': 136 + resolution: {integrity: sha512-Yq9+crJ7WQl7sxStVpHgie5Z51R05etaK9DLWYG/7bR5T4bhdcIgF6IfklLShtZwLYdVVj+K15s0BqW9a8PSDA==} 137 + engines: {node: '>=18.7.0'} 138 + 139 + '@atproto/did@0.1.5': 140 + resolution: {integrity: sha512-8+1D08QdGE5TF0bB0vV8HLVrVZJeLNITpRTUVEoABNMRaUS7CoYSVb0+JNQDeJIVmqMjOL8dOjvCUDkp3gEaGQ==} 141 + 142 + '@atproto/identity@0.4.6': 143 + resolution: {integrity: sha512-fJq/cIp9MOgHxZfxuyki6mobk0QxRnbts53DstRixlvb5mOoxwttb9Gp6A8u9q49zBsfOmXNTHmP97I9iMHmTQ==} 144 + engines: {node: '>=18.7.0'} 145 + 146 + '@atproto/jwk-jose@0.1.4': 147 + resolution: {integrity: sha512-JzLn1wUzuLfweznSECdTjSHTxQBEz7Q8oJ4XKjRNludqzyJW8etEH00l1WolLipFxoj1QCG9qy00JmlC59Y6Rw==} 148 + 149 + '@atproto/jwk@0.1.3': 150 + resolution: {integrity: sha512-5rBgA8Fk4fg6MfNyEQvUnwq1MRn5xZOXYj4oxLuZ549XeNp2Rm2v+psuEkICD+o6pfIoMX4Hw7UTlXDrpsKKlQ==} 151 + 152 + '@atproto/lexicon@0.4.7': 153 + resolution: {integrity: sha512-/x6h3tAiDNzSi4eXtC8ke65B7UzsagtlGRHmUD95698x5lBRpDnpizj0fZWTZVYed5qnOmz/ZEue+v3wDmO61g==} 154 + 155 + '@atproto/oauth-provider@0.4.0': 156 + resolution: {integrity: sha512-epY+4BXNyK7DBpMfCigD0580xNWYqRr6rpb7m3q0Oa5+L9AoJvcWZfUHXw6J7PIlk6jmj/aeDFjE89p+SivyFw==} 157 + engines: {node: '>=18.7.0'} 158 + 159 + '@atproto/oauth-types@0.2.3': 160 + resolution: {integrity: sha512-M+0WW/alS2BfhKtwvdU3rSaLoycw6kTH1kGKeyDdmb/xN/8QjU7T6dkJe+wX4NC7F23xdKfti9DZhBpEtn+/kg==} 161 + 162 + '@atproto/ozone@0.1.86': 163 + resolution: {integrity: sha512-NEHQj0aC03JN0k3MZ0zpGF3+isDMKlrD+RgvUhMpk64WBUe7TBCWhRr3qcoZDbaOJQK/5rPnNQRzhbk+JERwXA==} 164 + engines: {node: '>=18.7.0'} 165 + hasBin: true 166 + 167 + '@atproto/pds@0.4.104': 168 + resolution: {integrity: sha512-sOInZB/RphJXYdghVaSQKkorAH+u6b+AfK57bPimhkcUa1kDnPasyC2HuuFm6wXQfifkQrxIMg45MnuZbbg5SA==} 169 + engines: {node: '>=18.7.0'} 170 + hasBin: true 171 + 172 + '@atproto/repo@0.7.0': 173 + resolution: {integrity: sha512-n0xyMsKuCxRyP7wROg1wX8vUEnt+H0umIyFUlMTz6jb8XPYk88p5XTcTmLV3dNNu0f71JPd2Jzt6/EGub9zxMg==} 174 + engines: {node: '>=18.7.0'} 175 + 176 + '@atproto/sync@0.1.15': 177 + resolution: {integrity: sha512-aDabG0vlCAIXr7luPe0lviWdf4SYLi3lQeOCclvptebRwmbXy50QNAvln3coshmx2DdsEbJHd2L0XZJVelR5XA==} 178 + engines: {node: '>=18.7.0'} 179 + 180 + '@atproto/syntax@0.3.3': 181 + resolution: {integrity: sha512-F1LZweesNYdBbZBXVa72N/cSvchG8Q1tG4/209ZXbIuM3FwQtkgn+zgmmV4P4ORmhOeXPBNXvMBpcqiwx/gEQQ==} 182 + 183 + '@atproto/xrpc-server@0.7.11': 184 + resolution: {integrity: sha512-kywMZMw2FbUFk0xBCtSI1mik+dc3uSvloNndI+N4X/+Qv1FGvoCRMi//9TqaSL13MFevTOynVoMVmaZbnaDG9A==} 185 + engines: {node: '>=18.7.0'} 186 + 187 + '@atproto/xrpc@0.6.9': 188 + resolution: {integrity: sha512-vQGA7++DYMNaHx3C7vEjT+2X6hYYLG7JNbBnDLWu0km1/1KYXgRkAz4h+FfYqg1mvzvIorHU7DAs5wevkJDDlw==} 189 + 190 + '@aws-crypto/crc32@5.2.0': 191 + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} 192 + engines: {node: '>=16.0.0'} 193 + 194 + '@aws-crypto/crc32c@5.2.0': 195 + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} 196 + 197 + '@aws-crypto/sha1-browser@5.2.0': 198 + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} 199 + 200 + '@aws-crypto/sha256-browser@5.2.0': 201 + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} 202 + 203 + '@aws-crypto/sha256-js@5.2.0': 204 + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} 205 + engines: {node: '>=16.0.0'} 206 + 207 + '@aws-crypto/supports-web-crypto@5.2.0': 208 + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} 209 + 210 + '@aws-crypto/util@5.2.0': 211 + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} 212 + 213 + '@aws-sdk/client-cloudfront@3.758.0': 214 + resolution: {integrity: sha512-kAIMe+cwH+ZuK/rM3L8NdM8rS5cnCoFTgCbjF4GVjDnZJ8JlNm3oRIKAK55mmgtGLuqEz1h6QVLrV01/fNvYaA==} 215 + engines: {node: '>=18.0.0'} 216 + 217 + '@aws-sdk/client-kms@3.758.0': 218 + resolution: {integrity: sha512-dHfIwtkvxV/TW/0/jhD8e5hbL/vaOLiDHEK+iL/bFNjDKI1AHZn7LLoNFLnlP/kdGpB3dOYWgA+BUwUlymgFOg==} 219 + engines: {node: '>=18.0.0'} 220 + 221 + '@aws-sdk/client-s3@3.758.0': 222 + resolution: {integrity: sha512-f8SlhU9/93OC/WEI6xVJf/x/GoQFj9a/xXK6QCtr5fvCjfSLgMVFmKTiIl/tgtDRzxUDc8YS6EGtbHjJ3Y/atg==} 223 + engines: {node: '>=18.0.0'} 224 + 225 + '@aws-sdk/client-sso@3.758.0': 226 + resolution: {integrity: sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==} 227 + engines: {node: '>=18.0.0'} 228 + 229 + '@aws-sdk/core@3.758.0': 230 + resolution: {integrity: sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==} 231 + engines: {node: '>=18.0.0'} 232 + 233 + '@aws-sdk/credential-provider-env@3.758.0': 234 + resolution: {integrity: sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==} 235 + engines: {node: '>=18.0.0'} 236 + 237 + '@aws-sdk/credential-provider-http@3.758.0': 238 + resolution: {integrity: sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==} 239 + engines: {node: '>=18.0.0'} 240 + 241 + '@aws-sdk/credential-provider-ini@3.758.0': 242 + resolution: {integrity: sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==} 243 + engines: {node: '>=18.0.0'} 244 + 245 + '@aws-sdk/credential-provider-node@3.758.0': 246 + resolution: {integrity: sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==} 247 + engines: {node: '>=18.0.0'} 248 + 249 + '@aws-sdk/credential-provider-process@3.758.0': 250 + resolution: {integrity: sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==} 251 + engines: {node: '>=18.0.0'} 252 + 253 + '@aws-sdk/credential-provider-sso@3.758.0': 254 + resolution: {integrity: sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==} 255 + engines: {node: '>=18.0.0'} 256 + 257 + '@aws-sdk/credential-provider-web-identity@3.758.0': 258 + resolution: {integrity: sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==} 259 + engines: {node: '>=18.0.0'} 260 + 261 + '@aws-sdk/lib-storage@3.758.0': 262 + resolution: {integrity: sha512-g07y7rA505zaTJNPTmvW4zYJA3gThFDE1be7kBUKhTKAdwv8jVSbOiAy2AhClXs2evSUoQiFFtD1xWxLRXPPRQ==} 263 + engines: {node: '>=18.0.0'} 264 + peerDependencies: 265 + '@aws-sdk/client-s3': ^3.758.0 266 + 267 + '@aws-sdk/middleware-bucket-endpoint@3.734.0': 268 + resolution: {integrity: sha512-etC7G18aF7KdZguW27GE/wpbrNmYLVT755EsFc8kXpZj8D6AFKxc7OuveinJmiy0bYXAMspJUWsF6CrGpOw6CQ==} 269 + engines: {node: '>=18.0.0'} 270 + 271 + '@aws-sdk/middleware-expect-continue@3.734.0': 272 + resolution: {integrity: sha512-P38/v1l6HjuB2aFUewt7ueAW5IvKkFcv5dalPtbMGRhLeyivBOHwbCyuRKgVs7z7ClTpu9EaViEGki2jEQqEsQ==} 273 + engines: {node: '>=18.0.0'} 274 + 275 + '@aws-sdk/middleware-flexible-checksums@3.758.0': 276 + resolution: {integrity: sha512-o8Rk71S08YTKLoSobucjnbj97OCGaXgpEDNKXpXaavUM5xLNoHCLSUPRCiEN86Ivqxg1n17Y2nSRhfbsveOXXA==} 277 + engines: {node: '>=18.0.0'} 278 + 279 + '@aws-sdk/middleware-host-header@3.734.0': 280 + resolution: {integrity: sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==} 281 + engines: {node: '>=18.0.0'} 282 + 283 + '@aws-sdk/middleware-location-constraint@3.734.0': 284 + resolution: {integrity: sha512-EJEIXwCQhto/cBfHdm3ZOeLxd2NlJD+X2F+ZTOxzokuhBtY0IONfC/91hOo5tWQweerojwshSMHRCKzRv1tlwg==} 285 + engines: {node: '>=18.0.0'} 286 + 287 + '@aws-sdk/middleware-logger@3.734.0': 288 + resolution: {integrity: sha512-mUMFITpJUW3LcKvFok176eI5zXAUomVtahb9IQBwLzkqFYOrMJvWAvoV4yuxrJ8TlQBG8gyEnkb9SnhZvjg67w==} 289 + engines: {node: '>=18.0.0'} 290 + 291 + '@aws-sdk/middleware-recursion-detection@3.734.0': 292 + resolution: {integrity: sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==} 293 + engines: {node: '>=18.0.0'} 294 + 295 + '@aws-sdk/middleware-sdk-s3@3.758.0': 296 + resolution: {integrity: sha512-6mJ2zyyHPYSV6bAcaFpsdoXZJeQlR1QgBnZZ6juY/+dcYiuyWCdyLUbGzSZSE7GTfx6i+9+QWFeoIMlWKgU63A==} 297 + engines: {node: '>=18.0.0'} 298 + 299 + '@aws-sdk/middleware-ssec@3.734.0': 300 + resolution: {integrity: sha512-d4yd1RrPW/sspEXizq2NSOUivnheac6LPeLSLnaeTbBG9g1KqIqvCzP1TfXEqv2CrWfHEsWtJpX7oyjySSPvDQ==} 301 + engines: {node: '>=18.0.0'} 302 + 303 + '@aws-sdk/middleware-user-agent@3.758.0': 304 + resolution: {integrity: sha512-iNyehQXtQlj69JCgfaOssgZD4HeYGOwxcaKeG6F+40cwBjTAi0+Ph1yfDwqk2qiBPIRWJ/9l2LodZbxiBqgrwg==} 305 + engines: {node: '>=18.0.0'} 306 + 307 + '@aws-sdk/nested-clients@3.758.0': 308 + resolution: {integrity: sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==} 309 + engines: {node: '>=18.0.0'} 310 + 311 + '@aws-sdk/region-config-resolver@3.734.0': 312 + resolution: {integrity: sha512-Lvj1kPRC5IuJBr9DyJ9T9/plkh+EfKLy+12s/mykOy1JaKHDpvj+XGy2YO6YgYVOb8JFtaqloid+5COtje4JTQ==} 313 + engines: {node: '>=18.0.0'} 314 + 315 + '@aws-sdk/signature-v4-multi-region@3.758.0': 316 + resolution: {integrity: sha512-0RPCo8fYJcrenJ6bRtiUbFOSgQ1CX/GpvwtLU2Fam1tS9h2klKK8d74caeV6A1mIUvBU7bhyQ0wMGlwMtn3EYw==} 317 + engines: {node: '>=18.0.0'} 318 + 319 + '@aws-sdk/token-providers@3.758.0': 320 + resolution: {integrity: sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==} 321 + engines: {node: '>=18.0.0'} 322 + 323 + '@aws-sdk/types@3.734.0': 324 + resolution: {integrity: sha512-o11tSPTT70nAkGV1fN9wm/hAIiLPyWX6SuGf+9JyTp7S/rC2cFWhR26MvA69nplcjNaXVzB0f+QFrLXXjOqCrg==} 325 + engines: {node: '>=18.0.0'} 326 + 327 + '@aws-sdk/util-arn-parser@3.723.0': 328 + resolution: {integrity: sha512-ZhEfvUwNliOQROcAk34WJWVYTlTa4694kSVhDSjW6lE1bMataPnIN8A0ycukEzBXmd8ZSoBcQLn6lKGl7XIJ5w==} 329 + engines: {node: '>=18.0.0'} 330 + 331 + '@aws-sdk/util-endpoints@3.743.0': 332 + resolution: {integrity: sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==} 333 + engines: {node: '>=18.0.0'} 334 + 335 + '@aws-sdk/util-locate-window@3.723.0': 336 + resolution: {integrity: sha512-Yf2CS10BqK688DRsrKI/EO6B8ff5J86NXe4C+VCysK7UOgN0l1zOTeTukZ3H8Q9tYYX3oaF1961o8vRkFm7Nmw==} 337 + engines: {node: '>=18.0.0'} 338 + 339 + '@aws-sdk/util-user-agent-browser@3.734.0': 340 + resolution: {integrity: sha512-xQTCus6Q9LwUuALW+S76OL0jcWtMOVu14q+GoLnWPUM7QeUw963oQcLhF7oq0CtaLLKyl4GOUfcwc773Zmwwng==} 341 + 342 + '@aws-sdk/util-user-agent-node@3.758.0': 343 + resolution: {integrity: sha512-A5EZw85V6WhoKMV2hbuFRvb9NPlxEErb4HPO6/SPXYY4QrjprIzScHxikqcWv1w4J3apB1wto9LPU3IMsYtfrw==} 344 + engines: {node: '>=18.0.0'} 345 + peerDependencies: 346 + aws-crt: '>=1.0.0' 347 + peerDependenciesMeta: 348 + aws-crt: 349 + optional: true 350 + 351 + '@aws-sdk/xml-builder@3.734.0': 352 + resolution: {integrity: sha512-Zrjxi5qwGEcUsJ0ru7fRtW74WcTS0rbLcehoFB+rN1GRi2hbLcFaYs4PwVA5diLeAJH0gszv3x4Hr/S87MfbKQ==} 353 + engines: {node: '>=18.0.0'} 354 + 355 + '@bufbuild/protobuf@1.10.0': 356 + resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} 357 + 358 + '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': 359 + resolution: {integrity: sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==} 360 + cpu: [arm64] 361 + os: [darwin] 362 + 363 + '@cbor-extract/cbor-extract-darwin-x64@2.2.0': 364 + resolution: {integrity: sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==} 365 + cpu: [x64] 366 + os: [darwin] 367 + 368 + '@cbor-extract/cbor-extract-linux-arm64@2.2.0': 369 + resolution: {integrity: sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==} 370 + cpu: [arm64] 371 + os: [linux] 372 + 373 + '@cbor-extract/cbor-extract-linux-arm@2.2.0': 374 + resolution: {integrity: sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==} 375 + cpu: [arm] 376 + os: [linux] 377 + 378 + '@cbor-extract/cbor-extract-linux-x64@2.2.0': 379 + resolution: {integrity: sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==} 380 + cpu: [x64] 381 + os: [linux] 382 + 383 + '@cbor-extract/cbor-extract-win32-x64@2.2.0': 384 + resolution: {integrity: sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==} 385 + cpu: [x64] 386 + os: [win32] 387 + 388 + '@connectrpc/connect-express@1.6.1': 389 + resolution: {integrity: sha512-iTMTBHWT8Q1chR1k/c8UcrFN5iunrAaoXMjqqrmdy9o0ZDee1o7SvF8XGpB7JsP+1kchrZ1Sig6pkRO9Ybhdbw==} 390 + engines: {node: '>=16.0.0'} 391 + peerDependencies: 392 + '@bufbuild/protobuf': ^1.10.0 393 + '@connectrpc/connect': 1.6.1 394 + '@connectrpc/connect-node': 1.6.1 395 + 396 + '@connectrpc/connect-node@1.6.1': 397 + resolution: {integrity: sha512-DxcD1wsF/aX9GegjAtl7VbpiZNjVJozy87VbaFoN6AF0Ln1Q757r5dgV59Gz0wmlk5f17txUsrEr1f2inlnnAg==} 398 + engines: {node: '>=16.0.0'} 399 + peerDependencies: 400 + '@bufbuild/protobuf': ^1.10.0 401 + '@connectrpc/connect': 1.6.1 402 + 403 + '@connectrpc/connect@1.6.1': 404 + resolution: {integrity: sha512-KchMDNtU4CDTdkyf0qG7ugJ6qHTOR/aI7XebYn3OTCNagaDYWiZUVKgRgwH79yeMkpNgvEUaXSK7wKjaBK9b/Q==} 405 + peerDependencies: 406 + '@bufbuild/protobuf': ^1.10.0 407 + 408 + '@did-plc/lib@0.0.1': 409 + resolution: {integrity: sha512-RkY5w9DbYMco3SjeepqIiMveqz35exjlVDipCs2gz9AXF4/cp9hvmrp9zUWEw2vny+FjV8vGEN7QpaXWaO6nhg==} 410 + 411 + '@did-plc/lib@0.0.4': 412 + resolution: {integrity: sha512-Omeawq3b8G/c/5CtkTtzovSOnWuvIuCI4GTJNrt1AmCskwEQV7zbX5d6km1mjJNbE0gHuQPTVqZxLVqetNbfwA==} 413 + 414 + '@did-plc/server@0.0.1': 415 + resolution: {integrity: sha512-GtxxHcOrOQ6fNI1ufq3Zqjc2PtWqPZOdsuzlwtxiH9XibUGwDkb0GmaBHyU5GiOxOKZEW1GspZ8mreBA6XOlTQ==} 416 + 417 + '@emnapi/runtime@1.3.1': 418 + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} 419 + 420 + '@fastify/busboy@2.1.1': 421 + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 422 + engines: {node: '>=14'} 423 + 424 + '@hapi/accept@6.0.3': 425 + resolution: {integrity: sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==} 426 + 427 + '@hapi/address@5.1.1': 428 + resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==} 429 + engines: {node: '>=14.0.0'} 430 + 431 + '@hapi/boom@10.0.1': 432 + resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} 433 + 434 + '@hapi/bourne@3.0.0': 435 + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} 436 + 437 + '@hapi/content@6.0.0': 438 + resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} 439 + 440 + '@hapi/hoek@11.0.7': 441 + resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==} 442 + 443 + '@img/sharp-darwin-arm64@0.33.5': 444 + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} 445 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 446 + cpu: [arm64] 447 + os: [darwin] 448 + 449 + '@img/sharp-darwin-x64@0.33.5': 450 + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} 451 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 452 + cpu: [x64] 453 + os: [darwin] 454 + 455 + '@img/sharp-libvips-darwin-arm64@1.0.4': 456 + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} 457 + cpu: [arm64] 458 + os: [darwin] 459 + 460 + '@img/sharp-libvips-darwin-x64@1.0.4': 461 + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} 462 + cpu: [x64] 463 + os: [darwin] 464 + 465 + '@img/sharp-libvips-linux-arm64@1.0.4': 466 + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} 467 + cpu: [arm64] 468 + os: [linux] 469 + 470 + '@img/sharp-libvips-linux-arm@1.0.5': 471 + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} 472 + cpu: [arm] 473 + os: [linux] 474 + 475 + '@img/sharp-libvips-linux-s390x@1.0.4': 476 + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} 477 + cpu: [s390x] 478 + os: [linux] 479 + 480 + '@img/sharp-libvips-linux-x64@1.0.4': 481 + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} 482 + cpu: [x64] 483 + os: [linux] 484 + 485 + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 486 + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} 487 + cpu: [arm64] 488 + os: [linux] 489 + 490 + '@img/sharp-libvips-linuxmusl-x64@1.0.4': 491 + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} 492 + cpu: [x64] 493 + os: [linux] 494 + 495 + '@img/sharp-linux-arm64@0.33.5': 496 + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} 497 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 498 + cpu: [arm64] 499 + os: [linux] 500 + 501 + '@img/sharp-linux-arm@0.33.5': 502 + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} 503 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 504 + cpu: [arm] 505 + os: [linux] 506 + 507 + '@img/sharp-linux-s390x@0.33.5': 508 + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} 509 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 510 + cpu: [s390x] 511 + os: [linux] 512 + 513 + '@img/sharp-linux-x64@0.33.5': 514 + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} 515 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 516 + cpu: [x64] 517 + os: [linux] 518 + 519 + '@img/sharp-linuxmusl-arm64@0.33.5': 520 + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} 521 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 522 + cpu: [arm64] 523 + os: [linux] 524 + 525 + '@img/sharp-linuxmusl-x64@0.33.5': 526 + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} 527 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 528 + cpu: [x64] 529 + os: [linux] 530 + 531 + '@img/sharp-wasm32@0.33.5': 532 + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} 533 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 534 + cpu: [wasm32] 535 + 536 + '@img/sharp-win32-ia32@0.33.5': 537 + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} 538 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 539 + cpu: [ia32] 540 + os: [win32] 541 + 542 + '@img/sharp-win32-x64@0.33.5': 543 + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} 544 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 545 + cpu: [x64] 546 + os: [win32] 547 + 548 + '@ioredis/commands@1.2.0': 549 + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} 550 + 551 + '@ipld/car@3.2.4': 552 + resolution: {integrity: sha512-rezKd+jk8AsTGOoJKqzfjLJ3WVft7NZNH95f0pfPbicROvzTyvHCNy567HzSUd6gRXZ9im29z5ZEv9Hw49jSYw==} 553 + 554 + '@ipld/dag-cbor@7.0.3': 555 + resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==} 556 + 557 + '@isaacs/cliui@8.0.2': 558 + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 559 + engines: {node: '>=12'} 560 + 561 + '@noble/curves@1.8.1': 562 + resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} 563 + engines: {node: ^14.21.3 || >=16} 564 + 565 + '@noble/hashes@1.7.1': 566 + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} 567 + engines: {node: ^14.21.3 || >=16} 568 + 569 + '@noble/secp256k1@1.7.1': 570 + resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} 571 + 572 + '@pkgjs/parseargs@0.11.0': 573 + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 574 + engines: {node: '>=14'} 575 + 576 + '@smithy/abort-controller@4.0.1': 577 + resolution: {integrity: sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==} 578 + engines: {node: '>=18.0.0'} 579 + 580 + '@smithy/chunked-blob-reader-native@4.0.0': 581 + resolution: {integrity: sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==} 582 + engines: {node: '>=18.0.0'} 583 + 584 + '@smithy/chunked-blob-reader@5.0.0': 585 + resolution: {integrity: sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==} 586 + engines: {node: '>=18.0.0'} 587 + 588 + '@smithy/config-resolver@4.0.1': 589 + resolution: {integrity: sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==} 590 + engines: {node: '>=18.0.0'} 591 + 592 + '@smithy/core@3.1.5': 593 + resolution: {integrity: sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==} 594 + engines: {node: '>=18.0.0'} 595 + 596 + '@smithy/credential-provider-imds@4.0.1': 597 + resolution: {integrity: sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==} 598 + engines: {node: '>=18.0.0'} 599 + 600 + '@smithy/eventstream-codec@4.0.1': 601 + resolution: {integrity: sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==} 602 + engines: {node: '>=18.0.0'} 603 + 604 + '@smithy/eventstream-serde-browser@4.0.1': 605 + resolution: {integrity: sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==} 606 + engines: {node: '>=18.0.0'} 607 + 608 + '@smithy/eventstream-serde-config-resolver@4.0.1': 609 + resolution: {integrity: sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==} 610 + engines: {node: '>=18.0.0'} 611 + 612 + '@smithy/eventstream-serde-node@4.0.1': 613 + resolution: {integrity: sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==} 614 + engines: {node: '>=18.0.0'} 615 + 616 + '@smithy/eventstream-serde-universal@4.0.1': 617 + resolution: {integrity: sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==} 618 + engines: {node: '>=18.0.0'} 619 + 620 + '@smithy/fetch-http-handler@5.0.1': 621 + resolution: {integrity: sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==} 622 + engines: {node: '>=18.0.0'} 623 + 624 + '@smithy/hash-blob-browser@4.0.1': 625 + resolution: {integrity: sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==} 626 + engines: {node: '>=18.0.0'} 627 + 628 + '@smithy/hash-node@4.0.1': 629 + resolution: {integrity: sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==} 630 + engines: {node: '>=18.0.0'} 631 + 632 + '@smithy/hash-stream-node@4.0.1': 633 + resolution: {integrity: sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==} 634 + engines: {node: '>=18.0.0'} 635 + 636 + '@smithy/invalid-dependency@4.0.1': 637 + resolution: {integrity: sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==} 638 + engines: {node: '>=18.0.0'} 639 + 640 + '@smithy/is-array-buffer@2.2.0': 641 + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} 642 + engines: {node: '>=14.0.0'} 643 + 644 + '@smithy/is-array-buffer@4.0.0': 645 + resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} 646 + engines: {node: '>=18.0.0'} 647 + 648 + '@smithy/md5-js@4.0.1': 649 + resolution: {integrity: sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==} 650 + engines: {node: '>=18.0.0'} 651 + 652 + '@smithy/middleware-content-length@4.0.1': 653 + resolution: {integrity: sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==} 654 + engines: {node: '>=18.0.0'} 655 + 656 + '@smithy/middleware-endpoint@4.0.6': 657 + resolution: {integrity: sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==} 658 + engines: {node: '>=18.0.0'} 659 + 660 + '@smithy/middleware-retry@4.0.7': 661 + resolution: {integrity: sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==} 662 + engines: {node: '>=18.0.0'} 663 + 664 + '@smithy/middleware-serde@4.0.2': 665 + resolution: {integrity: sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==} 666 + engines: {node: '>=18.0.0'} 667 + 668 + '@smithy/middleware-stack@4.0.1': 669 + resolution: {integrity: sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==} 670 + engines: {node: '>=18.0.0'} 671 + 672 + '@smithy/node-config-provider@4.0.1': 673 + resolution: {integrity: sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==} 674 + engines: {node: '>=18.0.0'} 675 + 676 + '@smithy/node-http-handler@4.0.3': 677 + resolution: {integrity: sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==} 678 + engines: {node: '>=18.0.0'} 679 + 680 + '@smithy/property-provider@4.0.1': 681 + resolution: {integrity: sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==} 682 + engines: {node: '>=18.0.0'} 683 + 684 + '@smithy/protocol-http@5.0.1': 685 + resolution: {integrity: sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==} 686 + engines: {node: '>=18.0.0'} 687 + 688 + '@smithy/querystring-builder@4.0.1': 689 + resolution: {integrity: sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==} 690 + engines: {node: '>=18.0.0'} 691 + 692 + '@smithy/querystring-parser@4.0.1': 693 + resolution: {integrity: sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==} 694 + engines: {node: '>=18.0.0'} 695 + 696 + '@smithy/service-error-classification@4.0.1': 697 + resolution: {integrity: sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==} 698 + engines: {node: '>=18.0.0'} 699 + 700 + '@smithy/shared-ini-file-loader@4.0.1': 701 + resolution: {integrity: sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==} 702 + engines: {node: '>=18.0.0'} 703 + 704 + '@smithy/signature-v4@5.0.1': 705 + resolution: {integrity: sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==} 706 + engines: {node: '>=18.0.0'} 707 + 708 + '@smithy/smithy-client@4.1.6': 709 + resolution: {integrity: sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==} 710 + engines: {node: '>=18.0.0'} 711 + 712 + '@smithy/types@4.1.0': 713 + resolution: {integrity: sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==} 714 + engines: {node: '>=18.0.0'} 715 + 716 + '@smithy/url-parser@4.0.1': 717 + resolution: {integrity: sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==} 718 + engines: {node: '>=18.0.0'} 719 + 720 + '@smithy/util-base64@4.0.0': 721 + resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==} 722 + engines: {node: '>=18.0.0'} 723 + 724 + '@smithy/util-body-length-browser@4.0.0': 725 + resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==} 726 + engines: {node: '>=18.0.0'} 727 + 728 + '@smithy/util-body-length-node@4.0.0': 729 + resolution: {integrity: sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==} 730 + engines: {node: '>=18.0.0'} 731 + 732 + '@smithy/util-buffer-from@2.2.0': 733 + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} 734 + engines: {node: '>=14.0.0'} 735 + 736 + '@smithy/util-buffer-from@4.0.0': 737 + resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} 738 + engines: {node: '>=18.0.0'} 739 + 740 + '@smithy/util-config-provider@4.0.0': 741 + resolution: {integrity: sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==} 742 + engines: {node: '>=18.0.0'} 743 + 744 + '@smithy/util-defaults-mode-browser@4.0.7': 745 + resolution: {integrity: sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==} 746 + engines: {node: '>=18.0.0'} 747 + 748 + '@smithy/util-defaults-mode-node@4.0.7': 749 + resolution: {integrity: sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==} 750 + engines: {node: '>=18.0.0'} 751 + 752 + '@smithy/util-endpoints@3.0.1': 753 + resolution: {integrity: sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==} 754 + engines: {node: '>=18.0.0'} 755 + 756 + '@smithy/util-hex-encoding@4.0.0': 757 + resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} 758 + engines: {node: '>=18.0.0'} 759 + 760 + '@smithy/util-middleware@4.0.1': 761 + resolution: {integrity: sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==} 762 + engines: {node: '>=18.0.0'} 763 + 764 + '@smithy/util-retry@4.0.1': 765 + resolution: {integrity: sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==} 766 + engines: {node: '>=18.0.0'} 767 + 768 + '@smithy/util-stream@4.1.2': 769 + resolution: {integrity: sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==} 770 + engines: {node: '>=18.0.0'} 771 + 772 + '@smithy/util-uri-escape@4.0.0': 773 + resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==} 774 + engines: {node: '>=18.0.0'} 775 + 776 + '@smithy/util-utf8@2.3.0': 777 + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} 778 + engines: {node: '>=14.0.0'} 779 + 780 + '@smithy/util-utf8@4.0.0': 781 + resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} 782 + engines: {node: '>=18.0.0'} 783 + 784 + '@smithy/util-waiter@4.0.2': 785 + resolution: {integrity: sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==} 786 + engines: {node: '>=18.0.0'} 787 + 788 + '@tokenizer/token@0.3.0': 789 + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} 790 + 791 + '@types/bn.js@5.1.6': 792 + resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} 793 + 794 + '@types/body-parser@1.19.5': 795 + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} 796 + 797 + '@types/connect@3.4.38': 798 + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} 799 + 800 + '@types/elliptic@6.4.18': 801 + resolution: {integrity: sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw==} 802 + 803 + '@types/express-serve-static-core@4.19.6': 804 + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} 805 + 806 + '@types/express@4.17.21': 807 + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} 808 + 809 + '@types/http-errors@2.0.4': 810 + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} 811 + 812 + '@types/mime@1.3.5': 813 + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} 814 + 815 + '@types/node@22.13.5': 816 + resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==} 817 + 818 + '@types/qs@6.9.18': 819 + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} 820 + 821 + '@types/range-parser@1.2.7': 822 + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} 823 + 824 + '@types/send@0.17.4': 825 + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} 826 + 827 + '@types/serve-static@1.15.7': 828 + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} 829 + 830 + abort-controller@3.0.0: 831 + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} 832 + engines: {node: '>=6.5'} 833 + 834 + accepts@1.3.8: 835 + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} 836 + engines: {node: '>= 0.6'} 837 + 838 + ansi-regex@5.0.1: 839 + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 840 + engines: {node: '>=8'} 841 + 842 + ansi-regex@6.1.0: 843 + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 844 + engines: {node: '>=12'} 845 + 846 + ansi-styles@4.3.0: 847 + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 848 + engines: {node: '>=8'} 849 + 850 + ansi-styles@6.2.1: 851 + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 852 + engines: {node: '>=12'} 853 + 854 + array-flatten@1.1.1: 855 + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} 856 + 857 + asn1.js@5.4.1: 858 + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} 859 + 860 + asynckit@0.4.0: 861 + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 862 + 863 + atomic-sleep@1.0.0: 864 + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} 865 + engines: {node: '>=8.0.0'} 866 + 867 + await-lock@2.2.2: 868 + resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==} 869 + 870 + axios@1.8.1: 871 + resolution: {integrity: sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==} 872 + 873 + balanced-match@1.0.2: 874 + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 875 + 876 + base64-js@1.5.1: 877 + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 878 + 879 + better-sqlite3@10.1.0: 880 + resolution: {integrity: sha512-hqpHJaCfKEZFaAWdMh6crdzRWyzQzfP6Ih8TYI0vFn01a6ZTDSbJIMXN+6AMBaBOh99DzUy8l3PsV9R3qnJDng==} 881 + 882 + big-integer@1.6.52: 883 + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} 884 + engines: {node: '>=0.6'} 885 + 886 + bindings@1.5.0: 887 + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 888 + 889 + bl@4.1.0: 890 + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 891 + 892 + bn.js@4.12.1: 893 + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} 894 + 895 + body-parser@1.20.3: 896 + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} 897 + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 898 + 899 + bowser@2.11.0: 900 + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} 901 + 902 + brace-expansion@2.0.1: 903 + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 904 + 905 + brorand@1.1.0: 906 + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} 907 + 908 + buffer@5.6.0: 909 + resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} 910 + 911 + buffer@5.7.1: 912 + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 913 + 914 + buffer@6.0.3: 915 + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} 916 + 917 + bytes@3.1.2: 918 + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 919 + engines: {node: '>= 0.8'} 920 + 921 + call-bind-apply-helpers@1.0.2: 922 + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 923 + engines: {node: '>= 0.4'} 924 + 925 + call-bound@1.0.3: 926 + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} 927 + engines: {node: '>= 0.4'} 928 + 929 + cbor-extract@2.2.0: 930 + resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==} 931 + hasBin: true 932 + 933 + cbor-x@1.6.0: 934 + resolution: {integrity: sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==} 935 + 936 + cborg@1.10.2: 937 + resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} 938 + hasBin: true 939 + 940 + chownr@1.1.4: 941 + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 942 + 943 + cluster-key-slot@1.1.2: 944 + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} 945 + engines: {node: '>=0.10.0'} 946 + 947 + color-convert@2.0.1: 948 + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 949 + engines: {node: '>=7.0.0'} 950 + 951 + color-name@1.1.4: 952 + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 953 + 954 + color-string@1.9.1: 955 + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} 956 + 957 + color@4.2.3: 958 + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} 959 + engines: {node: '>=12.5.0'} 960 + 961 + combined-stream@1.0.8: 962 + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 963 + engines: {node: '>= 0.8'} 964 + 965 + compressible@2.0.18: 966 + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} 967 + engines: {node: '>= 0.6'} 968 + 969 + compression@1.8.0: 970 + resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} 971 + engines: {node: '>= 0.8.0'} 972 + 973 + content-disposition@0.5.4: 974 + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} 975 + engines: {node: '>= 0.6'} 976 + 977 + content-type@1.0.5: 978 + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} 979 + engines: {node: '>= 0.6'} 980 + 981 + cookie-signature@1.0.6: 982 + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} 983 + 984 + cookie@0.6.0: 985 + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} 986 + engines: {node: '>= 0.6'} 987 + 988 + cookie@0.7.1: 989 + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} 990 + engines: {node: '>= 0.6'} 991 + 992 + cors@2.8.5: 993 + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} 994 + engines: {node: '>= 0.10'} 995 + 996 + cross-spawn@7.0.6: 997 + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 998 + engines: {node: '>= 8'} 999 + 1000 + debug@2.6.9: 1001 + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} 1002 + peerDependencies: 1003 + supports-color: '*' 1004 + peerDependenciesMeta: 1005 + supports-color: 1006 + optional: true 1007 + 1008 + debug@4.4.0: 1009 + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 1010 + engines: {node: '>=6.0'} 1011 + peerDependencies: 1012 + supports-color: '*' 1013 + peerDependenciesMeta: 1014 + supports-color: 1015 + optional: true 1016 + 1017 + decompress-response@6.0.0: 1018 + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 1019 + engines: {node: '>=10'} 1020 + 1021 + deep-extend@0.6.0: 1022 + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} 1023 + engines: {node: '>=4.0.0'} 1024 + 1025 + deepmerge@4.3.1: 1026 + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 1027 + engines: {node: '>=0.10.0'} 1028 + 1029 + delay@5.0.0: 1030 + resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} 1031 + engines: {node: '>=10'} 1032 + 1033 + delayed-stream@1.0.0: 1034 + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 1035 + engines: {node: '>=0.4.0'} 1036 + 1037 + denque@2.1.0: 1038 + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} 1039 + engines: {node: '>=0.10'} 1040 + 1041 + depd@2.0.0: 1042 + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} 1043 + engines: {node: '>= 0.8'} 1044 + 1045 + destroy@1.2.0: 1046 + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} 1047 + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} 1048 + 1049 + detect-libc@2.0.3: 1050 + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 1051 + engines: {node: '>=8'} 1052 + 1053 + disposable-email-domains-js@1.10.0: 1054 + resolution: {integrity: sha512-U6K1hdl/ZNpDHO9XWe4PMH4UqjUZjRleBqTFXKTxG6UMHjqh6Ki7gmHwWAFczq6VOkQvNz5Ux082fZg2czyjcQ==} 1055 + 1056 + dom-serializer@1.4.1: 1057 + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} 1058 + 1059 + domelementtype@2.3.0: 1060 + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 1061 + 1062 + domhandler@4.3.1: 1063 + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} 1064 + engines: {node: '>= 4'} 1065 + 1066 + domutils@2.8.0: 1067 + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} 1068 + 1069 + dotenv@16.4.7: 1070 + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} 1071 + engines: {node: '>=12'} 1072 + 1073 + dunder-proto@1.0.1: 1074 + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 1075 + engines: {node: '>= 0.4'} 1076 + 1077 + eastasianwidth@0.2.0: 1078 + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 1079 + 1080 + ee-first@1.1.1: 1081 + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} 1082 + 1083 + elliptic@6.6.1: 1084 + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} 1085 + 1086 + emoji-regex@8.0.0: 1087 + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 1088 + 1089 + emoji-regex@9.2.2: 1090 + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 1091 + 1092 + encodeurl@1.0.2: 1093 + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} 1094 + engines: {node: '>= 0.8'} 1095 + 1096 + encodeurl@2.0.0: 1097 + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} 1098 + engines: {node: '>= 0.8'} 1099 + 1100 + end-of-stream@1.4.4: 1101 + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 1102 + 1103 + entities@2.2.0: 1104 + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} 1105 + 1106 + es-define-property@1.0.1: 1107 + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 1108 + engines: {node: '>= 0.4'} 1109 + 1110 + es-errors@1.3.0: 1111 + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 1112 + engines: {node: '>= 0.4'} 1113 + 1114 + es-object-atoms@1.1.1: 1115 + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 1116 + engines: {node: '>= 0.4'} 1117 + 1118 + es-set-tostringtag@2.1.0: 1119 + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} 1120 + engines: {node: '>= 0.4'} 1121 + 1122 + escape-html@1.0.3: 1123 + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} 1124 + 1125 + etag@1.8.1: 1126 + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 1127 + engines: {node: '>= 0.6'} 1128 + 1129 + event-target-shim@5.0.1: 1130 + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} 1131 + engines: {node: '>=6'} 1132 + 1133 + eventemitter3@4.0.7: 1134 + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} 1135 + 1136 + events@3.3.0: 1137 + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} 1138 + engines: {node: '>=0.8.x'} 1139 + 1140 + expand-template@2.0.3: 1141 + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} 1142 + engines: {node: '>=6'} 1143 + 1144 + express-async-errors@3.1.1: 1145 + resolution: {integrity: sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==} 1146 + peerDependencies: 1147 + express: ^4.16.2 1148 + 1149 + express@4.21.2: 1150 + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} 1151 + engines: {node: '>= 0.10.0'} 1152 + 1153 + fast-printf@1.6.10: 1154 + resolution: {integrity: sha512-GwTgG9O4FVIdShhbVF3JxOgSBY2+ePGsu2V/UONgoCPzF9VY6ZdBMKsHKCYQHZwNk3qNouUolRDsgVxcVA5G1w==} 1155 + engines: {node: '>=10.0'} 1156 + 1157 + fast-redact@3.5.0: 1158 + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} 1159 + engines: {node: '>=6'} 1160 + 1161 + fast-xml-parser@4.4.1: 1162 + resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} 1163 + hasBin: true 1164 + 1165 + file-type@16.5.4: 1166 + resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==} 1167 + engines: {node: '>=10'} 1168 + 1169 + file-uri-to-path@1.0.0: 1170 + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 1171 + 1172 + finalhandler@1.3.1: 1173 + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} 1174 + engines: {node: '>= 0.8'} 1175 + 1176 + follow-redirects@1.15.9: 1177 + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} 1178 + engines: {node: '>=4.0'} 1179 + peerDependencies: 1180 + debug: '*' 1181 + peerDependenciesMeta: 1182 + debug: 1183 + optional: true 1184 + 1185 + foreground-child@3.3.1: 1186 + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 1187 + engines: {node: '>=14'} 1188 + 1189 + form-data@4.0.2: 1190 + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} 1191 + engines: {node: '>= 6'} 1192 + 1193 + forwarded@0.2.0: 1194 + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 1195 + engines: {node: '>= 0.6'} 1196 + 1197 + fresh@0.5.2: 1198 + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} 1199 + engines: {node: '>= 0.6'} 1200 + 1201 + fs-constants@1.0.0: 1202 + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} 1203 + 1204 + function-bind@1.1.2: 1205 + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1206 + 1207 + get-caller-file@2.0.5: 1208 + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 1209 + engines: {node: 6.* || 8.* || >= 10.*} 1210 + 1211 + get-intrinsic@1.3.0: 1212 + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 1213 + engines: {node: '>= 0.4'} 1214 + 1215 + get-port@5.1.1: 1216 + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} 1217 + engines: {node: '>=8'} 1218 + 1219 + get-proto@1.0.1: 1220 + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 1221 + engines: {node: '>= 0.4'} 1222 + 1223 + github-from-package@0.0.0: 1224 + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} 1225 + 1226 + glob@10.4.5: 1227 + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1228 + hasBin: true 1229 + 1230 + gopd@1.2.0: 1231 + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 1232 + engines: {node: '>= 0.4'} 1233 + 1234 + graphemer@1.4.0: 1235 + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 1236 + 1237 + handlebars@4.7.8: 1238 + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} 1239 + engines: {node: '>=0.4.7'} 1240 + hasBin: true 1241 + 1242 + has-symbols@1.1.0: 1243 + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 1244 + engines: {node: '>= 0.4'} 1245 + 1246 + has-tostringtag@1.0.2: 1247 + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} 1248 + engines: {node: '>= 0.4'} 1249 + 1250 + hash.js@1.1.7: 1251 + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} 1252 + 1253 + hasown@2.0.2: 1254 + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1255 + engines: {node: '>= 0.4'} 1256 + 1257 + he@1.2.0: 1258 + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 1259 + hasBin: true 1260 + 1261 + hmac-drbg@1.0.1: 1262 + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} 1263 + 1264 + html-to-text@7.1.1: 1265 + resolution: {integrity: sha512-c9QWysrfnRZevVpS8MlE7PyOdSuIOjg8Bt8ZE10jMU/BEngA6j3llj4GRfAmtQzcd1FjKE0sWu5IHXRUH9YxIQ==} 1266 + engines: {node: '>=10.23.2'} 1267 + hasBin: true 1268 + 1269 + htmlparser2@6.1.0: 1270 + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} 1271 + 1272 + http-errors@2.0.0: 1273 + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} 1274 + engines: {node: '>= 0.8'} 1275 + 1276 + http-terminator@3.2.0: 1277 + resolution: {integrity: sha512-JLjck1EzPaWjsmIf8bziM3p9fgR1Y3JoUKAkyYEbZmFrIvJM6I8vVJfBGWlEtV9IWOvzNnaTtjuwZeBY2kwB4g==} 1278 + engines: {node: '>=14'} 1279 + 1280 + iconv-lite@0.4.24: 1281 + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1282 + engines: {node: '>=0.10.0'} 1283 + 1284 + ieee754@1.2.1: 1285 + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 1286 + 1287 + inherits@2.0.4: 1288 + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1289 + 1290 + ini@1.3.8: 1291 + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 1292 + 1293 + ioredis@5.5.0: 1294 + resolution: {integrity: sha512-7CutT89g23FfSa8MDoIFs2GYYa0PaNiW/OrT+nRyjRXHDZd17HmIgy+reOQ/yhh72NznNjGuS8kbCAcA4Ro4mw==} 1295 + engines: {node: '>=12.22.0'} 1296 + 1297 + ip3country@5.0.0: 1298 + resolution: {integrity: sha512-lcFLMFU4eO1Z7tIpbVFZkaZ5ltqpeaRx7L9NsAbA9uA7/O/rj3RF8+evE5gDitooaTTIqjdzZrenFO/OOxQ2ew==} 1299 + 1300 + ipaddr.js@1.9.1: 1301 + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 1302 + engines: {node: '>= 0.10'} 1303 + 1304 + ipaddr.js@2.2.0: 1305 + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} 1306 + engines: {node: '>= 10'} 1307 + 1308 + is-arrayish@0.3.2: 1309 + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} 1310 + 1311 + is-fullwidth-code-point@3.0.0: 1312 + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1313 + engines: {node: '>=8'} 1314 + 1315 + isexe@2.0.0: 1316 + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1317 + 1318 + iso-datestring-validator@2.2.2: 1319 + resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==} 1320 + 1321 + jackspeak@3.4.3: 1322 + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1323 + 1324 + jose@5.10.0: 1325 + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} 1326 + 1327 + key-encoder@2.0.3: 1328 + resolution: {integrity: sha512-fgBtpAGIr/Fy5/+ZLQZIPPhsZEcbSlYu/Wu96tNDFNSjSACw5lEIOFeaVdQ/iwrb8oxjlWi6wmWdH76hV6GZjg==} 1329 + 1330 + kysely@0.22.0: 1331 + resolution: {integrity: sha512-ZE3qWtnqLOalodzfK5QUEcm7AEulhxsPNuKaGFsC3XiqO92vMLm+mAHk/NnbSIOtC4RmGm0nsv700i8KDp1gfQ==} 1332 + engines: {node: '>=14.0.0'} 1333 + 1334 + kysely@0.23.5: 1335 + resolution: {integrity: sha512-TH+b56pVXQq0tsyooYLeNfV11j6ih7D50dyN8tkM0e7ndiUH28Nziojiog3qRFlmEj9XePYdZUrNJ2079Qjdow==} 1336 + engines: {node: '>=14.0.0'} 1337 + 1338 + lande@1.0.10: 1339 + resolution: {integrity: sha512-yT52DQh+UV2pEp08jOYrA4drDv0DbjpiRyZYgl25ak9G2cVR2AimzrqkYQWrD9a7Ud+qkAcaiDDoNH9DXfHPmw==} 1340 + 1341 + lodash.defaults@4.2.0: 1342 + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} 1343 + 1344 + lodash.isarguments@3.1.0: 1345 + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} 1346 + 1347 + lru-cache@10.4.3: 1348 + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1349 + 1350 + math-intrinsics@1.1.0: 1351 + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 1352 + engines: {node: '>= 0.4'} 1353 + 1354 + media-typer@0.3.0: 1355 + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} 1356 + engines: {node: '>= 0.6'} 1357 + 1358 + merge-descriptors@1.0.3: 1359 + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} 1360 + 1361 + methods@1.1.2: 1362 + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} 1363 + engines: {node: '>= 0.6'} 1364 + 1365 + mime-db@1.52.0: 1366 + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 1367 + engines: {node: '>= 0.6'} 1368 + 1369 + mime-db@1.53.0: 1370 + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} 1371 + engines: {node: '>= 0.6'} 1372 + 1373 + mime-types@2.1.35: 1374 + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 1375 + engines: {node: '>= 0.6'} 1376 + 1377 + mime@1.6.0: 1378 + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} 1379 + engines: {node: '>=4'} 1380 + hasBin: true 1381 + 1382 + mimic-response@3.1.0: 1383 + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 1384 + engines: {node: '>=10'} 1385 + 1386 + minimalistic-assert@1.0.1: 1387 + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} 1388 + 1389 + minimalistic-crypto-utils@1.0.1: 1390 + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} 1391 + 1392 + minimatch@9.0.5: 1393 + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1394 + engines: {node: '>=16 || 14 >=14.17'} 1395 + 1396 + minimist@1.2.8: 1397 + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 1398 + 1399 + minipass@7.1.2: 1400 + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1401 + engines: {node: '>=16 || 14 >=14.17'} 1402 + 1403 + mkdirp-classic@0.5.3: 1404 + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} 1405 + 1406 + ms@2.0.0: 1407 + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} 1408 + 1409 + ms@2.1.3: 1410 + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1411 + 1412 + multiformats@9.9.0: 1413 + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} 1414 + 1415 + murmurhash@2.0.1: 1416 + resolution: {integrity: sha512-5vQEh3y+DG/lMPM0mCGPDnyV8chYg/g7rl6v3Gd8WMF9S429ox3Xk8qrk174kWhG767KQMqqxLD1WnGd77hiew==} 1417 + 1418 + napi-build-utils@2.0.0: 1419 + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} 1420 + 1421 + negotiator@0.6.3: 1422 + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} 1423 + engines: {node: '>= 0.6'} 1424 + 1425 + negotiator@0.6.4: 1426 + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} 1427 + engines: {node: '>= 0.6'} 1428 + 1429 + neo-async@2.6.2: 1430 + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} 1431 + 1432 + node-abi@3.74.0: 1433 + resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} 1434 + engines: {node: '>=10'} 1435 + 1436 + node-fetch@2.7.0: 1437 + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 1438 + engines: {node: 4.x || >=6.0.0} 1439 + peerDependencies: 1440 + encoding: ^0.1.0 1441 + peerDependenciesMeta: 1442 + encoding: 1443 + optional: true 1444 + 1445 + node-gyp-build-optional-packages@5.1.1: 1446 + resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==} 1447 + hasBin: true 1448 + 1449 + nodemailer-html-to-text@3.2.0: 1450 + resolution: {integrity: sha512-RJUC6640QV1PzTHHapOrc6IzrAJUZtk2BdVdINZ9VTLm+mcQNyBO9LYyhrnufkzqiD9l8hPLJ97rSyK4WanPNg==} 1451 + engines: {node: '>= 10.23.0'} 1452 + 1453 + nodemailer@6.10.0: 1454 + resolution: {integrity: sha512-SQ3wZCExjeSatLE/HBaXS5vqUOQk6GtBdIIKxiFdmm01mOQZX/POJkO3SUX1wDiYcwUOJwT23scFSC9fY2H8IA==} 1455 + engines: {node: '>=6.0.0'} 1456 + 1457 + object-assign@4.1.1: 1458 + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1459 + engines: {node: '>=0.10.0'} 1460 + 1461 + object-inspect@1.13.4: 1462 + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} 1463 + engines: {node: '>= 0.4'} 1464 + 1465 + on-exit-leak-free@2.1.2: 1466 + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} 1467 + engines: {node: '>=14.0.0'} 1468 + 1469 + on-finished@2.4.1: 1470 + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 1471 + engines: {node: '>= 0.8'} 1472 + 1473 + on-headers@1.0.2: 1474 + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} 1475 + engines: {node: '>= 0.8'} 1476 + 1477 + once@1.4.0: 1478 + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1479 + 1480 + one-webcrypto@1.0.3: 1481 + resolution: {integrity: sha512-fu9ywBVBPx0gS9K0etIROTiCkvI5S1TDjFsYFb3rC1ewFxeOqsbzq7aIMBHsYfrTHBcGXJaONXXjTl8B01cW1Q==} 1482 + 1483 + p-finally@1.0.0: 1484 + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} 1485 + engines: {node: '>=4'} 1486 + 1487 + p-queue@6.6.2: 1488 + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} 1489 + engines: {node: '>=8'} 1490 + 1491 + p-timeout@3.2.0: 1492 + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} 1493 + engines: {node: '>=8'} 1494 + 1495 + p-wait-for@3.2.0: 1496 + resolution: {integrity: sha512-wpgERjNkLrBiFmkMEjuZJEWKKDrNfHCKA1OhyN1wg1FrLkULbviEy6py1AyJUgZ72YWFbZ38FIpnqvVqAlDUwA==} 1497 + engines: {node: '>=8'} 1498 + 1499 + package-json-from-dist@1.0.1: 1500 + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1501 + 1502 + parseurl@1.3.3: 1503 + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 1504 + engines: {node: '>= 0.8'} 1505 + 1506 + path-key@3.1.1: 1507 + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1508 + engines: {node: '>=8'} 1509 + 1510 + path-scurry@1.11.1: 1511 + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1512 + engines: {node: '>=16 || 14 >=14.18'} 1513 + 1514 + path-to-regexp@0.1.12: 1515 + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} 1516 + 1517 + peek-readable@4.1.0: 1518 + resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} 1519 + engines: {node: '>=8'} 1520 + 1521 + pg-cloudflare@1.1.1: 1522 + resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} 1523 + 1524 + pg-connection-string@2.7.0: 1525 + resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} 1526 + 1527 + pg-int8@1.0.1: 1528 + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} 1529 + engines: {node: '>=4.0.0'} 1530 + 1531 + pg-pool@3.7.1: 1532 + resolution: {integrity: sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw==} 1533 + peerDependencies: 1534 + pg: '>=8.0' 1535 + 1536 + pg-protocol@1.7.1: 1537 + resolution: {integrity: sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==} 1538 + 1539 + pg-types@2.2.0: 1540 + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} 1541 + engines: {node: '>=4'} 1542 + 1543 + pg@8.13.3: 1544 + resolution: {integrity: sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ==} 1545 + engines: {node: '>= 8.0.0'} 1546 + peerDependencies: 1547 + pg-native: '>=3.0.1' 1548 + peerDependenciesMeta: 1549 + pg-native: 1550 + optional: true 1551 + 1552 + pgpass@1.0.5: 1553 + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} 1554 + 1555 + pino-abstract-transport@1.2.0: 1556 + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} 1557 + 1558 + pino-http@8.6.1: 1559 + resolution: {integrity: sha512-J0hiJgUExtBXP2BjrK4VB305tHXS31sCmWJ9XJo2wPkLHa1NFPuW4V9wjG27PAc2fmBCigiNhQKpvrx+kntBPA==} 1560 + 1561 + pino-std-serializers@6.2.2: 1562 + resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} 1563 + 1564 + pino@8.21.0: 1565 + resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==} 1566 + hasBin: true 1567 + 1568 + postgres-array@2.0.0: 1569 + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} 1570 + engines: {node: '>=4'} 1571 + 1572 + postgres-bytea@1.0.0: 1573 + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} 1574 + engines: {node: '>=0.10.0'} 1575 + 1576 + postgres-date@1.0.7: 1577 + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} 1578 + engines: {node: '>=0.10.0'} 1579 + 1580 + postgres-interval@1.2.0: 1581 + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} 1582 + engines: {node: '>=0.10.0'} 1583 + 1584 + prebuild-install@7.1.3: 1585 + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} 1586 + engines: {node: '>=10'} 1587 + hasBin: true 1588 + 1589 + process-warning@3.0.0: 1590 + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} 1591 + 1592 + process@0.11.10: 1593 + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} 1594 + engines: {node: '>= 0.6.0'} 1595 + 1596 + proxy-addr@2.0.7: 1597 + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 1598 + engines: {node: '>= 0.10'} 1599 + 1600 + proxy-from-env@1.1.0: 1601 + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 1602 + 1603 + psl@1.15.0: 1604 + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} 1605 + 1606 + pump@3.0.2: 1607 + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} 1608 + 1609 + punycode@2.3.1: 1610 + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1611 + engines: {node: '>=6'} 1612 + 1613 + qs@6.13.0: 1614 + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} 1615 + engines: {node: '>=0.6'} 1616 + 1617 + quick-format-unescaped@4.0.4: 1618 + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} 1619 + 1620 + range-parser@1.2.1: 1621 + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} 1622 + engines: {node: '>= 0.6'} 1623 + 1624 + rate-limiter-flexible@2.4.2: 1625 + resolution: {integrity: sha512-rMATGGOdO1suFyf/mI5LYhts71g1sbdhmd6YvdiXO2gJnd42Tt6QS4JUKJKSWVVkMtBacm6l40FR7Trjo6Iruw==} 1626 + 1627 + raw-body@2.5.2: 1628 + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} 1629 + engines: {node: '>= 0.8'} 1630 + 1631 + rc@1.2.8: 1632 + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} 1633 + hasBin: true 1634 + 1635 + readable-stream@3.6.2: 1636 + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 1637 + engines: {node: '>= 6'} 1638 + 1639 + readable-stream@4.7.0: 1640 + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} 1641 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1642 + 1643 + readable-web-to-node-stream@3.0.4: 1644 + resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==} 1645 + engines: {node: '>=8'} 1646 + 1647 + real-require@0.2.0: 1648 + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} 1649 + engines: {node: '>= 12.13.0'} 1650 + 1651 + redis-errors@1.2.0: 1652 + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} 1653 + engines: {node: '>=4'} 1654 + 1655 + redis-parser@3.0.0: 1656 + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} 1657 + engines: {node: '>=4'} 1658 + 1659 + roarr@7.21.1: 1660 + resolution: {integrity: sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==} 1661 + engines: {node: '>=18.0'} 1662 + 1663 + rxjs@7.8.2: 1664 + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} 1665 + 1666 + safe-buffer@5.2.1: 1667 + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1668 + 1669 + safe-stable-stringify@2.5.0: 1670 + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} 1671 + engines: {node: '>=10'} 1672 + 1673 + safer-buffer@2.1.2: 1674 + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1675 + 1676 + semver-compare@1.0.0: 1677 + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} 1678 + 1679 + semver@7.7.1: 1680 + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 1681 + engines: {node: '>=10'} 1682 + hasBin: true 1683 + 1684 + send@0.19.0: 1685 + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} 1686 + engines: {node: '>= 0.8.0'} 1687 + 1688 + serve-static@1.16.2: 1689 + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} 1690 + engines: {node: '>= 0.8.0'} 1691 + 1692 + setprototypeof@1.2.0: 1693 + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} 1694 + 1695 + sharp@0.33.5: 1696 + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} 1697 + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 1698 + 1699 + shebang-command@2.0.0: 1700 + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1701 + engines: {node: '>=8'} 1702 + 1703 + shebang-regex@3.0.0: 1704 + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1705 + engines: {node: '>=8'} 1706 + 1707 + side-channel-list@1.0.0: 1708 + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} 1709 + engines: {node: '>= 0.4'} 1710 + 1711 + side-channel-map@1.0.1: 1712 + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} 1713 + engines: {node: '>= 0.4'} 1714 + 1715 + side-channel-weakmap@1.0.2: 1716 + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} 1717 + engines: {node: '>= 0.4'} 1718 + 1719 + side-channel@1.1.0: 1720 + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} 1721 + engines: {node: '>= 0.4'} 1722 + 1723 + signal-exit@4.1.0: 1724 + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1725 + engines: {node: '>=14'} 1726 + 1727 + simple-concat@1.0.1: 1728 + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} 1729 + 1730 + simple-get@4.0.1: 1731 + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} 1732 + 1733 + simple-swizzle@0.2.2: 1734 + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} 1735 + 1736 + sonic-boom@3.8.1: 1737 + resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} 1738 + 1739 + source-map@0.6.1: 1740 + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1741 + engines: {node: '>=0.10.0'} 1742 + 1743 + split2@4.2.0: 1744 + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} 1745 + engines: {node: '>= 10.x'} 1746 + 1747 + standard-as-callback@2.1.0: 1748 + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} 1749 + 1750 + statsig-node@5.33.0: 1751 + resolution: {integrity: sha512-gyJhGnGkzZKyswvoS/bQfMQlEjJHWlVA1pvOl9KtyfLpqlk8i0V+fOqmFUqGHiDm91jfQVH6y385xz3t/shEiA==} 1752 + 1753 + statuses@2.0.1: 1754 + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 1755 + engines: {node: '>= 0.8'} 1756 + 1757 + stream-browserify@3.0.0: 1758 + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} 1759 + 1760 + string-width@4.2.3: 1761 + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1762 + engines: {node: '>=8'} 1763 + 1764 + string-width@5.1.2: 1765 + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1766 + engines: {node: '>=12'} 1767 + 1768 + string_decoder@1.3.0: 1769 + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 1770 + 1771 + strip-ansi@6.0.1: 1772 + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1773 + engines: {node: '>=8'} 1774 + 1775 + strip-ansi@7.1.0: 1776 + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1777 + engines: {node: '>=12'} 1778 + 1779 + strip-json-comments@2.0.1: 1780 + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} 1781 + engines: {node: '>=0.10.0'} 1782 + 1783 + strnum@1.1.2: 1784 + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} 1785 + 1786 + strtok3@6.3.0: 1787 + resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} 1788 + engines: {node: '>=10'} 1789 + 1790 + structured-headers@1.0.1: 1791 + resolution: {integrity: sha512-QYBxdBtA4Tl5rFPuqmbmdrS9kbtren74RTJTcs0VSQNVV5iRhJD4QlYTLD0+81SBwUQctjEQzjTRI3WG4DzICA==} 1792 + engines: {node: '>= 14', npm: '>=6'} 1793 + 1794 + tar-fs@2.1.2: 1795 + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} 1796 + 1797 + tar-stream@2.2.0: 1798 + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} 1799 + engines: {node: '>=6'} 1800 + 1801 + thread-stream@2.7.0: 1802 + resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==} 1803 + 1804 + tlds@1.255.0: 1805 + resolution: {integrity: sha512-tcwMRIioTcF/FcxLev8MJWxCp+GUALRhFEqbDoZrnowmKSGqPrl5pqS+Sut2m8BgJ6S4FExCSSpGffZ0Tks6Aw==} 1806 + hasBin: true 1807 + 1808 + toidentifier@1.0.1: 1809 + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} 1810 + engines: {node: '>=0.6'} 1811 + 1812 + token-types@4.2.1: 1813 + resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} 1814 + engines: {node: '>=10'} 1815 + 1816 + toygrad@2.6.0: 1817 + resolution: {integrity: sha512-g4zBmlSbvzOE5FOILxYkAybTSxijKLkj1WoNqVGnbMcWDyj4wWQ+eYSr3ik7XOpIgMq/7eBcPRTJX3DM2E0YMg==} 1818 + 1819 + tr46@0.0.3: 1820 + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1821 + 1822 + tslib@2.8.1: 1823 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1824 + 1825 + tunnel-agent@0.6.0: 1826 + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} 1827 + 1828 + type-fest@2.19.0: 1829 + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} 1830 + engines: {node: '>=12.20'} 1831 + 1832 + type-is@1.6.18: 1833 + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} 1834 + engines: {node: '>= 0.6'} 1835 + 1836 + typed-emitter@2.1.0: 1837 + resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} 1838 + 1839 + typescript@5.7.3: 1840 + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} 1841 + engines: {node: '>=14.17'} 1842 + hasBin: true 1843 + 1844 + ua-parser-js@1.0.40: 1845 + resolution: {integrity: sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==} 1846 + hasBin: true 1847 + 1848 + uglify-js@3.19.3: 1849 + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} 1850 + engines: {node: '>=0.8.0'} 1851 + hasBin: true 1852 + 1853 + uint8arrays@3.0.0: 1854 + resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==} 1855 + 1856 + undici-types@6.20.0: 1857 + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 1858 + 1859 + undici@5.28.5: 1860 + resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==} 1861 + engines: {node: '>=14.0'} 1862 + 1863 + undici@6.21.1: 1864 + resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==} 1865 + engines: {node: '>=18.17'} 1866 + 1867 + unpipe@1.0.0: 1868 + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 1869 + engines: {node: '>= 0.8'} 1870 + 1871 + util-deprecate@1.0.2: 1872 + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1873 + 1874 + utils-merge@1.0.1: 1875 + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} 1876 + engines: {node: '>= 0.4.0'} 1877 + 1878 + uuid@8.3.2: 1879 + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} 1880 + hasBin: true 1881 + 1882 + uuid@9.0.1: 1883 + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} 1884 + hasBin: true 1885 + 1886 + varint@6.0.0: 1887 + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} 1888 + 1889 + vary@1.1.2: 1890 + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} 1891 + engines: {node: '>= 0.8'} 1892 + 1893 + webidl-conversions@3.0.1: 1894 + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 1895 + 1896 + whatwg-url@5.0.0: 1897 + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 1898 + 1899 + which@2.0.2: 1900 + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1901 + engines: {node: '>= 8'} 1902 + hasBin: true 1903 + 1904 + wordwrap@1.0.0: 1905 + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} 1906 + 1907 + wrap-ansi@7.0.0: 1908 + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1909 + engines: {node: '>=10'} 1910 + 1911 + wrap-ansi@8.1.0: 1912 + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1913 + engines: {node: '>=12'} 1914 + 1915 + wrappy@1.0.2: 1916 + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1917 + 1918 + ws@8.18.1: 1919 + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} 1920 + engines: {node: '>=10.0.0'} 1921 + peerDependencies: 1922 + bufferutil: ^4.0.1 1923 + utf-8-validate: '>=5.0.2' 1924 + peerDependenciesMeta: 1925 + bufferutil: 1926 + optional: true 1927 + utf-8-validate: 1928 + optional: true 1929 + 1930 + xtend@4.0.2: 1931 + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} 1932 + engines: {node: '>=0.4'} 1933 + 1934 + zod@3.24.2: 1935 + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} 1936 + 1937 + snapshots: 1938 + 1939 + '@atproto-labs/fetch-node@0.1.7': 1940 + dependencies: 1941 + '@atproto-labs/fetch': 0.2.1 1942 + '@atproto-labs/pipe': 0.1.0 1943 + ipaddr.js: 2.2.0 1944 + psl: 1.15.0 1945 + undici: 6.21.1 1946 + 1947 + '@atproto-labs/fetch@0.2.1': 1948 + dependencies: 1949 + '@atproto-labs/pipe': 0.1.0 1950 + optionalDependencies: 1951 + zod: 3.24.2 1952 + 1953 + '@atproto-labs/pipe@0.1.0': {} 1954 + 1955 + '@atproto-labs/simple-store-memory@0.1.2': 1956 + dependencies: 1957 + '@atproto-labs/simple-store': 0.1.2 1958 + lru-cache: 10.4.3 1959 + 1960 + '@atproto-labs/simple-store@0.1.2': {} 1961 + 1962 + '@atproto-labs/xrpc-utils@0.0.7': 1963 + dependencies: 1964 + '@atproto/xrpc': 0.6.9 1965 + '@atproto/xrpc-server': 0.7.11 1966 + transitivePeerDependencies: 1967 + - bufferutil 1968 + - supports-color 1969 + - utf-8-validate 1970 + 1971 + '@atproto/api@0.14.7': 1972 + dependencies: 1973 + '@atproto/common-web': 0.4.0 1974 + '@atproto/lexicon': 0.4.7 1975 + '@atproto/syntax': 0.3.3 1976 + '@atproto/xrpc': 0.6.9 1977 + await-lock: 2.2.2 1978 + multiformats: 9.9.0 1979 + tlds: 1.255.0 1980 + zod: 3.24.2 1981 + 1982 + '@atproto/aws@0.2.16': 1983 + dependencies: 1984 + '@atproto/common': 0.4.8 1985 + '@atproto/crypto': 0.4.4 1986 + '@atproto/repo': 0.7.0 1987 + '@aws-sdk/client-cloudfront': 3.758.0 1988 + '@aws-sdk/client-kms': 3.758.0 1989 + '@aws-sdk/client-s3': 3.758.0 1990 + '@aws-sdk/lib-storage': 3.758.0(@aws-sdk/client-s3@3.758.0) 1991 + '@noble/curves': 1.8.1 1992 + key-encoder: 2.0.3 1993 + multiformats: 9.9.0 1994 + uint8arrays: 3.0.0 1995 + transitivePeerDependencies: 1996 + - aws-crt 1997 + 1998 + '@atproto/bsky@0.0.124': 1999 + dependencies: 2000 + '@atproto-labs/fetch-node': 0.1.7 2001 + '@atproto-labs/xrpc-utils': 0.0.7 2002 + '@atproto/api': 0.14.7 2003 + '@atproto/common': 0.4.8 2004 + '@atproto/crypto': 0.4.4 2005 + '@atproto/did': 0.1.5 2006 + '@atproto/identity': 0.4.6 2007 + '@atproto/lexicon': 0.4.7 2008 + '@atproto/repo': 0.7.0 2009 + '@atproto/sync': 0.1.15 2010 + '@atproto/syntax': 0.3.3 2011 + '@atproto/xrpc-server': 0.7.11 2012 + '@bufbuild/protobuf': 1.10.0 2013 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) 2014 + '@connectrpc/connect-express': 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect-node@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)))(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) 2015 + '@connectrpc/connect-node': 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) 2016 + '@did-plc/lib': 0.0.1 2017 + '@types/http-errors': 2.0.4 2018 + compression: 1.8.0 2019 + cors: 2.8.5 2020 + express: 4.21.2 2021 + http-errors: 2.0.0 2022 + http-terminator: 3.2.0 2023 + ioredis: 5.5.0 2024 + jose: 5.10.0 2025 + key-encoder: 2.0.3 2026 + kysely: 0.22.0 2027 + multiformats: 9.9.0 2028 + murmurhash: 2.0.1 2029 + p-queue: 6.6.2 2030 + pg: 8.13.3 2031 + pino: 8.21.0 2032 + pino-http: 8.6.1 2033 + sharp: 0.33.5 2034 + statsig-node: 5.33.0 2035 + structured-headers: 1.0.1 2036 + typed-emitter: 2.1.0 2037 + uint8arrays: 3.0.0 2038 + undici: 6.21.1 2039 + transitivePeerDependencies: 2040 + - bufferutil 2041 + - debug 2042 + - encoding 2043 + - pg-native 2044 + - supports-color 2045 + - utf-8-validate 2046 + 2047 + '@atproto/bsync@0.0.14': 2048 + dependencies: 2049 + '@atproto/common': 0.4.8 2050 + '@atproto/syntax': 0.3.3 2051 + '@bufbuild/protobuf': 1.10.0 2052 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) 2053 + '@connectrpc/connect-node': 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) 2054 + http-terminator: 3.2.0 2055 + kysely: 0.22.0 2056 + pg: 8.13.3 2057 + pino-http: 8.6.1 2058 + typed-emitter: 2.1.0 2059 + transitivePeerDependencies: 2060 + - pg-native 2061 + 2062 + '@atproto/common-web@0.4.0': 2063 + dependencies: 2064 + graphemer: 1.4.0 2065 + multiformats: 9.9.0 2066 + uint8arrays: 3.0.0 2067 + zod: 3.24.2 2068 + 2069 + '@atproto/common@0.1.0': 2070 + dependencies: 2071 + '@ipld/dag-cbor': 7.0.3 2072 + multiformats: 9.9.0 2073 + pino: 8.21.0 2074 + zod: 3.24.2 2075 + 2076 + '@atproto/common@0.1.1': 2077 + dependencies: 2078 + '@ipld/dag-cbor': 7.0.3 2079 + multiformats: 9.9.0 2080 + pino: 8.21.0 2081 + zod: 3.24.2 2082 + 2083 + '@atproto/common@0.4.8': 2084 + dependencies: 2085 + '@atproto/common-web': 0.4.0 2086 + '@ipld/dag-cbor': 7.0.3 2087 + cbor-x: 1.6.0 2088 + iso-datestring-validator: 2.2.2 2089 + multiformats: 9.9.0 2090 + pino: 8.21.0 2091 + 2092 + '@atproto/crypto@0.1.0': 2093 + dependencies: 2094 + '@noble/secp256k1': 1.7.1 2095 + big-integer: 1.6.52 2096 + multiformats: 9.9.0 2097 + one-webcrypto: 1.0.3 2098 + uint8arrays: 3.0.0 2099 + 2100 + '@atproto/crypto@0.4.4': 2101 + dependencies: 2102 + '@noble/curves': 1.8.1 2103 + '@noble/hashes': 1.7.1 2104 + uint8arrays: 3.0.0 2105 + 2106 + '@atproto/did@0.1.5': 2107 + dependencies: 2108 + zod: 3.24.2 2109 + 2110 + '@atproto/identity@0.4.6': 2111 + dependencies: 2112 + '@atproto/common-web': 0.4.0 2113 + '@atproto/crypto': 0.4.4 2114 + 2115 + '@atproto/jwk-jose@0.1.4': 2116 + dependencies: 2117 + '@atproto/jwk': 0.1.3 2118 + jose: 5.10.0 2119 + 2120 + '@atproto/jwk@0.1.3': 2121 + dependencies: 2122 + multiformats: 9.9.0 2123 + zod: 3.24.2 2124 + 2125 + '@atproto/lexicon@0.4.7': 2126 + dependencies: 2127 + '@atproto/common-web': 0.4.0 2128 + '@atproto/syntax': 0.3.3 2129 + iso-datestring-validator: 2.2.2 2130 + multiformats: 9.9.0 2131 + zod: 3.24.2 2132 + 2133 + '@atproto/oauth-provider@0.4.0': 2134 + dependencies: 2135 + '@atproto-labs/fetch': 0.2.1 2136 + '@atproto-labs/fetch-node': 0.1.7 2137 + '@atproto-labs/pipe': 0.1.0 2138 + '@atproto-labs/simple-store': 0.1.2 2139 + '@atproto-labs/simple-store-memory': 0.1.2 2140 + '@atproto/common': 0.4.8 2141 + '@atproto/jwk': 0.1.3 2142 + '@atproto/jwk-jose': 0.1.4 2143 + '@atproto/oauth-types': 0.2.3 2144 + '@hapi/accept': 6.0.3 2145 + '@hapi/bourne': 3.0.0 2146 + '@hapi/content': 6.0.0 2147 + cookie: 0.6.0 2148 + forwarded: 0.2.0 2149 + http-errors: 2.0.0 2150 + ioredis: 5.5.0 2151 + jose: 5.10.0 2152 + psl: 1.15.0 2153 + zod: 3.24.2 2154 + transitivePeerDependencies: 2155 + - supports-color 2156 + 2157 + '@atproto/oauth-types@0.2.3': 2158 + dependencies: 2159 + '@atproto/jwk': 0.1.3 2160 + zod: 3.24.2 2161 + 2162 + '@atproto/ozone@0.1.86': 2163 + dependencies: 2164 + '@atproto/api': 0.14.7 2165 + '@atproto/common': 0.4.8 2166 + '@atproto/crypto': 0.4.4 2167 + '@atproto/identity': 0.4.6 2168 + '@atproto/lexicon': 0.4.7 2169 + '@atproto/syntax': 0.3.3 2170 + '@atproto/xrpc': 0.6.9 2171 + '@atproto/xrpc-server': 0.7.11 2172 + '@did-plc/lib': 0.0.1 2173 + compression: 1.8.0 2174 + cors: 2.8.5 2175 + express: 4.21.2 2176 + http-terminator: 3.2.0 2177 + kysely: 0.22.0 2178 + lande: 1.0.10 2179 + multiformats: 9.9.0 2180 + p-queue: 6.6.2 2181 + pg: 8.13.3 2182 + pino-http: 8.6.1 2183 + structured-headers: 1.0.1 2184 + typed-emitter: 2.1.0 2185 + uint8arrays: 3.0.0 2186 + undici: 6.21.1 2187 + transitivePeerDependencies: 2188 + - bufferutil 2189 + - debug 2190 + - pg-native 2191 + - supports-color 2192 + - utf-8-validate 2193 + 2194 + '@atproto/pds@0.4.104': 2195 + dependencies: 2196 + '@atproto-labs/fetch-node': 0.1.7 2197 + '@atproto-labs/xrpc-utils': 0.0.7 2198 + '@atproto/api': 0.14.7 2199 + '@atproto/aws': 0.2.16 2200 + '@atproto/common': 0.4.8 2201 + '@atproto/crypto': 0.4.4 2202 + '@atproto/identity': 0.4.6 2203 + '@atproto/lexicon': 0.4.7 2204 + '@atproto/oauth-provider': 0.4.0 2205 + '@atproto/repo': 0.7.0 2206 + '@atproto/syntax': 0.3.3 2207 + '@atproto/xrpc': 0.6.9 2208 + '@atproto/xrpc-server': 0.7.11 2209 + '@did-plc/lib': 0.0.4 2210 + '@hapi/address': 5.1.1 2211 + better-sqlite3: 10.1.0 2212 + bytes: 3.1.2 2213 + compression: 1.8.0 2214 + cors: 2.8.5 2215 + disposable-email-domains-js: 1.10.0 2216 + express: 4.21.2 2217 + express-async-errors: 3.1.1(express@4.21.2) 2218 + file-type: 16.5.4 2219 + glob: 10.4.5 2220 + handlebars: 4.7.8 2221 + http-terminator: 3.2.0 2222 + ioredis: 5.5.0 2223 + jose: 5.10.0 2224 + key-encoder: 2.0.3 2225 + kysely: 0.22.0 2226 + multiformats: 9.9.0 2227 + nodemailer: 6.10.0 2228 + nodemailer-html-to-text: 3.2.0 2229 + p-queue: 6.6.2 2230 + pino: 8.21.0 2231 + pino-http: 8.6.1 2232 + sharp: 0.33.5 2233 + typed-emitter: 2.1.0 2234 + uint8arrays: 3.0.0 2235 + undici: 6.21.1 2236 + zod: 3.24.2 2237 + transitivePeerDependencies: 2238 + - aws-crt 2239 + - bufferutil 2240 + - debug 2241 + - supports-color 2242 + - utf-8-validate 2243 + 2244 + '@atproto/repo@0.7.0': 2245 + dependencies: 2246 + '@atproto/common': 0.4.8 2247 + '@atproto/common-web': 0.4.0 2248 + '@atproto/crypto': 0.4.4 2249 + '@atproto/lexicon': 0.4.7 2250 + '@ipld/car': 3.2.4 2251 + '@ipld/dag-cbor': 7.0.3 2252 + multiformats: 9.9.0 2253 + uint8arrays: 3.0.0 2254 + zod: 3.24.2 2255 + 2256 + '@atproto/sync@0.1.15': 2257 + dependencies: 2258 + '@atproto/common': 0.4.8 2259 + '@atproto/identity': 0.4.6 2260 + '@atproto/lexicon': 0.4.7 2261 + '@atproto/repo': 0.7.0 2262 + '@atproto/syntax': 0.3.3 2263 + '@atproto/xrpc-server': 0.7.11 2264 + multiformats: 9.9.0 2265 + p-queue: 6.6.2 2266 + ws: 8.18.1 2267 + transitivePeerDependencies: 2268 + - bufferutil 2269 + - supports-color 2270 + - utf-8-validate 2271 + 2272 + '@atproto/syntax@0.3.3': {} 2273 + 2274 + '@atproto/xrpc-server@0.7.11': 2275 + dependencies: 2276 + '@atproto/common': 0.4.8 2277 + '@atproto/crypto': 0.4.4 2278 + '@atproto/lexicon': 0.4.7 2279 + '@atproto/xrpc': 0.6.9 2280 + cbor-x: 1.6.0 2281 + express: 4.21.2 2282 + http-errors: 2.0.0 2283 + mime-types: 2.1.35 2284 + rate-limiter-flexible: 2.4.2 2285 + uint8arrays: 3.0.0 2286 + ws: 8.18.1 2287 + zod: 3.24.2 2288 + transitivePeerDependencies: 2289 + - bufferutil 2290 + - supports-color 2291 + - utf-8-validate 2292 + 2293 + '@atproto/xrpc@0.6.9': 2294 + dependencies: 2295 + '@atproto/lexicon': 0.4.7 2296 + zod: 3.24.2 2297 + 2298 + '@aws-crypto/crc32@5.2.0': 2299 + dependencies: 2300 + '@aws-crypto/util': 5.2.0 2301 + '@aws-sdk/types': 3.734.0 2302 + tslib: 2.8.1 2303 + 2304 + '@aws-crypto/crc32c@5.2.0': 2305 + dependencies: 2306 + '@aws-crypto/util': 5.2.0 2307 + '@aws-sdk/types': 3.734.0 2308 + tslib: 2.8.1 2309 + 2310 + '@aws-crypto/sha1-browser@5.2.0': 2311 + dependencies: 2312 + '@aws-crypto/supports-web-crypto': 5.2.0 2313 + '@aws-crypto/util': 5.2.0 2314 + '@aws-sdk/types': 3.734.0 2315 + '@aws-sdk/util-locate-window': 3.723.0 2316 + '@smithy/util-utf8': 2.3.0 2317 + tslib: 2.8.1 2318 + 2319 + '@aws-crypto/sha256-browser@5.2.0': 2320 + dependencies: 2321 + '@aws-crypto/sha256-js': 5.2.0 2322 + '@aws-crypto/supports-web-crypto': 5.2.0 2323 + '@aws-crypto/util': 5.2.0 2324 + '@aws-sdk/types': 3.734.0 2325 + '@aws-sdk/util-locate-window': 3.723.0 2326 + '@smithy/util-utf8': 2.3.0 2327 + tslib: 2.8.1 2328 + 2329 + '@aws-crypto/sha256-js@5.2.0': 2330 + dependencies: 2331 + '@aws-crypto/util': 5.2.0 2332 + '@aws-sdk/types': 3.734.0 2333 + tslib: 2.8.1 2334 + 2335 + '@aws-crypto/supports-web-crypto@5.2.0': 2336 + dependencies: 2337 + tslib: 2.8.1 2338 + 2339 + '@aws-crypto/util@5.2.0': 2340 + dependencies: 2341 + '@aws-sdk/types': 3.734.0 2342 + '@smithy/util-utf8': 2.3.0 2343 + tslib: 2.8.1 2344 + 2345 + '@aws-sdk/client-cloudfront@3.758.0': 2346 + dependencies: 2347 + '@aws-crypto/sha256-browser': 5.2.0 2348 + '@aws-crypto/sha256-js': 5.2.0 2349 + '@aws-sdk/core': 3.758.0 2350 + '@aws-sdk/credential-provider-node': 3.758.0 2351 + '@aws-sdk/middleware-host-header': 3.734.0 2352 + '@aws-sdk/middleware-logger': 3.734.0 2353 + '@aws-sdk/middleware-recursion-detection': 3.734.0 2354 + '@aws-sdk/middleware-user-agent': 3.758.0 2355 + '@aws-sdk/region-config-resolver': 3.734.0 2356 + '@aws-sdk/types': 3.734.0 2357 + '@aws-sdk/util-endpoints': 3.743.0 2358 + '@aws-sdk/util-user-agent-browser': 3.734.0 2359 + '@aws-sdk/util-user-agent-node': 3.758.0 2360 + '@aws-sdk/xml-builder': 3.734.0 2361 + '@smithy/config-resolver': 4.0.1 2362 + '@smithy/core': 3.1.5 2363 + '@smithy/fetch-http-handler': 5.0.1 2364 + '@smithy/hash-node': 4.0.1 2365 + '@smithy/invalid-dependency': 4.0.1 2366 + '@smithy/middleware-content-length': 4.0.1 2367 + '@smithy/middleware-endpoint': 4.0.6 2368 + '@smithy/middleware-retry': 4.0.7 2369 + '@smithy/middleware-serde': 4.0.2 2370 + '@smithy/middleware-stack': 4.0.1 2371 + '@smithy/node-config-provider': 4.0.1 2372 + '@smithy/node-http-handler': 4.0.3 2373 + '@smithy/protocol-http': 5.0.1 2374 + '@smithy/smithy-client': 4.1.6 2375 + '@smithy/types': 4.1.0 2376 + '@smithy/url-parser': 4.0.1 2377 + '@smithy/util-base64': 4.0.0 2378 + '@smithy/util-body-length-browser': 4.0.0 2379 + '@smithy/util-body-length-node': 4.0.0 2380 + '@smithy/util-defaults-mode-browser': 4.0.7 2381 + '@smithy/util-defaults-mode-node': 4.0.7 2382 + '@smithy/util-endpoints': 3.0.1 2383 + '@smithy/util-middleware': 4.0.1 2384 + '@smithy/util-retry': 4.0.1 2385 + '@smithy/util-stream': 4.1.2 2386 + '@smithy/util-utf8': 4.0.0 2387 + '@smithy/util-waiter': 4.0.2 2388 + tslib: 2.8.1 2389 + transitivePeerDependencies: 2390 + - aws-crt 2391 + 2392 + '@aws-sdk/client-kms@3.758.0': 2393 + dependencies: 2394 + '@aws-crypto/sha256-browser': 5.2.0 2395 + '@aws-crypto/sha256-js': 5.2.0 2396 + '@aws-sdk/core': 3.758.0 2397 + '@aws-sdk/credential-provider-node': 3.758.0 2398 + '@aws-sdk/middleware-host-header': 3.734.0 2399 + '@aws-sdk/middleware-logger': 3.734.0 2400 + '@aws-sdk/middleware-recursion-detection': 3.734.0 2401 + '@aws-sdk/middleware-user-agent': 3.758.0 2402 + '@aws-sdk/region-config-resolver': 3.734.0 2403 + '@aws-sdk/types': 3.734.0 2404 + '@aws-sdk/util-endpoints': 3.743.0 2405 + '@aws-sdk/util-user-agent-browser': 3.734.0 2406 + '@aws-sdk/util-user-agent-node': 3.758.0 2407 + '@smithy/config-resolver': 4.0.1 2408 + '@smithy/core': 3.1.5 2409 + '@smithy/fetch-http-handler': 5.0.1 2410 + '@smithy/hash-node': 4.0.1 2411 + '@smithy/invalid-dependency': 4.0.1 2412 + '@smithy/middleware-content-length': 4.0.1 2413 + '@smithy/middleware-endpoint': 4.0.6 2414 + '@smithy/middleware-retry': 4.0.7 2415 + '@smithy/middleware-serde': 4.0.2 2416 + '@smithy/middleware-stack': 4.0.1 2417 + '@smithy/node-config-provider': 4.0.1 2418 + '@smithy/node-http-handler': 4.0.3 2419 + '@smithy/protocol-http': 5.0.1 2420 + '@smithy/smithy-client': 4.1.6 2421 + '@smithy/types': 4.1.0 2422 + '@smithy/url-parser': 4.0.1 2423 + '@smithy/util-base64': 4.0.0 2424 + '@smithy/util-body-length-browser': 4.0.0 2425 + '@smithy/util-body-length-node': 4.0.0 2426 + '@smithy/util-defaults-mode-browser': 4.0.7 2427 + '@smithy/util-defaults-mode-node': 4.0.7 2428 + '@smithy/util-endpoints': 3.0.1 2429 + '@smithy/util-middleware': 4.0.1 2430 + '@smithy/util-retry': 4.0.1 2431 + '@smithy/util-utf8': 4.0.0 2432 + tslib: 2.8.1 2433 + transitivePeerDependencies: 2434 + - aws-crt 2435 + 2436 + '@aws-sdk/client-s3@3.758.0': 2437 + dependencies: 2438 + '@aws-crypto/sha1-browser': 5.2.0 2439 + '@aws-crypto/sha256-browser': 5.2.0 2440 + '@aws-crypto/sha256-js': 5.2.0 2441 + '@aws-sdk/core': 3.758.0 2442 + '@aws-sdk/credential-provider-node': 3.758.0 2443 + '@aws-sdk/middleware-bucket-endpoint': 3.734.0 2444 + '@aws-sdk/middleware-expect-continue': 3.734.0 2445 + '@aws-sdk/middleware-flexible-checksums': 3.758.0 2446 + '@aws-sdk/middleware-host-header': 3.734.0 2447 + '@aws-sdk/middleware-location-constraint': 3.734.0 2448 + '@aws-sdk/middleware-logger': 3.734.0 2449 + '@aws-sdk/middleware-recursion-detection': 3.734.0 2450 + '@aws-sdk/middleware-sdk-s3': 3.758.0 2451 + '@aws-sdk/middleware-ssec': 3.734.0 2452 + '@aws-sdk/middleware-user-agent': 3.758.0 2453 + '@aws-sdk/region-config-resolver': 3.734.0 2454 + '@aws-sdk/signature-v4-multi-region': 3.758.0 2455 + '@aws-sdk/types': 3.734.0 2456 + '@aws-sdk/util-endpoints': 3.743.0 2457 + '@aws-sdk/util-user-agent-browser': 3.734.0 2458 + '@aws-sdk/util-user-agent-node': 3.758.0 2459 + '@aws-sdk/xml-builder': 3.734.0 2460 + '@smithy/config-resolver': 4.0.1 2461 + '@smithy/core': 3.1.5 2462 + '@smithy/eventstream-serde-browser': 4.0.1 2463 + '@smithy/eventstream-serde-config-resolver': 4.0.1 2464 + '@smithy/eventstream-serde-node': 4.0.1 2465 + '@smithy/fetch-http-handler': 5.0.1 2466 + '@smithy/hash-blob-browser': 4.0.1 2467 + '@smithy/hash-node': 4.0.1 2468 + '@smithy/hash-stream-node': 4.0.1 2469 + '@smithy/invalid-dependency': 4.0.1 2470 + '@smithy/md5-js': 4.0.1 2471 + '@smithy/middleware-content-length': 4.0.1 2472 + '@smithy/middleware-endpoint': 4.0.6 2473 + '@smithy/middleware-retry': 4.0.7 2474 + '@smithy/middleware-serde': 4.0.2 2475 + '@smithy/middleware-stack': 4.0.1 2476 + '@smithy/node-config-provider': 4.0.1 2477 + '@smithy/node-http-handler': 4.0.3 2478 + '@smithy/protocol-http': 5.0.1 2479 + '@smithy/smithy-client': 4.1.6 2480 + '@smithy/types': 4.1.0 2481 + '@smithy/url-parser': 4.0.1 2482 + '@smithy/util-base64': 4.0.0 2483 + '@smithy/util-body-length-browser': 4.0.0 2484 + '@smithy/util-body-length-node': 4.0.0 2485 + '@smithy/util-defaults-mode-browser': 4.0.7 2486 + '@smithy/util-defaults-mode-node': 4.0.7 2487 + '@smithy/util-endpoints': 3.0.1 2488 + '@smithy/util-middleware': 4.0.1 2489 + '@smithy/util-retry': 4.0.1 2490 + '@smithy/util-stream': 4.1.2 2491 + '@smithy/util-utf8': 4.0.0 2492 + '@smithy/util-waiter': 4.0.2 2493 + tslib: 2.8.1 2494 + transitivePeerDependencies: 2495 + - aws-crt 2496 + 2497 + '@aws-sdk/client-sso@3.758.0': 2498 + dependencies: 2499 + '@aws-crypto/sha256-browser': 5.2.0 2500 + '@aws-crypto/sha256-js': 5.2.0 2501 + '@aws-sdk/core': 3.758.0 2502 + '@aws-sdk/middleware-host-header': 3.734.0 2503 + '@aws-sdk/middleware-logger': 3.734.0 2504 + '@aws-sdk/middleware-recursion-detection': 3.734.0 2505 + '@aws-sdk/middleware-user-agent': 3.758.0 2506 + '@aws-sdk/region-config-resolver': 3.734.0 2507 + '@aws-sdk/types': 3.734.0 2508 + '@aws-sdk/util-endpoints': 3.743.0 2509 + '@aws-sdk/util-user-agent-browser': 3.734.0 2510 + '@aws-sdk/util-user-agent-node': 3.758.0 2511 + '@smithy/config-resolver': 4.0.1 2512 + '@smithy/core': 3.1.5 2513 + '@smithy/fetch-http-handler': 5.0.1 2514 + '@smithy/hash-node': 4.0.1 2515 + '@smithy/invalid-dependency': 4.0.1 2516 + '@smithy/middleware-content-length': 4.0.1 2517 + '@smithy/middleware-endpoint': 4.0.6 2518 + '@smithy/middleware-retry': 4.0.7 2519 + '@smithy/middleware-serde': 4.0.2 2520 + '@smithy/middleware-stack': 4.0.1 2521 + '@smithy/node-config-provider': 4.0.1 2522 + '@smithy/node-http-handler': 4.0.3 2523 + '@smithy/protocol-http': 5.0.1 2524 + '@smithy/smithy-client': 4.1.6 2525 + '@smithy/types': 4.1.0 2526 + '@smithy/url-parser': 4.0.1 2527 + '@smithy/util-base64': 4.0.0 2528 + '@smithy/util-body-length-browser': 4.0.0 2529 + '@smithy/util-body-length-node': 4.0.0 2530 + '@smithy/util-defaults-mode-browser': 4.0.7 2531 + '@smithy/util-defaults-mode-node': 4.0.7 2532 + '@smithy/util-endpoints': 3.0.1 2533 + '@smithy/util-middleware': 4.0.1 2534 + '@smithy/util-retry': 4.0.1 2535 + '@smithy/util-utf8': 4.0.0 2536 + tslib: 2.8.1 2537 + transitivePeerDependencies: 2538 + - aws-crt 2539 + 2540 + '@aws-sdk/core@3.758.0': 2541 + dependencies: 2542 + '@aws-sdk/types': 3.734.0 2543 + '@smithy/core': 3.1.5 2544 + '@smithy/node-config-provider': 4.0.1 2545 + '@smithy/property-provider': 4.0.1 2546 + '@smithy/protocol-http': 5.0.1 2547 + '@smithy/signature-v4': 5.0.1 2548 + '@smithy/smithy-client': 4.1.6 2549 + '@smithy/types': 4.1.0 2550 + '@smithy/util-middleware': 4.0.1 2551 + fast-xml-parser: 4.4.1 2552 + tslib: 2.8.1 2553 + 2554 + '@aws-sdk/credential-provider-env@3.758.0': 2555 + dependencies: 2556 + '@aws-sdk/core': 3.758.0 2557 + '@aws-sdk/types': 3.734.0 2558 + '@smithy/property-provider': 4.0.1 2559 + '@smithy/types': 4.1.0 2560 + tslib: 2.8.1 2561 + 2562 + '@aws-sdk/credential-provider-http@3.758.0': 2563 + dependencies: 2564 + '@aws-sdk/core': 3.758.0 2565 + '@aws-sdk/types': 3.734.0 2566 + '@smithy/fetch-http-handler': 5.0.1 2567 + '@smithy/node-http-handler': 4.0.3 2568 + '@smithy/property-provider': 4.0.1 2569 + '@smithy/protocol-http': 5.0.1 2570 + '@smithy/smithy-client': 4.1.6 2571 + '@smithy/types': 4.1.0 2572 + '@smithy/util-stream': 4.1.2 2573 + tslib: 2.8.1 2574 + 2575 + '@aws-sdk/credential-provider-ini@3.758.0': 2576 + dependencies: 2577 + '@aws-sdk/core': 3.758.0 2578 + '@aws-sdk/credential-provider-env': 3.758.0 2579 + '@aws-sdk/credential-provider-http': 3.758.0 2580 + '@aws-sdk/credential-provider-process': 3.758.0 2581 + '@aws-sdk/credential-provider-sso': 3.758.0 2582 + '@aws-sdk/credential-provider-web-identity': 3.758.0 2583 + '@aws-sdk/nested-clients': 3.758.0 2584 + '@aws-sdk/types': 3.734.0 2585 + '@smithy/credential-provider-imds': 4.0.1 2586 + '@smithy/property-provider': 4.0.1 2587 + '@smithy/shared-ini-file-loader': 4.0.1 2588 + '@smithy/types': 4.1.0 2589 + tslib: 2.8.1 2590 + transitivePeerDependencies: 2591 + - aws-crt 2592 + 2593 + '@aws-sdk/credential-provider-node@3.758.0': 2594 + dependencies: 2595 + '@aws-sdk/credential-provider-env': 3.758.0 2596 + '@aws-sdk/credential-provider-http': 3.758.0 2597 + '@aws-sdk/credential-provider-ini': 3.758.0 2598 + '@aws-sdk/credential-provider-process': 3.758.0 2599 + '@aws-sdk/credential-provider-sso': 3.758.0 2600 + '@aws-sdk/credential-provider-web-identity': 3.758.0 2601 + '@aws-sdk/types': 3.734.0 2602 + '@smithy/credential-provider-imds': 4.0.1 2603 + '@smithy/property-provider': 4.0.1 2604 + '@smithy/shared-ini-file-loader': 4.0.1 2605 + '@smithy/types': 4.1.0 2606 + tslib: 2.8.1 2607 + transitivePeerDependencies: 2608 + - aws-crt 2609 + 2610 + '@aws-sdk/credential-provider-process@3.758.0': 2611 + dependencies: 2612 + '@aws-sdk/core': 3.758.0 2613 + '@aws-sdk/types': 3.734.0 2614 + '@smithy/property-provider': 4.0.1 2615 + '@smithy/shared-ini-file-loader': 4.0.1 2616 + '@smithy/types': 4.1.0 2617 + tslib: 2.8.1 2618 + 2619 + '@aws-sdk/credential-provider-sso@3.758.0': 2620 + dependencies: 2621 + '@aws-sdk/client-sso': 3.758.0 2622 + '@aws-sdk/core': 3.758.0 2623 + '@aws-sdk/token-providers': 3.758.0 2624 + '@aws-sdk/types': 3.734.0 2625 + '@smithy/property-provider': 4.0.1 2626 + '@smithy/shared-ini-file-loader': 4.0.1 2627 + '@smithy/types': 4.1.0 2628 + tslib: 2.8.1 2629 + transitivePeerDependencies: 2630 + - aws-crt 2631 + 2632 + '@aws-sdk/credential-provider-web-identity@3.758.0': 2633 + dependencies: 2634 + '@aws-sdk/core': 3.758.0 2635 + '@aws-sdk/nested-clients': 3.758.0 2636 + '@aws-sdk/types': 3.734.0 2637 + '@smithy/property-provider': 4.0.1 2638 + '@smithy/types': 4.1.0 2639 + tslib: 2.8.1 2640 + transitivePeerDependencies: 2641 + - aws-crt 2642 + 2643 + '@aws-sdk/lib-storage@3.758.0(@aws-sdk/client-s3@3.758.0)': 2644 + dependencies: 2645 + '@aws-sdk/client-s3': 3.758.0 2646 + '@smithy/abort-controller': 4.0.1 2647 + '@smithy/middleware-endpoint': 4.0.6 2648 + '@smithy/smithy-client': 4.1.6 2649 + buffer: 5.6.0 2650 + events: 3.3.0 2651 + stream-browserify: 3.0.0 2652 + tslib: 2.8.1 2653 + 2654 + '@aws-sdk/middleware-bucket-endpoint@3.734.0': 2655 + dependencies: 2656 + '@aws-sdk/types': 3.734.0 2657 + '@aws-sdk/util-arn-parser': 3.723.0 2658 + '@smithy/node-config-provider': 4.0.1 2659 + '@smithy/protocol-http': 5.0.1 2660 + '@smithy/types': 4.1.0 2661 + '@smithy/util-config-provider': 4.0.0 2662 + tslib: 2.8.1 2663 + 2664 + '@aws-sdk/middleware-expect-continue@3.734.0': 2665 + dependencies: 2666 + '@aws-sdk/types': 3.734.0 2667 + '@smithy/protocol-http': 5.0.1 2668 + '@smithy/types': 4.1.0 2669 + tslib: 2.8.1 2670 + 2671 + '@aws-sdk/middleware-flexible-checksums@3.758.0': 2672 + dependencies: 2673 + '@aws-crypto/crc32': 5.2.0 2674 + '@aws-crypto/crc32c': 5.2.0 2675 + '@aws-crypto/util': 5.2.0 2676 + '@aws-sdk/core': 3.758.0 2677 + '@aws-sdk/types': 3.734.0 2678 + '@smithy/is-array-buffer': 4.0.0 2679 + '@smithy/node-config-provider': 4.0.1 2680 + '@smithy/protocol-http': 5.0.1 2681 + '@smithy/types': 4.1.0 2682 + '@smithy/util-middleware': 4.0.1 2683 + '@smithy/util-stream': 4.1.2 2684 + '@smithy/util-utf8': 4.0.0 2685 + tslib: 2.8.1 2686 + 2687 + '@aws-sdk/middleware-host-header@3.734.0': 2688 + dependencies: 2689 + '@aws-sdk/types': 3.734.0 2690 + '@smithy/protocol-http': 5.0.1 2691 + '@smithy/types': 4.1.0 2692 + tslib: 2.8.1 2693 + 2694 + '@aws-sdk/middleware-location-constraint@3.734.0': 2695 + dependencies: 2696 + '@aws-sdk/types': 3.734.0 2697 + '@smithy/types': 4.1.0 2698 + tslib: 2.8.1 2699 + 2700 + '@aws-sdk/middleware-logger@3.734.0': 2701 + dependencies: 2702 + '@aws-sdk/types': 3.734.0 2703 + '@smithy/types': 4.1.0 2704 + tslib: 2.8.1 2705 + 2706 + '@aws-sdk/middleware-recursion-detection@3.734.0': 2707 + dependencies: 2708 + '@aws-sdk/types': 3.734.0 2709 + '@smithy/protocol-http': 5.0.1 2710 + '@smithy/types': 4.1.0 2711 + tslib: 2.8.1 2712 + 2713 + '@aws-sdk/middleware-sdk-s3@3.758.0': 2714 + dependencies: 2715 + '@aws-sdk/core': 3.758.0 2716 + '@aws-sdk/types': 3.734.0 2717 + '@aws-sdk/util-arn-parser': 3.723.0 2718 + '@smithy/core': 3.1.5 2719 + '@smithy/node-config-provider': 4.0.1 2720 + '@smithy/protocol-http': 5.0.1 2721 + '@smithy/signature-v4': 5.0.1 2722 + '@smithy/smithy-client': 4.1.6 2723 + '@smithy/types': 4.1.0 2724 + '@smithy/util-config-provider': 4.0.0 2725 + '@smithy/util-middleware': 4.0.1 2726 + '@smithy/util-stream': 4.1.2 2727 + '@smithy/util-utf8': 4.0.0 2728 + tslib: 2.8.1 2729 + 2730 + '@aws-sdk/middleware-ssec@3.734.0': 2731 + dependencies: 2732 + '@aws-sdk/types': 3.734.0 2733 + '@smithy/types': 4.1.0 2734 + tslib: 2.8.1 2735 + 2736 + '@aws-sdk/middleware-user-agent@3.758.0': 2737 + dependencies: 2738 + '@aws-sdk/core': 3.758.0 2739 + '@aws-sdk/types': 3.734.0 2740 + '@aws-sdk/util-endpoints': 3.743.0 2741 + '@smithy/core': 3.1.5 2742 + '@smithy/protocol-http': 5.0.1 2743 + '@smithy/types': 4.1.0 2744 + tslib: 2.8.1 2745 + 2746 + '@aws-sdk/nested-clients@3.758.0': 2747 + dependencies: 2748 + '@aws-crypto/sha256-browser': 5.2.0 2749 + '@aws-crypto/sha256-js': 5.2.0 2750 + '@aws-sdk/core': 3.758.0 2751 + '@aws-sdk/middleware-host-header': 3.734.0 2752 + '@aws-sdk/middleware-logger': 3.734.0 2753 + '@aws-sdk/middleware-recursion-detection': 3.734.0 2754 + '@aws-sdk/middleware-user-agent': 3.758.0 2755 + '@aws-sdk/region-config-resolver': 3.734.0 2756 + '@aws-sdk/types': 3.734.0 2757 + '@aws-sdk/util-endpoints': 3.743.0 2758 + '@aws-sdk/util-user-agent-browser': 3.734.0 2759 + '@aws-sdk/util-user-agent-node': 3.758.0 2760 + '@smithy/config-resolver': 4.0.1 2761 + '@smithy/core': 3.1.5 2762 + '@smithy/fetch-http-handler': 5.0.1 2763 + '@smithy/hash-node': 4.0.1 2764 + '@smithy/invalid-dependency': 4.0.1 2765 + '@smithy/middleware-content-length': 4.0.1 2766 + '@smithy/middleware-endpoint': 4.0.6 2767 + '@smithy/middleware-retry': 4.0.7 2768 + '@smithy/middleware-serde': 4.0.2 2769 + '@smithy/middleware-stack': 4.0.1 2770 + '@smithy/node-config-provider': 4.0.1 2771 + '@smithy/node-http-handler': 4.0.3 2772 + '@smithy/protocol-http': 5.0.1 2773 + '@smithy/smithy-client': 4.1.6 2774 + '@smithy/types': 4.1.0 2775 + '@smithy/url-parser': 4.0.1 2776 + '@smithy/util-base64': 4.0.0 2777 + '@smithy/util-body-length-browser': 4.0.0 2778 + '@smithy/util-body-length-node': 4.0.0 2779 + '@smithy/util-defaults-mode-browser': 4.0.7 2780 + '@smithy/util-defaults-mode-node': 4.0.7 2781 + '@smithy/util-endpoints': 3.0.1 2782 + '@smithy/util-middleware': 4.0.1 2783 + '@smithy/util-retry': 4.0.1 2784 + '@smithy/util-utf8': 4.0.0 2785 + tslib: 2.8.1 2786 + transitivePeerDependencies: 2787 + - aws-crt 2788 + 2789 + '@aws-sdk/region-config-resolver@3.734.0': 2790 + dependencies: 2791 + '@aws-sdk/types': 3.734.0 2792 + '@smithy/node-config-provider': 4.0.1 2793 + '@smithy/types': 4.1.0 2794 + '@smithy/util-config-provider': 4.0.0 2795 + '@smithy/util-middleware': 4.0.1 2796 + tslib: 2.8.1 2797 + 2798 + '@aws-sdk/signature-v4-multi-region@3.758.0': 2799 + dependencies: 2800 + '@aws-sdk/middleware-sdk-s3': 3.758.0 2801 + '@aws-sdk/types': 3.734.0 2802 + '@smithy/protocol-http': 5.0.1 2803 + '@smithy/signature-v4': 5.0.1 2804 + '@smithy/types': 4.1.0 2805 + tslib: 2.8.1 2806 + 2807 + '@aws-sdk/token-providers@3.758.0': 2808 + dependencies: 2809 + '@aws-sdk/nested-clients': 3.758.0 2810 + '@aws-sdk/types': 3.734.0 2811 + '@smithy/property-provider': 4.0.1 2812 + '@smithy/shared-ini-file-loader': 4.0.1 2813 + '@smithy/types': 4.1.0 2814 + tslib: 2.8.1 2815 + transitivePeerDependencies: 2816 + - aws-crt 2817 + 2818 + '@aws-sdk/types@3.734.0': 2819 + dependencies: 2820 + '@smithy/types': 4.1.0 2821 + tslib: 2.8.1 2822 + 2823 + '@aws-sdk/util-arn-parser@3.723.0': 2824 + dependencies: 2825 + tslib: 2.8.1 2826 + 2827 + '@aws-sdk/util-endpoints@3.743.0': 2828 + dependencies: 2829 + '@aws-sdk/types': 3.734.0 2830 + '@smithy/types': 4.1.0 2831 + '@smithy/util-endpoints': 3.0.1 2832 + tslib: 2.8.1 2833 + 2834 + '@aws-sdk/util-locate-window@3.723.0': 2835 + dependencies: 2836 + tslib: 2.8.1 2837 + 2838 + '@aws-sdk/util-user-agent-browser@3.734.0': 2839 + dependencies: 2840 + '@aws-sdk/types': 3.734.0 2841 + '@smithy/types': 4.1.0 2842 + bowser: 2.11.0 2843 + tslib: 2.8.1 2844 + 2845 + '@aws-sdk/util-user-agent-node@3.758.0': 2846 + dependencies: 2847 + '@aws-sdk/middleware-user-agent': 3.758.0 2848 + '@aws-sdk/types': 3.734.0 2849 + '@smithy/node-config-provider': 4.0.1 2850 + '@smithy/types': 4.1.0 2851 + tslib: 2.8.1 2852 + 2853 + '@aws-sdk/xml-builder@3.734.0': 2854 + dependencies: 2855 + '@smithy/types': 4.1.0 2856 + tslib: 2.8.1 2857 + 2858 + '@bufbuild/protobuf@1.10.0': {} 2859 + 2860 + '@cbor-extract/cbor-extract-darwin-arm64@2.2.0': 2861 + optional: true 2862 + 2863 + '@cbor-extract/cbor-extract-darwin-x64@2.2.0': 2864 + optional: true 2865 + 2866 + '@cbor-extract/cbor-extract-linux-arm64@2.2.0': 2867 + optional: true 2868 + 2869 + '@cbor-extract/cbor-extract-linux-arm@2.2.0': 2870 + optional: true 2871 + 2872 + '@cbor-extract/cbor-extract-linux-x64@2.2.0': 2873 + optional: true 2874 + 2875 + '@cbor-extract/cbor-extract-win32-x64@2.2.0': 2876 + optional: true 2877 + 2878 + '@connectrpc/connect-express@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect-node@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)))(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': 2879 + dependencies: 2880 + '@bufbuild/protobuf': 1.10.0 2881 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) 2882 + '@connectrpc/connect-node': 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) 2883 + 2884 + '@connectrpc/connect-node@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': 2885 + dependencies: 2886 + '@bufbuild/protobuf': 1.10.0 2887 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) 2888 + undici: 5.28.5 2889 + 2890 + '@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)': 2891 + dependencies: 2892 + '@bufbuild/protobuf': 1.10.0 2893 + 2894 + '@did-plc/lib@0.0.1': 2895 + dependencies: 2896 + '@atproto/common': 0.1.0 2897 + '@atproto/crypto': 0.1.0 2898 + '@ipld/dag-cbor': 7.0.3 2899 + axios: 1.8.1 2900 + multiformats: 9.9.0 2901 + uint8arrays: 3.0.0 2902 + zod: 3.24.2 2903 + transitivePeerDependencies: 2904 + - debug 2905 + 2906 + '@did-plc/lib@0.0.4': 2907 + dependencies: 2908 + '@atproto/common': 0.1.1 2909 + '@atproto/crypto': 0.1.0 2910 + '@ipld/dag-cbor': 7.0.3 2911 + axios: 1.8.1 2912 + multiformats: 9.9.0 2913 + uint8arrays: 3.0.0 2914 + zod: 3.24.2 2915 + transitivePeerDependencies: 2916 + - debug 2917 + 2918 + '@did-plc/server@0.0.1': 2919 + dependencies: 2920 + '@atproto/common': 0.1.0 2921 + '@atproto/crypto': 0.1.0 2922 + '@did-plc/lib': 0.0.1 2923 + axios: 1.8.1 2924 + cors: 2.8.5 2925 + express: 4.21.2 2926 + express-async-errors: 3.1.1(express@4.21.2) 2927 + http-terminator: 3.2.0 2928 + kysely: 0.23.5 2929 + multiformats: 9.9.0 2930 + pg: 8.13.3 2931 + pino: 8.21.0 2932 + pino-http: 8.6.1 2933 + transitivePeerDependencies: 2934 + - debug 2935 + - pg-native 2936 + - supports-color 2937 + 2938 + '@emnapi/runtime@1.3.1': 2939 + dependencies: 2940 + tslib: 2.8.1 2941 + optional: true 2942 + 2943 + '@fastify/busboy@2.1.1': {} 2944 + 2945 + '@hapi/accept@6.0.3': 2946 + dependencies: 2947 + '@hapi/boom': 10.0.1 2948 + '@hapi/hoek': 11.0.7 2949 + 2950 + '@hapi/address@5.1.1': 2951 + dependencies: 2952 + '@hapi/hoek': 11.0.7 2953 + 2954 + '@hapi/boom@10.0.1': 2955 + dependencies: 2956 + '@hapi/hoek': 11.0.7 2957 + 2958 + '@hapi/bourne@3.0.0': {} 2959 + 2960 + '@hapi/content@6.0.0': 2961 + dependencies: 2962 + '@hapi/boom': 10.0.1 2963 + 2964 + '@hapi/hoek@11.0.7': {} 2965 + 2966 + '@img/sharp-darwin-arm64@0.33.5': 2967 + optionalDependencies: 2968 + '@img/sharp-libvips-darwin-arm64': 1.0.4 2969 + optional: true 2970 + 2971 + '@img/sharp-darwin-x64@0.33.5': 2972 + optionalDependencies: 2973 + '@img/sharp-libvips-darwin-x64': 1.0.4 2974 + optional: true 2975 + 2976 + '@img/sharp-libvips-darwin-arm64@1.0.4': 2977 + optional: true 2978 + 2979 + '@img/sharp-libvips-darwin-x64@1.0.4': 2980 + optional: true 2981 + 2982 + '@img/sharp-libvips-linux-arm64@1.0.4': 2983 + optional: true 2984 + 2985 + '@img/sharp-libvips-linux-arm@1.0.5': 2986 + optional: true 2987 + 2988 + '@img/sharp-libvips-linux-s390x@1.0.4': 2989 + optional: true 2990 + 2991 + '@img/sharp-libvips-linux-x64@1.0.4': 2992 + optional: true 2993 + 2994 + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': 2995 + optional: true 2996 + 2997 + '@img/sharp-libvips-linuxmusl-x64@1.0.4': 2998 + optional: true 2999 + 3000 + '@img/sharp-linux-arm64@0.33.5': 3001 + optionalDependencies: 3002 + '@img/sharp-libvips-linux-arm64': 1.0.4 3003 + optional: true 3004 + 3005 + '@img/sharp-linux-arm@0.33.5': 3006 + optionalDependencies: 3007 + '@img/sharp-libvips-linux-arm': 1.0.5 3008 + optional: true 3009 + 3010 + '@img/sharp-linux-s390x@0.33.5': 3011 + optionalDependencies: 3012 + '@img/sharp-libvips-linux-s390x': 1.0.4 3013 + optional: true 3014 + 3015 + '@img/sharp-linux-x64@0.33.5': 3016 + optionalDependencies: 3017 + '@img/sharp-libvips-linux-x64': 1.0.4 3018 + optional: true 3019 + 3020 + '@img/sharp-linuxmusl-arm64@0.33.5': 3021 + optionalDependencies: 3022 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 3023 + optional: true 3024 + 3025 + '@img/sharp-linuxmusl-x64@0.33.5': 3026 + optionalDependencies: 3027 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 3028 + optional: true 3029 + 3030 + '@img/sharp-wasm32@0.33.5': 3031 + dependencies: 3032 + '@emnapi/runtime': 1.3.1 3033 + optional: true 3034 + 3035 + '@img/sharp-win32-ia32@0.33.5': 3036 + optional: true 3037 + 3038 + '@img/sharp-win32-x64@0.33.5': 3039 + optional: true 3040 + 3041 + '@ioredis/commands@1.2.0': {} 3042 + 3043 + '@ipld/car@3.2.4': 3044 + dependencies: 3045 + '@ipld/dag-cbor': 7.0.3 3046 + multiformats: 9.9.0 3047 + varint: 6.0.0 3048 + 3049 + '@ipld/dag-cbor@7.0.3': 3050 + dependencies: 3051 + cborg: 1.10.2 3052 + multiformats: 9.9.0 3053 + 3054 + '@isaacs/cliui@8.0.2': 3055 + dependencies: 3056 + string-width: 5.1.2 3057 + string-width-cjs: string-width@4.2.3 3058 + strip-ansi: 7.1.0 3059 + strip-ansi-cjs: strip-ansi@6.0.1 3060 + wrap-ansi: 8.1.0 3061 + wrap-ansi-cjs: wrap-ansi@7.0.0 3062 + 3063 + '@noble/curves@1.8.1': 3064 + dependencies: 3065 + '@noble/hashes': 1.7.1 3066 + 3067 + '@noble/hashes@1.7.1': {} 3068 + 3069 + '@noble/secp256k1@1.7.1': {} 3070 + 3071 + '@pkgjs/parseargs@0.11.0': 3072 + optional: true 3073 + 3074 + '@smithy/abort-controller@4.0.1': 3075 + dependencies: 3076 + '@smithy/types': 4.1.0 3077 + tslib: 2.8.1 3078 + 3079 + '@smithy/chunked-blob-reader-native@4.0.0': 3080 + dependencies: 3081 + '@smithy/util-base64': 4.0.0 3082 + tslib: 2.8.1 3083 + 3084 + '@smithy/chunked-blob-reader@5.0.0': 3085 + dependencies: 3086 + tslib: 2.8.1 3087 + 3088 + '@smithy/config-resolver@4.0.1': 3089 + dependencies: 3090 + '@smithy/node-config-provider': 4.0.1 3091 + '@smithy/types': 4.1.0 3092 + '@smithy/util-config-provider': 4.0.0 3093 + '@smithy/util-middleware': 4.0.1 3094 + tslib: 2.8.1 3095 + 3096 + '@smithy/core@3.1.5': 3097 + dependencies: 3098 + '@smithy/middleware-serde': 4.0.2 3099 + '@smithy/protocol-http': 5.0.1 3100 + '@smithy/types': 4.1.0 3101 + '@smithy/util-body-length-browser': 4.0.0 3102 + '@smithy/util-middleware': 4.0.1 3103 + '@smithy/util-stream': 4.1.2 3104 + '@smithy/util-utf8': 4.0.0 3105 + tslib: 2.8.1 3106 + 3107 + '@smithy/credential-provider-imds@4.0.1': 3108 + dependencies: 3109 + '@smithy/node-config-provider': 4.0.1 3110 + '@smithy/property-provider': 4.0.1 3111 + '@smithy/types': 4.1.0 3112 + '@smithy/url-parser': 4.0.1 3113 + tslib: 2.8.1 3114 + 3115 + '@smithy/eventstream-codec@4.0.1': 3116 + dependencies: 3117 + '@aws-crypto/crc32': 5.2.0 3118 + '@smithy/types': 4.1.0 3119 + '@smithy/util-hex-encoding': 4.0.0 3120 + tslib: 2.8.1 3121 + 3122 + '@smithy/eventstream-serde-browser@4.0.1': 3123 + dependencies: 3124 + '@smithy/eventstream-serde-universal': 4.0.1 3125 + '@smithy/types': 4.1.0 3126 + tslib: 2.8.1 3127 + 3128 + '@smithy/eventstream-serde-config-resolver@4.0.1': 3129 + dependencies: 3130 + '@smithy/types': 4.1.0 3131 + tslib: 2.8.1 3132 + 3133 + '@smithy/eventstream-serde-node@4.0.1': 3134 + dependencies: 3135 + '@smithy/eventstream-serde-universal': 4.0.1 3136 + '@smithy/types': 4.1.0 3137 + tslib: 2.8.1 3138 + 3139 + '@smithy/eventstream-serde-universal@4.0.1': 3140 + dependencies: 3141 + '@smithy/eventstream-codec': 4.0.1 3142 + '@smithy/types': 4.1.0 3143 + tslib: 2.8.1 3144 + 3145 + '@smithy/fetch-http-handler@5.0.1': 3146 + dependencies: 3147 + '@smithy/protocol-http': 5.0.1 3148 + '@smithy/querystring-builder': 4.0.1 3149 + '@smithy/types': 4.1.0 3150 + '@smithy/util-base64': 4.0.0 3151 + tslib: 2.8.1 3152 + 3153 + '@smithy/hash-blob-browser@4.0.1': 3154 + dependencies: 3155 + '@smithy/chunked-blob-reader': 5.0.0 3156 + '@smithy/chunked-blob-reader-native': 4.0.0 3157 + '@smithy/types': 4.1.0 3158 + tslib: 2.8.1 3159 + 3160 + '@smithy/hash-node@4.0.1': 3161 + dependencies: 3162 + '@smithy/types': 4.1.0 3163 + '@smithy/util-buffer-from': 4.0.0 3164 + '@smithy/util-utf8': 4.0.0 3165 + tslib: 2.8.1 3166 + 3167 + '@smithy/hash-stream-node@4.0.1': 3168 + dependencies: 3169 + '@smithy/types': 4.1.0 3170 + '@smithy/util-utf8': 4.0.0 3171 + tslib: 2.8.1 3172 + 3173 + '@smithy/invalid-dependency@4.0.1': 3174 + dependencies: 3175 + '@smithy/types': 4.1.0 3176 + tslib: 2.8.1 3177 + 3178 + '@smithy/is-array-buffer@2.2.0': 3179 + dependencies: 3180 + tslib: 2.8.1 3181 + 3182 + '@smithy/is-array-buffer@4.0.0': 3183 + dependencies: 3184 + tslib: 2.8.1 3185 + 3186 + '@smithy/md5-js@4.0.1': 3187 + dependencies: 3188 + '@smithy/types': 4.1.0 3189 + '@smithy/util-utf8': 4.0.0 3190 + tslib: 2.8.1 3191 + 3192 + '@smithy/middleware-content-length@4.0.1': 3193 + dependencies: 3194 + '@smithy/protocol-http': 5.0.1 3195 + '@smithy/types': 4.1.0 3196 + tslib: 2.8.1 3197 + 3198 + '@smithy/middleware-endpoint@4.0.6': 3199 + dependencies: 3200 + '@smithy/core': 3.1.5 3201 + '@smithy/middleware-serde': 4.0.2 3202 + '@smithy/node-config-provider': 4.0.1 3203 + '@smithy/shared-ini-file-loader': 4.0.1 3204 + '@smithy/types': 4.1.0 3205 + '@smithy/url-parser': 4.0.1 3206 + '@smithy/util-middleware': 4.0.1 3207 + tslib: 2.8.1 3208 + 3209 + '@smithy/middleware-retry@4.0.7': 3210 + dependencies: 3211 + '@smithy/node-config-provider': 4.0.1 3212 + '@smithy/protocol-http': 5.0.1 3213 + '@smithy/service-error-classification': 4.0.1 3214 + '@smithy/smithy-client': 4.1.6 3215 + '@smithy/types': 4.1.0 3216 + '@smithy/util-middleware': 4.0.1 3217 + '@smithy/util-retry': 4.0.1 3218 + tslib: 2.8.1 3219 + uuid: 9.0.1 3220 + 3221 + '@smithy/middleware-serde@4.0.2': 3222 + dependencies: 3223 + '@smithy/types': 4.1.0 3224 + tslib: 2.8.1 3225 + 3226 + '@smithy/middleware-stack@4.0.1': 3227 + dependencies: 3228 + '@smithy/types': 4.1.0 3229 + tslib: 2.8.1 3230 + 3231 + '@smithy/node-config-provider@4.0.1': 3232 + dependencies: 3233 + '@smithy/property-provider': 4.0.1 3234 + '@smithy/shared-ini-file-loader': 4.0.1 3235 + '@smithy/types': 4.1.0 3236 + tslib: 2.8.1 3237 + 3238 + '@smithy/node-http-handler@4.0.3': 3239 + dependencies: 3240 + '@smithy/abort-controller': 4.0.1 3241 + '@smithy/protocol-http': 5.0.1 3242 + '@smithy/querystring-builder': 4.0.1 3243 + '@smithy/types': 4.1.0 3244 + tslib: 2.8.1 3245 + 3246 + '@smithy/property-provider@4.0.1': 3247 + dependencies: 3248 + '@smithy/types': 4.1.0 3249 + tslib: 2.8.1 3250 + 3251 + '@smithy/protocol-http@5.0.1': 3252 + dependencies: 3253 + '@smithy/types': 4.1.0 3254 + tslib: 2.8.1 3255 + 3256 + '@smithy/querystring-builder@4.0.1': 3257 + dependencies: 3258 + '@smithy/types': 4.1.0 3259 + '@smithy/util-uri-escape': 4.0.0 3260 + tslib: 2.8.1 3261 + 3262 + '@smithy/querystring-parser@4.0.1': 3263 + dependencies: 3264 + '@smithy/types': 4.1.0 3265 + tslib: 2.8.1 3266 + 3267 + '@smithy/service-error-classification@4.0.1': 3268 + dependencies: 3269 + '@smithy/types': 4.1.0 3270 + 3271 + '@smithy/shared-ini-file-loader@4.0.1': 3272 + dependencies: 3273 + '@smithy/types': 4.1.0 3274 + tslib: 2.8.1 3275 + 3276 + '@smithy/signature-v4@5.0.1': 3277 + dependencies: 3278 + '@smithy/is-array-buffer': 4.0.0 3279 + '@smithy/protocol-http': 5.0.1 3280 + '@smithy/types': 4.1.0 3281 + '@smithy/util-hex-encoding': 4.0.0 3282 + '@smithy/util-middleware': 4.0.1 3283 + '@smithy/util-uri-escape': 4.0.0 3284 + '@smithy/util-utf8': 4.0.0 3285 + tslib: 2.8.1 3286 + 3287 + '@smithy/smithy-client@4.1.6': 3288 + dependencies: 3289 + '@smithy/core': 3.1.5 3290 + '@smithy/middleware-endpoint': 4.0.6 3291 + '@smithy/middleware-stack': 4.0.1 3292 + '@smithy/protocol-http': 5.0.1 3293 + '@smithy/types': 4.1.0 3294 + '@smithy/util-stream': 4.1.2 3295 + tslib: 2.8.1 3296 + 3297 + '@smithy/types@4.1.0': 3298 + dependencies: 3299 + tslib: 2.8.1 3300 + 3301 + '@smithy/url-parser@4.0.1': 3302 + dependencies: 3303 + '@smithy/querystring-parser': 4.0.1 3304 + '@smithy/types': 4.1.0 3305 + tslib: 2.8.1 3306 + 3307 + '@smithy/util-base64@4.0.0': 3308 + dependencies: 3309 + '@smithy/util-buffer-from': 4.0.0 3310 + '@smithy/util-utf8': 4.0.0 3311 + tslib: 2.8.1 3312 + 3313 + '@smithy/util-body-length-browser@4.0.0': 3314 + dependencies: 3315 + tslib: 2.8.1 3316 + 3317 + '@smithy/util-body-length-node@4.0.0': 3318 + dependencies: 3319 + tslib: 2.8.1 3320 + 3321 + '@smithy/util-buffer-from@2.2.0': 3322 + dependencies: 3323 + '@smithy/is-array-buffer': 2.2.0 3324 + tslib: 2.8.1 3325 + 3326 + '@smithy/util-buffer-from@4.0.0': 3327 + dependencies: 3328 + '@smithy/is-array-buffer': 4.0.0 3329 + tslib: 2.8.1 3330 + 3331 + '@smithy/util-config-provider@4.0.0': 3332 + dependencies: 3333 + tslib: 2.8.1 3334 + 3335 + '@smithy/util-defaults-mode-browser@4.0.7': 3336 + dependencies: 3337 + '@smithy/property-provider': 4.0.1 3338 + '@smithy/smithy-client': 4.1.6 3339 + '@smithy/types': 4.1.0 3340 + bowser: 2.11.0 3341 + tslib: 2.8.1 3342 + 3343 + '@smithy/util-defaults-mode-node@4.0.7': 3344 + dependencies: 3345 + '@smithy/config-resolver': 4.0.1 3346 + '@smithy/credential-provider-imds': 4.0.1 3347 + '@smithy/node-config-provider': 4.0.1 3348 + '@smithy/property-provider': 4.0.1 3349 + '@smithy/smithy-client': 4.1.6 3350 + '@smithy/types': 4.1.0 3351 + tslib: 2.8.1 3352 + 3353 + '@smithy/util-endpoints@3.0.1': 3354 + dependencies: 3355 + '@smithy/node-config-provider': 4.0.1 3356 + '@smithy/types': 4.1.0 3357 + tslib: 2.8.1 3358 + 3359 + '@smithy/util-hex-encoding@4.0.0': 3360 + dependencies: 3361 + tslib: 2.8.1 3362 + 3363 + '@smithy/util-middleware@4.0.1': 3364 + dependencies: 3365 + '@smithy/types': 4.1.0 3366 + tslib: 2.8.1 3367 + 3368 + '@smithy/util-retry@4.0.1': 3369 + dependencies: 3370 + '@smithy/service-error-classification': 4.0.1 3371 + '@smithy/types': 4.1.0 3372 + tslib: 2.8.1 3373 + 3374 + '@smithy/util-stream@4.1.2': 3375 + dependencies: 3376 + '@smithy/fetch-http-handler': 5.0.1 3377 + '@smithy/node-http-handler': 4.0.3 3378 + '@smithy/types': 4.1.0 3379 + '@smithy/util-base64': 4.0.0 3380 + '@smithy/util-buffer-from': 4.0.0 3381 + '@smithy/util-hex-encoding': 4.0.0 3382 + '@smithy/util-utf8': 4.0.0 3383 + tslib: 2.8.1 3384 + 3385 + '@smithy/util-uri-escape@4.0.0': 3386 + dependencies: 3387 + tslib: 2.8.1 3388 + 3389 + '@smithy/util-utf8@2.3.0': 3390 + dependencies: 3391 + '@smithy/util-buffer-from': 2.2.0 3392 + tslib: 2.8.1 3393 + 3394 + '@smithy/util-utf8@4.0.0': 3395 + dependencies: 3396 + '@smithy/util-buffer-from': 4.0.0 3397 + tslib: 2.8.1 3398 + 3399 + '@smithy/util-waiter@4.0.2': 3400 + dependencies: 3401 + '@smithy/abort-controller': 4.0.1 3402 + '@smithy/types': 4.1.0 3403 + tslib: 2.8.1 3404 + 3405 + '@tokenizer/token@0.3.0': {} 3406 + 3407 + '@types/bn.js@5.1.6': 3408 + dependencies: 3409 + '@types/node': 22.13.5 3410 + 3411 + '@types/body-parser@1.19.5': 3412 + dependencies: 3413 + '@types/connect': 3.4.38 3414 + '@types/node': 22.13.5 3415 + 3416 + '@types/connect@3.4.38': 3417 + dependencies: 3418 + '@types/node': 22.13.5 3419 + 3420 + '@types/elliptic@6.4.18': 3421 + dependencies: 3422 + '@types/bn.js': 5.1.6 3423 + 3424 + '@types/express-serve-static-core@4.19.6': 3425 + dependencies: 3426 + '@types/node': 22.13.5 3427 + '@types/qs': 6.9.18 3428 + '@types/range-parser': 1.2.7 3429 + '@types/send': 0.17.4 3430 + 3431 + '@types/express@4.17.21': 3432 + dependencies: 3433 + '@types/body-parser': 1.19.5 3434 + '@types/express-serve-static-core': 4.19.6 3435 + '@types/qs': 6.9.18 3436 + '@types/serve-static': 1.15.7 3437 + 3438 + '@types/http-errors@2.0.4': {} 3439 + 3440 + '@types/mime@1.3.5': {} 3441 + 3442 + '@types/node@22.13.5': 3443 + dependencies: 3444 + undici-types: 6.20.0 3445 + 3446 + '@types/qs@6.9.18': {} 3447 + 3448 + '@types/range-parser@1.2.7': {} 3449 + 3450 + '@types/send@0.17.4': 3451 + dependencies: 3452 + '@types/mime': 1.3.5 3453 + '@types/node': 22.13.5 3454 + 3455 + '@types/serve-static@1.15.7': 3456 + dependencies: 3457 + '@types/http-errors': 2.0.4 3458 + '@types/node': 22.13.5 3459 + '@types/send': 0.17.4 3460 + 3461 + abort-controller@3.0.0: 3462 + dependencies: 3463 + event-target-shim: 5.0.1 3464 + 3465 + accepts@1.3.8: 3466 + dependencies: 3467 + mime-types: 2.1.35 3468 + negotiator: 0.6.3 3469 + 3470 + ansi-regex@5.0.1: {} 3471 + 3472 + ansi-regex@6.1.0: {} 3473 + 3474 + ansi-styles@4.3.0: 3475 + dependencies: 3476 + color-convert: 2.0.1 3477 + 3478 + ansi-styles@6.2.1: {} 3479 + 3480 + array-flatten@1.1.1: {} 3481 + 3482 + asn1.js@5.4.1: 3483 + dependencies: 3484 + bn.js: 4.12.1 3485 + inherits: 2.0.4 3486 + minimalistic-assert: 1.0.1 3487 + safer-buffer: 2.1.2 3488 + 3489 + asynckit@0.4.0: {} 3490 + 3491 + atomic-sleep@1.0.0: {} 3492 + 3493 + await-lock@2.2.2: {} 3494 + 3495 + axios@1.8.1: 3496 + dependencies: 3497 + follow-redirects: 1.15.9 3498 + form-data: 4.0.2 3499 + proxy-from-env: 1.1.0 3500 + transitivePeerDependencies: 3501 + - debug 3502 + 3503 + balanced-match@1.0.2: {} 3504 + 3505 + base64-js@1.5.1: {} 3506 + 3507 + better-sqlite3@10.1.0: 3508 + dependencies: 3509 + bindings: 1.5.0 3510 + prebuild-install: 7.1.3 3511 + 3512 + big-integer@1.6.52: {} 3513 + 3514 + bindings@1.5.0: 3515 + dependencies: 3516 + file-uri-to-path: 1.0.0 3517 + 3518 + bl@4.1.0: 3519 + dependencies: 3520 + buffer: 5.7.1 3521 + inherits: 2.0.4 3522 + readable-stream: 3.6.2 3523 + 3524 + bn.js@4.12.1: {} 3525 + 3526 + body-parser@1.20.3: 3527 + dependencies: 3528 + bytes: 3.1.2 3529 + content-type: 1.0.5 3530 + debug: 2.6.9 3531 + depd: 2.0.0 3532 + destroy: 1.2.0 3533 + http-errors: 2.0.0 3534 + iconv-lite: 0.4.24 3535 + on-finished: 2.4.1 3536 + qs: 6.13.0 3537 + raw-body: 2.5.2 3538 + type-is: 1.6.18 3539 + unpipe: 1.0.0 3540 + transitivePeerDependencies: 3541 + - supports-color 3542 + 3543 + bowser@2.11.0: {} 3544 + 3545 + brace-expansion@2.0.1: 3546 + dependencies: 3547 + balanced-match: 1.0.2 3548 + 3549 + brorand@1.1.0: {} 3550 + 3551 + buffer@5.6.0: 3552 + dependencies: 3553 + base64-js: 1.5.1 3554 + ieee754: 1.2.1 3555 + 3556 + buffer@5.7.1: 3557 + dependencies: 3558 + base64-js: 1.5.1 3559 + ieee754: 1.2.1 3560 + 3561 + buffer@6.0.3: 3562 + dependencies: 3563 + base64-js: 1.5.1 3564 + ieee754: 1.2.1 3565 + 3566 + bytes@3.1.2: {} 3567 + 3568 + call-bind-apply-helpers@1.0.2: 3569 + dependencies: 3570 + es-errors: 1.3.0 3571 + function-bind: 1.1.2 3572 + 3573 + call-bound@1.0.3: 3574 + dependencies: 3575 + call-bind-apply-helpers: 1.0.2 3576 + get-intrinsic: 1.3.0 3577 + 3578 + cbor-extract@2.2.0: 3579 + dependencies: 3580 + node-gyp-build-optional-packages: 5.1.1 3581 + optionalDependencies: 3582 + '@cbor-extract/cbor-extract-darwin-arm64': 2.2.0 3583 + '@cbor-extract/cbor-extract-darwin-x64': 2.2.0 3584 + '@cbor-extract/cbor-extract-linux-arm': 2.2.0 3585 + '@cbor-extract/cbor-extract-linux-arm64': 2.2.0 3586 + '@cbor-extract/cbor-extract-linux-x64': 2.2.0 3587 + '@cbor-extract/cbor-extract-win32-x64': 2.2.0 3588 + optional: true 3589 + 3590 + cbor-x@1.6.0: 3591 + optionalDependencies: 3592 + cbor-extract: 2.2.0 3593 + 3594 + cborg@1.10.2: {} 3595 + 3596 + chownr@1.1.4: {} 3597 + 3598 + cluster-key-slot@1.1.2: {} 3599 + 3600 + color-convert@2.0.1: 3601 + dependencies: 3602 + color-name: 1.1.4 3603 + 3604 + color-name@1.1.4: {} 3605 + 3606 + color-string@1.9.1: 3607 + dependencies: 3608 + color-name: 1.1.4 3609 + simple-swizzle: 0.2.2 3610 + 3611 + color@4.2.3: 3612 + dependencies: 3613 + color-convert: 2.0.1 3614 + color-string: 1.9.1 3615 + 3616 + combined-stream@1.0.8: 3617 + dependencies: 3618 + delayed-stream: 1.0.0 3619 + 3620 + compressible@2.0.18: 3621 + dependencies: 3622 + mime-db: 1.53.0 3623 + 3624 + compression@1.8.0: 3625 + dependencies: 3626 + bytes: 3.1.2 3627 + compressible: 2.0.18 3628 + debug: 2.6.9 3629 + negotiator: 0.6.4 3630 + on-headers: 1.0.2 3631 + safe-buffer: 5.2.1 3632 + vary: 1.1.2 3633 + transitivePeerDependencies: 3634 + - supports-color 3635 + 3636 + content-disposition@0.5.4: 3637 + dependencies: 3638 + safe-buffer: 5.2.1 3639 + 3640 + content-type@1.0.5: {} 3641 + 3642 + cookie-signature@1.0.6: {} 3643 + 3644 + cookie@0.6.0: {} 3645 + 3646 + cookie@0.7.1: {} 3647 + 3648 + cors@2.8.5: 3649 + dependencies: 3650 + object-assign: 4.1.1 3651 + vary: 1.1.2 3652 + 3653 + cross-spawn@7.0.6: 3654 + dependencies: 3655 + path-key: 3.1.1 3656 + shebang-command: 2.0.0 3657 + which: 2.0.2 3658 + 3659 + debug@2.6.9: 3660 + dependencies: 3661 + ms: 2.0.0 3662 + 3663 + debug@4.4.0: 3664 + dependencies: 3665 + ms: 2.1.3 3666 + 3667 + decompress-response@6.0.0: 3668 + dependencies: 3669 + mimic-response: 3.1.0 3670 + 3671 + deep-extend@0.6.0: {} 3672 + 3673 + deepmerge@4.3.1: {} 3674 + 3675 + delay@5.0.0: {} 3676 + 3677 + delayed-stream@1.0.0: {} 3678 + 3679 + denque@2.1.0: {} 3680 + 3681 + depd@2.0.0: {} 3682 + 3683 + destroy@1.2.0: {} 3684 + 3685 + detect-libc@2.0.3: {} 3686 + 3687 + disposable-email-domains-js@1.10.0: {} 3688 + 3689 + dom-serializer@1.4.1: 3690 + dependencies: 3691 + domelementtype: 2.3.0 3692 + domhandler: 4.3.1 3693 + entities: 2.2.0 3694 + 3695 + domelementtype@2.3.0: {} 3696 + 3697 + domhandler@4.3.1: 3698 + dependencies: 3699 + domelementtype: 2.3.0 3700 + 3701 + domutils@2.8.0: 3702 + dependencies: 3703 + dom-serializer: 1.4.1 3704 + domelementtype: 2.3.0 3705 + domhandler: 4.3.1 3706 + 3707 + dotenv@16.4.7: {} 3708 + 3709 + dunder-proto@1.0.1: 3710 + dependencies: 3711 + call-bind-apply-helpers: 1.0.2 3712 + es-errors: 1.3.0 3713 + gopd: 1.2.0 3714 + 3715 + eastasianwidth@0.2.0: {} 3716 + 3717 + ee-first@1.1.1: {} 3718 + 3719 + elliptic@6.6.1: 3720 + dependencies: 3721 + bn.js: 4.12.1 3722 + brorand: 1.1.0 3723 + hash.js: 1.1.7 3724 + hmac-drbg: 1.0.1 3725 + inherits: 2.0.4 3726 + minimalistic-assert: 1.0.1 3727 + minimalistic-crypto-utils: 1.0.1 3728 + 3729 + emoji-regex@8.0.0: {} 3730 + 3731 + emoji-regex@9.2.2: {} 3732 + 3733 + encodeurl@1.0.2: {} 3734 + 3735 + encodeurl@2.0.0: {} 3736 + 3737 + end-of-stream@1.4.4: 3738 + dependencies: 3739 + once: 1.4.0 3740 + 3741 + entities@2.2.0: {} 3742 + 3743 + es-define-property@1.0.1: {} 3744 + 3745 + es-errors@1.3.0: {} 3746 + 3747 + es-object-atoms@1.1.1: 3748 + dependencies: 3749 + es-errors: 1.3.0 3750 + 3751 + es-set-tostringtag@2.1.0: 3752 + dependencies: 3753 + es-errors: 1.3.0 3754 + get-intrinsic: 1.3.0 3755 + has-tostringtag: 1.0.2 3756 + hasown: 2.0.2 3757 + 3758 + escape-html@1.0.3: {} 3759 + 3760 + etag@1.8.1: {} 3761 + 3762 + event-target-shim@5.0.1: {} 3763 + 3764 + eventemitter3@4.0.7: {} 3765 + 3766 + events@3.3.0: {} 3767 + 3768 + expand-template@2.0.3: {} 3769 + 3770 + express-async-errors@3.1.1(express@4.21.2): 3771 + dependencies: 3772 + express: 4.21.2 3773 + 3774 + express@4.21.2: 3775 + dependencies: 3776 + accepts: 1.3.8 3777 + array-flatten: 1.1.1 3778 + body-parser: 1.20.3 3779 + content-disposition: 0.5.4 3780 + content-type: 1.0.5 3781 + cookie: 0.7.1 3782 + cookie-signature: 1.0.6 3783 + debug: 2.6.9 3784 + depd: 2.0.0 3785 + encodeurl: 2.0.0 3786 + escape-html: 1.0.3 3787 + etag: 1.8.1 3788 + finalhandler: 1.3.1 3789 + fresh: 0.5.2 3790 + http-errors: 2.0.0 3791 + merge-descriptors: 1.0.3 3792 + methods: 1.1.2 3793 + on-finished: 2.4.1 3794 + parseurl: 1.3.3 3795 + path-to-regexp: 0.1.12 3796 + proxy-addr: 2.0.7 3797 + qs: 6.13.0 3798 + range-parser: 1.2.1 3799 + safe-buffer: 5.2.1 3800 + send: 0.19.0 3801 + serve-static: 1.16.2 3802 + setprototypeof: 1.2.0 3803 + statuses: 2.0.1 3804 + type-is: 1.6.18 3805 + utils-merge: 1.0.1 3806 + vary: 1.1.2 3807 + transitivePeerDependencies: 3808 + - supports-color 3809 + 3810 + fast-printf@1.6.10: {} 3811 + 3812 + fast-redact@3.5.0: {} 3813 + 3814 + fast-xml-parser@4.4.1: 3815 + dependencies: 3816 + strnum: 1.1.2 3817 + 3818 + file-type@16.5.4: 3819 + dependencies: 3820 + readable-web-to-node-stream: 3.0.4 3821 + strtok3: 6.3.0 3822 + token-types: 4.2.1 3823 + 3824 + file-uri-to-path@1.0.0: {} 3825 + 3826 + finalhandler@1.3.1: 3827 + dependencies: 3828 + debug: 2.6.9 3829 + encodeurl: 2.0.0 3830 + escape-html: 1.0.3 3831 + on-finished: 2.4.1 3832 + parseurl: 1.3.3 3833 + statuses: 2.0.1 3834 + unpipe: 1.0.0 3835 + transitivePeerDependencies: 3836 + - supports-color 3837 + 3838 + follow-redirects@1.15.9: {} 3839 + 3840 + foreground-child@3.3.1: 3841 + dependencies: 3842 + cross-spawn: 7.0.6 3843 + signal-exit: 4.1.0 3844 + 3845 + form-data@4.0.2: 3846 + dependencies: 3847 + asynckit: 0.4.0 3848 + combined-stream: 1.0.8 3849 + es-set-tostringtag: 2.1.0 3850 + mime-types: 2.1.35 3851 + 3852 + forwarded@0.2.0: {} 3853 + 3854 + fresh@0.5.2: {} 3855 + 3856 + fs-constants@1.0.0: {} 3857 + 3858 + function-bind@1.1.2: {} 3859 + 3860 + get-caller-file@2.0.5: {} 3861 + 3862 + get-intrinsic@1.3.0: 3863 + dependencies: 3864 + call-bind-apply-helpers: 1.0.2 3865 + es-define-property: 1.0.1 3866 + es-errors: 1.3.0 3867 + es-object-atoms: 1.1.1 3868 + function-bind: 1.1.2 3869 + get-proto: 1.0.1 3870 + gopd: 1.2.0 3871 + has-symbols: 1.1.0 3872 + hasown: 2.0.2 3873 + math-intrinsics: 1.1.0 3874 + 3875 + get-port@5.1.1: {} 3876 + 3877 + get-proto@1.0.1: 3878 + dependencies: 3879 + dunder-proto: 1.0.1 3880 + es-object-atoms: 1.1.1 3881 + 3882 + github-from-package@0.0.0: {} 3883 + 3884 + glob@10.4.5: 3885 + dependencies: 3886 + foreground-child: 3.3.1 3887 + jackspeak: 3.4.3 3888 + minimatch: 9.0.5 3889 + minipass: 7.1.2 3890 + package-json-from-dist: 1.0.1 3891 + path-scurry: 1.11.1 3892 + 3893 + gopd@1.2.0: {} 3894 + 3895 + graphemer@1.4.0: {} 3896 + 3897 + handlebars@4.7.8: 3898 + dependencies: 3899 + minimist: 1.2.8 3900 + neo-async: 2.6.2 3901 + source-map: 0.6.1 3902 + wordwrap: 1.0.0 3903 + optionalDependencies: 3904 + uglify-js: 3.19.3 3905 + 3906 + has-symbols@1.1.0: {} 3907 + 3908 + has-tostringtag@1.0.2: 3909 + dependencies: 3910 + has-symbols: 1.1.0 3911 + 3912 + hash.js@1.1.7: 3913 + dependencies: 3914 + inherits: 2.0.4 3915 + minimalistic-assert: 1.0.1 3916 + 3917 + hasown@2.0.2: 3918 + dependencies: 3919 + function-bind: 1.1.2 3920 + 3921 + he@1.2.0: {} 3922 + 3923 + hmac-drbg@1.0.1: 3924 + dependencies: 3925 + hash.js: 1.1.7 3926 + minimalistic-assert: 1.0.1 3927 + minimalistic-crypto-utils: 1.0.1 3928 + 3929 + html-to-text@7.1.1: 3930 + dependencies: 3931 + deepmerge: 4.3.1 3932 + he: 1.2.0 3933 + htmlparser2: 6.1.0 3934 + minimist: 1.2.8 3935 + 3936 + htmlparser2@6.1.0: 3937 + dependencies: 3938 + domelementtype: 2.3.0 3939 + domhandler: 4.3.1 3940 + domutils: 2.8.0 3941 + entities: 2.2.0 3942 + 3943 + http-errors@2.0.0: 3944 + dependencies: 3945 + depd: 2.0.0 3946 + inherits: 2.0.4 3947 + setprototypeof: 1.2.0 3948 + statuses: 2.0.1 3949 + toidentifier: 1.0.1 3950 + 3951 + http-terminator@3.2.0: 3952 + dependencies: 3953 + delay: 5.0.0 3954 + p-wait-for: 3.2.0 3955 + roarr: 7.21.1 3956 + type-fest: 2.19.0 3957 + 3958 + iconv-lite@0.4.24: 3959 + dependencies: 3960 + safer-buffer: 2.1.2 3961 + 3962 + ieee754@1.2.1: {} 3963 + 3964 + inherits@2.0.4: {} 3965 + 3966 + ini@1.3.8: {} 3967 + 3968 + ioredis@5.5.0: 3969 + dependencies: 3970 + '@ioredis/commands': 1.2.0 3971 + cluster-key-slot: 1.1.2 3972 + debug: 4.4.0 3973 + denque: 2.1.0 3974 + lodash.defaults: 4.2.0 3975 + lodash.isarguments: 3.1.0 3976 + redis-errors: 1.2.0 3977 + redis-parser: 3.0.0 3978 + standard-as-callback: 2.1.0 3979 + transitivePeerDependencies: 3980 + - supports-color 3981 + 3982 + ip3country@5.0.0: {} 3983 + 3984 + ipaddr.js@1.9.1: {} 3985 + 3986 + ipaddr.js@2.2.0: {} 3987 + 3988 + is-arrayish@0.3.2: {} 3989 + 3990 + is-fullwidth-code-point@3.0.0: {} 3991 + 3992 + isexe@2.0.0: {} 3993 + 3994 + iso-datestring-validator@2.2.2: {} 3995 + 3996 + jackspeak@3.4.3: 3997 + dependencies: 3998 + '@isaacs/cliui': 8.0.2 3999 + optionalDependencies: 4000 + '@pkgjs/parseargs': 0.11.0 4001 + 4002 + jose@5.10.0: {} 4003 + 4004 + key-encoder@2.0.3: 4005 + dependencies: 4006 + '@types/elliptic': 6.4.18 4007 + asn1.js: 5.4.1 4008 + bn.js: 4.12.1 4009 + elliptic: 6.6.1 4010 + 4011 + kysely@0.22.0: {} 4012 + 4013 + kysely@0.23.5: {} 4014 + 4015 + lande@1.0.10: 4016 + dependencies: 4017 + toygrad: 2.6.0 4018 + 4019 + lodash.defaults@4.2.0: {} 4020 + 4021 + lodash.isarguments@3.1.0: {} 4022 + 4023 + lru-cache@10.4.3: {} 4024 + 4025 + math-intrinsics@1.1.0: {} 4026 + 4027 + media-typer@0.3.0: {} 4028 + 4029 + merge-descriptors@1.0.3: {} 4030 + 4031 + methods@1.1.2: {} 4032 + 4033 + mime-db@1.52.0: {} 4034 + 4035 + mime-db@1.53.0: {} 4036 + 4037 + mime-types@2.1.35: 4038 + dependencies: 4039 + mime-db: 1.52.0 4040 + 4041 + mime@1.6.0: {} 4042 + 4043 + mimic-response@3.1.0: {} 4044 + 4045 + minimalistic-assert@1.0.1: {} 4046 + 4047 + minimalistic-crypto-utils@1.0.1: {} 4048 + 4049 + minimatch@9.0.5: 4050 + dependencies: 4051 + brace-expansion: 2.0.1 4052 + 4053 + minimist@1.2.8: {} 4054 + 4055 + minipass@7.1.2: {} 4056 + 4057 + mkdirp-classic@0.5.3: {} 4058 + 4059 + ms@2.0.0: {} 4060 + 4061 + ms@2.1.3: {} 4062 + 4063 + multiformats@9.9.0: {} 4064 + 4065 + murmurhash@2.0.1: {} 4066 + 4067 + napi-build-utils@2.0.0: {} 4068 + 4069 + negotiator@0.6.3: {} 4070 + 4071 + negotiator@0.6.4: {} 4072 + 4073 + neo-async@2.6.2: {} 4074 + 4075 + node-abi@3.74.0: 4076 + dependencies: 4077 + semver: 7.7.1 4078 + 4079 + node-fetch@2.7.0: 4080 + dependencies: 4081 + whatwg-url: 5.0.0 4082 + 4083 + node-gyp-build-optional-packages@5.1.1: 4084 + dependencies: 4085 + detect-libc: 2.0.3 4086 + optional: true 4087 + 4088 + nodemailer-html-to-text@3.2.0: 4089 + dependencies: 4090 + html-to-text: 7.1.1 4091 + 4092 + nodemailer@6.10.0: {} 4093 + 4094 + object-assign@4.1.1: {} 4095 + 4096 + object-inspect@1.13.4: {} 4097 + 4098 + on-exit-leak-free@2.1.2: {} 4099 + 4100 + on-finished@2.4.1: 4101 + dependencies: 4102 + ee-first: 1.1.1 4103 + 4104 + on-headers@1.0.2: {} 4105 + 4106 + once@1.4.0: 4107 + dependencies: 4108 + wrappy: 1.0.2 4109 + 4110 + one-webcrypto@1.0.3: {} 4111 + 4112 + p-finally@1.0.0: {} 4113 + 4114 + p-queue@6.6.2: 4115 + dependencies: 4116 + eventemitter3: 4.0.7 4117 + p-timeout: 3.2.0 4118 + 4119 + p-timeout@3.2.0: 4120 + dependencies: 4121 + p-finally: 1.0.0 4122 + 4123 + p-wait-for@3.2.0: 4124 + dependencies: 4125 + p-timeout: 3.2.0 4126 + 4127 + package-json-from-dist@1.0.1: {} 4128 + 4129 + parseurl@1.3.3: {} 4130 + 4131 + path-key@3.1.1: {} 4132 + 4133 + path-scurry@1.11.1: 4134 + dependencies: 4135 + lru-cache: 10.4.3 4136 + minipass: 7.1.2 4137 + 4138 + path-to-regexp@0.1.12: {} 4139 + 4140 + peek-readable@4.1.0: {} 4141 + 4142 + pg-cloudflare@1.1.1: 4143 + optional: true 4144 + 4145 + pg-connection-string@2.7.0: {} 4146 + 4147 + pg-int8@1.0.1: {} 4148 + 4149 + pg-pool@3.7.1(pg@8.13.3): 4150 + dependencies: 4151 + pg: 8.13.3 4152 + 4153 + pg-protocol@1.7.1: {} 4154 + 4155 + pg-types@2.2.0: 4156 + dependencies: 4157 + pg-int8: 1.0.1 4158 + postgres-array: 2.0.0 4159 + postgres-bytea: 1.0.0 4160 + postgres-date: 1.0.7 4161 + postgres-interval: 1.2.0 4162 + 4163 + pg@8.13.3: 4164 + dependencies: 4165 + pg-connection-string: 2.7.0 4166 + pg-pool: 3.7.1(pg@8.13.3) 4167 + pg-protocol: 1.7.1 4168 + pg-types: 2.2.0 4169 + pgpass: 1.0.5 4170 + optionalDependencies: 4171 + pg-cloudflare: 1.1.1 4172 + 4173 + pgpass@1.0.5: 4174 + dependencies: 4175 + split2: 4.2.0 4176 + 4177 + pino-abstract-transport@1.2.0: 4178 + dependencies: 4179 + readable-stream: 4.7.0 4180 + split2: 4.2.0 4181 + 4182 + pino-http@8.6.1: 4183 + dependencies: 4184 + get-caller-file: 2.0.5 4185 + pino: 8.21.0 4186 + pino-std-serializers: 6.2.2 4187 + process-warning: 3.0.0 4188 + 4189 + pino-std-serializers@6.2.2: {} 4190 + 4191 + pino@8.21.0: 4192 + dependencies: 4193 + atomic-sleep: 1.0.0 4194 + fast-redact: 3.5.0 4195 + on-exit-leak-free: 2.1.2 4196 + pino-abstract-transport: 1.2.0 4197 + pino-std-serializers: 6.2.2 4198 + process-warning: 3.0.0 4199 + quick-format-unescaped: 4.0.4 4200 + real-require: 0.2.0 4201 + safe-stable-stringify: 2.5.0 4202 + sonic-boom: 3.8.1 4203 + thread-stream: 2.7.0 4204 + 4205 + postgres-array@2.0.0: {} 4206 + 4207 + postgres-bytea@1.0.0: {} 4208 + 4209 + postgres-date@1.0.7: {} 4210 + 4211 + postgres-interval@1.2.0: 4212 + dependencies: 4213 + xtend: 4.0.2 4214 + 4215 + prebuild-install@7.1.3: 4216 + dependencies: 4217 + detect-libc: 2.0.3 4218 + expand-template: 2.0.3 4219 + github-from-package: 0.0.0 4220 + minimist: 1.2.8 4221 + mkdirp-classic: 0.5.3 4222 + napi-build-utils: 2.0.0 4223 + node-abi: 3.74.0 4224 + pump: 3.0.2 4225 + rc: 1.2.8 4226 + simple-get: 4.0.1 4227 + tar-fs: 2.1.2 4228 + tunnel-agent: 0.6.0 4229 + 4230 + process-warning@3.0.0: {} 4231 + 4232 + process@0.11.10: {} 4233 + 4234 + proxy-addr@2.0.7: 4235 + dependencies: 4236 + forwarded: 0.2.0 4237 + ipaddr.js: 1.9.1 4238 + 4239 + proxy-from-env@1.1.0: {} 4240 + 4241 + psl@1.15.0: 4242 + dependencies: 4243 + punycode: 2.3.1 4244 + 4245 + pump@3.0.2: 4246 + dependencies: 4247 + end-of-stream: 1.4.4 4248 + once: 1.4.0 4249 + 4250 + punycode@2.3.1: {} 4251 + 4252 + qs@6.13.0: 4253 + dependencies: 4254 + side-channel: 1.1.0 4255 + 4256 + quick-format-unescaped@4.0.4: {} 4257 + 4258 + range-parser@1.2.1: {} 4259 + 4260 + rate-limiter-flexible@2.4.2: {} 4261 + 4262 + raw-body@2.5.2: 4263 + dependencies: 4264 + bytes: 3.1.2 4265 + http-errors: 2.0.0 4266 + iconv-lite: 0.4.24 4267 + unpipe: 1.0.0 4268 + 4269 + rc@1.2.8: 4270 + dependencies: 4271 + deep-extend: 0.6.0 4272 + ini: 1.3.8 4273 + minimist: 1.2.8 4274 + strip-json-comments: 2.0.1 4275 + 4276 + readable-stream@3.6.2: 4277 + dependencies: 4278 + inherits: 2.0.4 4279 + string_decoder: 1.3.0 4280 + util-deprecate: 1.0.2 4281 + 4282 + readable-stream@4.7.0: 4283 + dependencies: 4284 + abort-controller: 3.0.0 4285 + buffer: 6.0.3 4286 + events: 3.3.0 4287 + process: 0.11.10 4288 + string_decoder: 1.3.0 4289 + 4290 + readable-web-to-node-stream@3.0.4: 4291 + dependencies: 4292 + readable-stream: 4.7.0 4293 + 4294 + real-require@0.2.0: {} 4295 + 4296 + redis-errors@1.2.0: {} 4297 + 4298 + redis-parser@3.0.0: 4299 + dependencies: 4300 + redis-errors: 1.2.0 4301 + 4302 + roarr@7.21.1: 4303 + dependencies: 4304 + fast-printf: 1.6.10 4305 + safe-stable-stringify: 2.5.0 4306 + semver-compare: 1.0.0 4307 + 4308 + rxjs@7.8.2: 4309 + dependencies: 4310 + tslib: 2.8.1 4311 + optional: true 4312 + 4313 + safe-buffer@5.2.1: {} 4314 + 4315 + safe-stable-stringify@2.5.0: {} 4316 + 4317 + safer-buffer@2.1.2: {} 4318 + 4319 + semver-compare@1.0.0: {} 4320 + 4321 + semver@7.7.1: {} 4322 + 4323 + send@0.19.0: 4324 + dependencies: 4325 + debug: 2.6.9 4326 + depd: 2.0.0 4327 + destroy: 1.2.0 4328 + encodeurl: 1.0.2 4329 + escape-html: 1.0.3 4330 + etag: 1.8.1 4331 + fresh: 0.5.2 4332 + http-errors: 2.0.0 4333 + mime: 1.6.0 4334 + ms: 2.1.3 4335 + on-finished: 2.4.1 4336 + range-parser: 1.2.1 4337 + statuses: 2.0.1 4338 + transitivePeerDependencies: 4339 + - supports-color 4340 + 4341 + serve-static@1.16.2: 4342 + dependencies: 4343 + encodeurl: 2.0.0 4344 + escape-html: 1.0.3 4345 + parseurl: 1.3.3 4346 + send: 0.19.0 4347 + transitivePeerDependencies: 4348 + - supports-color 4349 + 4350 + setprototypeof@1.2.0: {} 4351 + 4352 + sharp@0.33.5: 4353 + dependencies: 4354 + color: 4.2.3 4355 + detect-libc: 2.0.3 4356 + semver: 7.7.1 4357 + optionalDependencies: 4358 + '@img/sharp-darwin-arm64': 0.33.5 4359 + '@img/sharp-darwin-x64': 0.33.5 4360 + '@img/sharp-libvips-darwin-arm64': 1.0.4 4361 + '@img/sharp-libvips-darwin-x64': 1.0.4 4362 + '@img/sharp-libvips-linux-arm': 1.0.5 4363 + '@img/sharp-libvips-linux-arm64': 1.0.4 4364 + '@img/sharp-libvips-linux-s390x': 1.0.4 4365 + '@img/sharp-libvips-linux-x64': 1.0.4 4366 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 4367 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 4368 + '@img/sharp-linux-arm': 0.33.5 4369 + '@img/sharp-linux-arm64': 0.33.5 4370 + '@img/sharp-linux-s390x': 0.33.5 4371 + '@img/sharp-linux-x64': 0.33.5 4372 + '@img/sharp-linuxmusl-arm64': 0.33.5 4373 + '@img/sharp-linuxmusl-x64': 0.33.5 4374 + '@img/sharp-wasm32': 0.33.5 4375 + '@img/sharp-win32-ia32': 0.33.5 4376 + '@img/sharp-win32-x64': 0.33.5 4377 + 4378 + shebang-command@2.0.0: 4379 + dependencies: 4380 + shebang-regex: 3.0.0 4381 + 4382 + shebang-regex@3.0.0: {} 4383 + 4384 + side-channel-list@1.0.0: 4385 + dependencies: 4386 + es-errors: 1.3.0 4387 + object-inspect: 1.13.4 4388 + 4389 + side-channel-map@1.0.1: 4390 + dependencies: 4391 + call-bound: 1.0.3 4392 + es-errors: 1.3.0 4393 + get-intrinsic: 1.3.0 4394 + object-inspect: 1.13.4 4395 + 4396 + side-channel-weakmap@1.0.2: 4397 + dependencies: 4398 + call-bound: 1.0.3 4399 + es-errors: 1.3.0 4400 + get-intrinsic: 1.3.0 4401 + object-inspect: 1.13.4 4402 + side-channel-map: 1.0.1 4403 + 4404 + side-channel@1.1.0: 4405 + dependencies: 4406 + es-errors: 1.3.0 4407 + object-inspect: 1.13.4 4408 + side-channel-list: 1.0.0 4409 + side-channel-map: 1.0.1 4410 + side-channel-weakmap: 1.0.2 4411 + 4412 + signal-exit@4.1.0: {} 4413 + 4414 + simple-concat@1.0.1: {} 4415 + 4416 + simple-get@4.0.1: 4417 + dependencies: 4418 + decompress-response: 6.0.0 4419 + once: 1.4.0 4420 + simple-concat: 1.0.1 4421 + 4422 + simple-swizzle@0.2.2: 4423 + dependencies: 4424 + is-arrayish: 0.3.2 4425 + 4426 + sonic-boom@3.8.1: 4427 + dependencies: 4428 + atomic-sleep: 1.0.0 4429 + 4430 + source-map@0.6.1: {} 4431 + 4432 + split2@4.2.0: {} 4433 + 4434 + standard-as-callback@2.1.0: {} 4435 + 4436 + statsig-node@5.33.0: 4437 + dependencies: 4438 + ip3country: 5.0.0 4439 + node-fetch: 2.7.0 4440 + ua-parser-js: 1.0.40 4441 + uuid: 8.3.2 4442 + transitivePeerDependencies: 4443 + - encoding 4444 + 4445 + statuses@2.0.1: {} 4446 + 4447 + stream-browserify@3.0.0: 4448 + dependencies: 4449 + inherits: 2.0.4 4450 + readable-stream: 3.6.2 4451 + 4452 + string-width@4.2.3: 4453 + dependencies: 4454 + emoji-regex: 8.0.0 4455 + is-fullwidth-code-point: 3.0.0 4456 + strip-ansi: 6.0.1 4457 + 4458 + string-width@5.1.2: 4459 + dependencies: 4460 + eastasianwidth: 0.2.0 4461 + emoji-regex: 9.2.2 4462 + strip-ansi: 7.1.0 4463 + 4464 + string_decoder@1.3.0: 4465 + dependencies: 4466 + safe-buffer: 5.2.1 4467 + 4468 + strip-ansi@6.0.1: 4469 + dependencies: 4470 + ansi-regex: 5.0.1 4471 + 4472 + strip-ansi@7.1.0: 4473 + dependencies: 4474 + ansi-regex: 6.1.0 4475 + 4476 + strip-json-comments@2.0.1: {} 4477 + 4478 + strnum@1.1.2: {} 4479 + 4480 + strtok3@6.3.0: 4481 + dependencies: 4482 + '@tokenizer/token': 0.3.0 4483 + peek-readable: 4.1.0 4484 + 4485 + structured-headers@1.0.1: {} 4486 + 4487 + tar-fs@2.1.2: 4488 + dependencies: 4489 + chownr: 1.1.4 4490 + mkdirp-classic: 0.5.3 4491 + pump: 3.0.2 4492 + tar-stream: 2.2.0 4493 + 4494 + tar-stream@2.2.0: 4495 + dependencies: 4496 + bl: 4.1.0 4497 + end-of-stream: 1.4.4 4498 + fs-constants: 1.0.0 4499 + inherits: 2.0.4 4500 + readable-stream: 3.6.2 4501 + 4502 + thread-stream@2.7.0: 4503 + dependencies: 4504 + real-require: 0.2.0 4505 + 4506 + tlds@1.255.0: {} 4507 + 4508 + toidentifier@1.0.1: {} 4509 + 4510 + token-types@4.2.1: 4511 + dependencies: 4512 + '@tokenizer/token': 0.3.0 4513 + ieee754: 1.2.1 4514 + 4515 + toygrad@2.6.0: {} 4516 + 4517 + tr46@0.0.3: {} 4518 + 4519 + tslib@2.8.1: {} 4520 + 4521 + tunnel-agent@0.6.0: 4522 + dependencies: 4523 + safe-buffer: 5.2.1 4524 + 4525 + type-fest@2.19.0: {} 4526 + 4527 + type-is@1.6.18: 4528 + dependencies: 4529 + media-typer: 0.3.0 4530 + mime-types: 2.1.35 4531 + 4532 + typed-emitter@2.1.0: 4533 + optionalDependencies: 4534 + rxjs: 7.8.2 4535 + 4536 + typescript@5.7.3: {} 4537 + 4538 + ua-parser-js@1.0.40: {} 4539 + 4540 + uglify-js@3.19.3: 4541 + optional: true 4542 + 4543 + uint8arrays@3.0.0: 4544 + dependencies: 4545 + multiformats: 9.9.0 4546 + 4547 + undici-types@6.20.0: {} 4548 + 4549 + undici@5.28.5: 4550 + dependencies: 4551 + '@fastify/busboy': 2.1.1 4552 + 4553 + undici@6.21.1: {} 4554 + 4555 + unpipe@1.0.0: {} 4556 + 4557 + util-deprecate@1.0.2: {} 4558 + 4559 + utils-merge@1.0.1: {} 4560 + 4561 + uuid@8.3.2: {} 4562 + 4563 + uuid@9.0.1: {} 4564 + 4565 + varint@6.0.0: {} 4566 + 4567 + vary@1.1.2: {} 4568 + 4569 + webidl-conversions@3.0.1: {} 4570 + 4571 + whatwg-url@5.0.0: 4572 + dependencies: 4573 + tr46: 0.0.3 4574 + webidl-conversions: 3.0.1 4575 + 4576 + which@2.0.2: 4577 + dependencies: 4578 + isexe: 2.0.0 4579 + 4580 + wordwrap@1.0.0: {} 4581 + 4582 + wrap-ansi@7.0.0: 4583 + dependencies: 4584 + ansi-styles: 4.3.0 4585 + string-width: 4.2.3 4586 + strip-ansi: 6.0.1 4587 + 4588 + wrap-ansi@8.1.0: 4589 + dependencies: 4590 + ansi-styles: 6.2.1 4591 + string-width: 5.1.2 4592 + strip-ansi: 7.1.0 4593 + 4594 + wrappy@1.0.2: {} 4595 + 4596 + ws@8.18.1: {} 4597 + 4598 + xtend@4.0.2: {} 4599 + 4600 + zod@3.24.2: {}
+59
services/dev-env/src/bin.ts
··· 1 + import './env' 2 + import { generateMockSetup } from './mock' 3 + import { TestNetwork } from './network' 4 + import { mockMailer } from './util' 5 + 6 + const run = async () => { 7 + console.log(` 8 + ██████╗ 9 + ██╔═══██╗ 10 + ██║██╗██║ 11 + ██║██║██║ 12 + ╚█║████╔╝ 13 + ╚╝╚═══╝ protocol 14 + 15 + [ created by Bluesky ]`) 16 + 17 + const network = await TestNetwork.create({ 18 + pds: { 19 + port: 2583, 20 + hostname: 'localhost', 21 + enableDidDocWithSession: true, 22 + }, 23 + bsky: { 24 + dbPostgresSchema: 'bsky', 25 + port: 2584, 26 + publicUrl: 'http://localhost:2584', 27 + }, 28 + plc: { port: 2582 }, 29 + ozone: { 30 + port: 2587, 31 + chatUrl: 'http://localhost:2590', // must run separate chat service 32 + chatDid: 'did:example:chat', 33 + dbMaterializedViewRefreshIntervalMs: 30_000, 34 + }, 35 + introspect: { port: 2581 }, 36 + }) 37 + mockMailer(network.pds) 38 + await generateMockSetup(network) 39 + 40 + if (network.introspect) { 41 + console.log( 42 + `🔍 Dev-env introspection server started http://localhost:${network.introspect.port}`, 43 + ) 44 + } 45 + console.log( 46 + `👤 DID Placeholder server started http://localhost:${network.plc.port}`, 47 + ) 48 + console.log( 49 + `🌞 Personal Data server started http://localhost:${network.pds.port}`, 50 + ) 51 + console.log(`🗼 Ozone server started http://localhost:${network.ozone.port}`) 52 + console.log(`🗼 Ozone service DID ${network.ozone.ctx.cfg.service.did}`) 53 + console.log(`🌅 Bsky Appview started http://localhost:${network.bsky.port}`) 54 + for (const fg of network.feedGens) { 55 + console.log(`🤖 Feed Generator started http://localhost:${fg.port}`) 56 + } 57 + } 58 + 59 + run()
+150
services/dev-env/src/bsky.ts
··· 1 + import { Client as PlcClient } from '@did-plc/lib' 2 + import getPort from 'get-port' 3 + import * as ui8 from 'uint8arrays' 4 + import { AtpAgent } from '@atproto/api' 5 + import * as bsky from '@atproto/bsky' 6 + import { Secp256k1Keypair } from '@atproto/crypto' 7 + import { ADMIN_PASSWORD, EXAMPLE_LABELER } from './const' 8 + import { BskyConfig } from './types' 9 + 10 + export * from '@atproto/bsky' 11 + 12 + export class TestBsky { 13 + constructor( 14 + public url: string, 15 + public port: number, 16 + public db: bsky.Database, 17 + public server: bsky.BskyAppView, 18 + public dataplane: bsky.DataPlaneServer, 19 + public bsync: bsky.MockBsync, 20 + public sub: bsky.RepoSubscription, 21 + ) {} 22 + 23 + static async create(cfg: BskyConfig): Promise<TestBsky> { 24 + const serviceKeypair = await Secp256k1Keypair.create() 25 + const plcClient = new PlcClient(cfg.plcUrl) 26 + 27 + const port = cfg.port || (await getPort()) 28 + const url = `http://localhost:${port}` 29 + const serverDid = await plcClient.createDid({ 30 + signingKey: serviceKeypair.did(), 31 + rotationKeys: [serviceKeypair.did()], 32 + handle: 'bsky.test', 33 + pds: `http://localhost:${port}`, 34 + signer: serviceKeypair, 35 + }) 36 + 37 + const endpoint = `http://localhost:${port}` 38 + 39 + await plcClient.updateData(serverDid, serviceKeypair, (x) => { 40 + x.services['bsky_notif'] = { 41 + type: 'BskyNotificationService', 42 + endpoint, 43 + } 44 + x.services['bsky_appview'] = { 45 + type: 'BskyAppView', 46 + endpoint, 47 + } 48 + return x 49 + }) 50 + 51 + // shared across server, ingester, and indexer in order to share pool, avoid too many pg connections. 52 + const db = new bsky.Database({ 53 + url: cfg.dbPostgresUrl, 54 + schema: cfg.dbPostgresSchema, 55 + poolSize: 10, 56 + }) 57 + 58 + const dataplanePort = await getPort() 59 + const dataplane = await bsky.DataPlaneServer.create( 60 + db, 61 + dataplanePort, 62 + cfg.plcUrl, 63 + ) 64 + 65 + const bsyncPort = await getPort() 66 + const bsync = await bsky.MockBsync.create(db, bsyncPort) 67 + 68 + const config = new bsky.ServerConfig({ 69 + version: 'unknown', 70 + port, 71 + didPlcUrl: cfg.plcUrl, 72 + publicUrl: 'https://bsky.public.url', 73 + serverDid, 74 + alternateAudienceDids: [], 75 + dataplaneUrls: [`http://localhost:${dataplanePort}`], 76 + dataplaneHttpVersion: '1.1', 77 + bsyncUrl: `http://localhost:${bsyncPort}`, 78 + bsyncHttpVersion: '1.1', 79 + modServiceDid: cfg.modServiceDid ?? 'did:example:invalidMod', 80 + labelsFromIssuerDids: [EXAMPLE_LABELER], 81 + bigThreadUris: new Set(), 82 + disableSsrfProtection: true, 83 + ...cfg, 84 + adminPasswords: [ADMIN_PASSWORD], 85 + // etcdHosts: [], 86 + }) 87 + 88 + // Separate migration db in case migration changes some connection state that we need in the tests, e.g. "alter database ... set ..." 89 + const migrationDb = new bsky.Database({ 90 + url: cfg.dbPostgresUrl, 91 + schema: cfg.dbPostgresSchema, 92 + }) 93 + if (cfg.migration) { 94 + await migrationDb.migrateToOrThrow(cfg.migration) 95 + } else { 96 + await migrationDb.migrateToLatestOrThrow() 97 + } 98 + await migrationDb.close() 99 + 100 + // api server 101 + const server = bsky.BskyAppView.create({ 102 + config, 103 + signingKey: serviceKeypair, 104 + }) 105 + 106 + const sub = new bsky.RepoSubscription({ 107 + service: cfg.repoProvider, 108 + db, 109 + idResolver: dataplane.idResolver, 110 + }) 111 + 112 + await server.start() 113 + 114 + sub.start() 115 + 116 + return new TestBsky(url, port, db, server, dataplane, bsync, sub) 117 + } 118 + 119 + get ctx(): bsky.AppContext { 120 + return this.server.ctx 121 + } 122 + 123 + getClient(): AtpAgent { 124 + const agent = new AtpAgent({ service: this.url }) 125 + agent.configureLabelers([EXAMPLE_LABELER]) 126 + return agent 127 + } 128 + 129 + adminAuth(): string { 130 + const [password] = this.ctx.cfg.adminPasswords 131 + return ( 132 + 'Basic ' + 133 + ui8.toString(ui8.fromString(`admin:${password}`, 'utf8'), 'base64pad') 134 + ) 135 + } 136 + 137 + adminAuthHeaders() { 138 + return { 139 + authorization: this.adminAuth(), 140 + } 141 + } 142 + 143 + async close() { 144 + await this.server.destroy() 145 + await this.bsync.destroy() 146 + await this.dataplane.destroy() 147 + await this.sub.destroy() 148 + await this.db.close() 149 + } 150 + }
+36
services/dev-env/src/bsync.ts
··· 1 + import getPort from 'get-port' 2 + import * as bsync from '@atproto/bsync' 3 + import { BsyncConfig } from './types' 4 + 5 + export class TestBsync { 6 + constructor( 7 + public url: string, 8 + public port: number, 9 + public service: bsync.BsyncService, 10 + ) {} 11 + 12 + static async create(cfg: BsyncConfig): Promise<TestBsync> { 13 + const port = cfg.port || (await getPort()) 14 + const url = `http://localhost:${port}` 15 + 16 + const config = bsync.envToCfg({ 17 + port, 18 + apiKeys: cfg.apiKeys ?? ['api-key'], 19 + ...cfg, 20 + }) 21 + 22 + const service = await bsync.BsyncService.create(config) 23 + await service.ctx.db.migrateToLatestOrThrow() 24 + await service.start() 25 + 26 + return new TestBsync(url, port, service) 27 + } 28 + 29 + get ctx(): bsync.AppContext { 30 + return this.service.ctx 31 + } 32 + 33 + async close() { 34 + await this.service.destroy() 35 + } 36 + }
+3
services/dev-env/src/const.ts
··· 1 + export const ADMIN_PASSWORD = 'admin-pass' 2 + export const JWT_SECRET = 'jwt-secret' 3 + export const EXAMPLE_LABELER = 'did:example:labeler'
+9
services/dev-env/src/env.ts
··· 1 + // NOTE: this file should be imported first, particularly before `@atproto/common` (for logging), to ensure that environment variables are respected in library code 2 + import dotenv from 'dotenv' 3 + 4 + const env = process.env.ENV 5 + if (env) { 6 + dotenv.config({ path: `./.${env}.env` }) 7 + } else { 8 + dotenv.config() 9 + }
+90
services/dev-env/src/feed-gen.ts
··· 1 + import events from 'node:events' 2 + import http from 'node:http' 3 + import * as plc from '@did-plc/lib' 4 + import express from 'express' 5 + import getPort from 'get-port' 6 + import { Secp256k1Keypair } from '@atproto/crypto' 7 + import { SkeletonHandler, createLexiconServer } from '@atproto/pds' 8 + import { InvalidRequestError } from '@atproto/xrpc-server' 9 + 10 + export class TestFeedGen { 11 + destroyed = false 12 + 13 + constructor( 14 + public port: number, 15 + public server: http.Server, 16 + public did: string, 17 + ) {} 18 + 19 + static async create( 20 + plcUrl: string, 21 + feeds: Record<string, SkeletonHandler>, 22 + ): Promise<TestFeedGen> { 23 + const port = await getPort() 24 + const did = await createFgDid(plcUrl, port) 25 + const app = express() 26 + const lexServer = createLexiconServer() 27 + 28 + lexServer.app.bsky.feed.getFeedSkeleton(async (args) => { 29 + const handler = feeds[args.params.feed] 30 + if (!handler) { 31 + throw new InvalidRequestError('unknown feed', 'UnknownFeed') 32 + } 33 + return handler(args) 34 + }) 35 + 36 + lexServer.app.bsky.feed.describeFeedGenerator(async () => { 37 + return { 38 + encoding: 'application/json', 39 + body: { 40 + did, 41 + feeds: Object.keys(feeds).map((uri) => ({ 42 + uri, 43 + })), 44 + }, 45 + } 46 + }) 47 + 48 + app.use(lexServer.xrpc.router) 49 + const server = app.listen(port) 50 + await events.once(server, 'listening') 51 + return new TestFeedGen(port, server, did) 52 + } 53 + 54 + close(): Promise<void> { 55 + return new Promise((resolve, reject) => { 56 + if (this.destroyed) return resolve() 57 + this.server.close((err) => { 58 + if (err) return reject(err) 59 + this.destroyed = true 60 + resolve() 61 + }) 62 + }) 63 + } 64 + } 65 + 66 + const createFgDid = async (plcUrl: string, port: number): Promise<string> => { 67 + const keypair = await Secp256k1Keypair.create() 68 + const plcClient = new plc.Client(plcUrl) 69 + const op = await plc.signOperation( 70 + { 71 + type: 'plc_operation', 72 + verificationMethods: { 73 + atproto: keypair.did(), 74 + }, 75 + rotationKeys: [keypair.did()], 76 + alsoKnownAs: [], 77 + services: { 78 + bsky_fg: { 79 + type: 'BskyFeedGenerator', 80 + endpoint: `http://localhost:${port}`, 81 + }, 82 + }, 83 + prev: null, 84 + }, 85 + keypair, 86 + ) 87 + const did = await plc.didForCreateOp(op) 88 + await plcClient.sendOperation(did, op) 89 + return did 90 + }
+14
services/dev-env/src/index.ts
··· 1 + export * from './bsky' 2 + export * from './bsync' 3 + export * from './network' 4 + export * from './network-no-appview' 5 + export * from './ozone' 6 + export * from './pds' 7 + export * from './plc' 8 + export * from './ozone' 9 + export * from './feed-gen' 10 + export * from './seed' 11 + export * from './moderator-client' 12 + export * from './types' 13 + export * from './util' 14 + export * from './const'
+54
services/dev-env/src/introspect.ts
··· 1 + import events from 'node:events' 2 + import http from 'node:http' 3 + import express from 'express' 4 + import { TestBsky } from './bsky' 5 + import { TestOzone } from './ozone' 6 + import { TestPds } from './pds' 7 + import { TestPlc } from './plc' 8 + 9 + export class IntrospectServer { 10 + constructor( 11 + public port: number, 12 + public server: http.Server, 13 + ) {} 14 + 15 + static async start( 16 + port: number, 17 + plc: TestPlc, 18 + pds: TestPds, 19 + bsky: TestBsky, 20 + ozone: TestOzone, 21 + ) { 22 + const app = express() 23 + app.get('/', (_req, res) => { 24 + res.status(200).send({ 25 + plc: { 26 + url: plc.url, 27 + }, 28 + pds: { 29 + url: pds.url, 30 + did: pds.ctx.cfg.service.did, 31 + }, 32 + bsky: { 33 + url: bsky.url, 34 + did: bsky.ctx.cfg.serverDid, 35 + }, 36 + ozone: { 37 + url: ozone.url, 38 + did: ozone.ctx.cfg.service.did, 39 + }, 40 + db: { 41 + url: ozone.ctx.cfg.db.postgresUrl, 42 + }, 43 + }) 44 + }) 45 + const server = app.listen(port) 46 + await events.once(server, 'listening') 47 + return new IntrospectServer(port, server) 48 + } 49 + 50 + async close() { 51 + this.server.close() 52 + await events.once(this.server, 'close') 53 + } 54 + }
+46
services/dev-env/src/mock/data.ts
··· 1 + export const postTexts = [ 2 + `Nervous? 3 + Yes. Very. 4 + First time? 5 + No, I've been nervous lots of times.`, 6 + `I am serious...and don't call me Shirley.`, 7 + `Looks like I picked the wrong week to quit smoking.`, 8 + `Looks like I picked the wrong week to quit drinking.`, 9 + `Looks like I picked the wrong week to quit amphetamines.`, 10 + `Looks like I picked the wrong week to quit sniffing glue.`, 11 + `Captain, how soon can we land? 12 + I can't tell. 13 + You can tell me, I'm a doctor.`, 14 + `Ladies and gentlemen, this is your stewardess speaking... We regret any inconvenience the sudden cabin movement might have caused, and we hope you enjoy the rest of your flight... By the way, is there anyone on board who knows how to fly a plane? `, 15 + `Joey, have you ever been in a turkish prison?`, 16 + `These people need to go to a hospital. 17 + What is it? 18 + It's a big place where sick people go, but that's not important right now.`, 19 + `I just want to tell you both good luck. We're all counting on you.`, 20 + `Joey, do you like movies about gladiators?`, 21 + `Captain, maybe we ought to turn on the searchlights now. 22 + No… that’s just what they’ll be expecting us to do.`, 23 + `Johnny, what can you make out of this? 24 + This? Why, I can make a hat or a brooch or a pterodactyl…`, 25 + `I need the best man on this. Someone who knows that plane inside and out and won’t crack under pressure. How about Mister Rogers?`, 26 + `What was it we had for dinner tonight? 27 + Well, we had a choice of steak or fish. 28 + Yes, yes, I remember, I had lasagna.`, 29 + `Jim never vomits at home.`, 30 + `The life of everyone on board depends upon just one thing: finding someone back there who can not only fly this plane, but who didn't have fish for dinner.`, 31 + `Shanna, they bought their tickets, they knew what they were getting into. I say, let 'em crash.`, 32 + ] 33 + 34 + export const replyTexts = [ 35 + 'Wow, so true!', 36 + 'Haha ikr', 37 + 'lol', 38 + 'What does this mean for pet owners in the midterms?', 39 + 'is it cool if I DM?', 40 + "This is sort of accurate, but honestly it misses a huge part of the issue at hand. There are just so many factors and I don't think a vibe is enough to cover it.", 41 + 'Wen token', 42 + 'fire', 43 + 'a/s/l?', 44 + 'finally! decentralization!', 45 + 'ugh when will hashtags get supported in this app', 46 + ]
+1
services/dev-env/src/mock/img/blur-hash-avatar-b64.ts
··· 1 + export default 'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAADMElEQVR4nOzVwQnAIBQFQYXff81RUkQCOyDj1YOPnbXWPmeTRef+/3O/OyBjzh3CD95BfqICMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMK0CMO0TAAD//2Anhf4QtqobAAAAAElFTkSuQmCC'
+1
services/dev-env/src/mock/img/labeled-img-b64.ts
··· 1 + export default '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AQSsAEHGSlAjgAACCCCAgDoBgoy6LqPBCCCAAAIIIGAFCDJWghoBBBBAAAEE1AkQZNR1GQ1GAAEEEEAAAStAkLES1AgggAACCCCgToAgo67LaDACOgW23HJLs+uuu5pddtkl+G+HHXYIdmTlypVG/vvll1/MokWLzK+//qpzB2k1AgiURIAgUxJ2v41uvfXWpm7dun4z/2+uP/74w6xatcp7/nxnlD9E2267behiGzZsMKtXrw6dJ6mJnTt3NltttZXX6qZPn27WrVvnNW+cmdq2bWsaN24cuoovvvjCfP7556HzRJnYvn17Y8NBruXnzJljli5dmmtyop/vtttupkePHqZdu3amXr16ZrPNNvNav3wfL1u2zMyfP9+88MILZsWKFV7LuWZq3bq12XPPPUNnW7JkiZk7d27oPFEnduzYMXAIW/6jjz4K9j3bPG3atDHNmjXLNknFZ/LzJz+HUho2bGgOO+wwZ7vl50R+XopdjjjiCLPddtuFbnbx4sXB92joTEwsigBBpijM0TZyww03mP3339974f/++8/06dPHrFmzxnuZfGY8//zzTdeuXZ2LDB482CxcuNA5X5wZGjVqZCZNmuS9ismTJxv5r9DlgQceMPIHPKx8/PHHZsSIEWGzRJr25JNPmvr164cuO2XKFDNx4sTQeeJMlCA1cOBAc8ABB+QVwsO2+f3335vnnnvOzJgxI2w257TbbrvNtGjRInQ++aN56aWXhs4TdaKEsjp16oQu/vjjj5unnnoq6zx33HGH2XvvvbNO0/DhX3/9Zbp37x40VfZD9sdV5MDopJNOMvK7rVilZcuWZvTo0c7NSeA+8cQTnfMxQ+EFCDKFN468hXyDjGzo7bff9vohjNIo3yAzZswYM3PmzCib8F7mjDPOCH7B+S7w3XffmUGDBvnOHnm+TTnISJ/IGRjfMy/5Iv/+++/m/vvvjxxoCDL5iic7f+UgI2seO3asad68uXMjU6dONRMmTHDOl9QMjzzyiNlxxx2dq3viiSeMHDxQSi9AkCl9H+RsQZQg888//5iePXsGl5lyrjjihDQFGTmrsNNOO3nviRzRydHg33//7b1MlBk3xSAjR7DDhg1zXnaM4pltmR9++MHccsst5uuvv842OednBJmcNEWZUDXINGjQwDz22GPO4Cu/00455ZSiXBqWy3+XX36500Mu4Z96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FZ/5PglVsUCVf5RLkJFxNeQ1BWEl7j0yBJnqupyRqW7i+kS+T2Vk7rDfbXYdvkM22PmpdQgQZFLcT0kGGdlNCQgSFMKK3CMi94pkK8UIMkOHDjXt27fPtvmKzz744ANz4403Vnzt+49OnTo5X3C4atWq4F0tvuusOl+5BBm5Z0rG6wgrcZ9aIshU1yXIVDfx+WTIkCHmyCOPdM4q8y1YsMA5HzPoEiDIpLi/kg4yPu8uWrZsWXA3fzaWYgQZn3sz5DLZ7NmzszUx9LPatWsHp5RdR27y0jkJNFFKuQSZMWPGmH322SeUIO4j6wSZ6rwEmeomPp906NAh9J1rso587qfy2SbzpEfg/wAAAP//mlRinwAAF9lJREFU7d0HjDVl1QfwBxsIKgpSgoABUUJAjYqKITZiQUVADCoajEGxICUWFGIUsVDEAhYUpNpQsEQsVDFRE0CCJiAaVEjEBhpFQSFWvu/c79t1d9+9M3Puu3f3LP4mMbv3zrkz5/6elft/5848s87WW299V7OUFHj3u9/dHve4x/X2dthhh7Wf/exnvXVR8OEPf7htt912nbVveMMb2vXXX79Gzetf//r2vOc9b43nFz7x/ve/v1122WULn+59vPnmm7czzjijs+6uu+5qe+yxR4ufkyxnn31222STTTpfes4557RPf/rTnTXjVp5yyiltq622Grd69PxVV13VjjrqqM6aSVZ+7nOfaw984AM7X/rFL36x1zg2cPTRR7fHP/7xnduKMRjy9zBuI9/4xjfaOuusM271oOczPZxwwgltxx137Nxu/N3H3/80li9/+cttvfXW69x0/N3F399yLF/72tfaPe95z85dfehDH2qXXHJJZ02FlU95ylPaEUcc0dlK5m+lc0NWlhNYR5ApNyazDU0jyGy//fYt/uPUtdx4443t4IMPXqNk2kHmNa95Tdtrr73W2O/cJ371q1+1V7/61XOfSv1+yCGHtOc85zmdr/n1r3/dDjzwwM6acSvvLkHm8MMPb09/+tPHvc3Z5yNU/vvf/559nPklglffB3vf+syHkyAzf3QEmfkeHq1eAUGm8NhNI8jE2z311FPblltu2fnOX/va17abbrppXs20g8xZZ53VNt1003n7XPjgvPPOa2eeeebCpwc/HhLk4sNx7733bv/4xz8Gb3em8O4SZGL899xzz5m3NfZn5mjg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+amdLkHxkKu14oN03333bXfcccdEe3zxi188OlE2zp9Z6uXWW28dfcBfffXVS73pQduLO6PH14FdNx8dtKFFisI9TvyOu2xnjsLM3ZQgM1ejje4z1ndLEne/nm/mUU0BQabmuIy6ijk44g7Nfcv+++8/usqlr26S9bvuumuLGWEzS1eQGXLZdcw+m91npr9xtbvvvns79NBDx62efT5zGfbsixb8EvePilATk+et7RLnE5166qltpQLM3P4joMVkh3GZdnwtubZfOUWo/cEPfjCaa+fPf/7z3F2lfx/yD4Mrr7xydHQpvfEBLxgS4pdqtucB7Yxubho3Oe1aYtbouJ1G9WXIzNMRhiNsW+5+AoLM3W9MvaNVJBDn5jztaU9rO++88+iDv+9ITfzHOO5iHXOzxBGKb3/72xMfoZg2U8x5ExP2PetZz2pxeXV8aMbRmnHhJt5b3CT05ptvbldccUW78MILUydWT/v92D4BAjUFBJma46Kr/2KB9ddffzRvzCabbNI22GCDUVCJc3Nibpn4oF/tS7ynmA8nwk18RRfBJU7ejauQLAQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgKCDJZMfUECBAgQIBAGQFBpsxQaIQAAQIECBDICggyWTH1BAgQIECAQBkBQabMUGiEAAECBAgQyAoIMlkx9QQIECBAgEAZAUGmzFBohAABAgQIEMgK/A951lPeQIDuUAAAAABJRU5ErkJggg=='
+522
services/dev-env/src/mock/index.ts
··· 1 + import { AtpAgent, COM_ATPROTO_MODERATION } from '@atproto/api' 2 + import { Database } from '@atproto/bsky' 3 + import { AtUri } from '@atproto/syntax' 4 + import { EXAMPLE_LABELER, RecordRef, TestNetwork } from '../index' 5 + import { postTexts, replyTexts } from './data' 6 + import blurHashB64 from './img/blur-hash-avatar-b64' 7 + import labeledImgB64 from './img/labeled-img-b64' 8 + 9 + // NOTE 10 + // deterministic date generator 11 + // we use this to ensure the mock dataset is always the same 12 + // which is very useful when testing 13 + // (not everything is currently deterministic but it could be) 14 + function* dateGen(): Generator<string, never> { 15 + let start = 1657846031914 16 + while (true) { 17 + yield new Date(start).toISOString() 18 + start += 1e3 19 + } 20 + } 21 + 22 + export async function generateMockSetup(env: TestNetwork) { 23 + const date = dateGen() 24 + 25 + const rand = (n: number) => Math.floor(Math.random() * n) 26 + const picka = <T>(arr: Array<T>): T => { 27 + if (arr.length) { 28 + return arr[rand(arr.length)] || arr[0] 29 + } 30 + throw new Error('Not found') 31 + } 32 + 33 + const loggedOut = env.pds.getClient() 34 + 35 + const users = [ 36 + { 37 + email: 'alice@test.com', 38 + handle: `alice.test`, 39 + password: 'hunter2', 40 + }, 41 + { 42 + email: 'bob@test.com', 43 + handle: `bob.test`, 44 + password: 'hunter2', 45 + }, 46 + { 47 + email: 'carla@test.com', 48 + handle: `carla.test`, 49 + password: 'hunter2', 50 + }, 51 + ] 52 + 53 + const userAgents = await Promise.all( 54 + users.map(async (user, i) => { 55 + const client: AtpAgent = env.pds.getClient() 56 + await client.createAccount(user) 57 + client.assertAuthenticated() 58 + await client.app.bsky.actor.profile.create( 59 + { repo: client.did }, 60 + { 61 + displayName: ucfirst(user.handle).slice(0, -5), 62 + description: `Test user ${i}`, 63 + }, 64 + ) 65 + return client 66 + }), 67 + ) 68 + 69 + const [alice, bob, carla] = userAgents 70 + 71 + // Create moderator accounts 72 + const triageRes = await loggedOut.com.atproto.server.createAccount({ 73 + email: 'triage@test.com', 74 + handle: 'triage.test', 75 + password: 'triage-pass', 76 + }) 77 + await env.ozone.addTriageDid(triageRes.data.did) 78 + const modRes = await loggedOut.com.atproto.server.createAccount({ 79 + email: 'mod@test.com', 80 + handle: 'mod.test', 81 + password: 'mod-pass', 82 + }) 83 + await env.ozone.addModeratorDid(modRes.data.did) 84 + const adminRes = await loggedOut.com.atproto.server.createAccount({ 85 + email: 'admin-mod@test.com', 86 + handle: 'admin-mod.test', 87 + password: 'admin-mod-pass', 88 + }) 89 + await env.ozone.addAdminDid(adminRes.data.did) 90 + 91 + // Report one user 92 + const reporter = picka(userAgents) 93 + await reporter.com.atproto.moderation.createReport({ 94 + reasonType: picka([ 95 + COM_ATPROTO_MODERATION.DefsReasonSpam, 96 + COM_ATPROTO_MODERATION.DefsReasonOther, 97 + ]), 98 + reason: picka(["Didn't look right to me", undefined, undefined]), 99 + subject: { 100 + $type: 'com.atproto.admin.defs#repoRef', 101 + did: picka(userAgents).did, 102 + }, 103 + }) 104 + 105 + // everybody follows everybody 106 + const follow = async (author: AtpAgent, subject: AtpAgent) => { 107 + await author.app.bsky.graph.follow.create( 108 + { repo: author.accountDid }, 109 + { 110 + subject: subject.accountDid, 111 + createdAt: date.next().value, 112 + }, 113 + ) 114 + } 115 + await follow(alice, bob) 116 + await follow(alice, carla) 117 + await follow(bob, alice) 118 + await follow(bob, carla) 119 + await follow(carla, alice) 120 + await follow(carla, bob) 121 + 122 + // a set of posts and reposts 123 + const posts: { uri: string; cid: string }[] = [] 124 + for (let i = 0; i < postTexts.length; i++) { 125 + const author = picka(userAgents) 126 + const post = await author.app.bsky.feed.post.create( 127 + { repo: author.did }, 128 + { 129 + text: postTexts[i], 130 + createdAt: date.next().value, 131 + }, 132 + ) 133 + posts.push(post) 134 + if (rand(10) === 0) { 135 + const reposter = picka(userAgents) 136 + await reposter.app.bsky.feed.repost.create( 137 + { repo: reposter.did }, 138 + { 139 + subject: picka(posts), 140 + createdAt: date.next().value, 141 + }, 142 + ) 143 + } 144 + if (rand(6) === 0) { 145 + const reporter = picka(userAgents) 146 + await reporter.com.atproto.moderation.createReport({ 147 + reasonType: picka([ 148 + COM_ATPROTO_MODERATION.DefsReasonSpam, 149 + COM_ATPROTO_MODERATION.DefsReasonOther, 150 + ]), 151 + reason: picka(["Didn't look right to me", undefined, undefined]), 152 + subject: { 153 + $type: 'com.atproto.repo.strongRef', 154 + uri: post.uri, 155 + cid: post.cid, 156 + }, 157 + }) 158 + } 159 + } 160 + 161 + // make some naughty posts & label them 162 + const file = Buffer.from(labeledImgB64, 'base64') 163 + const uploadedImg = await bob.com.atproto.repo.uploadBlob(file, { 164 + encoding: 'image/png', 165 + }) 166 + const labeledPost = await bob.app.bsky.feed.post.create( 167 + { repo: bob.accountDid }, 168 + { 169 + text: 'naughty post', 170 + embed: { 171 + $type: 'app.bsky.embed.images', 172 + images: [ 173 + { 174 + image: uploadedImg.data.blob, 175 + alt: 'naughty naughty', 176 + }, 177 + ], 178 + }, 179 + createdAt: date.next().value, 180 + }, 181 + ) 182 + 183 + const filteredPost = await bob.app.bsky.feed.post.create( 184 + { repo: bob.accountDid }, 185 + { 186 + text: 'reallly bad post should be deleted', 187 + createdAt: date.next().value, 188 + }, 189 + ) 190 + 191 + await createLabel(env.bsky.db, { 192 + uri: labeledPost.uri, 193 + cid: labeledPost.cid, 194 + val: 'nudity', 195 + }) 196 + await createLabel(env.bsky.db, { 197 + uri: filteredPost.uri, 198 + cid: filteredPost.cid, 199 + val: 'dmca-violation', 200 + }) 201 + 202 + // a set of replies 203 + for (let i = 0; i < 100; i++) { 204 + const targetUri = picka(posts).uri 205 + const urip = new AtUri(targetUri) 206 + const target = await alice.app.bsky.feed.post.get({ 207 + repo: urip.host, 208 + rkey: urip.rkey, 209 + }) 210 + const author = picka(userAgents) 211 + posts.push( 212 + await author.app.bsky.feed.post.create( 213 + { repo: author.did }, 214 + { 215 + text: picka(replyTexts), 216 + reply: { 217 + root: target.value.reply ? target.value.reply.root : target, 218 + parent: target, 219 + }, 220 + createdAt: date.next().value, 221 + }, 222 + ), 223 + ) 224 + } 225 + 226 + // a set of likes 227 + for (const post of posts) { 228 + for (const user of userAgents) { 229 + if (rand(3) === 0) { 230 + await user.app.bsky.feed.like.create( 231 + { repo: user.did }, 232 + { 233 + subject: post, 234 + createdAt: date.next().value, 235 + }, 236 + ) 237 + } 238 + } 239 + } 240 + 241 + // a couple feed generators that returns some posts 242 + const fg1Uri = AtUri.make( 243 + alice.accountDid, 244 + 'app.bsky.feed.generator', 245 + 'alice-favs', 246 + ) 247 + const fg1 = await env.createFeedGen({ 248 + [fg1Uri.toString()]: async () => { 249 + const feed = posts 250 + .filter(() => rand(2) === 0) 251 + .map((post) => ({ post: post.uri })) 252 + return { 253 + encoding: 'application/json', 254 + body: { 255 + feed, 256 + }, 257 + } 258 + }, 259 + }) 260 + const avatarImg = Buffer.from(blurHashB64, 'base64') 261 + const avatarRes = await alice.com.atproto.repo.uploadBlob(avatarImg, { 262 + encoding: 'image/png', 263 + }) 264 + const fgAliceRes = await alice.app.bsky.feed.generator.create( 265 + { repo: alice.accountDid, rkey: fg1Uri.rkey }, 266 + { 267 + did: fg1.did, 268 + displayName: 'alices feed', 269 + description: 'all my fav stuff', 270 + avatar: avatarRes.data.blob, 271 + createdAt: date.next().value, 272 + }, 273 + ) 274 + 275 + await alice.app.bsky.feed.post.create( 276 + { repo: alice.accountDid }, 277 + { 278 + text: 'check out my algorithm!', 279 + embed: { 280 + $type: 'app.bsky.embed.record', 281 + record: fgAliceRes, 282 + }, 283 + createdAt: date.next().value, 284 + }, 285 + ) 286 + for (const user of [alice, bob, carla]) { 287 + await user.app.bsky.feed.like.create( 288 + { repo: user.did }, 289 + { 290 + subject: fgAliceRes, 291 + createdAt: date.next().value, 292 + }, 293 + ) 294 + } 295 + 296 + const fg2Uri = AtUri.make( 297 + bob.accountDid, 298 + 'app.bsky.feed.generator', 299 + 'bob-redux', 300 + ) 301 + const fg2 = await env.createFeedGen({ 302 + [fg2Uri.toString()]: async () => { 303 + const feed = posts 304 + .filter(() => rand(2) === 0) 305 + .map((post) => ({ post: post.uri })) 306 + return { 307 + encoding: 'application/json', 308 + body: { 309 + feed, 310 + }, 311 + } 312 + }, 313 + }) 314 + const fgBobRes = await bob.app.bsky.feed.generator.create( 315 + { repo: bob.accountDid, rkey: fg2Uri.rkey }, 316 + { 317 + did: fg2.did, 318 + displayName: 'Bobby boy hot new algo', 319 + createdAt: date.next().value, 320 + }, 321 + ) 322 + 323 + await alice.app.bsky.feed.post.create( 324 + { repo: alice.accountDid }, 325 + { 326 + text: `bobs feed is neat too`, 327 + embed: { 328 + $type: 'app.bsky.embed.record', 329 + record: fgBobRes, 330 + }, 331 + createdAt: date.next().value, 332 + }, 333 + ) 334 + 335 + // create a labeler account 336 + { 337 + const labeler = env.pds.getClient() 338 + const res = await labeler.createAccount({ 339 + email: 'labeler@test.com', 340 + handle: 'labeler.test', 341 + password: 'hunter2', 342 + }) 343 + await labeler.app.bsky.actor.profile.create( 344 + { repo: res.data.did }, 345 + { 346 + displayName: 'Test Labeler', 347 + description: `Labeling things across the atmosphere`, 348 + }, 349 + ) 350 + 351 + await labeler.app.bsky.labeler.service.create( 352 + { repo: res.data.did, rkey: 'self' }, 353 + { 354 + policies: { 355 + labelValues: [ 356 + '!hide', 357 + 'porn', 358 + 'rude', 359 + 'spam', 360 + 'spider', 361 + 'misinfo', 362 + 'cool', 363 + 'curate', 364 + ], 365 + labelValueDefinitions: [ 366 + { 367 + identifier: 'rude', 368 + blurs: 'content', 369 + severity: 'alert', 370 + defaultSetting: 'warn', 371 + adultOnly: true, 372 + locales: [ 373 + { 374 + lang: 'en', 375 + name: 'Rude', 376 + description: 'Just such a jerk, you wouldnt believe it.', 377 + }, 378 + ], 379 + }, 380 + { 381 + identifier: 'spam', 382 + blurs: 'content', 383 + severity: 'inform', 384 + defaultSetting: 'hide', 385 + locales: [ 386 + { 387 + lang: 'en', 388 + name: 'Spam', 389 + description: 390 + 'Low quality posts that dont add to the conversation.', 391 + }, 392 + ], 393 + }, 394 + { 395 + identifier: 'spider', 396 + blurs: 'media', 397 + severity: 'alert', 398 + defaultSetting: 'warn', 399 + locales: [ 400 + { 401 + lang: 'en', 402 + name: 'Spider!', 403 + description: 'Oh no its a spider.', 404 + }, 405 + ], 406 + }, 407 + { 408 + identifier: 'cool', 409 + blurs: 'none', 410 + severity: 'inform', 411 + defaultSetting: 'warn', 412 + locales: [ 413 + { 414 + lang: 'en', 415 + name: 'Cool', 416 + description: 'The coolest peeps in the atmosphere.', 417 + }, 418 + ], 419 + }, 420 + { 421 + identifier: 'curate', 422 + blurs: 'none', 423 + severity: 'none', 424 + defaultSetting: 'warn', 425 + locales: [ 426 + { 427 + lang: 'en', 428 + name: 'Curation filter', 429 + description: 'We just dont want to see it as much.', 430 + }, 431 + ], 432 + }, 433 + ], 434 + }, 435 + createdAt: date.next().value, 436 + }, 437 + ) 438 + await createLabel(env.bsky.db, { 439 + uri: alice.accountDid, 440 + cid: '', 441 + val: 'rude', 442 + src: res.data.did, 443 + }) 444 + await createLabel(env.bsky.db, { 445 + uri: `at://${alice.accountDid}/app.bsky.feed.generator/alice-favs`, 446 + cid: '', 447 + val: 'cool', 448 + src: res.data.did, 449 + }) 450 + await createLabel(env.bsky.db, { 451 + uri: bob.accountDid, 452 + cid: '', 453 + val: 'cool', 454 + src: res.data.did, 455 + }) 456 + await createLabel(env.bsky.db, { 457 + uri: carla.accountDid, 458 + cid: '', 459 + val: 'spam', 460 + src: res.data.did, 461 + }) 462 + } 463 + 464 + // Create lists and add people to the lists 465 + { 466 + const flowerLovers = await alice.app.bsky.graph.list.create( 467 + { repo: alice.accountDid }, 468 + { 469 + name: 'Flower Lovers', 470 + purpose: 'app.bsky.graph.defs#curatelist', 471 + createdAt: new Date().toISOString(), 472 + description: 'A list of posts about flowers', 473 + }, 474 + ) 475 + const labelHaters = await bob.app.bsky.graph.list.create( 476 + { repo: bob.accountDid }, 477 + { 478 + name: 'Label Haters', 479 + purpose: 'app.bsky.graph.defs#modlist', 480 + createdAt: new Date().toISOString(), 481 + description: 'A list of people who hate labels', 482 + }, 483 + ) 484 + await alice.app.bsky.graph.listitem.create( 485 + { repo: alice.accountDid }, 486 + { 487 + subject: bob.accountDid, 488 + createdAt: new Date().toISOString(), 489 + list: new RecordRef(flowerLovers.uri, flowerLovers.cid).uriStr, 490 + }, 491 + ) 492 + await bob.app.bsky.graph.listitem.create( 493 + { repo: bob.accountDid }, 494 + { 495 + subject: alice.accountDid, 496 + createdAt: new Date().toISOString(), 497 + list: new RecordRef(labelHaters.uri, labelHaters.cid).uriStr, 498 + }, 499 + ) 500 + } 501 + } 502 + 503 + function ucfirst(str: string): string { 504 + return str.at(0)?.toUpperCase() + str.slice(1) 505 + } 506 + 507 + const createLabel = async ( 508 + db: Database, 509 + opts: { uri: string; cid: string; val: string; src?: string }, 510 + ) => { 511 + await db.db 512 + .insertInto('label') 513 + .values({ 514 + uri: opts.uri, 515 + cid: opts.cid, 516 + val: opts.val, 517 + cts: new Date().toISOString(), 518 + neg: false, 519 + src: opts.src ?? EXAMPLE_LABELER, 520 + }) 521 + .execute() 522 + }
+220
services/dev-env/src/moderator-client.ts
··· 1 + import { 2 + AtpAgent, 3 + ToolsOzoneModerationEmitEvent as EmitModerationEvent, 4 + ToolsOzoneModerationQueryEvents as QueryModerationEvents, 5 + ToolsOzoneModerationQueryStatuses as QueryModerationStatuses, 6 + ToolsOzoneSettingRemoveOptions, 7 + ToolsOzoneSettingUpsertOption, 8 + } from '@atproto/api' 9 + import { TestOzone } from './ozone' 10 + 11 + type TakeActionInput = EmitModerationEvent.InputSchema 12 + type QueryStatusesParams = QueryModerationStatuses.QueryParams 13 + type QueryEventsParams = QueryModerationEvents.QueryParams 14 + type ModLevel = 'admin' | 'moderator' | 'triage' 15 + 16 + export class ModeratorClient { 17 + agent: AtpAgent 18 + constructor(public ozone: TestOzone) { 19 + this.agent = ozone.getClient() 20 + } 21 + 22 + async getEvent(id: number, role?: ModLevel) { 23 + const result = await this.agent.tools.ozone.moderation.getEvent( 24 + { id }, 25 + { 26 + headers: await this.ozone.modHeaders( 27 + 'tools.ozone.moderation.getEvent', 28 + role, 29 + ), 30 + }, 31 + ) 32 + return result.data 33 + } 34 + 35 + async queryStatuses(input: QueryStatusesParams, role?: ModLevel) { 36 + const result = await this.agent.tools.ozone.moderation.queryStatuses( 37 + input, 38 + { 39 + headers: await this.ozone.modHeaders( 40 + 'tools.ozone.moderation.queryStatuses', 41 + role, 42 + ), 43 + }, 44 + ) 45 + return result.data 46 + } 47 + 48 + async getReporterStats(dids: string[]) { 49 + const result = await this.agent.tools.ozone.moderation.getReporterStats( 50 + { dids }, 51 + { 52 + headers: await this.ozone.modHeaders( 53 + 'tools.ozone.moderation.getReporterStats', 54 + 'admin', 55 + ), 56 + }, 57 + ) 58 + return result.data 59 + } 60 + 61 + async queryEvents(input: QueryEventsParams, role?: ModLevel) { 62 + const result = await this.agent.tools.ozone.moderation.queryEvents(input, { 63 + headers: await this.ozone.modHeaders( 64 + 'tools.ozone.moderation.queryEvents', 65 + role, 66 + ), 67 + }) 68 + return result.data 69 + } 70 + 71 + async emitEvent( 72 + opts: { 73 + event: TakeActionInput['event'] 74 + subject: TakeActionInput['subject'] 75 + subjectBlobCids?: TakeActionInput['subjectBlobCids'] 76 + reason?: string 77 + createdBy?: string 78 + meta?: unknown 79 + }, 80 + role?: ModLevel, 81 + ) { 82 + const { 83 + event, 84 + subject, 85 + subjectBlobCids, 86 + reason = 'X', 87 + createdBy = 'did:example:admin', 88 + } = opts 89 + const result = await this.agent.tools.ozone.moderation.emitEvent( 90 + { 91 + event, 92 + subject, 93 + subjectBlobCids, 94 + createdBy, 95 + // @ts-expect-error this a valid input property 96 + reason, 97 + }, 98 + { 99 + encoding: 'application/json', 100 + headers: await this.ozone.modHeaders( 101 + 'tools.ozone.moderation.emitEvent', 102 + role, 103 + ), 104 + }, 105 + ) 106 + return result.data 107 + } 108 + 109 + async reverseAction( 110 + opts: { 111 + id: number 112 + subject: TakeActionInput['subject'] 113 + reason?: string 114 + createdBy?: string 115 + }, 116 + role?: ModLevel, 117 + ) { 118 + const { subject, reason = 'X', createdBy = 'did:example:admin' } = opts 119 + const result = await this.agent.tools.ozone.moderation.emitEvent( 120 + { 121 + subject, 122 + event: { 123 + $type: 'tools.ozone.moderation.defs#modEventReverseTakedown', 124 + comment: reason, 125 + }, 126 + createdBy, 127 + }, 128 + { 129 + encoding: 'application/json', 130 + headers: await this.ozone.modHeaders( 131 + 'tools.ozone.moderation.emitEvent', 132 + role, 133 + ), 134 + }, 135 + ) 136 + return result.data 137 + } 138 + 139 + async performTakedown( 140 + opts: { 141 + subject: TakeActionInput['subject'] 142 + subjectBlobCids?: TakeActionInput['subjectBlobCids'] 143 + durationInHours?: number 144 + acknowledgeAccountSubjects?: boolean 145 + reason?: string 146 + policies?: string[] 147 + }, 148 + role?: ModLevel, 149 + ) { 150 + const { durationInHours, acknowledgeAccountSubjects, policies, ...rest } = 151 + opts 152 + return this.emitEvent( 153 + { 154 + event: { 155 + $type: 'tools.ozone.moderation.defs#modEventTakedown', 156 + acknowledgeAccountSubjects, 157 + durationInHours, 158 + policies, 159 + }, 160 + ...rest, 161 + }, 162 + role, 163 + ) 164 + } 165 + 166 + async performReverseTakedown( 167 + opts: { 168 + subject: TakeActionInput['subject'] 169 + subjectBlobCids?: TakeActionInput['subjectBlobCids'] 170 + reason?: string 171 + }, 172 + role?: ModLevel, 173 + ) { 174 + return this.emitEvent( 175 + { 176 + event: { 177 + $type: 'tools.ozone.moderation.defs#modEventReverseTakedown', 178 + }, 179 + ...opts, 180 + }, 181 + role, 182 + ) 183 + } 184 + 185 + async upsertSettingOption( 186 + setting: ToolsOzoneSettingUpsertOption.InputSchema, 187 + callerRole: 'admin' | 'moderator' | 'triage' = 'admin', 188 + ) { 189 + const { data } = await this.agent.tools.ozone.setting.upsertOption( 190 + setting, 191 + { 192 + encoding: 'application/json', 193 + headers: await this.ozone.modHeaders( 194 + 'tools.ozone.setting.upsertOption', 195 + callerRole, 196 + ), 197 + }, 198 + ) 199 + 200 + return data 201 + } 202 + 203 + async removeSettingOptions( 204 + params: ToolsOzoneSettingRemoveOptions.InputSchema, 205 + callerRole: 'admin' | 'moderator' | 'triage' = 'admin', 206 + ) { 207 + const { data } = await this.agent.tools.ozone.setting.removeOptions( 208 + params, 209 + { 210 + encoding: 'application/json', 211 + headers: await this.ozone.modHeaders( 212 + 'tools.ozone.setting.removeOptions', 213 + callerRole, 214 + ), 215 + }, 216 + ) 217 + 218 + return data 219 + } 220 + }
+52
services/dev-env/src/network-no-appview.ts
··· 1 + import { SkeletonHandler } from '@atproto/pds' 2 + import { TestFeedGen } from './feed-gen' 3 + import { TestPds } from './pds' 4 + import { TestPlc } from './plc' 5 + import { SeedClient } from './seed/client' 6 + import { TestServerParams } from './types' 7 + import { mockNetworkUtilities } from './util' 8 + 9 + export class TestNetworkNoAppView { 10 + feedGens: TestFeedGen[] = [] 11 + constructor( 12 + public plc: TestPlc, 13 + public pds: TestPds, 14 + ) {} 15 + 16 + static async create( 17 + params: Partial<TestServerParams> = {}, 18 + ): Promise<TestNetworkNoAppView> { 19 + const plc = await TestPlc.create(params.plc ?? {}) 20 + const pds = await TestPds.create({ 21 + didPlcUrl: plc.url, 22 + ...params.pds, 23 + }) 24 + 25 + mockNetworkUtilities(pds) 26 + 27 + return new TestNetworkNoAppView(plc, pds) 28 + } 29 + 30 + async createFeedGen( 31 + feeds: Record<string, SkeletonHandler>, 32 + ): Promise<TestFeedGen> { 33 + const fg = await TestFeedGen.create(this.plc.url, feeds) 34 + this.feedGens.push(fg) 35 + return fg 36 + } 37 + 38 + getSeedClient(): SeedClient<typeof this> { 39 + const agent = this.pds.getClient() 40 + return new SeedClient(this, agent) 41 + } 42 + 43 + async processAll() { 44 + await this.pds.processAll() 45 + } 46 + 47 + async close() { 48 + await Promise.all(this.feedGens.map((fg) => fg.close())) 49 + await this.pds.close() 50 + await this.plc.close() 51 + } 52 + }
+197
services/dev-env/src/network.ts
··· 1 + import assert from 'node:assert' 2 + import getPort from 'get-port' 3 + import * as uint8arrays from 'uint8arrays' 4 + import { wait } from '@atproto/common-web' 5 + import { createServiceJwt } from '@atproto/xrpc-server' 6 + import { TestBsky } from './bsky' 7 + import { EXAMPLE_LABELER } from './const' 8 + import { IntrospectServer } from './introspect' 9 + import { TestNetworkNoAppView } from './network-no-appview' 10 + import { TestOzone } from './ozone' 11 + import { OzoneServiceProfile } from './ozone-service-profile' 12 + import { TestPds } from './pds' 13 + import { TestPlc } from './plc' 14 + import { TestServerParams } from './types' 15 + import { mockNetworkUtilities } from './util' 16 + 17 + const ADMIN_USERNAME = 'admin' 18 + const ADMIN_PASSWORD = 'admin-pass' 19 + 20 + export class TestNetwork extends TestNetworkNoAppView { 21 + constructor( 22 + public plc: TestPlc, 23 + public pds: TestPds, 24 + public bsky: TestBsky, 25 + public ozone: TestOzone, 26 + public introspect?: IntrospectServer, 27 + ) { 28 + super(plc, pds) 29 + } 30 + 31 + static async create( 32 + params: Partial<TestServerParams> = {}, 33 + ): Promise<TestNetwork> { 34 + const redisHost = process.env.REDIS_HOST 35 + const dbPostgresUrl = params.dbPostgresUrl || process.env.DB_POSTGRES_URL 36 + assert(dbPostgresUrl, 'Missing postgres url for tests') 37 + assert(redisHost, 'Missing redis host for tests') 38 + const dbPostgresSchema = 39 + params.dbPostgresSchema || process.env.DB_POSTGRES_SCHEMA 40 + 41 + const plc = await TestPlc.create(params.plc ?? {}) 42 + 43 + const bskyPort = params.bsky?.port ?? (await getPort()) 44 + const pdsPort = params.pds?.port ?? (await getPort()) 45 + const ozonePort = params.ozone?.port ?? (await getPort()) 46 + 47 + const thirdPartyPdsProps = { 48 + didPlcUrl: plc.url, 49 + ...params.pds, 50 + inviteRequired: false, 51 + port: await getPort(), 52 + } 53 + const thirdPartyPds = await TestPds.create(thirdPartyPdsProps) 54 + const ozoneServiceProfile = new OzoneServiceProfile(thirdPartyPds) 55 + const { did: ozoneDid, key: ozoneKey } = 56 + await ozoneServiceProfile.createDidAndKey() 57 + 58 + const bsky = await TestBsky.create({ 59 + port: bskyPort, 60 + plcUrl: plc.url, 61 + pdsPort, 62 + repoProvider: `ws://localhost:${pdsPort}`, 63 + dbPostgresSchema: `appview_${dbPostgresSchema}`, 64 + dbPostgresUrl, 65 + redisHost, 66 + modServiceDid: ozoneDid, 67 + labelsFromIssuerDids: [ozoneDid, EXAMPLE_LABELER], 68 + ...params.bsky, 69 + }) 70 + 71 + const modServiceUrl = `http://localhost:${ozonePort}` 72 + const pdsProps = { 73 + port: pdsPort, 74 + didPlcUrl: plc.url, 75 + bskyAppViewUrl: bsky.url, 76 + bskyAppViewDid: bsky.ctx.cfg.serverDid, 77 + modServiceUrl, 78 + modServiceDid: ozoneDid, 79 + ...params.pds, 80 + } 81 + 82 + const pds = await TestPds.create(pdsProps) 83 + 84 + const ozone = await TestOzone.create({ 85 + port: ozonePort, 86 + plcUrl: plc.url, 87 + signingKey: ozoneKey, 88 + serverDid: ozoneDid, 89 + dbPostgresSchema: `ozone_${dbPostgresSchema || 'db'}`, 90 + dbPostgresUrl, 91 + appviewUrl: bsky.url, 92 + appviewDid: bsky.ctx.cfg.serverDid, 93 + appviewPushEvents: true, 94 + pdsUrl: pds.url, 95 + pdsDid: pds.ctx.cfg.service.did, 96 + ...params.ozone, 97 + }) 98 + 99 + let inviteCode: string | undefined 100 + if (pdsProps.inviteRequired) { 101 + const { data: invite } = await pds 102 + .getClient() 103 + .api.com.atproto.server.createInviteCode( 104 + { useCount: 1 }, 105 + { 106 + encoding: 'application/json', 107 + headers: pds.adminAuthHeaders(), 108 + }, 109 + ) 110 + inviteCode = invite.code 111 + } 112 + await ozoneServiceProfile.createServiceDetails(pds, modServiceUrl, { 113 + inviteCode, 114 + }) 115 + 116 + await ozone.addAdminDid(ozoneDid) 117 + 118 + mockNetworkUtilities(pds, bsky) 119 + await pds.processAll() 120 + await bsky.sub.processAll() 121 + await thirdPartyPds.close() 122 + 123 + let introspect: IntrospectServer | undefined = undefined 124 + if (params.introspect?.port) { 125 + introspect = await IntrospectServer.start( 126 + params.introspect.port, 127 + plc, 128 + pds, 129 + bsky, 130 + ozone, 131 + ) 132 + } 133 + 134 + return new TestNetwork(plc, pds, bsky, ozone, introspect) 135 + } 136 + 137 + async processFullSubscription(timeout = 5000) { 138 + const sub = this.bsky.sub 139 + const start = Date.now() 140 + const lastSeq = await this.pds.ctx.sequencer.curr() 141 + if (!lastSeq) return 142 + while (Date.now() - start < timeout) { 143 + await sub.processAll() 144 + const runnerCursor = await sub.runner.getCursor() 145 + // if subscription claims to be done, ensure we are at the most recent cursor from PDS, else wait to process again 146 + // (the subscription may claim to be finished before the PDS has even emitted it's event) 147 + if (runnerCursor && runnerCursor >= lastSeq) { 148 + return 149 + } 150 + await wait(5) 151 + } 152 + throw new Error(`Sequence was not processed within ${timeout}ms`) 153 + } 154 + 155 + async processAll(timeout?: number) { 156 + await this.pds.processAll() 157 + await this.ozone.processAll() 158 + await this.processFullSubscription(timeout) 159 + } 160 + 161 + async serviceHeaders(did: string, lxm: string, aud?: string) { 162 + const keypair = await this.pds.ctx.actorStore.keypair(did) 163 + const jwt = await createServiceJwt({ 164 + iss: did, 165 + aud: aud ?? this.bsky.ctx.cfg.serverDid, 166 + lxm, 167 + keypair, 168 + }) 169 + return { authorization: `Bearer ${jwt}` } 170 + } 171 + 172 + async adminHeaders({ 173 + username = ADMIN_USERNAME, 174 + password = ADMIN_PASSWORD, 175 + }: { 176 + username?: string 177 + password?: string 178 + }) { 179 + return { 180 + authorization: 181 + 'Basic ' + 182 + uint8arrays.toString( 183 + uint8arrays.fromString(`${username}:${password}`, 'utf8'), 184 + 'base64pad', 185 + ), 186 + } 187 + } 188 + 189 + async close() { 190 + await Promise.all(this.feedGens.map((fg) => fg.close())) 191 + await this.ozone.close() 192 + await this.bsky.close() 193 + await this.pds.close() 194 + await this.plc.close() 195 + await this.introspect?.close() 196 + } 197 + }
+413
services/dev-env/src/ozone-service-profile.ts
··· 1 + import { AtpAgent } from '@atproto/api' 2 + import { Secp256k1Keypair } from '@atproto/crypto' 3 + import { TestPds } from './pds' 4 + 5 + export class OzoneServiceProfile { 6 + did?: string 7 + key?: Secp256k1Keypair 8 + thirdPartyPdsClient: AtpAgent 9 + 10 + modUserDetails = { 11 + email: 'mod-authority@test.com', 12 + handle: 'mod-authority.test', 13 + password: 'hunter2', 14 + } 15 + 16 + public constructor(public thirdPartyPds: TestPds) { 17 + this.thirdPartyPdsClient = this.thirdPartyPds.getClient() 18 + } 19 + 20 + async createDidAndKey() { 21 + await this.thirdPartyPdsClient.createAccount(this.modUserDetails) 22 + 23 + this.did = this.thirdPartyPdsClient.accountDid 24 + this.key = await Secp256k1Keypair.create({ exportable: true }) 25 + return { did: this.did, key: this.key } 26 + } 27 + 28 + async createServiceDetails( 29 + pds: TestPds, 30 + ozoneUrl: string, 31 + userDetails: { inviteCode?: string } = {}, 32 + ) { 33 + if (!this.did || !this.key) { 34 + throw new Error('No DID/key found!') 35 + } 36 + const pdsClient = pds.getClient() 37 + const describeRes = await pdsClient.com.atproto.server.describeServer() 38 + const newServerDid = describeRes.data.did 39 + 40 + const serviceJwtRes = 41 + await this.thirdPartyPdsClient.com.atproto.server.getServiceAuth({ 42 + aud: newServerDid, 43 + lxm: 'com.atproto.server.createAccount', 44 + }) 45 + const serviceJwt = serviceJwtRes.data.token 46 + 47 + await pdsClient.createAccount( 48 + { 49 + ...this.modUserDetails, 50 + ...userDetails, 51 + did: this.did, 52 + }, 53 + { 54 + headers: { authorization: `Bearer ${serviceJwt}` }, 55 + encoding: 'application/json', 56 + }, 57 + ) 58 + 59 + // For some reason, the tests fail if the client uses the PDS URL to make 60 + // its requests. This is a workaround to make the tests pass by simulating 61 + // old behavior (that was not relying on the session management). 62 + pdsClient.sessionManager.pdsUrl = undefined 63 + 64 + const getDidCredentials = 65 + await pdsClient.com.atproto.identity.getRecommendedDidCredentials() 66 + 67 + await this.thirdPartyPdsClient.com.atproto.identity.requestPlcOperationSignature() 68 + 69 + const tokenRes = await this.thirdPartyPds.ctx.accountManager.db.db 70 + .selectFrom('email_token') 71 + .selectAll() 72 + .where('did', '=', this.did) 73 + .where('purpose', '=', 'plc_operation') 74 + .executeTakeFirst() 75 + const token = tokenRes?.token 76 + const plcOperationData = { 77 + token, 78 + ...getDidCredentials.data, 79 + } 80 + 81 + if (!plcOperationData.services) plcOperationData.services = {} 82 + plcOperationData.services['atproto_labeler'] = { 83 + type: 'AtprotoLabeler', 84 + endpoint: ozoneUrl, 85 + } 86 + if (!plcOperationData.verificationMethods) 87 + plcOperationData.verificationMethods = {} 88 + plcOperationData.verificationMethods['atproto_label'] = this.key.did() 89 + 90 + const plcOp = 91 + await this.thirdPartyPdsClient.com.atproto.identity.signPlcOperation( 92 + plcOperationData, 93 + ) 94 + 95 + await pdsClient.com.atproto.identity.submitPlcOperation({ 96 + operation: plcOp.data.operation, 97 + }) 98 + 99 + await pdsClient.com.atproto.server.activateAccount() 100 + 101 + await pdsClient.app.bsky.actor.profile.create( 102 + { repo: this.did }, 103 + { 104 + displayName: 'Dev-env Moderation', 105 + description: `The pretend version of mod.bsky.app`, 106 + }, 107 + ) 108 + 109 + await pdsClient.app.bsky.labeler.service.create( 110 + { repo: this.did, rkey: 'self' }, 111 + { 112 + policies: { 113 + labelValues: [ 114 + '!hide', 115 + '!warn', 116 + 'porn', 117 + 'sexual', 118 + 'nudity', 119 + 'sexual-figurative', 120 + 'graphic-media', 121 + 'self-harm', 122 + 'sensitive', 123 + 'extremist', 124 + 'intolerant', 125 + 'threat', 126 + 'rude', 127 + 'illicit', 128 + 'security', 129 + 'unsafe-link', 130 + 'impersonation', 131 + 'misinformation', 132 + 'scam', 133 + 'engagement-farming', 134 + 'spam', 135 + 'rumor', 136 + 'misleading', 137 + 'inauthentic', 138 + ], 139 + labelValueDefinitions: [ 140 + { 141 + identifier: 'spam', 142 + blurs: 'content', 143 + severity: 'inform', 144 + defaultSetting: 'hide', 145 + adultOnly: false, 146 + locales: [ 147 + { 148 + lang: 'en', 149 + name: 'Spam', 150 + description: 151 + 'Unwanted, repeated, or unrelated actions that bother users.', 152 + }, 153 + ], 154 + }, 155 + { 156 + identifier: 'impersonation', 157 + blurs: 'none', 158 + severity: 'inform', 159 + defaultSetting: 'hide', 160 + adultOnly: false, 161 + locales: [ 162 + { 163 + lang: 'en', 164 + name: 'Impersonation', 165 + description: 166 + 'Pretending to be someone else without permission.', 167 + }, 168 + ], 169 + }, 170 + { 171 + identifier: 'scam', 172 + blurs: 'content', 173 + severity: 'alert', 174 + defaultSetting: 'hide', 175 + adultOnly: false, 176 + locales: [ 177 + { 178 + lang: 'en', 179 + name: 'Scam', 180 + description: 'Scams, phishing & fraud.', 181 + }, 182 + ], 183 + }, 184 + { 185 + identifier: 'intolerant', 186 + blurs: 'content', 187 + severity: 'alert', 188 + defaultSetting: 'warn', 189 + adultOnly: false, 190 + locales: [ 191 + { 192 + lang: 'en', 193 + name: 'Intolerance', 194 + description: 'Discrimination against protected groups.', 195 + }, 196 + ], 197 + }, 198 + { 199 + identifier: 'self-harm', 200 + blurs: 'content', 201 + severity: 'alert', 202 + defaultSetting: 'warn', 203 + adultOnly: false, 204 + locales: [ 205 + { 206 + lang: 'en', 207 + name: 'Self-Harm', 208 + description: 209 + 'Promotes self-harm, including graphic images, glorifying discussions, or triggering stories.', 210 + }, 211 + ], 212 + }, 213 + { 214 + identifier: 'security', 215 + blurs: 'content', 216 + severity: 'alert', 217 + defaultSetting: 'hide', 218 + adultOnly: false, 219 + locales: [ 220 + { 221 + lang: 'en', 222 + name: 'Security Concerns', 223 + description: 224 + 'May be unsafe and could harm your device, steal your info, or get your account hacked.', 225 + }, 226 + ], 227 + }, 228 + { 229 + identifier: 'misleading', 230 + blurs: 'content', 231 + severity: 'alert', 232 + defaultSetting: 'warn', 233 + adultOnly: false, 234 + locales: [ 235 + { 236 + lang: 'en', 237 + name: 'Misleading', 238 + description: 239 + 'Altered images/videos, deceptive links, or false statements.', 240 + }, 241 + ], 242 + }, 243 + { 244 + identifier: 'threat', 245 + blurs: 'content', 246 + severity: 'inform', 247 + defaultSetting: 'hide', 248 + adultOnly: false, 249 + locales: [ 250 + { 251 + lang: 'en', 252 + name: 'Threats', 253 + description: 254 + 'Promotes violence or harm towards others, including threats, incitement, or advocacy of harm.', 255 + }, 256 + ], 257 + }, 258 + { 259 + identifier: 'unsafe-link', 260 + blurs: 'content', 261 + severity: 'alert', 262 + defaultSetting: 'hide', 263 + adultOnly: false, 264 + locales: [ 265 + { 266 + lang: 'en', 267 + name: 'Unsafe link', 268 + description: 269 + 'Links to harmful sites with malware, phishing, or violating content that risk security and privacy.', 270 + }, 271 + ], 272 + }, 273 + { 274 + identifier: 'illicit', 275 + blurs: 'content', 276 + severity: 'alert', 277 + defaultSetting: 'hide', 278 + adultOnly: false, 279 + locales: [ 280 + { 281 + lang: 'en', 282 + name: 'Illicit', 283 + description: 284 + 'Promoting or selling potentially illicit goods, services, or activities.', 285 + }, 286 + ], 287 + }, 288 + { 289 + identifier: 'misinformation', 290 + blurs: 'content', 291 + severity: 'inform', 292 + defaultSetting: 'warn', 293 + adultOnly: false, 294 + locales: [ 295 + { 296 + lang: 'en', 297 + name: 'Misinformation', 298 + description: 299 + 'Spreading false or misleading info, including unverified claims and harmful conspiracy theories.', 300 + }, 301 + ], 302 + }, 303 + { 304 + identifier: 'rumor', 305 + blurs: 'content', 306 + severity: 'inform', 307 + defaultSetting: 'warn', 308 + adultOnly: false, 309 + locales: [ 310 + { 311 + lang: 'en', 312 + name: 'Rumor', 313 + description: 314 + 'Approach with caution, as these claims lack evidence from credible sources.', 315 + }, 316 + ], 317 + }, 318 + { 319 + identifier: 'rude', 320 + blurs: 'content', 321 + severity: 'inform', 322 + defaultSetting: 'hide', 323 + adultOnly: false, 324 + locales: [ 325 + { 326 + lang: 'en', 327 + name: 'Rude', 328 + description: 329 + 'Rude or impolite, including crude language and disrespectful comments, without constructive purpose.', 330 + }, 331 + ], 332 + }, 333 + { 334 + identifier: 'extremist', 335 + blurs: 'content', 336 + severity: 'alert', 337 + defaultSetting: 'hide', 338 + adultOnly: false, 339 + locales: [ 340 + { 341 + lang: 'en', 342 + name: 'Extremist', 343 + description: 344 + 'Radical views advocating violence, hate, or discrimination against individuals or groups.', 345 + }, 346 + ], 347 + }, 348 + { 349 + identifier: 'sensitive', 350 + blurs: 'content', 351 + severity: 'alert', 352 + defaultSetting: 'warn', 353 + adultOnly: false, 354 + locales: [ 355 + { 356 + lang: 'en', 357 + name: 'Sensitive', 358 + description: 359 + 'May be upsetting, covering topics like substance abuse or mental health issues, cautioning sensitive viewers.', 360 + }, 361 + ], 362 + }, 363 + { 364 + identifier: 'engagement-farming', 365 + blurs: 'content', 366 + severity: 'alert', 367 + defaultSetting: 'hide', 368 + adultOnly: false, 369 + locales: [ 370 + { 371 + lang: 'en', 372 + name: 'Engagement Farming', 373 + description: 374 + 'Insincere content or bulk actions aimed at gaining followers, including frequent follows, posts, and likes.', 375 + }, 376 + ], 377 + }, 378 + { 379 + identifier: 'inauthentic', 380 + blurs: 'content', 381 + severity: 'alert', 382 + defaultSetting: 'hide', 383 + adultOnly: false, 384 + locales: [ 385 + { 386 + lang: 'en', 387 + name: 'Inauthentic Account', 388 + description: 'Bot or a person pretending to be someone else.', 389 + }, 390 + ], 391 + }, 392 + { 393 + identifier: 'sexual-figurative', 394 + blurs: 'media', 395 + severity: 'none', 396 + defaultSetting: 'show', 397 + adultOnly: true, 398 + locales: [ 399 + { 400 + lang: 'en', 401 + name: 'Sexually Suggestive (Cartoon)', 402 + description: 403 + 'Art with explicit or suggestive sexual themes, including provocative imagery or partial nudity.', 404 + }, 405 + ], 406 + }, 407 + ], 408 + }, 409 + createdAt: new Date().toISOString(), 410 + }, 411 + ) 412 + } 413 + }
+202
services/dev-env/src/ozone.ts
··· 1 + import * as plc from '@did-plc/lib' 2 + import getPort from 'get-port' 3 + import * as ui8 from 'uint8arrays' 4 + import { AtpAgent } from '@atproto/api' 5 + import { Keypair, Secp256k1Keypair } from '@atproto/crypto' 6 + import * as ozone from '@atproto/ozone' 7 + import { createServiceJwt } from '@atproto/xrpc-server' 8 + import { ADMIN_PASSWORD, EXAMPLE_LABELER } from './const' 9 + import { ModeratorClient } from './moderator-client' 10 + import { DidAndKey, OzoneConfig } from './types' 11 + import { createDidAndKey } from './util' 12 + 13 + export class TestOzone { 14 + constructor( 15 + public url: string, 16 + public port: number, 17 + public server: ozone.OzoneService, 18 + public daemon: ozone.OzoneDaemon, 19 + public adminAccnt: DidAndKey, 20 + public moderatorAccnt: DidAndKey, 21 + public triageAccnt: DidAndKey, 22 + ) {} 23 + 24 + static async create(config: OzoneConfig): Promise<TestOzone> { 25 + const serviceKeypair = 26 + config.signingKey ?? (await Secp256k1Keypair.create({ exportable: true })) 27 + const signingKeyHex = ui8.toString(await serviceKeypair.export(), 'hex') 28 + let serverDid = config.serverDid 29 + if (!serverDid) { 30 + serverDid = await createOzoneDid(config.plcUrl, serviceKeypair) 31 + } 32 + 33 + const admin = await createDidAndKey({ 34 + plcUrl: config.plcUrl, 35 + handle: 'admin.ozone', 36 + pds: 'https://pds.invalid', 37 + }) 38 + 39 + const moderator = await createDidAndKey({ 40 + plcUrl: config.plcUrl, 41 + handle: 'moderator.ozone', 42 + pds: 'https://pds.invalid', 43 + }) 44 + 45 + const triage = await createDidAndKey({ 46 + plcUrl: config.plcUrl, 47 + handle: 'triage.ozone', 48 + pds: 'https://pds.invalid', 49 + }) 50 + 51 + const port = config.port || (await getPort()) 52 + const url = `http://localhost:${port}` 53 + 54 + const env: ozone.OzoneEnvironment = { 55 + devMode: true, 56 + version: '0.0.0', 57 + port, 58 + didPlcUrl: config.plcUrl, 59 + publicUrl: url, 60 + serverDid, 61 + signingKeyHex, 62 + ...config, 63 + adminPassword: ADMIN_PASSWORD, 64 + adminDids: [...(config.adminDids ?? []), admin.did], 65 + moderatorDids: [ 66 + ...(config.moderatorDids ?? []), 67 + config.appviewDid, 68 + moderator.did, 69 + ], 70 + triageDids: [...(config.triageDids ?? []), triage.did], 71 + } 72 + 73 + // Separate migration db in case migration changes some connection state that we need in the tests, e.g. "alter database ... set ..." 74 + const migrationDb = new ozone.Database({ 75 + schema: config.dbPostgresSchema, 76 + url: config.dbPostgresUrl, 77 + }) 78 + if (config.migration) { 79 + await migrationDb.migrateToOrThrow(config.migration) 80 + } else { 81 + await migrationDb.migrateToLatestOrThrow() 82 + } 83 + await migrationDb.close() 84 + 85 + const cfg = ozone.envToCfg(env) 86 + const secrets = ozone.envToSecrets(env) 87 + 88 + // api server 89 + const server = await ozone.OzoneService.create(cfg, secrets, { 90 + imgInvalidator: config.imgInvalidator, 91 + }) 92 + await server.start() 93 + 94 + const daemon = await ozone.OzoneDaemon.create(cfg, secrets) 95 + await daemon.start() 96 + // don't do event reversal in dev-env 97 + await daemon.ctx.eventReverser.destroy() 98 + 99 + return new TestOzone(url, port, server, daemon, admin, moderator, triage) 100 + } 101 + 102 + get ctx(): ozone.AppContext { 103 + return this.server.ctx 104 + } 105 + 106 + getClient(): AtpAgent { 107 + const agent = new AtpAgent({ service: this.url }) 108 + agent.configureLabelers([EXAMPLE_LABELER]) 109 + return agent 110 + } 111 + 112 + getModClient() { 113 + return new ModeratorClient(this) 114 + } 115 + 116 + async addAdminDid(did: string) { 117 + await this.ctx.teamService(this.ctx.db).create({ 118 + did, 119 + disabled: false, 120 + lastUpdatedBy: this.ctx.cfg.service.did, 121 + role: 'tools.ozone.team.defs#roleAdmin', 122 + }) 123 + this.ctx.cfg.access.admins.push(did) 124 + } 125 + 126 + async addModeratorDid(did: string) { 127 + await this.ctx.teamService(this.ctx.db).create({ 128 + did, 129 + disabled: false, 130 + lastUpdatedBy: this.ctx.cfg.service.did, 131 + role: 'tools.ozone.team.defs#roleModerator', 132 + }) 133 + this.ctx.cfg.access.moderators.push(did) 134 + } 135 + 136 + async addTriageDid(did: string) { 137 + await this.ctx.teamService(this.ctx.db).create({ 138 + did, 139 + disabled: false, 140 + lastUpdatedBy: this.ctx.cfg.service.did, 141 + role: 'tools.ozone.team.defs#roleTriage', 142 + }) 143 + this.ctx.cfg.access.triage.push(did) 144 + } 145 + 146 + async modHeaders( 147 + lxm: string, 148 + role: 'admin' | 'moderator' | 'triage' = 'moderator', 149 + ) { 150 + const account = 151 + role === 'admin' 152 + ? this.adminAccnt 153 + : role === 'moderator' 154 + ? this.moderatorAccnt 155 + : this.triageAccnt 156 + const jwt = await createServiceJwt({ 157 + iss: account.did, 158 + aud: this.ctx.cfg.service.did, 159 + lxm, 160 + keypair: account.key, 161 + }) 162 + return { authorization: `Bearer ${jwt}` } 163 + } 164 + 165 + async processAll() { 166 + await this.ctx.backgroundQueue.processAll() 167 + await this.daemon.processAll() 168 + } 169 + 170 + async close() { 171 + await this.daemon.destroy() 172 + await this.server.destroy() 173 + } 174 + } 175 + 176 + export const createOzoneDid = async ( 177 + plcUrl: string, 178 + keypair: Keypair, 179 + ): Promise<string> => { 180 + const plcClient = new plc.Client(plcUrl) 181 + const plcOp = await plc.signOperation( 182 + { 183 + type: 'plc_operation', 184 + alsoKnownAs: [], 185 + rotationKeys: [keypair.did()], 186 + verificationMethods: { 187 + atproto_label: keypair.did(), 188 + }, 189 + services: { 190 + atproto_labeler: { 191 + type: 'AtprotoLabeler', 192 + endpoint: 'https://ozone.public.url', 193 + }, 194 + }, 195 + prev: null, 196 + }, 197 + keypair, 198 + ) 199 + const did = await plc.didForCreateOp(plcOp) 200 + await plcClient.sendOperation(did, plcOp) 201 + return did 202 + }
+107
services/dev-env/src/pds.ts
··· 1 + import fs from "node:fs/promises"; 2 + import os from "node:os"; 3 + import path from "node:path"; 4 + import getPort from "get-port"; 5 + import * as ui8 from "uint8arrays"; 6 + import { AtpAgent } from "@atproto/api"; 7 + import { Secp256k1Keypair, randomStr } from "@atproto/crypto"; 8 + import * as pds from "../../pds"; 9 + import { createSecretKeyObject } from "@atproto/pds"; 10 + import { ADMIN_PASSWORD, EXAMPLE_LABELER, JWT_SECRET } from "./const"; 11 + import { PdsConfig } from "./types"; 12 + 13 + export class TestPds { 14 + constructor( 15 + public url: string, 16 + public port: number, 17 + public server: pds.PDS 18 + ) {} 19 + 20 + static async create(config: PdsConfig): Promise<TestPds> { 21 + const plcRotationKey = await Secp256k1Keypair.create({ exportable: true }); 22 + const plcRotationPriv = ui8.toString(await plcRotationKey.export(), "hex"); 23 + const recoveryKey = (await Secp256k1Keypair.create()).did(); 24 + 25 + const port = config.port || (await getPort()); 26 + const url = `http://localhost:${port}`; 27 + 28 + const blobstoreLoc = path.join(os.tmpdir(), randomStr(8, "base32")); 29 + const dataDirectory = path.join(os.tmpdir(), randomStr(8, "base32")); 30 + await fs.mkdir(dataDirectory, { recursive: true }); 31 + 32 + const env: pds.ServerEnvironment = { 33 + devMode: true, 34 + port, 35 + dataDirectory: dataDirectory, 36 + blobstoreDiskLocation: blobstoreLoc, 37 + recoveryDidKey: recoveryKey, 38 + adminPassword: ADMIN_PASSWORD, 39 + jwtSecret: JWT_SECRET, 40 + serviceHandleDomains: [".test"], 41 + bskyAppViewUrl: "https://appview.invalid", 42 + bskyAppViewDid: "did:example:invalid", 43 + bskyAppViewCdnUrlPattern: "http://cdn.appview.com/%s/%s/%s", 44 + modServiceUrl: "https://moderator.invalid", 45 + modServiceDid: "did:example:invalid", 46 + plcRotationKeyK256PrivateKeyHex: plcRotationPriv, 47 + inviteRequired: false, 48 + disableSsrfProtection: true, 49 + serviceName: "Development PDS", 50 + brandColor: "#ffcb1e", 51 + errorColor: undefined, 52 + logoUrl: 53 + "https://uxwing.com/wp-content/themes/uxwing/download/animals-and-birds/bee-icon.png", 54 + homeUrl: "https://bsky.social/", 55 + termsOfServiceUrl: "https://bsky.social/about/support/tos", 56 + privacyPolicyUrl: "https://bsky.social/about/support/privacy-policy", 57 + supportUrl: "https://blueskyweb.zendesk.com/hc/en-us", 58 + ...config, 59 + }; 60 + const cfg = pds.envToCfg(env); 61 + const secrets = pds.envToSecrets(env); 62 + 63 + const server = await pds.PDS.create(cfg, secrets); 64 + 65 + await server.start(); 66 + 67 + return new TestPds(url, port, server); 68 + } 69 + 70 + get ctx(): pds.AppContext { 71 + return this.server.ctx; 72 + } 73 + 74 + getClient(): AtpAgent { 75 + const agent = new AtpAgent({ service: this.url }); 76 + agent.configureLabelers([EXAMPLE_LABELER]); 77 + return agent; 78 + } 79 + 80 + adminAuth(): string { 81 + return ( 82 + "Basic " + 83 + ui8.toString( 84 + ui8.fromString(`admin:${ADMIN_PASSWORD}`, "utf8"), 85 + "base64pad" 86 + ) 87 + ); 88 + } 89 + 90 + adminAuthHeaders() { 91 + return { 92 + authorization: this.adminAuth(), 93 + }; 94 + } 95 + 96 + jwtSecretKey() { 97 + return createSecretKeyObject(JWT_SECRET); 98 + } 99 + 100 + async processAll() { 101 + await this.ctx.backgroundQueue.processAll(); 102 + } 103 + 104 + async close() { 105 + await this.server.destroy(); 106 + } 107 + }
+33
services/dev-env/src/plc.ts
··· 1 + import { Client as PlcClient } from '@did-plc/lib' 2 + import * as plc from '@did-plc/server' 3 + import getPort from 'get-port' 4 + import { PlcConfig } from './types' 5 + 6 + export class TestPlc { 7 + constructor( 8 + public url: string, 9 + public port: number, 10 + public server: plc.PlcServer, 11 + ) {} 12 + 13 + static async create(cfg: PlcConfig): Promise<TestPlc> { 14 + const db = plc.Database.mock() 15 + const port = cfg.port || (await getPort()) 16 + const url = `http://localhost:${port}` 17 + const server = plc.PlcServer.create({ db, port, ...cfg }) 18 + await server.start() 19 + return new TestPlc(url, port, server) 20 + } 21 + 22 + get ctx(): plc.AppContext { 23 + return this.server.ctx 24 + } 25 + 26 + getClient(): PlcClient { 27 + return new PlcClient(this.url) 28 + } 29 + 30 + async close() { 31 + await this.server.destroy() 32 + } 33 + }
+98
services/dev-env/src/seed/author-feed.ts
··· 1 + import basicSeed from './basic' 2 + import { SeedClient } from './client' 3 + 4 + export default async (sc: SeedClient) => { 5 + await basicSeed(sc) 6 + await sc.createAccount('eve', { 7 + email: 'eve@test.com', 8 + handle: 'eve.test', 9 + password: 'eve-pass', 10 + }) 11 + await sc.createAccount('fred', { 12 + email: 'fred@test.com', 13 + handle: 'fred.test', 14 + password: 'fred-pass', 15 + }) 16 + 17 + const alice = sc.dids.alice 18 + const eve = sc.dids.eve 19 + const fred = sc.dids.fred 20 + 21 + /* 22 + * Self thread 23 + */ 24 + await sc.post(eve, evePosts[0]) 25 + await sc.reply( 26 + eve, 27 + sc.posts[eve][0].ref, 28 + sc.posts[eve][0].ref, 29 + eveOwnThreadReplies[0], 30 + ) 31 + await sc.reply( 32 + eve, 33 + sc.posts[eve][0].ref, 34 + sc.replies[eve][0].ref, 35 + eveOwnThreadReplies[1], 36 + ) 37 + await sc.reply( 38 + eve, 39 + sc.posts[eve][0].ref, 40 + sc.replies[eve][1].ref, 41 + eveOwnThreadReplies[2], 42 + ) 43 + 44 + /** 45 + * Two replies to Alice 46 + */ 47 + await sc.reply( 48 + eve, 49 + sc.posts[alice][1].ref, 50 + sc.posts[alice][1].ref, 51 + eveAliceReplies[0], 52 + ) 53 + await sc.reply( 54 + eve, 55 + sc.posts[alice][1].ref, 56 + sc.replies[eve][3].ref, 57 + eveAliceReplies[1], 58 + ) 59 + 60 + /** 61 + * Two replies to Fred, who replied to Eve's root post. This creates a 62 + * "detached" thread, where one Fred post breaks the continuity. 63 + */ 64 + await sc.post(eve, evePosts[1]) 65 + const fredReply = await sc.reply( 66 + fred, 67 + sc.posts[eve][1].ref, 68 + sc.posts[eve][1].ref, 69 + fredReplies[0], 70 + ) 71 + await sc.reply( 72 + eve, 73 + sc.posts[eve][1].ref, 74 + sc.replies[fred][0].ref, 75 + eveFredReplies[0], 76 + ) 77 + await sc.reply( 78 + eve, 79 + sc.posts[eve][1].ref, 80 + sc.replies[eve][4].ref, 81 + eveFredReplies[1], 82 + ) 83 + 84 + // a repost for eve's feed 85 + await sc.repost(eve, fredReply.ref) 86 + 87 + return sc 88 + } 89 + 90 + const evePosts = ['eve own thread', 'eve detached thread'] 91 + const eveOwnThreadReplies = [ 92 + 'eve own reply 1', 93 + 'eve own reply 2', 94 + 'eve own reply 3', 95 + ] 96 + const eveAliceReplies = ['eve reply to alice 1', 'eve reply to alice 2'] 97 + const eveFredReplies = ['eve reply to fred 1', 'eve reply to fred 2'] 98 + const fredReplies = ['fred reply to eve 1']
+189
services/dev-env/src/seed/basic.ts
··· 1 + import { TestBsky } from '../bsky' 2 + import { EXAMPLE_LABELER } from '../const' 3 + import { TestNetwork } from '../network' 4 + import { TestNetworkNoAppView } from '../network-no-appview' 5 + import { SeedClient } from './client' 6 + import usersSeed from './users' 7 + 8 + export default async ( 9 + sc: SeedClient<TestNetwork | TestNetworkNoAppView>, 10 + users = true, 11 + ) => { 12 + if (users) await usersSeed(sc) 13 + 14 + const alice = sc.dids.alice 15 + const bob = sc.dids.bob 16 + const carol = sc.dids.carol 17 + const dan = sc.dids.dan 18 + const createdAtMicroseconds = () => ({ 19 + createdAt: new Date().toISOString().replace('Z', '000Z'), // microseconds 20 + }) 21 + const createdAtTimezone = () => ({ 22 + createdAt: new Date().toISOString().replace('Z', '+00:00'), // iso timezone format 23 + }) 24 + 25 + await sc.follow(alice, bob) 26 + await sc.follow(alice, carol) 27 + await sc.follow(alice, dan) 28 + await sc.follow(carol, alice) 29 + await sc.follow(bob, alice) 30 + await sc.follow(bob, carol, createdAtMicroseconds()) 31 + await sc.follow(dan, bob, createdAtTimezone()) 32 + await sc.post(alice, posts.alice[0], undefined, undefined, undefined, { 33 + labels: { 34 + $type: 'com.atproto.label.defs#selfLabels', 35 + values: [{ val: 'self-label' }], 36 + }, 37 + }) 38 + await sc.post(bob, posts.bob[0], undefined, undefined, undefined, { 39 + langs: ['en-US', 'i-klingon'], 40 + }) 41 + const img1 = await sc.uploadFile( 42 + carol, 43 + '../dev-env/assets/key-landscape-small.jpg', 44 + 'image/jpeg', 45 + ) 46 + const img2 = await sc.uploadFile( 47 + carol, 48 + '../dev-env/assets/key-alt.jpg', 49 + 'image/jpeg', 50 + ) 51 + await sc.post( 52 + carol, 53 + posts.carol[0], 54 + undefined, 55 + [img1, img2], // Contains both images and a quote 56 + sc.posts[bob][0].ref, 57 + ) 58 + await sc.post(dan, posts.dan[0]) 59 + await sc.post( 60 + dan, 61 + posts.dan[1], 62 + [ 63 + { 64 + index: { byteStart: 0, byteEnd: 18 }, 65 + features: [ 66 + { 67 + $type: `app.bsky.richtext.facet#mention`, 68 + did: alice, 69 + }, 70 + ], 71 + }, 72 + ], 73 + undefined, 74 + sc.posts[carol][0].ref, // This post contains an images embed 75 + ) 76 + await sc.post( 77 + alice, 78 + posts.alice[1], 79 + undefined, 80 + undefined, 81 + undefined, 82 + createdAtMicroseconds(), 83 + ) 84 + await sc.post( 85 + bob, 86 + posts.bob[1], 87 + undefined, 88 + undefined, 89 + undefined, 90 + createdAtTimezone(), 91 + ) 92 + await sc.post( 93 + alice, 94 + posts.alice[2], 95 + undefined, 96 + undefined, 97 + sc.posts[dan][1].ref, // This post contains a record embed which contains an images embed 98 + ) 99 + await sc.like(bob, sc.posts[alice][1].ref) 100 + await sc.like(bob, sc.posts[alice][2].ref) 101 + await sc.like(carol, sc.posts[alice][1].ref) 102 + await sc.like(carol, sc.posts[alice][2].ref) 103 + await sc.like(dan, sc.posts[alice][1].ref) 104 + await sc.like(alice, sc.posts[carol][0].ref, createdAtMicroseconds()) 105 + await sc.like(bob, sc.posts[carol][0].ref, createdAtTimezone()) 106 + 107 + const replyImg = await sc.uploadFile( 108 + bob, 109 + '../dev-env/assets/key-landscape-small.jpg', 110 + 'image/jpeg', 111 + ) 112 + // must ensure ordering of replies in indexing 113 + await sc.network.processAll() 114 + await sc.reply( 115 + bob, 116 + sc.posts[alice][1].ref, 117 + sc.posts[alice][1].ref, 118 + replies.bob[0], 119 + undefined, 120 + [replyImg], 121 + ) 122 + await sc.reply( 123 + carol, 124 + sc.posts[alice][1].ref, 125 + sc.posts[alice][1].ref, 126 + replies.carol[0], 127 + ) 128 + await sc.network.processAll() 129 + const alicesReplyToBob = await sc.reply( 130 + alice, 131 + sc.posts[alice][1].ref, 132 + sc.replies[bob][0].ref, 133 + replies.alice[0], 134 + ) 135 + await sc.repost(carol, sc.posts[dan][1].ref) 136 + await sc.repost(dan, sc.posts[alice][1].ref) 137 + await sc.repost(dan, alicesReplyToBob.ref) 138 + 139 + if (sc.network instanceof TestNetwork) { 140 + const bsky = sc.network.bsky 141 + await createLabel(bsky, { 142 + val: 'test-label', 143 + uri: sc.posts[alice][2].ref.uriStr, 144 + cid: sc.posts[alice][2].ref.cidStr, 145 + }) 146 + await createLabel(bsky, { 147 + val: 'test-label', 148 + uri: sc.replies[bob][0].ref.uriStr, 149 + cid: sc.replies[bob][0].ref.cidStr, 150 + }) 151 + await createLabel(bsky, { 152 + val: 'test-label-2', 153 + uri: sc.replies[bob][0].ref.uriStr, 154 + cid: sc.replies[bob][0].ref.cidStr, 155 + }) 156 + } 157 + 158 + return sc 159 + } 160 + 161 + export const posts = { 162 + alice: ['hey there', 'again', 'yoohoo label_me'], 163 + bob: ['bob back at it again!', 'bobby boy here', 'yoohoo'], 164 + carol: ['hi im carol'], 165 + dan: ['dan here!', '@alice.bluesky.xyz is the best'], 166 + } 167 + 168 + export const replies = { 169 + alice: ['thanks bob'], 170 + bob: ['hear that label_me label_me_2'], 171 + carol: ['of course'], 172 + } 173 + 174 + const createLabel = async ( 175 + bsky: TestBsky, 176 + opts: { uri: string; cid: string; val: string }, 177 + ) => { 178 + await bsky.db.db 179 + .insertInto('label') 180 + .values({ 181 + uri: opts.uri, 182 + cid: opts.cid, 183 + val: opts.val, 184 + cts: new Date().toISOString(), 185 + neg: false, 186 + src: EXAMPLE_LABELER, // this did is also configured on labelsFromIssuerDids 187 + }) 188 + .execute() 189 + }
+565
services/dev-env/src/seed/client.ts
··· 1 + import fs from 'node:fs/promises' 2 + import path from 'node:path' 3 + import { CID } from 'multiformats/cid' 4 + import { 5 + AppBskyFeedLike, 6 + AppBskyFeedPost, 7 + AppBskyGraphBlock, 8 + AppBskyGraphFollow, 9 + AppBskyGraphList, 10 + AppBskyRichtextFacet, 11 + AtpAgent, 12 + ComAtprotoModerationCreateReport, 13 + } from '@atproto/api' 14 + import { BlobRef } from '@atproto/lexicon' 15 + import { AtUri } from '@atproto/syntax' 16 + import { TestNetworkNoAppView } from '../network-no-appview' 17 + 18 + // Makes it simple to create data via the XRPC client, 19 + // and keeps track of all created data in memory for convenience. 20 + 21 + let AVATAR_IMG: Uint8Array | undefined 22 + 23 + // AVATAR_PATH is defined in a non-CWD-dependant way, so this works 24 + // for any consumer of this package, even outside the atproto repo. 25 + const AVATAR_PATH = path.resolve( 26 + __dirname, 27 + '../../assets/key-portrait-small.jpg', 28 + ) 29 + 30 + export type ImageRef = { 31 + image: BlobRef 32 + alt: string 33 + } 34 + 35 + export class RecordRef { 36 + uri: AtUri 37 + cid: CID 38 + 39 + constructor(uri: AtUri | string, cid: CID | string) { 40 + this.uri = new AtUri(uri.toString()) 41 + this.cid = CID.parse(cid.toString()) 42 + } 43 + 44 + get raw(): { uri: string; cid: string } { 45 + return { 46 + uri: this.uri.toString(), 47 + cid: this.cid.toString(), 48 + } 49 + } 50 + 51 + get uriStr(): string { 52 + return this.uri.toString() 53 + } 54 + 55 + get cidStr(): string { 56 + return this.cid.toString() 57 + } 58 + } 59 + 60 + export class SeedClient< 61 + Network extends TestNetworkNoAppView = TestNetworkNoAppView, 62 + > { 63 + accounts: Record< 64 + string, 65 + { 66 + did: string 67 + accessJwt: string 68 + refreshJwt: string 69 + handle: string 70 + email: string 71 + password: string 72 + } 73 + > 74 + profiles: Record< 75 + string, 76 + { 77 + displayName: string 78 + description: string 79 + avatar: { cid: string; mimeType: string } 80 + joinedViaStarterPack: RecordRef | undefined 81 + ref: RecordRef 82 + } 83 + > 84 + follows: Record<string, Record<string, RecordRef>> 85 + blocks: Record<string, Record<string, RecordRef>> 86 + posts: Record< 87 + string, 88 + { text: string; ref: RecordRef; images: ImageRef[]; quote?: RecordRef }[] 89 + > 90 + likes: Record<string, Record<string, AtUri>> 91 + replies: Record< 92 + string, 93 + { text: string; ref: RecordRef; images: ImageRef[] }[] 94 + > 95 + reposts: Record<string, RecordRef[]> 96 + lists: Record< 97 + string, 98 + Record<string, { ref: RecordRef; items: Record<string, RecordRef> }> 99 + > 100 + feedgens: Record< 101 + string, 102 + Record<string, { ref: RecordRef; items: Record<string, RecordRef> }> 103 + > 104 + starterpacks: Record< 105 + string, 106 + Record< 107 + string, 108 + { 109 + ref: RecordRef 110 + name: string 111 + list: RecordRef 112 + feeds: string[] 113 + } 114 + > 115 + > 116 + dids: Record<string, string> 117 + 118 + constructor( 119 + public network: Network, 120 + public agent: AtpAgent, 121 + ) { 122 + this.accounts = {} 123 + this.profiles = {} 124 + this.follows = {} 125 + this.blocks = {} 126 + this.posts = {} 127 + this.likes = {} 128 + this.replies = {} 129 + this.reposts = {} 130 + this.lists = {} 131 + this.feedgens = {} 132 + this.starterpacks = {} 133 + this.dids = {} 134 + } 135 + 136 + async createAccount( 137 + shortName: string, 138 + params: { 139 + handle: string 140 + email: string 141 + password: string 142 + inviteCode?: string 143 + }, 144 + ) { 145 + const { data: account } = 146 + await this.agent.com.atproto.server.createAccount(params) 147 + this.dids[shortName] = account.did 148 + this.accounts[account.did] = { 149 + ...account, 150 + email: params.email, 151 + password: params.password, 152 + } 153 + return this.accounts[account.did] 154 + } 155 + 156 + async updateHandle(by: string, handle: string) { 157 + await this.agent.com.atproto.identity.updateHandle( 158 + { handle }, 159 + { encoding: 'application/json', headers: this.getHeaders(by) }, 160 + ) 161 + } 162 + 163 + async createProfile( 164 + by: string, 165 + displayName: string, 166 + description: string, 167 + selfLabels?: string[], 168 + joinedViaStarterPack?: RecordRef, 169 + ): Promise<{ 170 + displayName: string 171 + description: string 172 + avatar: { cid: string; mimeType: string } 173 + ref: RecordRef 174 + joinedViaStarterPack?: RecordRef 175 + }> { 176 + AVATAR_IMG ??= await fs.readFile(AVATAR_PATH) 177 + 178 + let avatarBlob 179 + { 180 + const res = await this.agent.com.atproto.repo.uploadBlob(AVATAR_IMG, { 181 + encoding: 'image/jpeg', 182 + headers: this.getHeaders(by), 183 + } as any) 184 + avatarBlob = res.data.blob 185 + } 186 + 187 + { 188 + const res = await this.agent.app.bsky.actor.profile.create( 189 + { repo: by }, 190 + { 191 + displayName, 192 + description, 193 + avatar: avatarBlob, 194 + labels: selfLabels 195 + ? { 196 + $type: 'com.atproto.label.defs#selfLabels', 197 + values: selfLabels.map((val) => ({ val })), 198 + } 199 + : undefined, 200 + joinedViaStarterPack: joinedViaStarterPack?.raw, 201 + createdAt: new Date().toISOString(), 202 + }, 203 + this.getHeaders(by), 204 + ) 205 + this.profiles[by] = { 206 + displayName, 207 + description, 208 + avatar: avatarBlob, 209 + joinedViaStarterPack, 210 + ref: new RecordRef(res.uri, res.cid), 211 + } 212 + } 213 + return this.profiles[by] 214 + } 215 + 216 + async updateProfile(by: string, record: Record<string, unknown>) { 217 + const res = await this.agent.com.atproto.repo.putRecord( 218 + { 219 + repo: by, 220 + collection: 'app.bsky.actor.profile', 221 + rkey: 'self', 222 + record, 223 + }, 224 + { headers: this.getHeaders(by), encoding: 'application/json' }, 225 + ) 226 + this.profiles[by] = { 227 + ...(this.profiles[by] ?? {}), 228 + ...record, 229 + ref: new RecordRef(res.data.uri, res.data.cid), 230 + } 231 + return this.profiles[by] 232 + } 233 + 234 + async follow( 235 + from: string, 236 + to: string, 237 + overrides?: Partial<AppBskyGraphFollow.Record>, 238 + ) { 239 + const res = await this.agent.app.bsky.graph.follow.create( 240 + { repo: from }, 241 + { 242 + subject: to, 243 + createdAt: new Date().toISOString(), 244 + ...overrides, 245 + }, 246 + this.getHeaders(from), 247 + ) 248 + this.follows[from] ??= {} 249 + this.follows[from][to] = new RecordRef(res.uri, res.cid) 250 + return this.follows[from][to] 251 + } 252 + 253 + async unfollow(from: string, to: string) { 254 + const follow = this.follows[from][to] 255 + if (!follow) { 256 + throw new Error('follow does not exist') 257 + } 258 + await this.agent.app.bsky.graph.follow.delete( 259 + { repo: from, rkey: follow.uri.rkey }, 260 + this.getHeaders(from), 261 + ) 262 + delete this.follows[from][to] 263 + } 264 + 265 + async block( 266 + from: string, 267 + to: string, 268 + overrides?: Partial<AppBskyGraphBlock.Record>, 269 + ) { 270 + const res = await this.agent.app.bsky.graph.block.create( 271 + { repo: from }, 272 + { 273 + subject: to, 274 + createdAt: new Date().toISOString(), 275 + ...overrides, 276 + }, 277 + this.getHeaders(from), 278 + ) 279 + this.blocks[from] ??= {} 280 + this.blocks[from][to] = new RecordRef(res.uri, res.cid) 281 + return this.blocks[from][to] 282 + } 283 + 284 + async unblock(from: string, to: string) { 285 + const block = this.blocks[from][to] 286 + if (!block) { 287 + throw new Error('block does not exist') 288 + } 289 + await this.agent.app.bsky.graph.block.delete( 290 + { repo: from, rkey: block.uri.rkey }, 291 + this.getHeaders(from), 292 + ) 293 + delete this.blocks[from][to] 294 + } 295 + 296 + async post( 297 + by: string, 298 + text: string, 299 + facets?: AppBskyRichtextFacet.Main[], 300 + images?: ImageRef[], 301 + quote?: RecordRef, 302 + overrides?: Partial<AppBskyFeedPost.Record>, 303 + ) { 304 + const imageEmbed = images && { 305 + $type: 'app.bsky.embed.images', 306 + images, 307 + } 308 + const recordEmbed = quote && { 309 + record: { uri: quote.uriStr, cid: quote.cidStr }, 310 + } 311 + const embed = 312 + imageEmbed && recordEmbed 313 + ? { 314 + $type: 'app.bsky.embed.recordWithMedia', 315 + record: recordEmbed, 316 + media: imageEmbed, 317 + } 318 + : recordEmbed 319 + ? { $type: 'app.bsky.embed.record', ...recordEmbed } 320 + : imageEmbed 321 + const res = await this.agent.app.bsky.feed.post.create( 322 + { repo: by }, 323 + { 324 + text: text, 325 + facets, 326 + embed, 327 + createdAt: new Date().toISOString(), 328 + ...overrides, 329 + }, 330 + this.getHeaders(by), 331 + ) 332 + this.posts[by] ??= [] 333 + const post = { 334 + text, 335 + ref: new RecordRef(res.uri, res.cid), 336 + images: images ?? [], 337 + quote, 338 + } 339 + this.posts[by].push(post) 340 + return post 341 + } 342 + 343 + async deletePost(by: string, uri: AtUri) { 344 + await this.agent.app.bsky.feed.post.delete( 345 + { 346 + repo: by, 347 + rkey: uri.rkey, 348 + }, 349 + this.getHeaders(by), 350 + ) 351 + } 352 + 353 + async uploadFile( 354 + by: string, 355 + filePath: string, 356 + encoding: string, 357 + ): Promise<ImageRef> { 358 + const file = await fs.readFile(filePath) 359 + const res = await this.agent.com.atproto.repo.uploadBlob(file, { 360 + headers: this.getHeaders(by), 361 + encoding, 362 + } as any) 363 + return { image: res.data.blob, alt: filePath } 364 + } 365 + 366 + async like( 367 + by: string, 368 + subject: RecordRef, 369 + overrides?: Partial<AppBskyFeedLike.Record>, 370 + ) { 371 + const res = await this.agent.app.bsky.feed.like.create( 372 + { repo: by }, 373 + { 374 + subject: subject.raw, 375 + createdAt: new Date().toISOString(), 376 + ...overrides, 377 + }, 378 + this.getHeaders(by), 379 + ) 380 + this.likes[by] ??= {} 381 + this.likes[by][subject.uriStr] = new AtUri(res.uri) 382 + return this.likes[by][subject.uriStr] 383 + } 384 + 385 + async reply( 386 + by: string, 387 + root: RecordRef, 388 + parent: RecordRef, 389 + text: string, 390 + facets?: AppBskyRichtextFacet.Main[], 391 + images?: ImageRef[], 392 + ) { 393 + const embed = images 394 + ? { 395 + $type: 'app.bsky.embed.images', 396 + images, 397 + } 398 + : undefined 399 + const res = await this.agent.app.bsky.feed.post.create( 400 + { repo: by }, 401 + { 402 + text: text, 403 + reply: { 404 + root: root.raw, 405 + parent: parent.raw, 406 + }, 407 + facets, 408 + embed, 409 + createdAt: new Date().toISOString(), 410 + }, 411 + this.getHeaders(by), 412 + ) 413 + this.replies[by] ??= [] 414 + const reply = { 415 + text, 416 + ref: new RecordRef(res.uri, res.cid), 417 + images: images ?? [], 418 + } 419 + this.replies[by].push(reply) 420 + return reply 421 + } 422 + 423 + async repost(by: string, subject: RecordRef) { 424 + const res = await this.agent.app.bsky.feed.repost.create( 425 + { repo: by }, 426 + { subject: subject.raw, createdAt: new Date().toISOString() }, 427 + this.getHeaders(by), 428 + ) 429 + this.reposts[by] ??= [] 430 + const repost = new RecordRef(res.uri, res.cid) 431 + this.reposts[by].push(repost) 432 + return repost 433 + } 434 + 435 + async createList( 436 + by: string, 437 + name: string, 438 + purpose: 'mod' | 'curate' | 'reference', 439 + overrides?: Partial<AppBskyGraphList.Record>, 440 + ) { 441 + const res = await this.agent.app.bsky.graph.list.create( 442 + { repo: by }, 443 + { 444 + name, 445 + purpose: 446 + purpose === 'mod' 447 + ? 'app.bsky.graph.defs#modlist' 448 + : purpose === 'curate' 449 + ? 'app.bsky.graph.defs#curatelist' 450 + : 'app.bsky.graph.defs#referencelist', 451 + createdAt: new Date().toISOString(), 452 + ...(overrides || {}), 453 + }, 454 + this.getHeaders(by), 455 + ) 456 + this.lists[by] ??= {} 457 + const ref = new RecordRef(res.uri, res.cid) 458 + this.lists[by][ref.uriStr] = { 459 + ref: ref, 460 + items: {}, 461 + } 462 + return ref 463 + } 464 + 465 + async createFeedGen(by: string, feedDid: string, name: string) { 466 + const res = await this.agent.app.bsky.feed.generator.create( 467 + { repo: by }, 468 + { 469 + did: feedDid, 470 + displayName: name, 471 + createdAt: new Date().toISOString(), 472 + }, 473 + this.getHeaders(by), 474 + ) 475 + this.feedgens[by] ??= {} 476 + const ref = new RecordRef(res.uri, res.cid) 477 + this.feedgens[by][ref.uriStr] = { 478 + ref: ref, 479 + items: {}, 480 + } 481 + return ref 482 + } 483 + 484 + async createStarterPack( 485 + by: string, 486 + name: string, 487 + actors: string[], 488 + feeds?: string[], 489 + ) { 490 + const list = await this.createList(by, 'n/a', 'reference') 491 + for (const did of actors) { 492 + await this.addToList(by, did, list) 493 + } 494 + const res = await this.agent.app.bsky.graph.starterpack.create( 495 + { repo: by }, 496 + { 497 + name, 498 + list: list.uriStr, 499 + feeds: feeds?.map((uri) => ({ uri })), 500 + createdAt: new Date().toISOString(), 501 + }, 502 + this.getHeaders(by), 503 + ) 504 + this.starterpacks[by] ??= {} 505 + const ref = new RecordRef(res.uri, res.cid) 506 + this.starterpacks[by][ref.uriStr] = { 507 + ref: ref, 508 + list, 509 + feeds: feeds ?? [], 510 + name, 511 + } 512 + return ref 513 + } 514 + 515 + async addToList(by: string, subject: string, list: RecordRef) { 516 + const res = await this.agent.app.bsky.graph.listitem.create( 517 + { repo: by }, 518 + { subject, list: list.uriStr, createdAt: new Date().toISOString() }, 519 + this.getHeaders(by), 520 + ) 521 + const ref = new RecordRef(res.uri, res.cid) 522 + const found = (this.lists[by] ?? {})[list.uriStr] 523 + if (found) { 524 + found.items[subject] = ref 525 + } 526 + return ref 527 + } 528 + 529 + async rmFromList(by: string, subject: string, list: RecordRef) { 530 + const foundList = (this.lists[by] ?? {})[list.uriStr] ?? {} 531 + if (!foundList) return 532 + const foundItem = foundList.items[subject] 533 + if (!foundItem) return 534 + await this.agent.app.bsky.graph.listitem.delete( 535 + { repo: by, rkey: foundItem.uri.rkey }, 536 + this.getHeaders(by), 537 + ) 538 + delete foundList.items[subject] 539 + } 540 + 541 + async createReport(opts: { 542 + reasonType: ComAtprotoModerationCreateReport.InputSchema['reasonType'] 543 + subject: ComAtprotoModerationCreateReport.InputSchema['subject'] 544 + reason?: string 545 + reportedBy: string 546 + }) { 547 + const { reasonType, subject, reason, reportedBy } = opts 548 + const result = await this.agent.com.atproto.moderation.createReport( 549 + { reasonType, subject, reason }, 550 + { 551 + encoding: 'application/json', 552 + headers: this.getHeaders(reportedBy), 553 + }, 554 + ) 555 + return result.data 556 + } 557 + 558 + getHeaders(did: string) { 559 + return SeedClient.getHeaders(this.accounts[did].accessJwt) 560 + } 561 + 562 + static getHeaders(jwt: string) { 563 + return { authorization: `Bearer ${jwt}` } 564 + } 565 + }
+57
services/dev-env/src/seed/follows.ts
··· 1 + import { SeedClient } from './client' 2 + 3 + export default async (sc: SeedClient) => { 4 + await sc.createAccount('alice', users.alice) 5 + await sc.createAccount('bob', users.bob) 6 + await sc.createAccount('carol', users.carol) 7 + await sc.createAccount('dan', users.dan) 8 + await sc.createAccount('eve', users.eve) 9 + for (const name in sc.dids) { 10 + await sc.createProfile(sc.dids[name], `display-${name}`, `descript-${name}`) 11 + } 12 + const alice = sc.dids.alice 13 + const bob = sc.dids.bob 14 + const carol = sc.dids.carol 15 + const dan = sc.dids.dan 16 + const eve = sc.dids.eve 17 + await sc.follow(alice, bob) 18 + await sc.follow(alice, carol) 19 + await sc.follow(alice, dan) 20 + await sc.follow(alice, eve) 21 + await sc.follow(carol, alice) 22 + await sc.follow(bob, alice) 23 + await sc.follow(bob, carol) 24 + await sc.follow(dan, alice) 25 + await sc.follow(dan, bob) 26 + await sc.follow(dan, eve) 27 + await sc.follow(eve, alice) 28 + await sc.follow(eve, carol) 29 + } 30 + 31 + const users = { 32 + alice: { 33 + email: 'alice@test.com', 34 + handle: 'alice.test', 35 + password: 'alice-pass', 36 + }, 37 + bob: { 38 + email: 'bob@test.com', 39 + handle: 'bob.test', 40 + password: 'bob-pass', 41 + }, 42 + carol: { 43 + email: 'carol@test.com', 44 + handle: 'carol.test', 45 + password: 'carol-pass', 46 + }, 47 + dan: { 48 + email: 'dan@test.com', 49 + handle: 'dan.test', 50 + password: 'dan-pass', 51 + }, 52 + eve: { 53 + email: 'eve@test.com', 54 + handle: 'eve.test', 55 + password: 'eve-pass', 56 + }, 57 + }
+10
services/dev-env/src/seed/index.ts
··· 1 + export * from './client' 2 + 3 + export { default as authorFeedSeed } from './author-feed' 4 + export { default as basicSeed } from './basic' 5 + export { default as followsSeed } from './follows' 6 + export { default as likesSeed } from './likes' 7 + export { default as repostsSeed } from './reposts' 8 + export { default as usersBulkSeed } from './users-bulk' 9 + export { default as usersSeed } from './users' 10 + export { default as quotesSeed } from './quotes'
+43
services/dev-env/src/seed/likes.ts
··· 1 + import basicSeed from './basic' 2 + import { SeedClient } from './client' 3 + 4 + export default async (sc: SeedClient) => { 5 + await basicSeed(sc) 6 + await sc.createAccount('eve', { 7 + email: 'eve@test.com', 8 + handle: 'eve.test', 9 + password: 'eve-pass', 10 + }) 11 + await sc.like(sc.dids.eve, sc.posts[sc.dids.alice][1].ref) 12 + await sc.like(sc.dids.carol, sc.replies[sc.dids.bob][0].ref) 13 + 14 + // give alice > 100 likes 15 + for (let i = 0; i < 50; i++) { 16 + const [b, c, d] = await Promise.all([ 17 + sc.post(sc.dids.bob, `bob post ${i}`), 18 + sc.post(sc.dids.carol, `carol post ${i}`), 19 + sc.post(sc.dids.dan, `dan post ${i}`), 20 + ]) 21 + await Promise.all( 22 + [ 23 + sc.like(sc.dids.alice, b.ref), // likes 50 of bobs posts 24 + i < 45 && sc.like(sc.dids.alice, c.ref), // likes 45 of carols posts 25 + i < 40 && sc.like(sc.dids.alice, d.ref), // likes 40 of dans posts 26 + ].filter(Boolean), 27 + ) 28 + } 29 + 30 + // couple more NPCs for suggested follows 31 + await sc.createAccount('fred', { 32 + email: 'fred@test.com', 33 + handle: 'fred.test', 34 + password: 'fred-pass', 35 + }) 36 + await sc.createAccount('gina', { 37 + email: 'gina@test.com', 38 + handle: 'gina.test', 39 + password: 'gina-pass', 40 + }) 41 + 42 + return sc 43 + }
+53
services/dev-env/src/seed/quotes.ts
··· 1 + import { default as basicSeed } from './basic' 2 + import { SeedClient } from './client' 3 + 4 + export default async (sc: SeedClient) => { 5 + await basicSeed(sc) 6 + await sc.createAccount('eve', { 7 + email: 'eve@test.com', 8 + handle: 'eve.test', 9 + password: 'eve-pass', 10 + }) 11 + 12 + await sc.post( 13 + sc.dids.eve, 14 + 'qUoTe 1', 15 + undefined, 16 + undefined, 17 + sc.posts[sc.dids.alice][0].ref, 18 + ) 19 + await sc.post( 20 + sc.dids.eve, 21 + 'qUoTe 2', 22 + undefined, 23 + undefined, 24 + sc.posts[sc.dids.alice][0].ref, 25 + ) 26 + 27 + await sc.post( 28 + sc.dids.eve, 29 + 'qUoTe 3', 30 + undefined, 31 + undefined, 32 + sc.replies[sc.dids.bob][0].ref, 33 + ) 34 + 35 + const carolPost = await sc.post(sc.dids.carol, 'post') 36 + await sc.post(sc.dids.eve, 'qUoTe 4', undefined, undefined, carolPost.ref) 37 + 38 + const spamPosts: Promise<any>[] = [] 39 + for (let i = 0; i < 5; i++) { 40 + spamPosts.push( 41 + sc.post( 42 + sc.dids.eve, 43 + `MASSIVE QUOTE SPAM ${i + 1}`, 44 + undefined, 45 + undefined, 46 + sc.posts[sc.dids.alice][1].ref, 47 + ), 48 + ) 49 + } 50 + await Promise.all(spamPosts) 51 + 52 + return sc 53 + }
+18
services/dev-env/src/seed/reposts.ts
··· 1 + import basicSeed from './basic' 2 + import { SeedClient } from './client' 3 + 4 + export default async (sc: SeedClient) => { 5 + await basicSeed(sc) 6 + await sc.createAccount('eve', { 7 + email: 'eve@test.com', 8 + handle: 'eve.test', 9 + password: 'eve-pass', 10 + }) 11 + await sc.repost(sc.dids.bob, sc.posts[sc.dids.alice][2].ref) 12 + await sc.repost(sc.dids.carol, sc.posts[sc.dids.alice][2].ref) 13 + await sc.repost(sc.dids.dan, sc.posts[sc.dids.alice][2].ref) 14 + await sc.repost(sc.dids.eve, sc.posts[sc.dids.alice][2].ref) 15 + await sc.repost(sc.dids.dan, sc.replies[sc.dids.bob][0].ref) 16 + await sc.repost(sc.dids.eve, sc.replies[sc.dids.bob][0].ref) 17 + return sc 18 + }
+228
services/dev-env/src/seed/users-bulk.ts
··· 1 + import { chunkArray } from '@atproto/common-web' 2 + import { SeedClient } from './client' 3 + 4 + export default async (sc: SeedClient, max = Infinity) => { 5 + // @TODO when these are run in parallel, seem to get an intermittent 6 + // "TypeError: fetch failed" while running the tests. 7 + const userSubset = users.slice(0, Math.min(max, users.length)) 8 + const chunks = chunkArray(userSubset, 50) 9 + for (const chunk of chunks) { 10 + await Promise.all( 11 + chunk.map(async (user) => { 12 + const { handle, displayName } = user 13 + await sc.createAccount(handle, { 14 + handle: handle, 15 + password: 'password', 16 + email: `${handle}@bsky.app`, 17 + }) 18 + if (displayName !== null) { 19 + await sc.createProfile(sc.dids[handle], displayName, '') 20 + } 21 + }), 22 + ) 23 + } 24 + return sc 25 + } 26 + 27 + const users = [ 28 + { handle: 'silas77.test', displayName: 'Tanya Denesik' }, 29 + { handle: 'nicolas-krajcik10.test', displayName: null }, 30 + { handle: 'lennie-strosin.test', displayName: null }, 31 + { handle: 'aliya-hodkiewicz.test', displayName: 'Carlton Abernathy IV' }, 32 + { handle: 'jeffrey-sawayn87.test', displayName: 'Patrick Sawayn' }, 33 + { handle: 'kaycee66.test', displayName: null }, 34 + { handle: 'adrienne49.test', displayName: 'Kim Streich' }, 35 + { handle: 'magnus53.test', displayName: 'Sally Funk' }, 36 + { handle: 'charles-spencer.test', displayName: null }, 37 + { handle: 'elta48.test', displayName: 'Dr. Lowell DuBuque' }, 38 + { handle: 'tressa-senger.test', displayName: null }, 39 + { handle: 'marietta-zboncak.test', displayName: null }, 40 + { handle: 'alexander-hickle.test', displayName: 'Winifred Harber' }, 41 + { handle: 'rodger-maggio24.test', displayName: 'Yolanda VonRueden' }, 42 + { handle: 'janiya48.test', displayName: 'Miss Terrell Ziemann' }, 43 + { handle: 'cayla-marquardt39.test', displayName: 'Rachel Kshlerin' }, 44 + { handle: 'jonathan-green.test', displayName: 'Erica Mertz' }, 45 + { handle: 'brycen-smith.test', displayName: null }, 46 + { handle: 'leonel-koch43.test', displayName: 'Karl Bosco IV' }, 47 + { handle: 'fidel-rath.test', displayName: null }, 48 + { handle: 'raleigh-metz.test', displayName: null }, 49 + { handle: 'kim41.test', displayName: null }, 50 + { handle: 'roderick-dibbert.test', displayName: null }, 51 + { handle: 'alec-bergnaum.test', displayName: 'Cody Berge' }, 52 + { handle: 'sven70.test', displayName: null }, 53 + { handle: 'ola-oconnell.test', displayName: null }, 54 + { handle: 'chauncey-klein.test', displayName: 'Kelvin Klein' }, 55 + { handle: 'ariel-krajcik.test', displayName: null }, 56 + { handle: 'murphy35.test', displayName: 'Mrs. Clifford Mertz' }, 57 + { handle: 'joshuah-parker11.test', displayName: null }, 58 + { handle: 'dewitt-wunsch.test', displayName: null }, 59 + { handle: 'kelton-nitzsche43.test', displayName: null }, 60 + { handle: 'dock-mann91.test', displayName: 'Miss Danielle Weber' }, 61 + { handle: 'herman-gleichner95.test', displayName: 'Kelli Schinner III' }, 62 + { handle: 'gerda-marquardt.test', displayName: 'Myron Wolf' }, 63 + { handle: 'jamil-batz.test', displayName: null }, 64 + { handle: 'hilario84.test', displayName: null }, 65 + { handle: 'kayli-bode.test', displayName: 'Miss Floyd McClure' }, 66 + { handle: 'elouise28.test', displayName: 'Alberta Fay' }, 67 + { handle: 'leann49.test', displayName: null }, 68 + { handle: 'javon24.test', displayName: null }, 69 + { handle: 'polly-shanahan45.test', displayName: null }, 70 + { handle: 'rosamond38.test', displayName: 'Karl Goyette' }, 71 + { handle: 'fredrick-mueller.test', displayName: null }, 72 + { handle: 'reina-runte33.test', displayName: 'Pablo Schmidt' }, 73 + { handle: 'bianka33.test', displayName: null }, 74 + { handle: 'carlos6.test', displayName: null }, 75 + { handle: 'jermain-smith.test', displayName: 'Eileen Stroman' }, 76 + { handle: 'gina97.test', displayName: null }, 77 + { handle: 'kiera97.test', displayName: null }, 78 + { handle: 'savannah-botsford.test', displayName: 'Darnell Kuvalis' }, 79 + { handle: 'lilliana-waters.test', displayName: null }, 80 + { handle: 'hailey-stroman.test', displayName: 'Elsa Schaden' }, 81 + { handle: 'dortha-terry.test', displayName: 'Nicole Bradtke' }, 82 + { handle: 'hank-powlowski32.test', displayName: null }, 83 + { handle: 'ervin-daugherty.test', displayName: null }, 84 + { handle: 'nannie18.test', displayName: null }, 85 + { handle: 'gilberto-watsica65.test', displayName: 'Ms. Ida Wilderman' }, 86 + { handle: 'kara-zieme58.test', displayName: 'Andres Towne' }, 87 + { handle: 'crystal-boyle.test', displayName: null }, 88 + { handle: 'tobin63.test', displayName: 'Alex Johnson' }, 89 + { handle: 'isai-kunze72.test', displayName: 'Marion Dickinson' }, 90 + { handle: 'paris-swift.test', displayName: null }, 91 + { handle: 'nestor90.test', displayName: 'Travis Hoppe' }, 92 + { handle: 'aliyah-flatley12.test', displayName: 'Loren Krajcik' }, 93 + { handle: 'maiya42.test', displayName: null }, 94 + { handle: 'dovie33.test', displayName: null }, 95 + { handle: 'kendra-ledner80.test', displayName: 'Sergio Hane' }, 96 + { handle: 'greyson-tromp3.test', displayName: null }, 97 + { handle: 'precious-fay.test', displayName: null }, 98 + { handle: 'kiana-schmitt39.test', displayName: null }, 99 + { handle: 'rhianna-stamm29.test', displayName: null }, 100 + { handle: 'tiara-mohr.test', displayName: null }, 101 + { handle: 'eleazar-balist70.test', displayName: 'Gordon Weissnat' }, 102 + { handle: 'bettie-bogisich96.test', displayName: null }, 103 + { handle: 'lura-jacobi55.test', displayName: null }, 104 + { handle: 'santa-hermann78.test', displayName: 'Melissa Johnson' }, 105 + { handle: 'dylan61.test', displayName: null }, 106 + { handle: 'ryley-kerluke.test', displayName: 'Alexander Purdy' }, 107 + { handle: 'moises-bins8.test', displayName: null }, 108 + { handle: 'angelita-schaef27.test', displayName: null }, 109 + { handle: 'natasha83.test', displayName: 'Dean Romaguera' }, 110 + { handle: 'sydni48.test', displayName: null }, 111 + { handle: 'darrion91.test', displayName: 'Jeanette Weimann' }, 112 + { handle: 'reynold-ortiz.test', displayName: null }, 113 + { handle: 'hassie-schuppe.test', displayName: 'Rita Zieme' }, 114 + { handle: 'clark-stehr8.test', displayName: 'Sammy Larkin' }, 115 + { handle: 'preston-harris.test', displayName: 'Ms. Bradford Thiel' }, 116 + { handle: 'benedict-schulist.test', displayName: 'Todd Stark' }, 117 + { handle: 'alden-wolff22.test', displayName: null }, 118 + { handle: 'joel-gulgowski.test', displayName: null }, 119 + { handle: 'joanie56.test', displayName: 'Ms. Darin Cole' }, 120 + { handle: 'israel-hermann0.test', displayName: 'Wilbur Schuster' }, 121 + { handle: 'tracy56.test', displayName: null }, 122 + { handle: 'kyle72.test', displayName: null }, 123 + { handle: 'gunnar-dare70.test', displayName: 'Mrs. Angelo Keeling' }, 124 + { handle: 'justus58.test', displayName: null }, 125 + { handle: 'brooke24.test', displayName: 'Clint Ward' }, 126 + { handle: 'angela-morissette.test', displayName: 'Jim Kertzmann' }, 127 + { handle: 'amy-bins.test', displayName: 'Angelina Hills' }, 128 + { handle: 'susanna81.test', displayName: null }, 129 + { handle: 'jailyn-hettinger50.test', displayName: 'Sheldon Ratke' }, 130 + { handle: 'wendell-hansen54.test', displayName: null }, 131 + { handle: 'jennyfer-spinka.test', displayName: 'Leticia Blick' }, 132 + { handle: 'alexandrea31.test', displayName: 'Leslie Von' }, 133 + { handle: 'hazle-davis.test', displayName: 'Ella Farrell' }, 134 + { handle: 'alta6.test', displayName: null }, 135 + { handle: 'sherwood4.test', displayName: 'Dr. Hattie Nienow I' }, 136 + { handle: 'marilie24.test', displayName: 'Gene Howell' }, 137 + { handle: 'jimmie-feeney82.test', displayName: null }, 138 + { handle: 'trisha-ohara.test', displayName: null }, 139 + { handle: 'jake-schuster33.test', displayName: 'Raymond Price' }, 140 + { handle: 'shane-torphy52.test', displayName: 'Sadie Carter' }, 141 + { handle: 'nakia-kuphal8.test', displayName: null }, 142 + { handle: 'lea-trantow.test', displayName: null }, 143 + { handle: 'joel62.test', displayName: 'Veronica Nitzsche' }, 144 + { handle: 'roosevelt33.test', displayName: 'Jay Moen' }, 145 + { handle: 'talon-okeefe85.test', displayName: null }, 146 + { handle: 'herman-dare.test', displayName: 'Eric White' }, 147 + { handle: 'flavio-fay.test', displayName: 'John Lindgren' }, 148 + { handle: 'elyse-prosacco.test', displayName: null }, 149 + { handle: 'jessyca-wiegand23.test', displayName: 'Debra Lockman' }, 150 + { handle: 'ara-spencer41.test', displayName: null }, 151 + { handle: 'frederic-fadel.test', displayName: null }, 152 + { handle: 'zora-gerlach.test', displayName: 'Noel Hansen' }, 153 + { handle: 'spencer4.test', displayName: 'Marjorie Gorczany' }, 154 + { handle: 'gage-wilkinson33.test', displayName: 'Preston Schoen V' }, 155 + { handle: 'kiley-runolfsson1.test', displayName: null }, 156 + { handle: 'ramona80.test', displayName: 'Sylvia Dietrich' }, 157 + { handle: 'rashad97.test', displayName: null }, 158 + { handle: 'kylie76.test', displayName: 'Josefina Pfeffer' }, 159 + { handle: 'alisha-zieme.test', displayName: null }, 160 + { handle: 'claud79.test', displayName: null }, 161 + { handle: 'jairo-kuvalis.test', displayName: 'Derrick Jacobson' }, 162 + { handle: 'delfina-emard.test', displayName: null }, 163 + { handle: 'waino-gutmann20.test', displayName: 'Wesley Kemmer' }, 164 + { handle: 'arvid-hermiston49.test', displayName: 'Vernon Towne PhD' }, 165 + { handle: 'hans79.test', displayName: 'Rex Hartmann' }, 166 + { handle: 'karlee-greenholt40.test', displayName: null }, 167 + { handle: 'nels-cummings.test', displayName: null }, 168 + { handle: 'andrew-maggio.test', displayName: null }, 169 + { handle: 'stephany75.test', displayName: null }, 170 + { handle: 'alba-lueilwitz.test', displayName: null }, 171 + { handle: 'fermin47.test', displayName: null }, 172 + { handle: 'milo-quitzon3.test', displayName: null }, 173 + { handle: 'eudora-dietrich4.test', displayName: 'Carol Littel' }, 174 + { handle: 'uriel-witting12.test', displayName: 'Sophia Schmidt' }, 175 + { handle: 'reuben-stracke48.test', displayName: 'Darrell Walker MD' }, 176 + { handle: 'letitia-sawayn11.test', displayName: 'Mrs. Sophie Reilly' }, 177 + { handle: 'macy-schaden.test', displayName: 'Lindsey Klein' }, 178 + { handle: 'imelda61.test', displayName: 'Shannon Beier' }, 179 + { handle: 'oswald-bailey.test', displayName: 'Angel Mann' }, 180 + { handle: 'pattie-fisher34.test', displayName: null }, 181 + { handle: 'loyce95.test', displayName: 'Claude Tromp' }, 182 + { handle: 'melyna-zboncak.test', displayName: null }, 183 + { handle: 'rowan-parisian.test', displayName: 'Mr. Veronica Feeney' }, 184 + { handle: 'lois-blanda20.test', displayName: 'Todd Rolfson' }, 185 + { handle: 'turner-bali76.test', displayName: null }, 186 + { handle: 'dee-hoppe65.test', displayName: null }, 187 + { handle: 'nikko-rosenbaum60.test', displayName: 'Joann Gutmann' }, 188 + { handle: 'cornell-rom53.test', displayName: null }, 189 + { handle: 'zack3.test', displayName: null }, 190 + { handle: 'fredrick41.test', displayName: 'Julius Kreiger' }, 191 + { handle: 'elwyn62.test', displayName: null }, 192 + { handle: 'isaias-hirthe37.test', displayName: 'Louis Cremin' }, 193 + { handle: 'ronaldo36.test', displayName: null }, 194 + { handle: 'jesse34.test', displayName: 'Bridget Schulist' }, 195 + { handle: 'darrel-mills17.test', displayName: null }, 196 + { handle: 'euna-mayert92.test', displayName: 'Grant Lang II' }, 197 + { handle: 'terrell92.test', displayName: null }, 198 + { handle: 'alyson-bogisich.test', displayName: 'Dana MacGyver' }, 199 + { handle: 'nicolas65.test', displayName: null }, 200 + { handle: 'bernita8.test', displayName: null }, 201 + { handle: 'gunner23.test', displayName: 'Maggie DuBuque' }, 202 + { handle: 'phoebe80.test', displayName: null }, 203 + { handle: 'cory-cruickshank.test', displayName: null }, 204 + { handle: 'conor-price.test', displayName: 'Ralph Daugherty III' }, 205 + { handle: 'rae91.test', displayName: null }, 206 + { handle: 'abigale-cronin.test', displayName: null }, 207 + { handle: 'aileen-reilly90.test', displayName: 'Charles Stanton' }, 208 + { handle: 'adrianna-hansen6.test', displayName: 'Elbert Langworth IV' }, 209 + { handle: 'pierre54.test', displayName: null }, 210 + { handle: 'jaida-stark62.test', displayName: 'Justin Stoltenberg MD' }, 211 + { handle: 'wade-witting.test', displayName: null }, 212 + { handle: 'yvonne-predovic5.test', displayName: 'Gregory Hamill' }, 213 + { handle: 'spencer-dubuque.test', displayName: null }, 214 + { handle: 'randi44.test', displayName: null }, 215 + { handle: 'maye-grimes.test', displayName: null }, 216 + { handle: 'margarette-effertz.test', displayName: null }, 217 + { handle: 'aimee98.test', displayName: null }, 218 + { handle: 'jaren-veum0.test', displayName: 'Dr. Omar Wolff' }, 219 + { handle: 'ariel-abbott54.test', displayName: 'Emanuel Powlowski' }, 220 + { handle: 'mercedes23.test', displayName: null }, 221 + { handle: 'jarrett-orn.test', displayName: null }, 222 + { handle: 'damion88.test', displayName: null }, 223 + { handle: 'nayeli-koss73.test', displayName: 'Johnny Lang' }, 224 + { handle: 'cara-wiegand69.test', displayName: null }, 225 + { handle: 'gideon-ohara51.test', displayName: null }, 226 + { handle: 'carolina-mcderm77.test', displayName: 'Latoya Windler' }, 227 + { handle: 'danyka90.test', displayName: 'Hope Kub' }, 228 + ]
+64
services/dev-env/src/seed/users.ts
··· 1 + import { SeedClient } from './client' 2 + 3 + export default async (sc: SeedClient) => { 4 + await sc.createAccount('alice', users.alice) 5 + await sc.createAccount('bob', users.bob) 6 + await sc.createAccount('carol', users.carol) 7 + await sc.createAccount('dan', users.dan) 8 + 9 + await sc.createProfile( 10 + sc.dids.alice, 11 + users.alice.displayName, 12 + users.alice.description, 13 + users.alice.selfLabels, 14 + ) 15 + await sc.createProfile( 16 + sc.dids.bob, 17 + users.bob.displayName, 18 + users.bob.description, 19 + users.bob.selfLabels, 20 + ) 21 + 22 + await sc.agent.api.chat.bsky.actor.declaration.create( 23 + { repo: sc.dids.dan }, 24 + { allowIncoming: 'none' }, 25 + sc.getHeaders(sc.dids.dan), 26 + ) 27 + 28 + return sc 29 + } 30 + 31 + const users = { 32 + alice: { 33 + email: 'alice@test.com', 34 + handle: 'alice.test', 35 + password: 'alice-pass', 36 + displayName: 'ali', 37 + description: 'its me!', 38 + selfLabels: ['self-label-a', 'self-label-b'], 39 + }, 40 + bob: { 41 + email: 'bob@test.com', 42 + handle: 'bob.test', 43 + password: 'bob-pass', 44 + displayName: 'bobby', 45 + description: 'hi im bob label_me', 46 + selfLabels: undefined, 47 + }, 48 + carol: { 49 + email: 'carol@test.com', 50 + handle: 'carol.test', 51 + password: 'carol-pass', 52 + displayName: undefined, 53 + description: undefined, 54 + selfLabels: undefined, 55 + }, 56 + dan: { 57 + email: 'dan@test.com', 58 + handle: 'dan.test', 59 + password: 'dan-pass', 60 + displayName: undefined, 61 + description: undefined, 62 + selfLabels: undefined, 63 + }, 64 + }
+58
services/dev-env/src/types.ts
··· 1 + import * as bsky from '@atproto/bsky' 2 + import * as bsync from '@atproto/bsync' 3 + import { ExportableKeypair, Keypair } from '@atproto/crypto' 4 + import * as ozone from '@atproto/ozone' 5 + import * as pds from '@atproto/pds' 6 + 7 + export type IntrospectConfig = { 8 + port?: number 9 + } 10 + 11 + export type PlcConfig = { 12 + port?: number 13 + version?: string 14 + } 15 + 16 + export type PdsConfig = Partial<pds.ServerEnvironment> & { 17 + didPlcUrl: string 18 + migration?: string 19 + } 20 + 21 + export type BskyConfig = Partial<bsky.ServerConfig> & { 22 + plcUrl: string 23 + repoProvider: string 24 + dbPostgresUrl: string 25 + dbPostgresSchema: string 26 + redisHost: string 27 + pdsPort: number 28 + migration?: string 29 + } 30 + 31 + export type BsyncConfig = Partial<bsync.ServerEnvironment> & { 32 + dbUrl: string 33 + } 34 + 35 + export type OzoneConfig = Partial<ozone.OzoneEnvironment> & { 36 + plcUrl: string 37 + appviewUrl: string 38 + appviewDid: string 39 + dbPostgresUrl: string 40 + migration?: string 41 + signingKey?: ExportableKeypair 42 + imgInvalidator?: ozone.ImageInvalidator 43 + } 44 + 45 + export type TestServerParams = { 46 + dbPostgresUrl: string 47 + dbPostgresSchema: string 48 + pds: Partial<PdsConfig> 49 + plc: Partial<PlcConfig> 50 + bsky: Partial<BskyConfig> 51 + ozone: Partial<OzoneConfig> 52 + introspect: Partial<IntrospectConfig> 53 + } 54 + 55 + export type DidAndKey = { 56 + did: string 57 + key: Keypair 58 + }
+97
services/dev-env/src/util.ts
··· 1 + import * as plc from '@did-plc/lib' 2 + import { request } from 'undici' 3 + import { Secp256k1Keypair } from '@atproto/crypto' 4 + import { IdResolver } from '@atproto/identity' 5 + import { TestBsky } from './bsky' 6 + import { TestPds } from './pds' 7 + import { DidAndKey } from './types' 8 + 9 + export const mockNetworkUtilities = (pds: TestPds, bsky?: TestBsky) => { 10 + mockResolvers(pds.ctx.idResolver, pds) 11 + if (bsky) { 12 + mockResolvers(bsky.ctx.idResolver, pds) 13 + mockResolvers(bsky.dataplane.idResolver, pds) 14 + } 15 + } 16 + 17 + export const mockResolvers = (idResolver: IdResolver, pds: TestPds) => { 18 + // Map pds public url to its local url when resolving from plc 19 + const origResolveDid = idResolver.did.resolveNoCache 20 + idResolver.did.resolveNoCache = async (did: string) => { 21 + const result = await (origResolveDid.call( 22 + idResolver.did, 23 + did, 24 + ) as ReturnType<typeof origResolveDid>) 25 + const service = result?.service?.find((svc) => svc.id === '#atproto_pds') 26 + if (typeof service?.serviceEndpoint === 'string') { 27 + service.serviceEndpoint = service.serviceEndpoint.replace( 28 + pds.ctx.cfg.service.publicUrl, 29 + `http://localhost:${pds.port}`, 30 + ) 31 + } 32 + return result 33 + } 34 + 35 + const origResolveHandleDns = idResolver.handle.resolveDns 36 + idResolver.handle.resolve = async (handle: string) => { 37 + const isPdsHandle = pds.ctx.cfg.identity.serviceHandleDomains.some( 38 + (domain) => handle.endsWith(domain), 39 + ) 40 + if (!isPdsHandle) { 41 + return origResolveHandleDns.call(idResolver.handle, handle) 42 + } 43 + 44 + const url = new URL(`/.well-known/atproto-did`, pds.url) 45 + try { 46 + const res = await request(url, { headers: { host: handle } }) 47 + if (res.statusCode !== 200) { 48 + await res.body.dump() 49 + return undefined 50 + } 51 + 52 + return res.body.text() 53 + } catch (err) { 54 + return undefined 55 + } 56 + } 57 + } 58 + 59 + export const mockMailer = (pds: TestPds) => { 60 + const mailer = pds.ctx.mailer 61 + const _origSendMail = mailer.transporter.sendMail 62 + mailer.transporter.sendMail = async (opts) => { 63 + const result = await _origSendMail.call(mailer.transporter, opts) 64 + console.log(`✉️ Email: ${JSON.stringify(result, null, 2)}`) 65 + return result 66 + } 67 + } 68 + 69 + const usedLockIds = new Set() 70 + export const uniqueLockId = () => { 71 + let lockId: number 72 + do { 73 + lockId = 1000 + Math.ceil(1000 * Math.random()) 74 + } while (usedLockIds.has(lockId)) 75 + usedLockIds.add(lockId) 76 + return lockId 77 + } 78 + 79 + export const createDidAndKey = async (opts: { 80 + plcUrl: string 81 + handle: string 82 + pds: string 83 + }): Promise<DidAndKey> => { 84 + const { plcUrl, handle, pds } = opts 85 + const key = await Secp256k1Keypair.create({ exportable: true }) 86 + const did = await new plc.Client(plcUrl).createDid({ 87 + signingKey: key.did(), 88 + rotationKeys: [key.did()], 89 + handle, 90 + pds, 91 + signer: key, 92 + }) 93 + return { 94 + key, 95 + did, 96 + } 97 + }
+36
services/dev-env/tsconfig.build.json
··· 1 + { 2 + "$schema": "https://json.schemastore.org/tsconfig", 3 + "compilerOptions": { 4 + "checkJs": true, 5 + "strict": true, 6 + "allowUnusedLabels": false, 7 + "allowUnreachableCode": false, 8 + "exactOptionalPropertyTypes": false, 9 + "noFallthroughCasesInSwitch": false, 10 + "noImplicitAny": false, 11 + "noImplicitReturns": false, 12 + "noUnusedLocals": false, 13 + "noUnusedParameters": false, 14 + "skipLibCheck": true, 15 + "allowSyntheticDefaultImports": true, 16 + "forceConsistentCasingInFileNames": true, 17 + "esModuleInterop": true, 18 + "isolatedModules": true, 19 + "preserveSymlinks": false, 20 + "useDefineForClassFields": true, 21 + "lib": ["ES2023", "ScriptHost"], 22 + "moduleResolution": "node", 23 + "resolveJsonModule": true, 24 + "types": ["node"], 25 + "noErrorTruncation": true, 26 + "declaration": true, 27 + "declarationMap": true, 28 + "sourceMap": true, 29 + "jsx": "preserve", 30 + "module": "CommonJS", 31 + "target": "ES2020", 32 + "rootDir": "./src", 33 + "outDir": "./dist" 34 + }, 35 + "include": ["./src"] 36 + }
+4
services/dev-env/tsconfig.json
··· 1 + { 2 + "include": [], 3 + "references": [{ "path": "./tsconfig.build.json" }] 4 + }
+83
services/dev-infra/README.md
··· 1 + # dev-infra 2 + 3 + Helpers for working with postgres and redis locally. Previously known as `pg`. 4 + 5 + ## Usage 6 + 7 + ### `with-test-db.sh` 8 + 9 + This script allows you to run any command with a fresh, ephemeral/single-use postgres database available. When the script starts a Dockerized postgres container starts-up, and when the script completes that container is removed. 10 + 11 + The environment variable `DB_POSTGRES_URL` will be set with a connection string that can be used to connect to the database. The [`PG*` environment variables](https://www.postgresql.org/docs/current/libpq-envars.html) that are recognized by libpq (i.e. used by the `psql` client) are also set. 12 + 13 + **Example** 14 + 15 + ``` 16 + $ ./with-test-db.sh psql -c 'select 1;' 17 + [+] Running 1/1 18 + ⠿ Container pg-db_test-1 Healthy 1.8s 19 + 20 + ?column? 21 + ---------- 22 + 1 23 + (1 row) 24 + 25 + 26 + [+] Running 1/1 27 + ⠿ Container pg-db_test-1 Stopped 0.1s 28 + Going to remove pg-db_test-1 29 + [+] Running 1/0 30 + ⠿ Container pg-db_test-1 Removed 31 + ``` 32 + 33 + ### `with-redis-and-test-db.sh` 34 + 35 + This script is similar to `with-test-db.sh`, but in addition to an ephemeral/single-use postgres database it also provides a single-use redis instance. When the script starts, Dockerized postgres and redis containers start-up, and when the script completes the containers are removed. 36 + 37 + The environment variables `DB_POSTGRES_URL` and `REDIS_HOST` will be set with a connection strings that can be used to connect to postgres and redis respectively. 38 + 39 + ### `docker-compose.yaml` 40 + 41 + The Docker compose file can be used to run containerized versions of postgres either for single use (as is used by `with-test-db.sh`), or for longer-term use. These are setup as separate services named `db_test` and `db` respectively. In both cases the database is available on the host machine's `localhost` and credentials are: 42 + 43 + - Username: pg 44 + - Password: password 45 + 46 + However, each service uses a different port, documented below, to avoid conflicts. 47 + 48 + #### `db_test` service for single use 49 + 50 + The single-use `db_test` service does not have any persistent storage. When the container is removed, data in the database disappears with it. 51 + 52 + This service runs on port `5433`. 53 + 54 + ``` 55 + $ docker compose up db_test # start container 56 + $ docker compose stop db_test # stop container 57 + $ docker compose rm db_test # remove container 58 + ``` 59 + 60 + #### `db` service for persistent use 61 + 62 + The `db` service has persistent storage on the host machine managed by Docker under a volume named `pg_atp_db`. When the container is removed, data in the database will remain on the host machine. In order to start fresh, you would need to remove the volume. 63 + 64 + This service runs on port `5432`. 65 + 66 + ``` 67 + $ docker compose up db -d # start container 68 + $ docker compose stop db # stop container 69 + $ docker compose rm db # remove container 70 + $ docker volume rm pg_atp_db # remove volume 71 + ``` 72 + 73 + #### `redis_test` service for single use 74 + 75 + The single-use `redis_test` service does not have any persistent storage. When the container is removed, the data in redis disappears with it. 76 + 77 + This service runs on port `6380`. 78 + 79 + #### `redis` service for persistent use 80 + 81 + The `redis` service has persistent storage on the host machine managed by Docker under a volume named `atp_redis`. When the container is removed, the data in redis will remain on the host machine. In order to start fresh, you would need to remove the volume. 82 + 83 + This service runs on port `6379`.
+181
services/dev-infra/_common.sh
··· 1 + #!/usr/bin/env sh 2 + 3 + # Exit if any command fails 4 + set -e 5 + 6 + get_container_id() { 7 + local compose_file=$1 8 + local service=$2 9 + if [ -z "${compose_file}" ] || [ -z "${service}" ]; then 10 + echo "usage: get_container_id <compose_file> <service>" 11 + exit 1 12 + fi 13 + 14 + # first line of jq normalizes for docker compose breaking change, see docker/compose#10958 15 + docker compose --file $compose_file ps --format json --status running \ 16 + | jq -sc '.[] | if type=="array" then .[] else . end' | jq -s \ 17 + | jq -r '.[]? | select(.Service == "'${service}'") | .ID' 18 + } 19 + 20 + # Exports all environment variables 21 + export_env() { 22 + export_pg_env 23 + export_redis_env 24 + } 25 + 26 + # Exports postgres environment variables 27 + export_pg_env() { 28 + # Based on creds in compose.yaml 29 + export PGPORT=5433 30 + export PGHOST=localhost 31 + export PGUSER=pg 32 + export PGPASSWORD=password 33 + export PGDATABASE=postgres 34 + export DB_POSTGRES_URL="postgresql://pg:password@127.0.0.1:5433/postgres" 35 + } 36 + 37 + # Exports redis environment variables 38 + export_redis_env() { 39 + export REDIS_HOST="127.0.0.1:6380" 40 + } 41 + 42 + pg_clear() { 43 + local pg_uri=$1 44 + 45 + for schema_name in `psql "${pg_uri}" -c "SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT LIKE 'pg_%' AND schema_name NOT LIKE 'information_schema';" -t`; do 46 + psql "${pg_uri}" -c "DROP SCHEMA \"${schema_name}\" CASCADE;" 47 + done 48 + } 49 + 50 + pg_init() { 51 + local pg_uri=$1 52 + 53 + psql "${pg_uri}" -c "CREATE SCHEMA IF NOT EXISTS \"public\";" 54 + } 55 + 56 + redis_clear() { 57 + local redis_uri=$1 58 + redis-cli -u "${redis_uri}" flushall 59 + } 60 + 61 + main_native() { 62 + local services=${SERVICES} 63 + local postgres_url_env_var=`[[ $services == *"db_test"* ]] && echo "DB_TEST_POSTGRES_URL" || echo "DB_POSTGRES_URL"` 64 + local redis_host_env_var=`[[ $services == *"redis_test"* ]] && echo "REDIS_TEST_HOST" || echo "REDIS_HOST"` 65 + 66 + postgres_url="${!postgres_url_env_var}" 67 + redis_host="${!redis_host_env_var}" 68 + 69 + if [ -n "${postgres_url}" ]; then 70 + echo "Using ${postgres_url_env_var} (${postgres_url}) to connect to postgres." 71 + pg_init "${postgres_url}" 72 + else 73 + echo "Postgres connection string missing did you set ${postgres_url_env_var}?" 74 + exit 1 75 + fi 76 + 77 + if [ -n "${redis_host}" ]; then 78 + echo "Using ${redis_host_env_var} (${redis_host}) to connect to Redis." 79 + else 80 + echo "Redis connection string missing did you set ${redis_host_env_var}?" 81 + echo "Continuing without Redis..." 82 + fi 83 + 84 + cleanup() { 85 + local services=$@ 86 + 87 + if [ -n "${redis_host}" ] && [[ $services == *"redis_test"* ]]; then 88 + redis_clear "redis://${redis_host}" &> /dev/null 89 + fi 90 + 91 + if [ -n "${postgres_url}" ] && [[ $services == *"db_test"* ]]; then 92 + pg_clear "${postgres_url}" &> /dev/null 93 + fi 94 + } 95 + 96 + # trap SIGINT and performs cleanup 97 + trap "on_sigint ${services}" INT 98 + on_sigint() { 99 + cleanup $@ 100 + exit $? 101 + } 102 + 103 + # Run the arguments as a command 104 + DB_POSTGRES_URL="${postgres_url}" \ 105 + REDIS_HOST="${redis_host}" \ 106 + "$@" 107 + code=$? 108 + 109 + cleanup ${services} 110 + 111 + exit ${code} 112 + } 113 + 114 + main_docker() { 115 + # Expect a SERVICES env var to be set with the docker service names 116 + local services=${SERVICES} 117 + 118 + dir=$(dirname $0) 119 + compose_file="${dir}/docker-compose.yaml" 120 + 121 + # whether this particular script started the container(s) 122 + started_container=false 123 + 124 + # performs cleanup as necessary, i.e. taking down containers 125 + # if this script started them 126 + cleanup() { 127 + local services=$@ 128 + echo # newline 129 + if $started_container; then 130 + docker compose --file $compose_file rm --force --stop --volumes ${services} 131 + fi 132 + } 133 + 134 + # trap SIGINT and performs cleanup 135 + trap "on_sigint ${services}" INT 136 + on_sigint() { 137 + cleanup $@ 138 + exit $? 139 + } 140 + 141 + # check if all services are running already 142 + not_running=false 143 + for service in $services; do 144 + container_id=$(get_container_id $compose_file $service) 145 + if [ -z $container_id ]; then 146 + not_running=true 147 + break 148 + fi 149 + done 150 + 151 + # if any are missing, recreate all services 152 + if $not_running; then 153 + started_container=true 154 + docker compose --file $compose_file up --wait --force-recreate ${services} 155 + else 156 + echo "all services ${services} are already running" 157 + fi 158 + 159 + # do not exit when following commands fail, so we can intercept exit code & tear down docker 160 + set +e 161 + 162 + # setup environment variables and run args 163 + export_env 164 + "$@" 165 + # save return code for later 166 + code=$? 167 + 168 + # performs cleanup as necessary 169 + cleanup ${services} 170 + exit ${code} 171 + } 172 + 173 + # Main entry point 174 + main() { 175 + if ! docker ps >/dev/null 2>&1; then 176 + echo "Docker unavailable. Running on host." 177 + main_native $@ 178 + else 179 + main_docker $@ 180 + fi 181 + }
+49
services/dev-infra/docker-compose.yaml
··· 1 + version: '3.8' 2 + services: 3 + # An ephermerally-stored postgres database for single-use test runs 4 + db_test: &db_test 5 + image: postgres:14.4-alpine 6 + environment: 7 + - POSTGRES_USER=pg 8 + - POSTGRES_PASSWORD=password 9 + ports: 10 + - '5433:5432' 11 + # Healthcheck ensures db is queryable when `docker-compose up --wait` completes 12 + healthcheck: 13 + test: 'pg_isready -U pg' 14 + interval: 500ms 15 + timeout: 10s 16 + retries: 20 17 + # A persistently-stored postgres database 18 + db: 19 + <<: *db_test 20 + ports: 21 + - '5432:5432' 22 + healthcheck: 23 + disable: true 24 + volumes: 25 + - atp_db:/var/lib/postgresql/data 26 + # An ephermerally-stored redis cache for single-use test runs 27 + redis_test: &redis_test 28 + image: redis:7.0-alpine 29 + ports: 30 + - '6380:6379' 31 + # Healthcheck ensures redis is queryable when `docker-compose up --wait` completes 32 + healthcheck: 33 + test: ['CMD-SHELL', '[ "$$(redis-cli ping)" = "PONG" ]'] 34 + interval: 500ms 35 + timeout: 10s 36 + retries: 20 37 + # A persistently-stored redis cache 38 + redis: 39 + <<: *redis_test 40 + command: redis-server --save 60 1 --loglevel warning 41 + ports: 42 + - '6379:6379' 43 + healthcheck: 44 + disable: true 45 + volumes: 46 + - atp_redis:/data 47 + volumes: 48 + atp_db: 49 + atp_redis:
+9
services/dev-infra/with-test-db.sh
··· 1 + #!/usr/bin/env sh 2 + 3 + # Example usage: 4 + # ./with-test-db.sh psql postgresql://pg:password@localhost:5433/postgres -c 'select 1;' 5 + 6 + dir=$(dirname $0) 7 + . ${dir}/_common.sh 8 + 9 + SERVICES="db_test" main "$@"
+10
services/dev-infra/with-test-redis-and-db.sh
··· 1 + #!/usr/bin/env sh 2 + 3 + # Example usage: 4 + # ./with-test-redis-and-db.sh psql postgresql://pg:password@localhost:5433/postgres -c 'select 1;' 5 + # ./with-test-redis-and-db.sh redis-cli -h localhost -p 6380 ping 6 + 7 + dir=$(dirname $0) 8 + . ${dir}/_common.sh 9 + 10 + SERVICES="db_test redis_test" main "$@"
+3
services/pds/.dockerignore
··· 30 30 .env.development.local 31 31 .env.test.local 32 32 .env.production.local 33 + .*.env 34 + .env.* 35 + .env 33 36 34 37 # vercel 35 38 .vercel