[WIP] A (somewhat barebones) atproto app for creating custom sites without hosting!

Compare changes

Choose any two refs to compare.

-2
.gitignore
··· 1 - server/node_modules/* 2 - server/local.db
+51
README.md
··· 1 + # atcities.dev 2 + 3 + A (somewhat barebones) atproto app for creating custom sites without hosting! 4 + 5 + > [!CAUTION] 6 + > This software is super duper alpha and not tested thoroughly! Use at your own risk! 7 + 8 + - Lexicons are located at [`./lexicons`](./lexicons/) 9 + - Server backend is located at [`./server`](./server/) 10 + - Upload CLI is located at [`./upload`](./upload/) 11 + - Web GUI **will be** located at [`./web-gui`](./web-gui/) 12 + - Fuse tool **will be** located at [`./fuse`](./fuse/) 13 + 14 + ## How to: 15 + 16 + **View someones site?** 17 + > Head to `https://<handle>.atcities.dev/` or `https://<did>.did-<method>.atcities.dev/`. 18 + 19 + **Upload your own site?** 20 + > Use the upload cli. Installation guide below. 21 + 22 + **Self host atcities.dev?** 23 + > Clone this repo and setup the `.env` file for `/server`, then run `deno run run` 24 + 25 + ### CLI installation guide. 26 + 27 + 1. Build from source: 28 + Prerequisites: `git` `cargo` `rust` 29 + ```sh 30 + git clone https://tangled.org/@vielle.dev/atcities.dev 31 + cd atcities.dev/upload 32 + cargo build 33 + sudo cp ./target/debug/atcities-upload /bin 34 + # Reload your shell environment 35 + atcities-upload --version 36 + ``` 37 + 38 + ## Todo: 39 + 40 + - [x] Resolve `handle.host` and `did.did-method.host` domains to records/blobs 41 + - [x] Backfill network 42 + - [x] Store did+route -> blob & mime type in database 43 + - [x] Store blobs for CDN (max ~0.25gb per user) 44 + - [x] Moderate illegal content or hope that people are niceys 45 + (Hope that people are niceys) 46 + - [x] Finish CLI tool 47 + - [x] Sign in via app password 48 + - [x] Clear old site 49 + - [x] Upload new site 50 + - [ ] Fuse uploader 51 + - [ ] Web GUI uploader
+33
lexicons/dev.atcities.route.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "dev.atcities.route", 4 + "description": "Define the route for a given page. Page content is a blob", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Page URL maps directly to a record key", 9 + "key": "any", 10 + "record": { 11 + "type": "object", 12 + "properties": { 13 + "page": { 14 + "type": "union", 15 + "refs": ["#blob"] 16 + } 17 + }, 18 + "required": ["page"] 19 + } 20 + }, 21 + 22 + "blob": { 23 + "type": "object", 24 + "properties": { 25 + "blob": { 26 + "type": "blob", 27 + "accept": ["*/*"] 28 + } 29 + }, 30 + "required": ["blob"] 31 + } 32 + } 33 + }
+4 -1
server/.env.template
··· 1 1 PORT=8000 2 2 HOSTNAME=localhost 3 - DB_FILE_NAME=file:local.db 3 + DB_FILE_NAME=file:local.db 4 + # requires `/xrpc/com.atproto.sync.listReposByCollection` endpoint 5 + # this is because im lazy 6 + ATPROTO_RELAY=https://relay1.us-east.bsky.network
+4
server/.gitignore
··· 1 + node_modules/* 2 + local.db 3 + .env 4 + blobs
+9 -3
server/deno.json
··· 1 1 { 2 2 "tasks": { 3 - "dev": "PORT=8000 deno run --watch --allow-net --allow-env=HOSTNAME,PORT,NODE_ENV --env-file src/index.ts", 4 - "lexgen": "deno run --allow-env --allow-sys --allow-read=. --allow-write=./src/lexicons --no-prompt @atcute/lex-cli generate -c ./lex.config.js && cat ./src/lexicons/index.ts | sed \"s/.js/.ts/\" > ./src/lexicons/index.ts" 3 + "dev": "deno run --watch --allow-net --allow-env --allow-sys --allow-read=/usr/bin/ldd,./blobs,./src --allow-write=./blobs --allow-ffi --env-file src/index.ts", 4 + "run": "deno run --allow-net --allow-env --allow-sys --allow-read=/usr/bin/ldd,./blobs,./src --allow-write=./blobs --allow-ffi --env-file src/index.ts", 5 + "lexgen": "deno run --allow-env --allow-sys --allow-read=.. --allow-write=./src/lexicons --no-prompt @atcute/lex-cli generate -c ./lex.config.js && cat ./src/lexicons/index.ts | sed \"s/.js/.ts/\" > ./src/lexicons/index.ts", 6 + "dk": "deno run -A --node-modules-dir npm:drizzle-kit" 5 7 }, 6 8 "imports": { 9 + "@atcute/cbor": "npm:@atcute/cbor@^2.2.6", 7 10 "@atcute/identity-resolver": "npm:@atcute/identity-resolver@^1.1.3", 8 11 "@atcute/atproto": "npm:@atcute/atproto@^3.1.4", 9 12 "@atcute/client": "npm:@atcute/client@^4.0.3", 10 13 "@atcute/lex-cli": "npm:@atcute/lex-cli@^2.2.0", 11 14 "@atcute/lexicons": "npm:@atcute/lexicons@^1.1.1", 12 - "@libsql/client": "npm:@libsql/client@^0.15.15" 15 + "@atproto-labs/fetch-node": "npm:@atproto-labs/fetch-node@^0.1.10", 16 + "@libsql/client": "npm:@libsql/client@^0.15.15", 17 + "drizzle-kit": "npm:drizzle-kit@^0.31.5", 18 + "drizzle-orm": "npm:drizzle-orm@^0.44.6" 13 19 }, 14 20 "unstable": ["raw-imports"] 15 21 }
+437 -2
server/deno.lock
··· 2 2 "version": "5", 3 3 "specifiers": { 4 4 "npm:@atcute/atproto@^3.1.4": "3.1.4", 5 + "npm:@atcute/cbor@^2.2.6": "2.2.6", 5 6 "npm:@atcute/client@^4.0.3": "4.0.3", 6 7 "npm:@atcute/identity-resolver@^1.1.3": "1.1.3_@atcute+identity@1.1.0", 7 8 "npm:@atcute/lex-cli@^2.2.0": "2.2.0_@badrap+valita@0.4.6", 8 9 "npm:@atcute/lexicons@^1.1.1": "1.1.1", 9 - "npm:@libsql/client@~0.15.15": "0.15.15" 10 + "npm:@atproto-labs/fetch-node@~0.1.10": "0.1.10", 11 + "npm:@libsql/client@~0.15.15": "0.15.15", 12 + "npm:drizzle-kit@*": "0.31.5_esbuild@0.25.10", 13 + "npm:drizzle-kit@~0.31.5": "0.31.5_esbuild@0.25.10", 14 + "npm:drizzle-orm@~0.44.6": "0.44.6_@libsql+client@0.15.15" 10 15 }, 11 16 "npm": { 12 17 "@atcute/atproto@3.1.4": { 13 18 "integrity": "sha512-v0/ue7mZYtjYw4vWbtda51bLwW88mqsUQB8F/UZNO18ANAQWmKq1HDceVqjvruaLe2QPqE43XM3WkEyZ2FhOrA==", 14 19 "dependencies": [ 15 20 "@atcute/lexicons" 21 + ] 22 + }, 23 + "@atcute/cbor@2.2.6": { 24 + "integrity": "sha512-pDfsn/vPTmgeXZiZdyc5vCGCPSxWlfTUIGFMCd5SroAgoLk1v9xxF7R/8+gt1lj1OKAwCwhS0doVmtLjqqzdbA==", 25 + "dependencies": [ 26 + "@atcute/cid", 27 + "@atcute/multibase", 28 + "@atcute/uint8array" 29 + ] 30 + }, 31 + "@atcute/cid@2.2.4": { 32 + "integrity": "sha512-6RUMyt7rp6KOSb4TWwifOZURnFrGgKqYyjVkYjiAcscZWgJpJxwoCUCdonxCfxhQtB0yJ+WlfqNXicGB+Pe94A==", 33 + "dependencies": [ 34 + "@atcute/multibase", 35 + "@atcute/uint8array" 16 36 ] 17 37 }, 18 38 "@atcute/client@4.0.3": { ··· 61 81 "esm-env" 62 82 ] 63 83 }, 84 + "@atcute/multibase@1.1.6": { 85 + "integrity": "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg==", 86 + "dependencies": [ 87 + "@atcute/uint8array" 88 + ] 89 + }, 90 + "@atcute/uint8array@1.0.5": { 91 + "integrity": "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q==" 92 + }, 64 93 "@atcute/util-fetch@1.0.1": { 65 94 "integrity": "sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow==", 66 95 "dependencies": [ 67 96 "@badrap/valita" 68 97 ] 69 98 }, 99 + "@atproto-labs/fetch-node@0.1.10": { 100 + "integrity": "sha512-o7hGaonA71A6p7O107VhM6UBUN/g9tTyYohMp1q0Kf6xQ4npnuZYRSHSf2g6reSfGQJ1GoFNjBObETTT1ge/jQ==", 101 + "dependencies": [ 102 + "@atproto-labs/fetch", 103 + "@atproto-labs/pipe", 104 + "ipaddr.js", 105 + "undici" 106 + ] 107 + }, 108 + "@atproto-labs/fetch@0.2.3": { 109 + "integrity": "sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==", 110 + "dependencies": [ 111 + "@atproto-labs/pipe" 112 + ] 113 + }, 114 + "@atproto-labs/pipe@0.1.1": { 115 + "integrity": "sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==" 116 + }, 70 117 "@badrap/valita@0.4.6": { 71 118 "integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==" 72 119 }, 120 + "@drizzle-team/brocli@0.10.2": { 121 + "integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==" 122 + }, 123 + "@esbuild-kit/core-utils@3.3.2": { 124 + "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==", 125 + "dependencies": [ 126 + "esbuild@0.18.20", 127 + "source-map-support" 128 + ], 129 + "deprecated": true 130 + }, 131 + "@esbuild-kit/esm-loader@2.6.5": { 132 + "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", 133 + "dependencies": [ 134 + "@esbuild-kit/core-utils", 135 + "get-tsconfig" 136 + ], 137 + "deprecated": true 138 + }, 139 + "@esbuild/aix-ppc64@0.25.10": { 140 + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", 141 + "os": ["aix"], 142 + "cpu": ["ppc64"] 143 + }, 144 + "@esbuild/android-arm64@0.18.20": { 145 + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", 146 + "os": ["android"], 147 + "cpu": ["arm64"] 148 + }, 149 + "@esbuild/android-arm64@0.25.10": { 150 + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", 151 + "os": ["android"], 152 + "cpu": ["arm64"] 153 + }, 154 + "@esbuild/android-arm@0.18.20": { 155 + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", 156 + "os": ["android"], 157 + "cpu": ["arm"] 158 + }, 159 + "@esbuild/android-arm@0.25.10": { 160 + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", 161 + "os": ["android"], 162 + "cpu": ["arm"] 163 + }, 164 + "@esbuild/android-x64@0.18.20": { 165 + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", 166 + "os": ["android"], 167 + "cpu": ["x64"] 168 + }, 169 + "@esbuild/android-x64@0.25.10": { 170 + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", 171 + "os": ["android"], 172 + "cpu": ["x64"] 173 + }, 174 + "@esbuild/darwin-arm64@0.18.20": { 175 + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", 176 + "os": ["darwin"], 177 + "cpu": ["arm64"] 178 + }, 179 + "@esbuild/darwin-arm64@0.25.10": { 180 + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", 181 + "os": ["darwin"], 182 + "cpu": ["arm64"] 183 + }, 184 + "@esbuild/darwin-x64@0.18.20": { 185 + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", 186 + "os": ["darwin"], 187 + "cpu": ["x64"] 188 + }, 189 + "@esbuild/darwin-x64@0.25.10": { 190 + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", 191 + "os": ["darwin"], 192 + "cpu": ["x64"] 193 + }, 194 + "@esbuild/freebsd-arm64@0.18.20": { 195 + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", 196 + "os": ["freebsd"], 197 + "cpu": ["arm64"] 198 + }, 199 + "@esbuild/freebsd-arm64@0.25.10": { 200 + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", 201 + "os": ["freebsd"], 202 + "cpu": ["arm64"] 203 + }, 204 + "@esbuild/freebsd-x64@0.18.20": { 205 + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", 206 + "os": ["freebsd"], 207 + "cpu": ["x64"] 208 + }, 209 + "@esbuild/freebsd-x64@0.25.10": { 210 + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", 211 + "os": ["freebsd"], 212 + "cpu": ["x64"] 213 + }, 214 + "@esbuild/linux-arm64@0.18.20": { 215 + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", 216 + "os": ["linux"], 217 + "cpu": ["arm64"] 218 + }, 219 + "@esbuild/linux-arm64@0.25.10": { 220 + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", 221 + "os": ["linux"], 222 + "cpu": ["arm64"] 223 + }, 224 + "@esbuild/linux-arm@0.18.20": { 225 + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", 226 + "os": ["linux"], 227 + "cpu": ["arm"] 228 + }, 229 + "@esbuild/linux-arm@0.25.10": { 230 + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", 231 + "os": ["linux"], 232 + "cpu": ["arm"] 233 + }, 234 + "@esbuild/linux-ia32@0.18.20": { 235 + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", 236 + "os": ["linux"], 237 + "cpu": ["ia32"] 238 + }, 239 + "@esbuild/linux-ia32@0.25.10": { 240 + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", 241 + "os": ["linux"], 242 + "cpu": ["ia32"] 243 + }, 244 + "@esbuild/linux-loong64@0.18.20": { 245 + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", 246 + "os": ["linux"], 247 + "cpu": ["loong64"] 248 + }, 249 + "@esbuild/linux-loong64@0.25.10": { 250 + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", 251 + "os": ["linux"], 252 + "cpu": ["loong64"] 253 + }, 254 + "@esbuild/linux-mips64el@0.18.20": { 255 + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", 256 + "os": ["linux"], 257 + "cpu": ["mips64el"] 258 + }, 259 + "@esbuild/linux-mips64el@0.25.10": { 260 + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", 261 + "os": ["linux"], 262 + "cpu": ["mips64el"] 263 + }, 264 + "@esbuild/linux-ppc64@0.18.20": { 265 + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", 266 + "os": ["linux"], 267 + "cpu": ["ppc64"] 268 + }, 269 + "@esbuild/linux-ppc64@0.25.10": { 270 + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", 271 + "os": ["linux"], 272 + "cpu": ["ppc64"] 273 + }, 274 + "@esbuild/linux-riscv64@0.18.20": { 275 + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", 276 + "os": ["linux"], 277 + "cpu": ["riscv64"] 278 + }, 279 + "@esbuild/linux-riscv64@0.25.10": { 280 + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", 281 + "os": ["linux"], 282 + "cpu": ["riscv64"] 283 + }, 284 + "@esbuild/linux-s390x@0.18.20": { 285 + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", 286 + "os": ["linux"], 287 + "cpu": ["s390x"] 288 + }, 289 + "@esbuild/linux-s390x@0.25.10": { 290 + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", 291 + "os": ["linux"], 292 + "cpu": ["s390x"] 293 + }, 294 + "@esbuild/linux-x64@0.18.20": { 295 + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", 296 + "os": ["linux"], 297 + "cpu": ["x64"] 298 + }, 299 + "@esbuild/linux-x64@0.25.10": { 300 + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", 301 + "os": ["linux"], 302 + "cpu": ["x64"] 303 + }, 304 + "@esbuild/netbsd-arm64@0.25.10": { 305 + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", 306 + "os": ["netbsd"], 307 + "cpu": ["arm64"] 308 + }, 309 + "@esbuild/netbsd-x64@0.18.20": { 310 + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", 311 + "os": ["netbsd"], 312 + "cpu": ["x64"] 313 + }, 314 + "@esbuild/netbsd-x64@0.25.10": { 315 + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", 316 + "os": ["netbsd"], 317 + "cpu": ["x64"] 318 + }, 319 + "@esbuild/openbsd-arm64@0.25.10": { 320 + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", 321 + "os": ["openbsd"], 322 + "cpu": ["arm64"] 323 + }, 324 + "@esbuild/openbsd-x64@0.18.20": { 325 + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", 326 + "os": ["openbsd"], 327 + "cpu": ["x64"] 328 + }, 329 + "@esbuild/openbsd-x64@0.25.10": { 330 + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", 331 + "os": ["openbsd"], 332 + "cpu": ["x64"] 333 + }, 334 + "@esbuild/openharmony-arm64@0.25.10": { 335 + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", 336 + "os": ["openharmony"], 337 + "cpu": ["arm64"] 338 + }, 339 + "@esbuild/sunos-x64@0.18.20": { 340 + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", 341 + "os": ["sunos"], 342 + "cpu": ["x64"] 343 + }, 344 + "@esbuild/sunos-x64@0.25.10": { 345 + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", 346 + "os": ["sunos"], 347 + "cpu": ["x64"] 348 + }, 349 + "@esbuild/win32-arm64@0.18.20": { 350 + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", 351 + "os": ["win32"], 352 + "cpu": ["arm64"] 353 + }, 354 + "@esbuild/win32-arm64@0.25.10": { 355 + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", 356 + "os": ["win32"], 357 + "cpu": ["arm64"] 358 + }, 359 + "@esbuild/win32-ia32@0.18.20": { 360 + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", 361 + "os": ["win32"], 362 + "cpu": ["ia32"] 363 + }, 364 + "@esbuild/win32-ia32@0.25.10": { 365 + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", 366 + "os": ["win32"], 367 + "cpu": ["ia32"] 368 + }, 369 + "@esbuild/win32-x64@0.18.20": { 370 + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", 371 + "os": ["win32"], 372 + "cpu": ["x64"] 373 + }, 374 + "@esbuild/win32-x64@0.25.10": { 375 + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", 376 + "os": ["win32"], 377 + "cpu": ["x64"] 378 + }, 73 379 "@externdefs/collider@0.3.0_@badrap+valita@0.4.6": { 74 380 "integrity": "sha512-x5CpeZ4c8n+1wMFthUMWSQKqCGcQo52/Qbda5ES+JFRRg/D8Ep6/JOvUUq5HExFuv/wW+6UYG2U/mXzw0IAd8Q==", 75 381 "dependencies": [ ··· 171 477 "@types/node" 172 478 ] 173 479 }, 480 + "buffer-from@1.1.2": { 481 + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" 482 + }, 174 483 "data-uri-to-buffer@4.0.1": { 175 484 "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" 176 485 }, 486 + "debug@4.4.3": { 487 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 488 + "dependencies": [ 489 + "ms" 490 + ] 491 + }, 177 492 "detect-libc@2.0.2": { 178 493 "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" 179 494 }, 495 + "drizzle-kit@0.31.5_esbuild@0.25.10": { 496 + "integrity": "sha512-+CHgPFzuoTQTt7cOYCV6MOw2w8vqEn/ap1yv4bpZOWL03u7rlVRQhUY0WYT3rHsgVTXwYQDZaSUJSQrMBUKuWg==", 497 + "dependencies": [ 498 + "@drizzle-team/brocli", 499 + "@esbuild-kit/esm-loader", 500 + "esbuild@0.25.10", 501 + "esbuild-register" 502 + ], 503 + "bin": true 504 + }, 505 + "drizzle-orm@0.44.6_@libsql+client@0.15.15": { 506 + "integrity": "sha512-uy6uarrrEOc9K1u5/uhBFJbdF5VJ5xQ/Yzbecw3eAYOunv5FDeYkR2m8iitocdHBOHbvorviKOW5GVw0U1j4LQ==", 507 + "dependencies": [ 508 + "@libsql/client" 509 + ], 510 + "optionalPeers": [ 511 + "@libsql/client" 512 + ] 513 + }, 514 + "esbuild-register@3.6.0_esbuild@0.25.10": { 515 + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", 516 + "dependencies": [ 517 + "debug", 518 + "esbuild@0.25.10" 519 + ] 520 + }, 521 + "esbuild@0.18.20": { 522 + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", 523 + "optionalDependencies": [ 524 + "@esbuild/android-arm@0.18.20", 525 + "@esbuild/android-arm64@0.18.20", 526 + "@esbuild/android-x64@0.18.20", 527 + "@esbuild/darwin-arm64@0.18.20", 528 + "@esbuild/darwin-x64@0.18.20", 529 + "@esbuild/freebsd-arm64@0.18.20", 530 + "@esbuild/freebsd-x64@0.18.20", 531 + "@esbuild/linux-arm@0.18.20", 532 + "@esbuild/linux-arm64@0.18.20", 533 + "@esbuild/linux-ia32@0.18.20", 534 + "@esbuild/linux-loong64@0.18.20", 535 + "@esbuild/linux-mips64el@0.18.20", 536 + "@esbuild/linux-ppc64@0.18.20", 537 + "@esbuild/linux-riscv64@0.18.20", 538 + "@esbuild/linux-s390x@0.18.20", 539 + "@esbuild/linux-x64@0.18.20", 540 + "@esbuild/netbsd-x64@0.18.20", 541 + "@esbuild/openbsd-x64@0.18.20", 542 + "@esbuild/sunos-x64@0.18.20", 543 + "@esbuild/win32-arm64@0.18.20", 544 + "@esbuild/win32-ia32@0.18.20", 545 + "@esbuild/win32-x64@0.18.20" 546 + ], 547 + "scripts": true, 548 + "bin": true 549 + }, 550 + "esbuild@0.25.10": { 551 + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", 552 + "optionalDependencies": [ 553 + "@esbuild/aix-ppc64", 554 + "@esbuild/android-arm@0.25.10", 555 + "@esbuild/android-arm64@0.25.10", 556 + "@esbuild/android-x64@0.25.10", 557 + "@esbuild/darwin-arm64@0.25.10", 558 + "@esbuild/darwin-x64@0.25.10", 559 + "@esbuild/freebsd-arm64@0.25.10", 560 + "@esbuild/freebsd-x64@0.25.10", 561 + "@esbuild/linux-arm@0.25.10", 562 + "@esbuild/linux-arm64@0.25.10", 563 + "@esbuild/linux-ia32@0.25.10", 564 + "@esbuild/linux-loong64@0.25.10", 565 + "@esbuild/linux-mips64el@0.25.10", 566 + "@esbuild/linux-ppc64@0.25.10", 567 + "@esbuild/linux-riscv64@0.25.10", 568 + "@esbuild/linux-s390x@0.25.10", 569 + "@esbuild/linux-x64@0.25.10", 570 + "@esbuild/netbsd-arm64", 571 + "@esbuild/netbsd-x64@0.25.10", 572 + "@esbuild/openbsd-arm64", 573 + "@esbuild/openbsd-x64@0.25.10", 574 + "@esbuild/openharmony-arm64", 575 + "@esbuild/sunos-x64@0.25.10", 576 + "@esbuild/win32-arm64@0.25.10", 577 + "@esbuild/win32-ia32@0.25.10", 578 + "@esbuild/win32-x64@0.25.10" 579 + ], 580 + "scripts": true, 581 + "bin": true 582 + }, 180 583 "esm-env@1.2.2": { 181 584 "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==" 182 585 }, ··· 193 596 "fetch-blob" 194 597 ] 195 598 }, 599 + "get-tsconfig@4.10.1": { 600 + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", 601 + "dependencies": [ 602 + "resolve-pkg-maps" 603 + ] 604 + }, 605 + "ipaddr.js@2.2.0": { 606 + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==" 607 + }, 196 608 "js-base64@3.7.8": { 197 609 "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==" 198 610 }, ··· 216 628 "os": ["darwin", "linux", "win32"], 217 629 "cpu": ["x64", "arm64", "wasm32", "arm"] 218 630 }, 631 + "ms@2.1.3": { 632 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 633 + }, 219 634 "node-domexception@1.0.0": { 220 635 "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 221 636 "deprecated": true ··· 238 653 "promise-limit@2.7.0": { 239 654 "integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==" 240 655 }, 656 + "resolve-pkg-maps@1.0.0": { 657 + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==" 658 + }, 659 + "source-map-support@0.5.21": { 660 + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 661 + "dependencies": [ 662 + "buffer-from", 663 + "source-map" 664 + ] 665 + }, 666 + "source-map@0.6.1": { 667 + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 668 + }, 241 669 "undici-types@7.10.0": { 242 670 "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" 671 + }, 672 + "undici@6.22.0": { 673 + "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==" 243 674 }, 244 675 "web-streams-polyfill@3.3.3": { 245 676 "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" ··· 251 682 "workspace": { 252 683 "dependencies": [ 253 684 "npm:@atcute/atproto@^3.1.4", 685 + "npm:@atcute/cbor@^2.2.6", 254 686 "npm:@atcute/client@^4.0.3", 255 687 "npm:@atcute/identity-resolver@^1.1.3", 256 688 "npm:@atcute/lex-cli@^2.2.0", 257 689 "npm:@atcute/lexicons@^1.1.1", 258 - "npm:@libsql/client@~0.15.15" 690 + "npm:@atproto-labs/fetch-node@~0.1.10", 691 + "npm:@libsql/client@~0.15.15", 692 + "npm:drizzle-kit@~0.31.5", 693 + "npm:drizzle-orm@~0.44.6" 259 694 ] 260 695 } 261 696 }
+10
server/drizzle.config.ts
··· 1 + import { defineConfig } from "drizzle-kit"; 2 + 3 + export default defineConfig({ 4 + out: "./drizzle", 5 + schema: "./src/db/schema.ts", 6 + dialect: "sqlite", 7 + dbCredentials: { 8 + url: Deno.env.get("DB_FILE_NAME")!, 9 + }, 10 + });
-22
server/lex/dev.atcities.route.json
··· 1 - { 2 - "lexicon": 1, 3 - "id": "dev.atcities.route", 4 - "description": "Define the route for a given page. Page content is a blob", 5 - "defs": { 6 - "main": { 7 - "type": "record", 8 - "description": "Page URL maps directly to a record key", 9 - "key": "any", 10 - "record": { 11 - "type": "object", 12 - "properties": { 13 - "page": { 14 - "type": "blob", 15 - "accept": ["*/*"] 16 - } 17 - }, 18 - "required": ["page"] 19 - } 20 - } 21 - } 22 - }
+1 -1
server/lex.config.js
··· 1 1 import { defineLexiconConfig } from "@atcute/lex-cli"; 2 2 3 3 export default defineLexiconConfig({ 4 - files: ["lex/**/*.json"], 4 + files: ["../lexicons/**/*.json"], 5 5 outdir: "src/lexicons/", 6 6 });
+44
server/src/backfill/blob.ts
··· 1 + import { Client } from "@atcute/client"; 2 + import { fetchHandler, getPds, MAX_SITE_SIZE } from "../utils.ts"; 3 + 4 + export default async function ( 5 + did: `did:${"plc" | "web"}:${string}`, 6 + cid: string 7 + ): Promise<Blob> { 8 + // if the user has been manually taken down (cache dir deleted and replaced with empty file) 9 + // this errors out for quick exit 10 + // saving the round trip to resolve the pds and blob. 11 + await Deno.mkdir(`./blobs/${did}`, { recursive: true }); 12 + 13 + const pds = await getPds(did); 14 + if (!pds) throw "PDS not found"; 15 + 16 + const { data, ok } = await new Client({ 17 + handler: fetchHandler({ service: pds }), 18 + }).get("com.atproto.sync.getBlob", { 19 + params: { 20 + did, 21 + cid, 22 + }, 23 + as: "blob", 24 + }); 25 + 26 + if (!ok) throw `${data.error}`; 27 + 28 + // if the file size cant be calculated or the file cant be written, still return the blob 29 + try { 30 + let size = 0; 31 + for await (const file of Deno.readDir(`./blobs/${did}`)) { 32 + size += (await Deno.stat(`./blobs/${did}/${file.name}`)).size; 33 + } 34 + // only write if total stays below max site size 35 + if (size + data.size <= MAX_SITE_SIZE) 36 + await Deno.writeFile(`./blobs/${did}/${cid}`, await data.bytes(), { 37 + createNew: true, 38 + }); 39 + } catch (e) { 40 + console.warn(e); 41 + } 42 + 43 + return data; 44 + }
+25
server/src/backfill/index.ts
··· 1 + import { drizzle } from "drizzle-orm/libsql"; 2 + import { routes } from "../db/schema.ts"; 3 + import * as schema from "../db/schema.ts"; 4 + import { db as db_type } from "../utils.ts"; 5 + import oldRecords from "./old-records.ts"; 6 + import newRecords from "./new-records.ts"; 7 + 8 + const db: db_type = drizzle<typeof schema>( 9 + Deno.env.get("DB_FILE_NAME")! || 10 + (() => { 11 + throw "DB_FILE_NAME not set"; 12 + })() 13 + ); 14 + 15 + // clear old records & blobs 16 + // accounts could have deleted their sites or anything 17 + // so we should just nuke them 18 + // blobs could be kept but would be a nightmare 19 + await db.delete(routes); 20 + await Deno.remove("./blobs", { recursive: true }); 21 + 22 + oldRecords(db); 23 + newRecords(db); 24 + 25 + export default db;
+188
server/src/backfill/new-records.ts
··· 1 + import { db, getPds, isDid, rkeyToUrl, fetchHandler } from "../utils.ts"; 2 + import { decodeFirst } from "@atcute/cbor"; 3 + import { DevAtcitiesRoute } from "../lexicons/index.ts"; 4 + import { is } from "@atcute/lexicons"; 5 + import { ComAtprotoSyncSubscribeRepos } from "@atcute/atproto"; 6 + import { Client } from "@atcute/client"; 7 + import { routes } from "../db/schema.ts"; 8 + import { and, eq } from "drizzle-orm"; 9 + 10 + const ErrorEvent = Symbol("error event"); 11 + export default function newRecords(db: db) { 12 + // https://pdsls.dev/at://did:plc:6msi3pj7krzih5qxqtryxlzw/com.atproto.lexicon.schema/com.atproto.sync.subscribeRepos 13 + const ws = new WebSocket( 14 + `${ 15 + Deno.env.get("ATPROTO_RELAY") || 16 + (() => { 17 + throw "ATPROTO_RELAY not set"; 18 + })() 19 + }/xrpc/com.atproto.sync.subscribeRepos` 20 + ); 21 + 22 + ws.addEventListener("close", (ev) => { 23 + throw ev; 24 + }); 25 + ws.addEventListener("error", (ev) => { 26 + throw ev; 27 + }); 28 + ws.addEventListener("open", () => console.log("Listening for new events.")); 29 + 30 + try { 31 + ws.addEventListener("message", async (ev) => { 32 + if (ev.data instanceof Blob) { 33 + try { 34 + const [header, remainder] = decodeFirst(await ev.data.bytes()); 35 + const [payload] = decodeFirst(remainder); 36 + // https://atproto.com/specs/event-stream#framing 37 + if (typeof header !== "object" || !header) return; 38 + if (!("op" in header) || typeof header.op !== "number") return; 39 + if (header.op === -1) { 40 + console.error(header); 41 + ws.close(); 42 + throw ErrorEvent; 43 + } 44 + 45 + // we only care about commits 46 + // identity events and similar are irrelevant 47 + if (!is(ComAtprotoSyncSubscribeRepos.commitSchema, payload)) { 48 + return; 49 + } 50 + if (!isDid(payload.repo)) { 51 + console.warn("Invalid did:", payload.repo); 52 + return; 53 + } 54 + const pds = await getPds(payload.repo); 55 + if (!pds) { 56 + return; 57 + } 58 + 59 + const client = new Client({ 60 + handler: fetchHandler({ 61 + service: pds, 62 + }), 63 + }); 64 + 65 + for (const op of payload.ops) { 66 + const [collection, rkey] = op.path.split("/"); 67 + if (!collection || !rkey) { 68 + console.warn("Invalid path", op.path); 69 + continue; 70 + } 71 + const path = rkeyToUrl(rkey); 72 + if (!path) continue; 73 + if (collection !== "dev.atcities.route") continue; 74 + 75 + switch (op.action) { 76 + case "create": 77 + case "update": { 78 + // hydrate data 79 + const { data, ok } = await client.get( 80 + "com.atproto.repo.getRecord", 81 + { 82 + params: { 83 + repo: payload.repo, 84 + collection: "dev.atcities.route", 85 + rkey, 86 + }, 87 + } 88 + ); 89 + 90 + if (!ok) { 91 + console.warn(data); 92 + continue; 93 + } 94 + 95 + if (!is(DevAtcitiesRoute.mainSchema, data.value)) { 96 + console.warn( 97 + "Invalid record:", 98 + `at://${payload.repo}/dev.atcities.route.${rkey}` 99 + ); 100 + continue; 101 + } 102 + 103 + if (data.value.page.$type !== "dev.atcities.route#blob") { 104 + continue; 105 + } 106 + 107 + // if this page exists in db, get the id so it can be replaced 108 + const id = ( 109 + await db 110 + .select({ 111 + id: routes.id, 112 + }) 113 + .from(routes) 114 + .where( 115 + and( 116 + eq(routes.did, payload.repo), 117 + eq(routes.url_route, path) 118 + ) 119 + ) 120 + ).at(0); 121 + 122 + await db.insert(routes).values({ 123 + did: payload.repo, 124 + url_route: path, 125 + id: id ? id.id : undefined, 126 + blob_cid: 127 + "ref" in data.value.page.blob 128 + ? data.value.page.blob.ref.$link 129 + : data.value.page.blob.cid, 130 + mime: data.value.page.blob.mimeType, 131 + }); 132 + 133 + continue; 134 + } 135 + case "delete": { 136 + const deleted = ( 137 + await db 138 + .select({ 139 + id: routes.id, 140 + cid: routes.blob_cid, 141 + }) 142 + .from(routes) 143 + .where( 144 + and( 145 + eq(routes.did, payload.repo), 146 + eq(routes.url_route, path) 147 + ) 148 + ) 149 + ).at(0); 150 + if (!deleted) continue; 151 + 152 + await db.delete(routes).where(eq(routes.id, deleted.id)); 153 + 154 + const cidInUse = 155 + ( 156 + await db 157 + .select({}) 158 + .from(routes) 159 + .where(eq(routes.blob_cid, deleted.cid)) 160 + ).length > 0; 161 + 162 + // purge cid if not in use 163 + if (!cidInUse) 164 + Deno.remove(`./blobs/${payload.repo}/${deleted.cid}`); 165 + 166 + continue; 167 + } 168 + } 169 + } 170 + } catch (e) { 171 + if (Error.isError(e)) { 172 + console.warn( 173 + "Invalid DAG-CBOR data:", 174 + e.name, 175 + e.message, 176 + e.cause, 177 + e.stack 178 + ); 179 + } else throw e; 180 + } 181 + } 182 + }); 183 + } catch (e) { 184 + // if and only if an error message was recived, reopen the connection 185 + if (e === ErrorEvent) newRecords(db); 186 + else throw e; 187 + } 188 + }
+96
server/src/backfill/old-records.ts
··· 1 + import { Client } from "@atcute/client"; 2 + import { db, fetchHandler, getPds, isDid, rkeyToUrl } from "../utils.ts"; 3 + import { is } from "@atcute/lexicons"; 4 + import { DevAtcitiesRoute } from "../lexicons/index.ts"; 5 + import { routes } from "../db/schema.ts"; 6 + 7 + async function indexUser(did: `did:${"web" | "plc"}:${string}`, db: db) { 8 + const pds = await getPds(did); 9 + if (!pds) return console.error(did, "could not be resolved to a pds."); 10 + const pdsClient = new Client({ 11 + handler: fetchHandler({ service: pds }), 12 + }); 13 + 14 + let cursor: string | undefined; 15 + while (true) { 16 + const { data, ok } = await pdsClient.get("com.atproto.repo.listRecords", { 17 + params: { 18 + repo: did, 19 + collection: "dev.atcities.route", 20 + cursor, 21 + }, 22 + }); 23 + 24 + if (!ok) { 25 + console.error("Got error:", data.error, data.message); 26 + break; 27 + } 28 + 29 + for (const record of data.records) { 30 + if (is(DevAtcitiesRoute.mainSchema, record.value)) { 31 + // ignore non blob page values 32 + // this will be expanded in future 33 + if (record.value.page.$type === "dev.atcities.route#blob") { 34 + const url = rkeyToUrl(record.uri.split("/")[4]); 35 + if (!url) continue; 36 + const data: typeof routes.$inferInsert = { 37 + did: did, 38 + url_route: url, 39 + blob_cid: 40 + "ref" in record.value.page.blob 41 + ? record.value.page.blob.ref.$link 42 + : record.value.page.blob.cid, 43 + mime: record.value.page.blob.mimeType, 44 + }; 45 + await db.insert(routes).values(data); 46 + } 47 + } else console.warn("Invalid record:", record.uri); 48 + } 49 + 50 + cursor = data.cursor; 51 + if (!cursor) break; 52 + } 53 + } 54 + 55 + export default async function (db: db) { 56 + const relay = new Client({ 57 + handler: fetchHandler({ 58 + service: 59 + Deno.env.get("ATPROTO_RELAY") || 60 + (() => { 61 + throw "ATPROTO_RELAY not set"; 62 + })(), 63 + }), 64 + }); 65 + 66 + let repos: `did:${string}:${string}`[] = []; 67 + let cursor: string | undefined; 68 + while (true) { 69 + const { data, ok } = await relay.get( 70 + "com.atproto.sync.listReposByCollection", 71 + { 72 + params: { 73 + collection: "dev.atcities.route", 74 + cursor, 75 + }, 76 + } 77 + ); 78 + 79 + if (!ok) { 80 + throw data.error + "\n" + data.message; 81 + } 82 + 83 + repos = [...repos, ...data.repos.map((x) => x.did)]; 84 + cursor = data.cursor; 85 + if (!cursor) break; 86 + } 87 + 88 + const pending: Promise<unknown>[] = []; 89 + for (const i in repos) { 90 + const did = repos[i]; 91 + console.log(`indexing ${Number(i) + 1}/${repos.length} ${did}`); 92 + if (isDid(did)) pending.push(indexUser(did, db)); 93 + } 94 + await Promise.all(pending); 95 + console.log("Finished backfilling."); 96 + }
+9
server/src/db/schema.ts
··· 1 + import { int, sqliteTable, text } from "drizzle-orm/sqlite-core"; 2 + 3 + export const routes = sqliteTable("routes", { 4 + id: int("id").primaryKey({ autoIncrement: true }), 5 + did: text("did").notNull(), 6 + url_route: text("url_route").notNull(), 7 + blob_cid: text("blob_cid").notNull(), 8 + mime: text("mime").notNull(), 9 + });
+23 -44
server/src/index.ts
··· 1 - import root from "./root.ts"; 2 - import user from "./user.ts"; 3 - 4 - const ROOT_DOMAIN = Deno.env.get("HOSTNAME") || "localhost"; 5 - const PORT = Number(Deno.env.get("PORT")) || 80; 1 + import root from "./routes/root.ts"; 2 + import user from "./routes/user.ts"; 3 + import backfill from "./backfill/index.ts"; 4 + import { clearCookies, PORT, ROOT_DOMAIN, SUBDOMAIN_REGEX } from "./utils.ts"; 6 5 7 - const SUBDOMAIN_REGEX = new RegExp(`.+(?=\\.${ROOT_DOMAIN}$)`, "gm"); 8 - 9 - function clearCookies(req: Request): Headers { 10 - const cookie_header = req.headers.get("Cookie"); 11 - // cookies are unset so return empty headers 12 - if (!cookie_header) return new Headers(); 13 - // get each kv pair and extract the key 14 - const cookies = cookie_header.split("; ").map((x) => x.split("=")[0]); 15 - const head = new Headers(); 16 - for (const key of cookies) { 17 - // max-age <= 0 means instant expiry .: deleted instantly 18 - head.append("Set-Cookie", `${key}=; Max-Age=-1`); 19 - } 20 - return head; 21 - } 6 + const db = await backfill; 22 7 23 8 Deno.serve({ port: PORT, hostname: ROOT_DOMAIN }, async (req) => { 24 9 const reqUrl = new URL(req.url); ··· 41 26 // did:plc example: `sjkdgfjk.did-plc.ROOT_DOMAIN` 42 27 // did:web example: `vielle.dev.did-web.ROOT_DOMAIN 43 28 // last segment must be did-plc or did-web 44 - if (subdomain.at(-1)?.match(/^did-(web|plc)+$/gm)) { 45 - const res = await user(req, { 46 - did: `did:${subdomain.at(-1) === "did-plc" ? "plc" : "web"}:${subdomain.slice(0, -1).join(".")}`, 47 - }); 48 - return new Response(res.body, { 49 - ...res, 50 - headers: { 51 - ...Array.from(res.headers.entries()).reduce( 52 - (acc, [k, v]) => ({ ...acc, [k]: v }), 53 - {} 54 - ), 55 - ...clearCookies(req), 56 - }, 57 - }); 58 - } 59 - 29 + const isDidSubdomain = !!subdomain.at(-1)?.match(/^did-(web|plc)+$/gm); 60 30 // ex: vielle.dev.ROOT_DOMAIN 61 31 // cannot contain hyphen in top level domain 62 - if (!subdomain.at(-1)?.startsWith("did-") && subdomain.length > 1) { 63 - const res = await user(req, { 64 - handle: subdomain.join(".") as `${string}.${string}`, 65 - }); 32 + const isHandleSubdomain = !isDidSubdomain && subdomain.length > 1; 33 + 34 + if (isDidSubdomain || isHandleSubdomain) { 35 + const res: Response = await user( 36 + db, 37 + req, 38 + isDidSubdomain 39 + ? { 40 + did: `did:${subdomain.at(-1) === "did-plc" ? "plc" : "web"}:${subdomain 41 + .slice(0, -1) 42 + .join(".")}`, 43 + } 44 + : { 45 + handle: subdomain.join(".") as `${string}.${string}`, 46 + } 47 + ); 66 48 return new Response(res.body, { 67 49 ...res, 68 50 headers: { 69 - ...Array.from(res.headers.entries()).reduce( 70 - (acc, [k, v]) => ({ ...acc, [k]: v }), 71 - {} 72 - ), 51 + ...res.headers, 73 52 ...clearCookies(req), 74 53 }, 75 54 });
+13 -1
server/src/lexicons/types/dev/atcities/route.ts
··· 2 2 import * as v from "@atcute/lexicons/validations"; 3 3 import type {} from "@atcute/lexicons/ambient"; 4 4 5 + const _blobSchema = /*#__PURE__*/ v.object({ 6 + $type: /*#__PURE__*/ v.optional( 7 + /*#__PURE__*/ v.literal("dev.atcities.route#blob"), 8 + ), 9 + blob: /*#__PURE__*/ v.blob(), 10 + }); 5 11 const _mainSchema = /*#__PURE__*/ v.record( 6 12 /*#__PURE__*/ v.string(), 7 13 /*#__PURE__*/ v.object({ 8 14 $type: /*#__PURE__*/ v.literal("dev.atcities.route"), 9 - page: /*#__PURE__*/ v.blob(), 15 + get page() { 16 + return /*#__PURE__*/ v.variant([blobSchema]); 17 + }, 10 18 }), 11 19 ); 12 20 21 + type blob$schematype = typeof _blobSchema; 13 22 type main$schematype = typeof _mainSchema; 14 23 24 + export interface blobSchema extends blob$schematype {} 15 25 export interface mainSchema extends main$schematype {} 16 26 27 + export const blobSchema = _blobSchema as blobSchema; 17 28 export const mainSchema = _mainSchema as mainSchema; 18 29 30 + export interface Blob extends v.InferInput<typeof blobSchema> {} 19 31 export interface Main extends v.InferInput<typeof mainSchema> {} 20 32 21 33 declare module "@atcute/lexicons/ambient" {
-13
server/src/root.ts
··· 1 - import index from "./www/index.html" with { type: "text" }; 2 - 3 - export default function (req: Request) { 4 - if (new URL(req.url).pathname === "/") 5 - return new Response(index, { 6 - headers: { 7 - "Content-Type": "text/html; charset=utf8", 8 - }, 9 - }); 10 - return new Response("404", { 11 - status: 404, 12 - }); 13 - }
+4
server/src/routes/ascii.txt
··· 1 + , | 2 + |\ -+-- 3 + |_\ | 4 + \\ \_/ ://cities
+38
server/src/routes/root.ts
··· 1 + import { ROOT_DOMAIN } from "../utils.ts"; 2 + import index from "../www/index.html" with { type: "text" }; 3 + import ascii from "./ascii.txt" with { type: "text" }; 4 + 5 + function route( 6 + path: string, 7 + callback: (req: Request) => Response 8 + ): { 9 + test: (path: string) => boolean; 10 + fn: (req: Request) => Response; 11 + } { 12 + const pattern = new URLPattern(path, `https://www.${ROOT_DOMAIN}`); 13 + return { 14 + test: (path) => pattern.test(path, `https://www.${ROOT_DOMAIN}`), 15 + fn: callback, 16 + }; 17 + } 18 + 19 + const routes = [ 20 + route( 21 + "/", 22 + () => 23 + new Response(index, { 24 + headers: { 25 + "Content-Type": "text/html; charset=utf8", 26 + }, 27 + }) 28 + ), 29 + route("/ascii.txt", () => new Response(ascii)), 30 + ]; 31 + 32 + export default function (req: Request) { 33 + const path = new URL(req.url).pathname; 34 + for (const r of routes) if (r.test(path)) return r.fn(req); 35 + return new Response("404", { 36 + status: 404, 37 + }); 38 + }
+116
server/src/routes/user.ts
··· 1 + /// <reference types="@atcute/atproto" /> 2 + import { 3 + CompositeHandleResolver, 4 + DohJsonHandleResolver, 5 + WellKnownHandleResolver, 6 + } from "@atcute/identity-resolver"; 7 + import { and, eq } from "drizzle-orm"; 8 + import { routes } from "../db/schema.ts"; 9 + import { type db, isDid, ROOT_DOMAIN } from "../utils.ts"; 10 + import ascii from "./ascii.txt" with { type: "text" }; 11 + import storeBlob from "../backfill/blob.ts"; 12 + 13 + const handleResolver = new CompositeHandleResolver({ 14 + strategy: "race", 15 + methods: { 16 + dns: new DohJsonHandleResolver({ 17 + dohUrl: "https://mozilla.cloudflare-dns.com/dns-query", 18 + }), 19 + http: new WellKnownHandleResolver(), 20 + }, 21 + }); 22 + 23 + export default async function ( 24 + db: db, 25 + req: Request, 26 + user: 27 + | { handle: `${string}.${string}` } 28 + | { did: `did:plc:${string}` | `did:web:${string}` } 29 + ): Promise<Response> { 30 + // if handle: resolve did 31 + let did: `did:${"plc" | "web"}:${string}`; 32 + if ("handle" in user) { 33 + try { 34 + // cast bc i know it will be `string.string` 35 + did = await handleResolver.resolve(user.handle); 36 + } catch { 37 + return new Response( 38 + `${ascii} 39 + 40 + This handle could not be resolved. 41 + `, 42 + { 43 + status: 500, 44 + statusText: "Internal Server Error", 45 + } 46 + ); 47 + } 48 + } else did = user.did; 49 + 50 + // look up in db 51 + const db_res = 52 + ( 53 + await db 54 + .select() 55 + .from(routes) 56 + .where( 57 + and( 58 + eq(routes.did, did), 59 + eq(routes.url_route, new URL(req.url).pathname) 60 + ) 61 + ) 62 + ).at(0) ?? 63 + ( 64 + await db 65 + .select() 66 + .from(routes) 67 + .where(and(eq(routes.did, did), eq(routes.url_route, "404"))) 68 + ).at(0); 69 + 70 + if (!db_res) { 71 + return new Response(`${ascii} 72 + 73 + 404: The user has no atcities site or is missing a 404 page. 74 + 75 + If you're the owner of this account, head to https://atcities.dev/ for more information. 76 + The index of this account is at https://${ 77 + "handle" in user 78 + ? user.handle 79 + : user.did.split(":").at(-1) + ".did-" + user.did.split(":").at(1) 80 + }.${ROOT_DOMAIN}/ 81 + `); 82 + } 83 + try { 84 + const file = await Deno.readFile( 85 + `./blobs/${db_res.did}/${db_res.blob_cid}` 86 + ); 87 + return new Response(file, { 88 + headers: { 89 + "Content-Type": db_res.mime, 90 + }, 91 + }); 92 + } catch { 93 + if (!isDid(db_res.did)) 94 + return new Response(`${ascii} 95 + 96 + ${db_res.did} is not a valid DID. This account could not be resolved 97 + `); 98 + try { 99 + const blob = await storeBlob(db_res.did, db_res.blob_cid); 100 + return new Response(blob, { 101 + headers: { 102 + "Content-Type": db_res.mime, 103 + }, 104 + }); 105 + } catch (e) { 106 + console.error(e); 107 + return new Response(`${ascii} 108 + 109 + This page could not be resolved. Either: 110 + - The user has no PDS 111 + - The blob does not exist 112 + - The user has been manually hidden for uploading illegal content. 113 + `); 114 + } 115 + } 116 + }
-294
server/src/user.ts
··· 1 - /// <reference types="@atcute/atproto" /> 2 - import { Client, simpleFetchHandler } from "@atcute/client"; 3 - import { is } from "@atcute/lexicons"; 4 - import { 5 - CompositeHandleResolver, 6 - DohJsonHandleResolver, 7 - WellKnownHandleResolver, 8 - CompositeDidDocumentResolver, 9 - PlcDidDocumentResolver, 10 - WebDidDocumentResolver, 11 - } from "@atcute/identity-resolver"; 12 - import { DevAtcitiesRoute } from "./lexicons/index.ts"; 13 - 14 - const handleResolver = new CompositeHandleResolver({ 15 - strategy: "race", 16 - methods: { 17 - dns: new DohJsonHandleResolver({ 18 - dohUrl: "https://mozilla.cloudflare-dns.com/dns-query", 19 - }), 20 - http: new WellKnownHandleResolver(), 21 - }, 22 - }); 23 - 24 - const docResolver = new CompositeDidDocumentResolver({ 25 - methods: { 26 - plc: new PlcDidDocumentResolver(), 27 - web: new WebDidDocumentResolver(), 28 - }, 29 - }); 30 - 31 - /** 32 - * given a valid url path string containing 33 - * - `/` for seperating characters 34 - * - a-zA-Z0-9 `-._~` as unreserved 35 - * - `!$&'()*+,;=` as reserved but valid in paths 36 - * - `:@` as neither reserved or unreserved but valid in paths 37 - * - %XX where X are hex digits for percent encoding 38 - * 39 - * we need to consistently and bidirectionally convert it into a string containing the characters A-Z, a-z, 0-9, `.-_:~` for an atproto rkey 40 - * A-Z a-z 0-9 are covered easily 41 - * we can also take -._~ as they are also unreserved 42 - * leaving : as a valid rkey character which looks nice for encoding 43 - * the uppercase versions MUST be used to prevent ambiguity 44 - * a colon which isnt followed by a valid character is an invalid rkey and should be ignored 45 - * - `/` `::` 46 - * - `%` `:~` 47 - * - `!` `:21` 48 - * - `$` `:24` 49 - * - `&` `:26` 50 - * - `'` `:27` 51 - * - `(` `:28` 52 - * - `)` `:29` 53 - * - `*` `:2A` 54 - * - `+` `:2B` 55 - * - `,` `:2C` 56 - * - `:` `:3A` 57 - * - `;` `:3B` 58 - * - `=` `:3D` 59 - * - `@` `:40` 60 - * @returns {string | undefined} undefined when input is invalid 61 - */ 62 - function urlToRkey(url: string): string | undefined { 63 - // contains 0-9A-Za-z + special valid chars and / seperator. also can contain %XX with XX being hex 64 - if (!url.match(/^([a-zA-Z0-9/\-._~!$&'()*+,;=:@]|(%[0-9a-fA-F]{2}))*$/gm)) 65 - return; 66 - return ( 67 - url 68 - // : replace is hoisted so it doesnt replace colons from elsewhere 69 - .replaceAll(":", ":3A") 70 - .replaceAll("/", "::") 71 - .replaceAll("%", ":~") 72 - .replaceAll("!", ":21") 73 - .replaceAll("$", ":24") 74 - .replaceAll("&", ":26") 75 - .replaceAll("'", ":27") 76 - .replaceAll("(", ":28") 77 - .replaceAll(")", ":29") 78 - .replaceAll("*", ":2A") 79 - .replaceAll("+", ":2B") 80 - .replaceAll(",", ":2C") 81 - .replaceAll(";", ":3B") 82 - .replaceAll("=", ":3D") 83 - .replaceAll("@", ":40") 84 - ); 85 - } 86 - 87 - /** 88 - * @see {@link urlToRkey} for rkey <=> url conversion syntax 89 - * @returns {string | undefined} undefined when input is invalid 90 - */ 91 - function rkeyToUrl(rkey: string): string | undefined { 92 - // contains 0-9A-Za-z .-_:~ 93 - if (!rkey.match(/^[A-Za-z0-9.\-_:~]*$/gm)) return; 94 - return rkey 95 - .replaceAll("::", "/") 96 - .replaceAll(":~", "%") 97 - .replaceAll(":21", "!") 98 - .replaceAll(":24", "$") 99 - .replaceAll(":26", "&") 100 - .replaceAll(":27", "'") 101 - .replaceAll(":28", "(") 102 - .replaceAll(":29", ")") 103 - .replaceAll(":2A", "*") 104 - .replaceAll(":2B", "+") 105 - .replaceAll(":2C", ",") 106 - .replaceAll(":3A", ":") 107 - .replaceAll(":3B", ";") 108 - .replaceAll(":3D", "=") 109 - .replaceAll(":40", "@"); 110 - } 111 - 112 - async function getRoute( 113 - did: `did:${"plc" | "web"}:${string}`, 114 - pds: string, 115 - route: string 116 - ): Promise<Response> { 117 - // get client to pds 118 - const client = new Client({ 119 - handler: simpleFetchHandler({ service: pds }), 120 - }); 121 - 122 - try { 123 - // note: / urls are reserved for special routes (404) 124 - // any path should be prefixed with a / 125 - // this is not enforced here so that this function can be used for special routes 126 - const targetRkey = urlToRkey(route); 127 - console.log("trying:", targetRkey, "for", route); 128 - 129 - if (!targetRkey) throw "invalid url"; 130 - 131 - const { ok: record_ok, data: record_data } = await client.get( 132 - "com.atproto.repo.getRecord", 133 - { 134 - params: { 135 - collection: "dev.atcities.route", 136 - repo: did, 137 - rkey: targetRkey, 138 - }, 139 - } 140 - ); 141 - 142 - if (!record_ok) { 143 - switch (record_data.error) { 144 - case "RecordNotFound": { 145 - // 404 error so try load 404 page 146 - if (route !== "404") { 147 - // try remove trailing / to see if that works 148 - // if that fails it'll get a 404 anyway 149 - if (route !== "/" && route.endsWith("/")) 150 - return new Response(undefined, { 151 - status: 308, 152 - statusText: "Permanent Redirect", 153 - headers: { 154 - Location: route.slice(0, -1), 155 - }, 156 - }); 157 - 158 - const r404 = await getRoute(did, pds, "404"); 159 - return new Response(r404.body, { 160 - status: 404, 161 - statusText: "Not Found", 162 - headers: r404.headers, 163 - }); 164 - } 165 - return new Response("Could not find page.", { 166 - status: 404, 167 - statusText: "Not Found", 168 - }); 169 - } 170 - // unless its a 404, internal error 171 - default: 172 - throw "Internal Error"; 173 - } 174 - } 175 - 176 - if (is(DevAtcitiesRoute.mainSchema, record_data.value)) { 177 - const { ok: blob_ok, data: blob_data } = await client.get( 178 - "com.atproto.sync.getBlob", 179 - { 180 - params: { 181 - did, 182 - cid: 183 - "ref" in record_data.value.page 184 - ? record_data.value.page.ref.$link 185 - : record_data.value.page.cid, 186 - }, 187 - as: "stream", 188 - } 189 - ); 190 - 191 - // possible errors include: 192 - // - request issue 193 - // - 404 not found 194 - // - account takedown 195 - // in all cases thats not recoverable 196 - // so throw out and take the happy path 197 - if (!blob_ok) { 198 - if (blob_data.error === "BlobNotFound") { 199 - // 404 error so try load 404 page 200 - if (route !== "404") { 201 - const r404 = await getRoute(did, pds, "404"); 202 - return new Response(r404.body, { 203 - status: 404, 204 - statusText: "Not Found", 205 - headers: r404.headers, 206 - }); 207 - } 208 - return new Response("Could not load page.", { 209 - status: 404, 210 - statusText: "Not Found", 211 - }); 212 - } else throw "Internal Error"; 213 - } 214 - 215 - return new Response(blob_data, { 216 - headers: { 217 - "Content-Type": record_data.value.page.mimeType, 218 - }, 219 - }); 220 - 221 - // isnt valid data so throw exception 222 - } else 223 - return new Response( 224 - "Malformed record for at://" + did + "/dev.atcities.route/" + targetRkey 225 - ); 226 - } catch (e) { 227 - console.error(e); 228 - return new Response("Something went wrong loading this route", { 229 - status: 500, 230 - statusText: "Internal Server Error", 231 - }); 232 - } 233 - } 234 - 235 - export default async function ( 236 - req: Request, 237 - user: 238 - | { handle: `${string}.${string}` } 239 - | { did: `did:plc:${string}` | `did:web:${string}` } 240 - ): Promise<Response> { 241 - // if handle: resolve did 242 - let did: `did:${"plc" | "web"}:${string}`; 243 - if ("handle" in user) { 244 - try { 245 - // cast bc i know it will be `string.string` 246 - did = await handleResolver.resolve(user.handle); 247 - } catch { 248 - return new Response("Failed to resolve handle", { 249 - status: 500, 250 - statusText: "Internal Server Error", 251 - }); 252 - } 253 - } else did = user.did; 254 - 255 - // resolve did doc 256 - let doc; 257 - try { 258 - doc = await docResolver.resolve(did); 259 - } catch { 260 - return new Response("Could not resolve " + did + ".\n", { 261 - status: 500, 262 - statusText: "Internal Server Error", 263 - }); 264 - } 265 - 266 - // handle must be in did document 267 - if ("handle" in user && !doc.alsoKnownAs?.includes(`at://${user.handle}`)) { 268 - return new Response( 269 - `Provided handle (at://${user.handle}) was not found in the did document for ${did}. Found handles:\n${doc.alsoKnownAs?.map((x) => "- " + x).join("\n") ?? "None"}`, 270 - { 271 - status: 500, 272 - statusText: "Internal Server Error", 273 - } 274 - ); 275 - } 276 - 277 - const pds = doc.service?.filter( 278 - (x) => 279 - x.id.endsWith("#atproto_pds") && 280 - x.type === "AtprotoPersonalDataServer" && 281 - typeof x.serviceEndpoint === "string" 282 - // cast as we type checked it above but it didnt acc apply? 283 - )[0].serviceEndpoint as string | undefined; 284 - if (!pds) 285 - return new Response( 286 - `Could not find a valid pds for ${"handle" in user ? user.handle : user.did}`, 287 - { 288 - status: 500, 289 - statusText: "Internal Server Error", 290 - } 291 - ); 292 - 293 - return await getRoute(did, pds, new URL(req.url).pathname); 294 - }
+165
server/src/utils.ts
··· 1 + import { LibSQLDatabase } from "drizzle-orm/libsql"; 2 + import { Client } from "@libsql/client"; 3 + import * as schema from "./db/schema.ts"; 4 + import { 5 + CompositeDidDocumentResolver, 6 + PlcDidDocumentResolver, 7 + WebDidDocumentResolver, 8 + } from "@atcute/identity-resolver"; 9 + import { FetchHandler, SimpleFetchHandlerOptions } from "@atcute/client"; 10 + import { safeFetchWrap } from "@atproto-labs/fetch-node"; 11 + 12 + export type db = LibSQLDatabase<typeof schema> & { 13 + $client: Client; 14 + }; 15 + 16 + export const ROOT_DOMAIN = Deno.env.get("HOSTNAME") || "localhost"; 17 + export const PORT = Number(Deno.env.get("PORT")) || 80; 18 + export const MAX_SITE_SIZE = Number(Deno.env.get("MAX_SITE_SIZE")) || 250000000; 19 + 20 + export const SUBDOMAIN_REGEX = new RegExp(`.+(?=\\.${ROOT_DOMAIN}$)`, "gm"); 21 + 22 + export function clearCookies(req: Request): Headers { 23 + const cookie_header = req.headers.get("Cookie"); 24 + // cookies are unset so return empty headers 25 + if (!cookie_header) return new Headers(); 26 + // get each kv pair and extract the key 27 + const cookies = cookie_header.split("; ").map((x) => x.split("=")[0]); 28 + const head = new Headers(); 29 + for (const key of cookies) { 30 + // max-age <= 0 means instant expiry .: deleted instantly 31 + head.append("Set-Cookie", `${key}=; Max-Age=-1`); 32 + } 33 + return head; 34 + } 35 + 36 + const docResolver = new CompositeDidDocumentResolver({ 37 + methods: { 38 + plc: new PlcDidDocumentResolver(), 39 + web: new WebDidDocumentResolver(), 40 + }, 41 + }); 42 + 43 + export const fetchHandler: ({ 44 + service, 45 + }: SimpleFetchHandlerOptions) => FetchHandler = ({ 46 + service, 47 + }: SimpleFetchHandlerOptions): FetchHandler => { 48 + const safeFetch = safeFetchWrap(); 49 + return async (pathname, init) => { 50 + const url = new URL(pathname, service); 51 + return await safeFetch(url, init); 52 + }; 53 + }; 54 + 55 + export async function getPds( 56 + did: `did:${"plc" | "web"}:${string}` 57 + ): Promise<string | undefined> { 58 + try { 59 + const doc = await docResolver.resolve(did); 60 + const pds = doc.service?.filter( 61 + (x) => 62 + x.id.endsWith("#atproto_pds") && x.type === "AtprotoPersonalDataServer" 63 + )[0].serviceEndpoint; 64 + return typeof pds === "string" ? pds : undefined; 65 + } catch { 66 + return undefined; 67 + } 68 + } 69 + 70 + export function isDid(did: unknown): did is `did:${"plc" | "web"}:${string}` { 71 + return ( 72 + typeof did === "string" && 73 + (did.startsWith("did:web:") || did.startsWith("did:plc:")) 74 + ); 75 + } 76 + 77 + /** 78 + * given a valid url path string containing 79 + * - `/` for seperating characters 80 + * - a-zA-Z0-9 `-._~` as unreserved 81 + * - `!$&'()*+,;=` as reserved but valid in paths 82 + * - `:@` as neither reserved or unreserved but valid in paths 83 + * - %XX where X are hex digits for percent encoding 84 + * 85 + * we need to consistently and bidirectionally convert it into a string containing the characters A-Z, a-z, 0-9, `.-_:~` for an atproto rkey 86 + * A-Z a-z 0-9 are covered easily 87 + * we can also take -._~ as they are also unreserved 88 + * leaving : as a valid rkey character which looks nice for encoding 89 + * the uppercase versions MUST be used to prevent ambiguity 90 + * a colon which isnt followed by a valid character is an invalid rkey and should be ignored 91 + * - `/` `::` 92 + * - `%` `:~` 93 + * - `!` `:21` 94 + * - `$` `:24` 95 + * - `&` `:26` 96 + * - `'` `:27` 97 + * - `(` `:28` 98 + * - `)` `:29` 99 + * - `*` `:2A` 100 + * - `+` `:2B` 101 + * - `,` `:2C` 102 + * - `:` `:3A` 103 + * - `;` `:3B` 104 + * - `=` `:3D` 105 + * - `@` `:40` 106 + * @returns {string | undefined} undefined when input is invalid 107 + */ 108 + export function urlToRkey(url: string): string | undefined { 109 + // contains 0-9A-Za-z + special valid chars and / seperator. also can contain %XX with XX being hex 110 + if ( 111 + !url.match(/^(?:[a-zA-Z0-9/\-._~!$&'()*+,;=:@]|(?:%[0-9a-fA-F]{2}))*$/gm) 112 + ) { 113 + return; 114 + } 115 + return ( 116 + url 117 + // : replace is hoisted so it doesnt replace colons from elsewhere 118 + .replaceAll(":", ":3A") 119 + .replaceAll("/", "::") 120 + .replaceAll("%", ":~") 121 + .replaceAll("!", ":21") 122 + .replaceAll("$", ":24") 123 + .replaceAll("&", ":26") 124 + .replaceAll("'", ":27") 125 + .replaceAll("(", ":28") 126 + .replaceAll(")", ":29") 127 + .replaceAll("*", ":2A") 128 + .replaceAll("+", ":2B") 129 + .replaceAll(",", ":2C") 130 + .replaceAll(";", ":3B") 131 + .replaceAll("=", ":3D") 132 + .replaceAll("@", ":40") 133 + ); 134 + } 135 + 136 + /** 137 + * @see {@link urlToRkey} for rkey <=> url conversion syntax 138 + * @returns {string | undefined} undefined when input is invalid 139 + */ 140 + export function rkeyToUrl(rkey: string): string | undefined { 141 + // contains 0-9A-Za-z .-_~ 142 + // or any valid colon escape sequence 143 + if ( 144 + !rkey.match( 145 + /^(?:[A-Za-z0-9.\-_~]|(?:::)|(?::~)|(?::21)|(?::24)|(?::26)|(?::27)|(?::28)|(?::29)|(?::2A)|(?::2B)|(?::2C)|(?::3A)|(?::3B)|(?::3D)|(?::40))*$/gm 146 + ) 147 + ) 148 + return; 149 + return rkey 150 + .replaceAll("::", "/") 151 + .replaceAll(":~", "%") 152 + .replaceAll(":21", "!") 153 + .replaceAll(":24", "$") 154 + .replaceAll(":26", "&") 155 + .replaceAll(":27", "'") 156 + .replaceAll(":28", "(") 157 + .replaceAll(":29", ")") 158 + .replaceAll(":2A", "*") 159 + .replaceAll(":2B", "+") 160 + .replaceAll(":2C", ",") 161 + .replaceAll(":3A", ":") 162 + .replaceAll(":3B", ";") 163 + .replaceAll(":3D", "=") 164 + .replaceAll(":40", "@"); 165 + }
+1 -1
server/src/www/index.html
··· 1 - <!doctype html> 1 + <!DOCTYPE html> 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="UTF-8" />
+4435
upload/Cargo.lock
··· 3 3 version = 4 4 4 5 5 [[package]] 6 + name = "abnf" 7 + version = "0.13.0" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a" 10 + dependencies = [ 11 + "abnf-core", 12 + "nom", 13 + ] 14 + 15 + [[package]] 16 + name = "abnf-core" 17 + version = "0.5.0" 18 + source = "registry+https://github.com/rust-lang/crates.io-index" 19 + checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" 20 + dependencies = [ 21 + "nom", 22 + ] 23 + 24 + [[package]] 25 + name = "addr2line" 26 + version = "0.25.1" 27 + source = "registry+https://github.com/rust-lang/crates.io-index" 28 + checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" 29 + dependencies = [ 30 + "gimli", 31 + ] 32 + 33 + [[package]] 34 + name = "adler2" 35 + version = "2.0.1" 36 + source = "registry+https://github.com/rust-lang/crates.io-index" 37 + checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 38 + 39 + [[package]] 40 + name = "adler32" 41 + version = "1.2.0" 42 + source = "registry+https://github.com/rust-lang/crates.io-index" 43 + checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 44 + 45 + [[package]] 46 + name = "aho-corasick" 47 + version = "1.1.3" 48 + source = "registry+https://github.com/rust-lang/crates.io-index" 49 + checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 50 + dependencies = [ 51 + "memchr", 52 + ] 53 + 54 + [[package]] 55 + name = "aliasable" 56 + version = "0.1.3" 57 + source = "registry+https://github.com/rust-lang/crates.io-index" 58 + checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" 59 + 60 + [[package]] 61 + name = "alloc-no-stdlib" 62 + version = "2.0.4" 63 + source = "registry+https://github.com/rust-lang/crates.io-index" 64 + checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 65 + 66 + [[package]] 67 + name = "alloc-stdlib" 68 + version = "0.2.2" 69 + source = "registry+https://github.com/rust-lang/crates.io-index" 70 + checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 71 + dependencies = [ 72 + "alloc-no-stdlib", 73 + ] 74 + 75 + [[package]] 76 + name = "android_system_properties" 77 + version = "0.1.5" 78 + source = "registry+https://github.com/rust-lang/crates.io-index" 79 + checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 80 + dependencies = [ 81 + "libc", 82 + ] 83 + 84 + [[package]] 85 + name = "anstream" 86 + version = "0.6.21" 87 + source = "registry+https://github.com/rust-lang/crates.io-index" 88 + checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" 89 + dependencies = [ 90 + "anstyle", 91 + "anstyle-parse", 92 + "anstyle-query", 93 + "anstyle-wincon", 94 + "colorchoice", 95 + "is_terminal_polyfill", 96 + "utf8parse", 97 + ] 98 + 99 + [[package]] 100 + name = "anstyle" 101 + version = "1.0.13" 102 + source = "registry+https://github.com/rust-lang/crates.io-index" 103 + checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" 104 + 105 + [[package]] 106 + name = "anstyle-parse" 107 + version = "0.2.7" 108 + source = "registry+https://github.com/rust-lang/crates.io-index" 109 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 110 + dependencies = [ 111 + "utf8parse", 112 + ] 113 + 114 + [[package]] 115 + name = "anstyle-query" 116 + version = "1.1.4" 117 + source = "registry+https://github.com/rust-lang/crates.io-index" 118 + checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 119 + dependencies = [ 120 + "windows-sys 0.60.2", 121 + ] 122 + 123 + [[package]] 124 + name = "anstyle-wincon" 125 + version = "3.0.10" 126 + source = "registry+https://github.com/rust-lang/crates.io-index" 127 + checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 128 + dependencies = [ 129 + "anstyle", 130 + "once_cell_polyfill", 131 + "windows-sys 0.60.2", 132 + ] 133 + 134 + [[package]] 135 + name = "ascii" 136 + version = "1.1.0" 137 + source = "registry+https://github.com/rust-lang/crates.io-index" 138 + checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" 139 + 140 + [[package]] 141 + name = "async-compression" 142 + version = "0.4.32" 143 + source = "registry+https://github.com/rust-lang/crates.io-index" 144 + checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" 145 + dependencies = [ 146 + "compression-codecs", 147 + "compression-core", 148 + "futures-core", 149 + "pin-project-lite", 150 + "tokio", 151 + ] 152 + 153 + [[package]] 154 + name = "async-trait" 155 + version = "0.1.89" 156 + source = "registry+https://github.com/rust-lang/crates.io-index" 157 + checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" 158 + dependencies = [ 159 + "proc-macro2", 160 + "quote", 161 + "syn 2.0.107", 162 + ] 163 + 164 + [[package]] 6 165 name = "atcities-upload" 166 + version = "1.0.1" 167 + dependencies = [ 168 + "clap", 169 + "env_logger", 170 + "ignore", 171 + "jacquard", 172 + "lexicons", 173 + "miette", 174 + "mime_guess", 175 + "regex", 176 + "reqwest", 177 + "thiserror 2.0.17", 178 + "tokio", 179 + ] 180 + 181 + [[package]] 182 + name = "atomic-waker" 183 + version = "1.1.2" 184 + source = "registry+https://github.com/rust-lang/crates.io-index" 185 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 186 + 187 + [[package]] 188 + name = "autocfg" 189 + version = "1.5.0" 190 + source = "registry+https://github.com/rust-lang/crates.io-index" 191 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 192 + 193 + [[package]] 194 + name = "backtrace" 195 + version = "0.3.76" 196 + source = "registry+https://github.com/rust-lang/crates.io-index" 197 + checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" 198 + dependencies = [ 199 + "addr2line", 200 + "cfg-if", 201 + "libc", 202 + "miniz_oxide", 203 + "object", 204 + "rustc-demangle", 205 + "windows-link 0.2.1", 206 + ] 207 + 208 + [[package]] 209 + name = "backtrace-ext" 210 + version = "0.2.1" 211 + source = "registry+https://github.com/rust-lang/crates.io-index" 212 + checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" 213 + dependencies = [ 214 + "backtrace", 215 + ] 216 + 217 + [[package]] 218 + name = "base-x" 219 + version = "0.2.11" 220 + source = "registry+https://github.com/rust-lang/crates.io-index" 221 + checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" 222 + 223 + [[package]] 224 + name = "base16ct" 225 + version = "0.2.0" 226 + source = "registry+https://github.com/rust-lang/crates.io-index" 227 + checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 228 + 229 + [[package]] 230 + name = "base256emoji" 231 + version = "1.0.2" 232 + source = "registry+https://github.com/rust-lang/crates.io-index" 233 + checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" 234 + dependencies = [ 235 + "const-str", 236 + "match-lookup", 237 + ] 238 + 239 + [[package]] 240 + name = "base64" 241 + version = "0.13.1" 242 + source = "registry+https://github.com/rust-lang/crates.io-index" 243 + checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 244 + 245 + [[package]] 246 + name = "base64" 247 + version = "0.22.1" 248 + source = "registry+https://github.com/rust-lang/crates.io-index" 249 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 250 + 251 + [[package]] 252 + name = "base64ct" 253 + version = "1.8.0" 254 + source = "registry+https://github.com/rust-lang/crates.io-index" 255 + checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" 256 + 257 + [[package]] 258 + name = "bitflags" 259 + version = "2.9.4" 260 + source = "registry+https://github.com/rust-lang/crates.io-index" 261 + checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 262 + 263 + [[package]] 264 + name = "block-buffer" 265 + version = "0.10.4" 266 + source = "registry+https://github.com/rust-lang/crates.io-index" 267 + checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 268 + dependencies = [ 269 + "generic-array", 270 + ] 271 + 272 + [[package]] 273 + name = "bon" 274 + version = "3.8.1" 275 + source = "registry+https://github.com/rust-lang/crates.io-index" 276 + checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1" 277 + dependencies = [ 278 + "bon-macros", 279 + "rustversion", 280 + ] 281 + 282 + [[package]] 283 + name = "bon-macros" 284 + version = "3.8.1" 285 + source = "registry+https://github.com/rust-lang/crates.io-index" 286 + checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645" 287 + dependencies = [ 288 + "darling", 289 + "ident_case", 290 + "prettyplease", 291 + "proc-macro2", 292 + "quote", 293 + "rustversion", 294 + "syn 2.0.107", 295 + ] 296 + 297 + [[package]] 298 + name = "borsh" 299 + version = "1.5.7" 300 + source = "registry+https://github.com/rust-lang/crates.io-index" 301 + checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" 302 + dependencies = [ 303 + "cfg_aliases", 304 + ] 305 + 306 + [[package]] 307 + name = "brotli" 308 + version = "3.5.0" 309 + source = "registry+https://github.com/rust-lang/crates.io-index" 310 + checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" 311 + dependencies = [ 312 + "alloc-no-stdlib", 313 + "alloc-stdlib", 314 + "brotli-decompressor", 315 + ] 316 + 317 + [[package]] 318 + name = "brotli-decompressor" 319 + version = "2.5.1" 320 + source = "registry+https://github.com/rust-lang/crates.io-index" 321 + checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" 322 + dependencies = [ 323 + "alloc-no-stdlib", 324 + "alloc-stdlib", 325 + ] 326 + 327 + [[package]] 328 + name = "bstr" 329 + version = "1.12.0" 330 + source = "registry+https://github.com/rust-lang/crates.io-index" 331 + checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" 332 + dependencies = [ 333 + "memchr", 334 + "serde", 335 + ] 336 + 337 + [[package]] 338 + name = "btree-range-map" 339 + version = "0.7.2" 340 + source = "registry+https://github.com/rust-lang/crates.io-index" 341 + checksum = "1be5c9672446d3800bcbcaabaeba121fe22f1fb25700c4562b22faf76d377c33" 342 + dependencies = [ 343 + "btree-slab", 344 + "cc-traits", 345 + "range-traits", 346 + "serde", 347 + "slab", 348 + ] 349 + 350 + [[package]] 351 + name = "btree-slab" 352 + version = "0.6.1" 353 + source = "registry+https://github.com/rust-lang/crates.io-index" 354 + checksum = "7a2b56d3029f075c4fa892428a098425b86cef5c89ae54073137ece416aef13c" 355 + dependencies = [ 356 + "cc-traits", 357 + "slab", 358 + "smallvec", 359 + ] 360 + 361 + [[package]] 362 + name = "buf_redux" 363 + version = "0.8.4" 364 + source = "registry+https://github.com/rust-lang/crates.io-index" 365 + checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" 366 + dependencies = [ 367 + "memchr", 368 + "safemem", 369 + ] 370 + 371 + [[package]] 372 + name = "bumpalo" 373 + version = "3.19.0" 374 + source = "registry+https://github.com/rust-lang/crates.io-index" 375 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 376 + 377 + [[package]] 378 + name = "byteorder" 379 + version = "1.5.0" 380 + source = "registry+https://github.com/rust-lang/crates.io-index" 381 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 382 + 383 + [[package]] 384 + name = "bytes" 385 + version = "1.10.1" 386 + source = "registry+https://github.com/rust-lang/crates.io-index" 387 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 388 + dependencies = [ 389 + "serde", 390 + ] 391 + 392 + [[package]] 393 + name = "cbor4ii" 394 + version = "0.2.14" 395 + source = "registry+https://github.com/rust-lang/crates.io-index" 396 + checksum = "b544cf8c89359205f4f990d0e6f3828db42df85b5dac95d09157a250eb0749c4" 397 + dependencies = [ 398 + "serde", 399 + ] 400 + 401 + [[package]] 402 + name = "cc" 403 + version = "1.2.41" 404 + source = "registry+https://github.com/rust-lang/crates.io-index" 405 + checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" 406 + dependencies = [ 407 + "find-msvc-tools", 408 + "shlex", 409 + ] 410 + 411 + [[package]] 412 + name = "cc-traits" 413 + version = "2.0.0" 414 + source = "registry+https://github.com/rust-lang/crates.io-index" 415 + checksum = "060303ef31ef4a522737e1b1ab68c67916f2a787bb2f4f54f383279adba962b5" 416 + dependencies = [ 417 + "slab", 418 + ] 419 + 420 + [[package]] 421 + name = "cesu8" 422 + version = "1.1.0" 423 + source = "registry+https://github.com/rust-lang/crates.io-index" 424 + checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 425 + 426 + [[package]] 427 + name = "cfg-if" 428 + version = "1.0.4" 429 + source = "registry+https://github.com/rust-lang/crates.io-index" 430 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 431 + 432 + [[package]] 433 + name = "cfg_aliases" 434 + version = "0.2.1" 435 + source = "registry+https://github.com/rust-lang/crates.io-index" 436 + checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 437 + 438 + [[package]] 439 + name = "chrono" 440 + version = "0.4.42" 441 + source = "registry+https://github.com/rust-lang/crates.io-index" 442 + checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" 443 + dependencies = [ 444 + "iana-time-zone", 445 + "js-sys", 446 + "num-traits", 447 + "wasm-bindgen", 448 + "windows-link 0.2.1", 449 + ] 450 + 451 + [[package]] 452 + name = "chunked_transfer" 453 + version = "1.5.0" 454 + source = "registry+https://github.com/rust-lang/crates.io-index" 455 + checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" 456 + 457 + [[package]] 458 + name = "ciborium" 459 + version = "0.2.2" 460 + source = "registry+https://github.com/rust-lang/crates.io-index" 461 + checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 462 + dependencies = [ 463 + "ciborium-io", 464 + "ciborium-ll", 465 + "serde", 466 + ] 467 + 468 + [[package]] 469 + name = "ciborium-io" 470 + version = "0.2.2" 471 + source = "registry+https://github.com/rust-lang/crates.io-index" 472 + checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 473 + 474 + [[package]] 475 + name = "ciborium-ll" 476 + version = "0.2.2" 477 + source = "registry+https://github.com/rust-lang/crates.io-index" 478 + checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 479 + dependencies = [ 480 + "ciborium-io", 481 + "half", 482 + ] 483 + 484 + [[package]] 485 + name = "cid" 486 + version = "0.11.1" 487 + source = "registry+https://github.com/rust-lang/crates.io-index" 488 + checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a" 489 + dependencies = [ 490 + "core2", 491 + "multibase", 492 + "multihash", 493 + "serde", 494 + "serde_bytes", 495 + "unsigned-varint", 496 + ] 497 + 498 + [[package]] 499 + name = "clap" 500 + version = "4.5.49" 501 + source = "registry+https://github.com/rust-lang/crates.io-index" 502 + checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" 503 + dependencies = [ 504 + "clap_builder", 505 + "clap_derive", 506 + ] 507 + 508 + [[package]] 509 + name = "clap_builder" 510 + version = "4.5.49" 511 + source = "registry+https://github.com/rust-lang/crates.io-index" 512 + checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" 513 + dependencies = [ 514 + "anstream", 515 + "anstyle", 516 + "clap_lex", 517 + "strsim", 518 + ] 519 + 520 + [[package]] 521 + name = "clap_derive" 522 + version = "4.5.49" 523 + source = "registry+https://github.com/rust-lang/crates.io-index" 524 + checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" 525 + dependencies = [ 526 + "heck 0.5.0", 527 + "proc-macro2", 528 + "quote", 529 + "syn 2.0.107", 530 + ] 531 + 532 + [[package]] 533 + name = "clap_lex" 534 + version = "0.7.6" 535 + source = "registry+https://github.com/rust-lang/crates.io-index" 536 + checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" 537 + 538 + [[package]] 539 + name = "colorchoice" 540 + version = "1.0.4" 541 + source = "registry+https://github.com/rust-lang/crates.io-index" 542 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 543 + 544 + [[package]] 545 + name = "combine" 546 + version = "4.6.7" 547 + source = "registry+https://github.com/rust-lang/crates.io-index" 548 + checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" 549 + dependencies = [ 550 + "bytes", 551 + "memchr", 552 + ] 553 + 554 + [[package]] 555 + name = "compression-codecs" 556 + version = "0.4.31" 557 + source = "registry+https://github.com/rust-lang/crates.io-index" 558 + checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" 559 + dependencies = [ 560 + "compression-core", 561 + "flate2", 562 + "memchr", 563 + ] 564 + 565 + [[package]] 566 + name = "compression-core" 567 + version = "0.4.29" 568 + source = "registry+https://github.com/rust-lang/crates.io-index" 569 + checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb" 570 + 571 + [[package]] 572 + name = "const-oid" 573 + version = "0.9.6" 574 + source = "registry+https://github.com/rust-lang/crates.io-index" 575 + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 576 + 577 + [[package]] 578 + name = "const-str" 579 + version = "0.4.3" 580 + source = "registry+https://github.com/rust-lang/crates.io-index" 581 + checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" 582 + 583 + [[package]] 584 + name = "core-foundation" 585 + version = "0.9.4" 586 + source = "registry+https://github.com/rust-lang/crates.io-index" 587 + checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 588 + dependencies = [ 589 + "core-foundation-sys", 590 + "libc", 591 + ] 592 + 593 + [[package]] 594 + name = "core-foundation-sys" 595 + version = "0.8.7" 596 + source = "registry+https://github.com/rust-lang/crates.io-index" 597 + checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 598 + 599 + [[package]] 600 + name = "core2" 601 + version = "0.4.0" 602 + source = "registry+https://github.com/rust-lang/crates.io-index" 603 + checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" 604 + dependencies = [ 605 + "memchr", 606 + ] 607 + 608 + [[package]] 609 + name = "cpufeatures" 610 + version = "0.2.17" 611 + source = "registry+https://github.com/rust-lang/crates.io-index" 612 + checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 613 + dependencies = [ 614 + "libc", 615 + ] 616 + 617 + [[package]] 618 + name = "crc32fast" 619 + version = "1.5.0" 620 + source = "registry+https://github.com/rust-lang/crates.io-index" 621 + checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" 622 + dependencies = [ 623 + "cfg-if", 624 + ] 625 + 626 + [[package]] 627 + name = "crossbeam-deque" 628 + version = "0.8.6" 629 + source = "registry+https://github.com/rust-lang/crates.io-index" 630 + checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 631 + dependencies = [ 632 + "crossbeam-epoch", 633 + "crossbeam-utils", 634 + ] 635 + 636 + [[package]] 637 + name = "crossbeam-epoch" 638 + version = "0.9.18" 639 + source = "registry+https://github.com/rust-lang/crates.io-index" 640 + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 641 + dependencies = [ 642 + "crossbeam-utils", 643 + ] 644 + 645 + [[package]] 646 + name = "crossbeam-utils" 647 + version = "0.8.21" 648 + source = "registry+https://github.com/rust-lang/crates.io-index" 649 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 650 + 651 + [[package]] 652 + name = "crunchy" 653 + version = "0.2.4" 654 + source = "registry+https://github.com/rust-lang/crates.io-index" 655 + checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 656 + 657 + [[package]] 658 + name = "crypto-bigint" 659 + version = "0.5.5" 660 + source = "registry+https://github.com/rust-lang/crates.io-index" 661 + checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" 662 + dependencies = [ 663 + "generic-array", 664 + "rand_core 0.6.4", 665 + "subtle", 666 + "zeroize", 667 + ] 668 + 669 + [[package]] 670 + name = "crypto-common" 671 + version = "0.1.6" 672 + source = "registry+https://github.com/rust-lang/crates.io-index" 673 + checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 674 + dependencies = [ 675 + "generic-array", 676 + "typenum", 677 + ] 678 + 679 + [[package]] 680 + name = "darling" 681 + version = "0.21.3" 682 + source = "registry+https://github.com/rust-lang/crates.io-index" 683 + checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" 684 + dependencies = [ 685 + "darling_core", 686 + "darling_macro", 687 + ] 688 + 689 + [[package]] 690 + name = "darling_core" 691 + version = "0.21.3" 692 + source = "registry+https://github.com/rust-lang/crates.io-index" 693 + checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" 694 + dependencies = [ 695 + "fnv", 696 + "ident_case", 697 + "proc-macro2", 698 + "quote", 699 + "strsim", 700 + "syn 2.0.107", 701 + ] 702 + 703 + [[package]] 704 + name = "darling_macro" 705 + version = "0.21.3" 706 + source = "registry+https://github.com/rust-lang/crates.io-index" 707 + checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" 708 + dependencies = [ 709 + "darling_core", 710 + "quote", 711 + "syn 2.0.107", 712 + ] 713 + 714 + [[package]] 715 + name = "dashmap" 716 + version = "6.1.0" 717 + source = "registry+https://github.com/rust-lang/crates.io-index" 718 + checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" 719 + dependencies = [ 720 + "cfg-if", 721 + "crossbeam-utils", 722 + "hashbrown 0.14.5", 723 + "lock_api", 724 + "once_cell", 725 + "parking_lot_core", 726 + ] 727 + 728 + [[package]] 729 + name = "data-encoding" 730 + version = "2.9.0" 731 + source = "registry+https://github.com/rust-lang/crates.io-index" 732 + checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" 733 + 734 + [[package]] 735 + name = "data-encoding-macro" 736 + version = "0.1.18" 737 + source = "registry+https://github.com/rust-lang/crates.io-index" 738 + checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" 739 + dependencies = [ 740 + "data-encoding", 741 + "data-encoding-macro-internal", 742 + ] 743 + 744 + [[package]] 745 + name = "data-encoding-macro-internal" 746 + version = "0.1.16" 747 + source = "registry+https://github.com/rust-lang/crates.io-index" 748 + checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" 749 + dependencies = [ 750 + "data-encoding", 751 + "syn 2.0.107", 752 + ] 753 + 754 + [[package]] 755 + name = "deflate" 756 + version = "1.0.0" 757 + source = "registry+https://github.com/rust-lang/crates.io-index" 758 + checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" 759 + dependencies = [ 760 + "adler32", 761 + "gzip-header", 762 + ] 763 + 764 + [[package]] 765 + name = "der" 766 + version = "0.7.10" 767 + source = "registry+https://github.com/rust-lang/crates.io-index" 768 + checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" 769 + dependencies = [ 770 + "const-oid", 771 + "pem-rfc7468", 772 + "zeroize", 773 + ] 774 + 775 + [[package]] 776 + name = "deranged" 777 + version = "0.5.4" 778 + source = "registry+https://github.com/rust-lang/crates.io-index" 779 + checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" 780 + dependencies = [ 781 + "powerfmt", 782 + ] 783 + 784 + [[package]] 785 + name = "digest" 786 + version = "0.10.7" 787 + source = "registry+https://github.com/rust-lang/crates.io-index" 788 + checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 789 + dependencies = [ 790 + "block-buffer", 791 + "const-oid", 792 + "crypto-common", 793 + "subtle", 794 + ] 795 + 796 + [[package]] 797 + name = "displaydoc" 798 + version = "0.2.5" 799 + source = "registry+https://github.com/rust-lang/crates.io-index" 800 + checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 801 + dependencies = [ 802 + "proc-macro2", 803 + "quote", 804 + "syn 2.0.107", 805 + ] 806 + 807 + [[package]] 808 + name = "ecdsa" 809 + version = "0.16.9" 810 + source = "registry+https://github.com/rust-lang/crates.io-index" 811 + checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 812 + dependencies = [ 813 + "der", 814 + "digest", 815 + "elliptic-curve", 816 + "rfc6979", 817 + "signature", 818 + "spki", 819 + ] 820 + 821 + [[package]] 822 + name = "elliptic-curve" 823 + version = "0.13.8" 824 + source = "registry+https://github.com/rust-lang/crates.io-index" 825 + checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" 826 + dependencies = [ 827 + "base16ct", 828 + "crypto-bigint", 829 + "digest", 830 + "ff", 831 + "generic-array", 832 + "group", 833 + "pem-rfc7468", 834 + "pkcs8", 835 + "rand_core 0.6.4", 836 + "sec1", 837 + "subtle", 838 + "zeroize", 839 + ] 840 + 841 + [[package]] 842 + name = "encoding_rs" 843 + version = "0.8.35" 844 + source = "registry+https://github.com/rust-lang/crates.io-index" 845 + checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 846 + dependencies = [ 847 + "cfg-if", 848 + ] 849 + 850 + [[package]] 851 + name = "enum-as-inner" 852 + version = "0.6.1" 853 + source = "registry+https://github.com/rust-lang/crates.io-index" 854 + checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" 855 + dependencies = [ 856 + "heck 0.5.0", 857 + "proc-macro2", 858 + "quote", 859 + "syn 2.0.107", 860 + ] 861 + 862 + [[package]] 863 + name = "env_filter" 864 + version = "0.1.4" 865 + source = "registry+https://github.com/rust-lang/crates.io-index" 866 + checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" 867 + dependencies = [ 868 + "log", 869 + "regex", 870 + ] 871 + 872 + [[package]] 873 + name = "env_logger" 874 + version = "0.11.8" 875 + source = "registry+https://github.com/rust-lang/crates.io-index" 876 + checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" 877 + dependencies = [ 878 + "anstream", 879 + "anstyle", 880 + "env_filter", 881 + "jiff", 882 + "log", 883 + ] 884 + 885 + [[package]] 886 + name = "equivalent" 887 + version = "1.0.2" 888 + source = "registry+https://github.com/rust-lang/crates.io-index" 889 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 890 + 891 + [[package]] 892 + name = "errno" 893 + version = "0.3.14" 894 + source = "registry+https://github.com/rust-lang/crates.io-index" 895 + checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 896 + dependencies = [ 897 + "libc", 898 + "windows-sys 0.61.2", 899 + ] 900 + 901 + [[package]] 902 + name = "fastrand" 903 + version = "2.3.0" 904 + source = "registry+https://github.com/rust-lang/crates.io-index" 905 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 906 + 907 + [[package]] 908 + name = "ff" 909 + version = "0.13.1" 910 + source = "registry+https://github.com/rust-lang/crates.io-index" 911 + checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" 912 + dependencies = [ 913 + "rand_core 0.6.4", 914 + "subtle", 915 + ] 916 + 917 + [[package]] 918 + name = "filetime" 919 + version = "0.2.26" 920 + source = "registry+https://github.com/rust-lang/crates.io-index" 921 + checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" 922 + dependencies = [ 923 + "cfg-if", 924 + "libc", 925 + "libredox", 926 + "windows-sys 0.60.2", 927 + ] 928 + 929 + [[package]] 930 + name = "find-msvc-tools" 931 + version = "0.1.4" 932 + source = "registry+https://github.com/rust-lang/crates.io-index" 933 + checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" 934 + 935 + [[package]] 936 + name = "flate2" 937 + version = "1.1.4" 938 + source = "registry+https://github.com/rust-lang/crates.io-index" 939 + checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" 940 + dependencies = [ 941 + "crc32fast", 942 + "miniz_oxide", 943 + ] 944 + 945 + [[package]] 946 + name = "fnv" 947 + version = "1.0.7" 948 + source = "registry+https://github.com/rust-lang/crates.io-index" 949 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 950 + 951 + [[package]] 952 + name = "foreign-types" 953 + version = "0.3.2" 954 + source = "registry+https://github.com/rust-lang/crates.io-index" 955 + checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 956 + dependencies = [ 957 + "foreign-types-shared", 958 + ] 959 + 960 + [[package]] 961 + name = "foreign-types-shared" 962 + version = "0.1.1" 963 + source = "registry+https://github.com/rust-lang/crates.io-index" 964 + checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 965 + 966 + [[package]] 967 + name = "form_urlencoded" 968 + version = "1.2.2" 969 + source = "registry+https://github.com/rust-lang/crates.io-index" 970 + checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 971 + dependencies = [ 972 + "percent-encoding", 973 + ] 974 + 975 + [[package]] 976 + name = "futures-channel" 977 + version = "0.3.31" 978 + source = "registry+https://github.com/rust-lang/crates.io-index" 979 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 980 + dependencies = [ 981 + "futures-core", 982 + ] 983 + 984 + [[package]] 985 + name = "futures-core" 986 + version = "0.3.31" 987 + source = "registry+https://github.com/rust-lang/crates.io-index" 988 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 989 + 990 + [[package]] 991 + name = "futures-io" 992 + version = "0.3.31" 993 + source = "registry+https://github.com/rust-lang/crates.io-index" 994 + checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 995 + 996 + [[package]] 997 + name = "futures-macro" 998 + version = "0.3.31" 999 + source = "registry+https://github.com/rust-lang/crates.io-index" 1000 + checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 1001 + dependencies = [ 1002 + "proc-macro2", 1003 + "quote", 1004 + "syn 2.0.107", 1005 + ] 1006 + 1007 + [[package]] 1008 + name = "futures-sink" 1009 + version = "0.3.31" 1010 + source = "registry+https://github.com/rust-lang/crates.io-index" 1011 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 1012 + 1013 + [[package]] 1014 + name = "futures-task" 1015 + version = "0.3.31" 1016 + source = "registry+https://github.com/rust-lang/crates.io-index" 1017 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 1018 + 1019 + [[package]] 1020 + name = "futures-util" 1021 + version = "0.3.31" 1022 + source = "registry+https://github.com/rust-lang/crates.io-index" 1023 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 1024 + dependencies = [ 1025 + "futures-core", 1026 + "futures-io", 1027 + "futures-macro", 1028 + "futures-sink", 1029 + "futures-task", 1030 + "memchr", 1031 + "pin-project-lite", 1032 + "pin-utils", 1033 + "slab", 1034 + ] 1035 + 1036 + [[package]] 1037 + name = "genawaiter" 1038 + version = "0.99.1" 1039 + source = "registry+https://github.com/rust-lang/crates.io-index" 1040 + checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" 1041 + dependencies = [ 1042 + "futures-core", 1043 + "genawaiter-macro", 1044 + "genawaiter-proc-macro", 1045 + "proc-macro-hack", 1046 + ] 1047 + 1048 + [[package]] 1049 + name = "genawaiter-macro" 1050 + version = "0.99.1" 1051 + source = "registry+https://github.com/rust-lang/crates.io-index" 1052 + checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" 1053 + 1054 + [[package]] 1055 + name = "genawaiter-proc-macro" 1056 + version = "0.99.1" 1057 + source = "registry+https://github.com/rust-lang/crates.io-index" 1058 + checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" 1059 + dependencies = [ 1060 + "proc-macro-error 0.4.12", 1061 + "proc-macro-hack", 1062 + "proc-macro2", 1063 + "quote", 1064 + "syn 1.0.109", 1065 + ] 1066 + 1067 + [[package]] 1068 + name = "generic-array" 1069 + version = "0.14.9" 1070 + source = "registry+https://github.com/rust-lang/crates.io-index" 1071 + checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" 1072 + dependencies = [ 1073 + "typenum", 1074 + "version_check", 1075 + "zeroize", 1076 + ] 1077 + 1078 + [[package]] 1079 + name = "getrandom" 1080 + version = "0.2.16" 1081 + source = "registry+https://github.com/rust-lang/crates.io-index" 1082 + checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 1083 + dependencies = [ 1084 + "cfg-if", 1085 + "js-sys", 1086 + "libc", 1087 + "wasi", 1088 + "wasm-bindgen", 1089 + ] 1090 + 1091 + [[package]] 1092 + name = "getrandom" 1093 + version = "0.3.4" 1094 + source = "registry+https://github.com/rust-lang/crates.io-index" 1095 + checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" 1096 + dependencies = [ 1097 + "cfg-if", 1098 + "js-sys", 1099 + "libc", 1100 + "r-efi", 1101 + "wasip2", 1102 + "wasm-bindgen", 1103 + ] 1104 + 1105 + [[package]] 1106 + name = "gimli" 1107 + version = "0.32.3" 1108 + source = "registry+https://github.com/rust-lang/crates.io-index" 1109 + checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" 1110 + 1111 + [[package]] 1112 + name = "globset" 1113 + version = "0.4.17" 1114 + source = "registry+https://github.com/rust-lang/crates.io-index" 1115 + checksum = "eab69130804d941f8075cfd713bf8848a2c3b3f201a9457a11e6f87e1ab62305" 1116 + dependencies = [ 1117 + "aho-corasick", 1118 + "bstr", 1119 + "log", 1120 + "regex-automata", 1121 + "regex-syntax", 1122 + ] 1123 + 1124 + [[package]] 1125 + name = "group" 1126 + version = "0.13.0" 1127 + source = "registry+https://github.com/rust-lang/crates.io-index" 1128 + checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 1129 + dependencies = [ 1130 + "ff", 1131 + "rand_core 0.6.4", 1132 + "subtle", 1133 + ] 1134 + 1135 + [[package]] 1136 + name = "gzip-header" 1137 + version = "1.0.0" 1138 + source = "registry+https://github.com/rust-lang/crates.io-index" 1139 + checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" 1140 + dependencies = [ 1141 + "crc32fast", 1142 + ] 1143 + 1144 + [[package]] 1145 + name = "h2" 1146 + version = "0.4.12" 1147 + source = "registry+https://github.com/rust-lang/crates.io-index" 1148 + checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" 1149 + dependencies = [ 1150 + "atomic-waker", 1151 + "bytes", 1152 + "fnv", 1153 + "futures-core", 1154 + "futures-sink", 1155 + "http", 1156 + "indexmap", 1157 + "slab", 1158 + "tokio", 1159 + "tokio-util", 1160 + "tracing", 1161 + ] 1162 + 1163 + [[package]] 1164 + name = "half" 1165 + version = "2.7.1" 1166 + source = "registry+https://github.com/rust-lang/crates.io-index" 1167 + checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" 1168 + dependencies = [ 1169 + "cfg-if", 1170 + "crunchy", 1171 + "zerocopy", 1172 + ] 1173 + 1174 + [[package]] 1175 + name = "hashbrown" 1176 + version = "0.14.5" 1177 + source = "registry+https://github.com/rust-lang/crates.io-index" 1178 + checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1179 + 1180 + [[package]] 1181 + name = "hashbrown" 1182 + version = "0.16.0" 1183 + source = "registry+https://github.com/rust-lang/crates.io-index" 1184 + checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" 1185 + 1186 + [[package]] 1187 + name = "heck" 1188 + version = "0.4.1" 1189 + source = "registry+https://github.com/rust-lang/crates.io-index" 1190 + checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 1191 + 1192 + [[package]] 1193 + name = "heck" 1194 + version = "0.5.0" 1195 + source = "registry+https://github.com/rust-lang/crates.io-index" 1196 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1197 + 1198 + [[package]] 1199 + name = "hermit-abi" 1200 + version = "0.5.2" 1201 + source = "registry+https://github.com/rust-lang/crates.io-index" 1202 + checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" 1203 + 1204 + [[package]] 1205 + name = "hex_fmt" 1206 + version = "0.3.0" 1207 + source = "registry+https://github.com/rust-lang/crates.io-index" 1208 + checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" 1209 + 1210 + [[package]] 1211 + name = "hickory-proto" 1212 + version = "0.24.4" 1213 + source = "registry+https://github.com/rust-lang/crates.io-index" 1214 + checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" 1215 + dependencies = [ 1216 + "async-trait", 1217 + "cfg-if", 1218 + "data-encoding", 1219 + "enum-as-inner", 1220 + "futures-channel", 1221 + "futures-io", 1222 + "futures-util", 1223 + "idna", 1224 + "ipnet", 1225 + "once_cell", 1226 + "rand 0.8.5", 1227 + "thiserror 1.0.69", 1228 + "tinyvec", 1229 + "tokio", 1230 + "tracing", 1231 + "url", 1232 + ] 1233 + 1234 + [[package]] 1235 + name = "hickory-resolver" 1236 + version = "0.24.4" 1237 + source = "registry+https://github.com/rust-lang/crates.io-index" 1238 + checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" 1239 + dependencies = [ 1240 + "cfg-if", 1241 + "futures-util", 1242 + "hickory-proto", 1243 + "ipconfig", 1244 + "lru-cache", 1245 + "once_cell", 1246 + "parking_lot", 1247 + "rand 0.8.5", 1248 + "resolv-conf", 1249 + "smallvec", 1250 + "thiserror 1.0.69", 1251 + "tokio", 1252 + "tracing", 1253 + ] 1254 + 1255 + [[package]] 1256 + name = "hmac" 1257 + version = "0.12.1" 1258 + source = "registry+https://github.com/rust-lang/crates.io-index" 1259 + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1260 + dependencies = [ 1261 + "digest", 1262 + ] 1263 + 1264 + [[package]] 1265 + name = "home" 1266 + version = "0.5.11" 1267 + source = "registry+https://github.com/rust-lang/crates.io-index" 1268 + checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 1269 + dependencies = [ 1270 + "windows-sys 0.59.0", 1271 + ] 1272 + 1273 + [[package]] 1274 + name = "http" 1275 + version = "1.3.1" 1276 + source = "registry+https://github.com/rust-lang/crates.io-index" 1277 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 1278 + dependencies = [ 1279 + "bytes", 1280 + "fnv", 1281 + "itoa", 1282 + ] 1283 + 1284 + [[package]] 1285 + name = "http-body" 1286 + version = "1.0.1" 1287 + source = "registry+https://github.com/rust-lang/crates.io-index" 1288 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1289 + dependencies = [ 1290 + "bytes", 1291 + "http", 1292 + ] 1293 + 1294 + [[package]] 1295 + name = "http-body-util" 1296 + version = "0.1.3" 1297 + source = "registry+https://github.com/rust-lang/crates.io-index" 1298 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 1299 + dependencies = [ 1300 + "bytes", 1301 + "futures-core", 1302 + "http", 1303 + "http-body", 1304 + "pin-project-lite", 1305 + ] 1306 + 1307 + [[package]] 1308 + name = "httparse" 1309 + version = "1.10.1" 1310 + source = "registry+https://github.com/rust-lang/crates.io-index" 1311 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 1312 + 1313 + [[package]] 1314 + name = "httpdate" 1315 + version = "1.0.3" 1316 + source = "registry+https://github.com/rust-lang/crates.io-index" 1317 + checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1318 + 1319 + [[package]] 1320 + name = "hyper" 1321 + version = "1.7.0" 1322 + source = "registry+https://github.com/rust-lang/crates.io-index" 1323 + checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" 1324 + dependencies = [ 1325 + "atomic-waker", 1326 + "bytes", 1327 + "futures-channel", 1328 + "futures-core", 1329 + "h2", 1330 + "http", 1331 + "http-body", 1332 + "httparse", 1333 + "itoa", 1334 + "pin-project-lite", 1335 + "pin-utils", 1336 + "smallvec", 1337 + "tokio", 1338 + "want", 1339 + ] 1340 + 1341 + [[package]] 1342 + name = "hyper-rustls" 1343 + version = "0.27.7" 1344 + source = "registry+https://github.com/rust-lang/crates.io-index" 1345 + checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" 1346 + dependencies = [ 1347 + "http", 1348 + "hyper", 1349 + "hyper-util", 1350 + "rustls", 1351 + "rustls-pki-types", 1352 + "tokio", 1353 + "tokio-rustls", 1354 + "tower-service", 1355 + "webpki-roots", 1356 + ] 1357 + 1358 + [[package]] 1359 + name = "hyper-tls" 1360 + version = "0.6.0" 1361 + source = "registry+https://github.com/rust-lang/crates.io-index" 1362 + checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 1363 + dependencies = [ 1364 + "bytes", 1365 + "http-body-util", 1366 + "hyper", 1367 + "hyper-util", 1368 + "native-tls", 1369 + "tokio", 1370 + "tokio-native-tls", 1371 + "tower-service", 1372 + ] 1373 + 1374 + [[package]] 1375 + name = "hyper-util" 1376 + version = "0.1.17" 1377 + source = "registry+https://github.com/rust-lang/crates.io-index" 1378 + checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" 1379 + dependencies = [ 1380 + "base64 0.22.1", 1381 + "bytes", 1382 + "futures-channel", 1383 + "futures-core", 1384 + "futures-util", 1385 + "http", 1386 + "http-body", 1387 + "hyper", 1388 + "ipnet", 1389 + "libc", 1390 + "percent-encoding", 1391 + "pin-project-lite", 1392 + "socket2 0.6.1", 1393 + "system-configuration", 1394 + "tokio", 1395 + "tower-service", 1396 + "tracing", 1397 + "windows-registry", 1398 + ] 1399 + 1400 + [[package]] 1401 + name = "iana-time-zone" 1402 + version = "0.1.64" 1403 + source = "registry+https://github.com/rust-lang/crates.io-index" 1404 + checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" 1405 + dependencies = [ 1406 + "android_system_properties", 1407 + "core-foundation-sys", 1408 + "iana-time-zone-haiku", 1409 + "js-sys", 1410 + "log", 1411 + "wasm-bindgen", 1412 + "windows-core", 1413 + ] 1414 + 1415 + [[package]] 1416 + name = "iana-time-zone-haiku" 1417 + version = "0.1.2" 1418 + source = "registry+https://github.com/rust-lang/crates.io-index" 1419 + checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1420 + dependencies = [ 1421 + "cc", 1422 + ] 1423 + 1424 + [[package]] 1425 + name = "icu_collections" 1426 + version = "2.0.0" 1427 + source = "registry+https://github.com/rust-lang/crates.io-index" 1428 + checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 1429 + dependencies = [ 1430 + "displaydoc", 1431 + "potential_utf", 1432 + "yoke", 1433 + "zerofrom", 1434 + "zerovec", 1435 + ] 1436 + 1437 + [[package]] 1438 + name = "icu_locale_core" 1439 + version = "2.0.0" 1440 + source = "registry+https://github.com/rust-lang/crates.io-index" 1441 + checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 1442 + dependencies = [ 1443 + "displaydoc", 1444 + "litemap", 1445 + "tinystr", 1446 + "writeable", 1447 + "zerovec", 1448 + ] 1449 + 1450 + [[package]] 1451 + name = "icu_normalizer" 1452 + version = "2.0.0" 1453 + source = "registry+https://github.com/rust-lang/crates.io-index" 1454 + checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 1455 + dependencies = [ 1456 + "displaydoc", 1457 + "icu_collections", 1458 + "icu_normalizer_data", 1459 + "icu_properties", 1460 + "icu_provider", 1461 + "smallvec", 1462 + "zerovec", 1463 + ] 1464 + 1465 + [[package]] 1466 + name = "icu_normalizer_data" 1467 + version = "2.0.0" 1468 + source = "registry+https://github.com/rust-lang/crates.io-index" 1469 + checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 1470 + 1471 + [[package]] 1472 + name = "icu_properties" 1473 + version = "2.0.1" 1474 + source = "registry+https://github.com/rust-lang/crates.io-index" 1475 + checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 1476 + dependencies = [ 1477 + "displaydoc", 1478 + "icu_collections", 1479 + "icu_locale_core", 1480 + "icu_properties_data", 1481 + "icu_provider", 1482 + "potential_utf", 1483 + "zerotrie", 1484 + "zerovec", 1485 + ] 1486 + 1487 + [[package]] 1488 + name = "icu_properties_data" 1489 + version = "2.0.1" 1490 + source = "registry+https://github.com/rust-lang/crates.io-index" 1491 + checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 1492 + 1493 + [[package]] 1494 + name = "icu_provider" 1495 + version = "2.0.0" 1496 + source = "registry+https://github.com/rust-lang/crates.io-index" 1497 + checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 1498 + dependencies = [ 1499 + "displaydoc", 1500 + "icu_locale_core", 1501 + "stable_deref_trait", 1502 + "tinystr", 1503 + "writeable", 1504 + "yoke", 1505 + "zerofrom", 1506 + "zerotrie", 1507 + "zerovec", 1508 + ] 1509 + 1510 + [[package]] 1511 + name = "ident_case" 1512 + version = "1.0.1" 1513 + source = "registry+https://github.com/rust-lang/crates.io-index" 1514 + checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1515 + 1516 + [[package]] 1517 + name = "idna" 1518 + version = "1.1.0" 1519 + source = "registry+https://github.com/rust-lang/crates.io-index" 1520 + checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 1521 + dependencies = [ 1522 + "idna_adapter", 1523 + "smallvec", 1524 + "utf8_iter", 1525 + ] 1526 + 1527 + [[package]] 1528 + name = "idna_adapter" 1529 + version = "1.2.1" 1530 + source = "registry+https://github.com/rust-lang/crates.io-index" 1531 + checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 1532 + dependencies = [ 1533 + "icu_normalizer", 1534 + "icu_properties", 1535 + ] 1536 + 1537 + [[package]] 1538 + name = "ignore" 1539 + version = "0.4.24" 1540 + source = "registry+https://github.com/rust-lang/crates.io-index" 1541 + checksum = "81776e6f9464432afcc28d03e52eb101c93b6f0566f52aef2427663e700f0403" 1542 + dependencies = [ 1543 + "crossbeam-deque", 1544 + "globset", 1545 + "log", 1546 + "memchr", 1547 + "regex-automata", 1548 + "same-file", 1549 + "walkdir", 1550 + "winapi-util", 1551 + ] 1552 + 1553 + [[package]] 1554 + name = "indexmap" 1555 + version = "2.12.0" 1556 + source = "registry+https://github.com/rust-lang/crates.io-index" 1557 + checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" 1558 + dependencies = [ 1559 + "equivalent", 1560 + "hashbrown 0.16.0", 1561 + ] 1562 + 1563 + [[package]] 1564 + name = "indoc" 1565 + version = "2.0.6" 1566 + source = "registry+https://github.com/rust-lang/crates.io-index" 1567 + checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" 1568 + 1569 + [[package]] 1570 + name = "ipconfig" 1571 + version = "0.3.2" 1572 + source = "registry+https://github.com/rust-lang/crates.io-index" 1573 + checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" 1574 + dependencies = [ 1575 + "socket2 0.5.10", 1576 + "widestring", 1577 + "windows-sys 0.48.0", 1578 + "winreg", 1579 + ] 1580 + 1581 + [[package]] 1582 + name = "ipld-core" 1583 + version = "0.4.2" 1584 + source = "registry+https://github.com/rust-lang/crates.io-index" 1585 + checksum = "104718b1cc124d92a6d01ca9c9258a7df311405debb3408c445a36452f9bf8db" 1586 + dependencies = [ 1587 + "cid", 1588 + "serde", 1589 + "serde_bytes", 1590 + ] 1591 + 1592 + [[package]] 1593 + name = "ipnet" 1594 + version = "2.11.0" 1595 + source = "registry+https://github.com/rust-lang/crates.io-index" 1596 + checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1597 + 1598 + [[package]] 1599 + name = "iri-string" 1600 + version = "0.7.8" 1601 + source = "registry+https://github.com/rust-lang/crates.io-index" 1602 + checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1603 + dependencies = [ 1604 + "memchr", 1605 + "serde", 1606 + ] 1607 + 1608 + [[package]] 1609 + name = "is_ci" 1610 + version = "1.2.0" 1611 + source = "registry+https://github.com/rust-lang/crates.io-index" 1612 + checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" 1613 + 1614 + [[package]] 1615 + name = "is_terminal_polyfill" 1616 + version = "1.70.1" 1617 + source = "registry+https://github.com/rust-lang/crates.io-index" 1618 + checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1619 + 1620 + [[package]] 1621 + name = "itoa" 1622 + version = "1.0.15" 1623 + source = "registry+https://github.com/rust-lang/crates.io-index" 1624 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1625 + 1626 + [[package]] 1627 + name = "jacquard" 1628 + version = "0.6.0" 1629 + source = "registry+https://github.com/rust-lang/crates.io-index" 1630 + checksum = "5857f000e67605995ba7c24c9833f840adf5c063a731a6f72f69e0e3c986791c" 1631 + dependencies = [ 1632 + "bon", 1633 + "bytes", 1634 + "getrandom 0.2.16", 1635 + "http", 1636 + "jacquard-api", 1637 + "jacquard-common", 1638 + "jacquard-derive", 1639 + "jacquard-identity", 1640 + "jacquard-oauth", 1641 + "jose-jwk", 1642 + "miette", 1643 + "p256", 1644 + "percent-encoding", 1645 + "rand_core 0.6.4", 1646 + "reqwest", 1647 + "serde", 1648 + "serde_html_form", 1649 + "serde_ipld_dagcbor", 1650 + "serde_json", 1651 + "smol_str", 1652 + "thiserror 2.0.17", 1653 + "tokio", 1654 + "trait-variant", 1655 + "url", 1656 + ] 1657 + 1658 + [[package]] 1659 + name = "jacquard-api" 1660 + version = "0.6.0" 1661 + source = "registry+https://github.com/rust-lang/crates.io-index" 1662 + checksum = "58132b60473124a34c64c267a1c3390c2e4a4dfd62c801639903c4aefd05f52d" 1663 + dependencies = [ 1664 + "bon", 1665 + "bytes", 1666 + "jacquard-common", 1667 + "jacquard-derive", 1668 + "miette", 1669 + "serde", 1670 + "serde_ipld_dagcbor", 1671 + "thiserror 2.0.17", 1672 + ] 1673 + 1674 + [[package]] 1675 + name = "jacquard-common" 1676 + version = "0.6.0" 1677 + source = "registry+https://github.com/rust-lang/crates.io-index" 1678 + checksum = "f7f1bab0279ae2e29c3383f132a05b9c708585fab62e94292affdf352ce13242" 1679 + dependencies = [ 1680 + "base64 0.22.1", 1681 + "bon", 1682 + "bytes", 1683 + "chrono", 1684 + "cid", 1685 + "genawaiter", 1686 + "getrandom 0.3.4", 1687 + "http", 1688 + "ipld-core", 1689 + "k256", 1690 + "langtag", 1691 + "miette", 1692 + "multibase", 1693 + "multihash", 1694 + "ouroboros", 1695 + "p256", 1696 + "rand 0.9.2", 1697 + "regex", 1698 + "reqwest", 1699 + "serde", 1700 + "serde_html_form", 1701 + "serde_ipld_dagcbor", 1702 + "serde_json", 1703 + "signature", 1704 + "smol_str", 1705 + "thiserror 2.0.17", 1706 + "tokio", 1707 + "tokio-util", 1708 + "trait-variant", 1709 + "url", 1710 + ] 1711 + 1712 + [[package]] 1713 + name = "jacquard-derive" 1714 + version = "0.6.0" 1715 + source = "registry+https://github.com/rust-lang/crates.io-index" 1716 + checksum = "a4741844c0638498156338e6230a81ecb54d0a061ffc6f4f54e97b94972a01fb" 1717 + dependencies = [ 1718 + "proc-macro2", 1719 + "quote", 1720 + "syn 2.0.107", 1721 + ] 1722 + 1723 + [[package]] 1724 + name = "jacquard-identity" 1725 + version = "0.6.0" 1726 + source = "registry+https://github.com/rust-lang/crates.io-index" 1727 + checksum = "65ae022725ddc09ce03c1a02a97b895279e1d46957c0574a032fa78b81273263" 1728 + dependencies = [ 1729 + "bon", 1730 + "bytes", 1731 + "hickory-resolver", 1732 + "http", 1733 + "jacquard-api", 1734 + "jacquard-common", 1735 + "miette", 1736 + "percent-encoding", 1737 + "reqwest", 1738 + "serde", 1739 + "serde_html_form", 1740 + "serde_json", 1741 + "thiserror 2.0.17", 1742 + "tokio", 1743 + "trait-variant", 1744 + "url", 1745 + "urlencoding", 1746 + ] 1747 + 1748 + [[package]] 1749 + name = "jacquard-oauth" 1750 + version = "0.6.0" 1751 + source = "registry+https://github.com/rust-lang/crates.io-index" 1752 + checksum = "8c37269e2ea0c6c3418bf61fb3d342aab87b1bda706ebae49e454f8e50580cab" 1753 + dependencies = [ 1754 + "base64 0.22.1", 1755 + "bytes", 1756 + "chrono", 1757 + "dashmap", 1758 + "elliptic-curve", 1759 + "http", 1760 + "jacquard-common", 1761 + "jacquard-identity", 1762 + "jose-jwa", 1763 + "jose-jwk", 1764 + "miette", 1765 + "p256", 1766 + "rand 0.8.5", 1767 + "rand_core 0.6.4", 1768 + "reqwest", 1769 + "rouille", 1770 + "serde", 1771 + "serde_html_form", 1772 + "serde_json", 1773 + "sha2", 1774 + "signature", 1775 + "smol_str", 1776 + "thiserror 2.0.17", 1777 + "tokio", 1778 + "trait-variant", 1779 + "url", 1780 + "webbrowser", 1781 + ] 1782 + 1783 + [[package]] 1784 + name = "jiff" 1785 + version = "0.2.15" 1786 + source = "registry+https://github.com/rust-lang/crates.io-index" 1787 + checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" 1788 + dependencies = [ 1789 + "jiff-static", 1790 + "log", 1791 + "portable-atomic", 1792 + "portable-atomic-util", 1793 + "serde", 1794 + ] 1795 + 1796 + [[package]] 1797 + name = "jiff-static" 1798 + version = "0.2.15" 1799 + source = "registry+https://github.com/rust-lang/crates.io-index" 1800 + checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" 1801 + dependencies = [ 1802 + "proc-macro2", 1803 + "quote", 1804 + "syn 2.0.107", 1805 + ] 1806 + 1807 + [[package]] 1808 + name = "jni" 1809 + version = "0.21.1" 1810 + source = "registry+https://github.com/rust-lang/crates.io-index" 1811 + checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" 1812 + dependencies = [ 1813 + "cesu8", 1814 + "cfg-if", 1815 + "combine", 1816 + "jni-sys", 1817 + "log", 1818 + "thiserror 1.0.69", 1819 + "walkdir", 1820 + "windows-sys 0.45.0", 1821 + ] 1822 + 1823 + [[package]] 1824 + name = "jni-sys" 1825 + version = "0.3.0" 1826 + source = "registry+https://github.com/rust-lang/crates.io-index" 1827 + checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 1828 + 1829 + [[package]] 1830 + name = "jose-b64" 1831 + version = "0.1.2" 1832 + source = "registry+https://github.com/rust-lang/crates.io-index" 1833 + checksum = "bec69375368709666b21c76965ce67549f2d2db7605f1f8707d17c9656801b56" 1834 + dependencies = [ 1835 + "base64ct", 1836 + "serde", 1837 + "subtle", 1838 + "zeroize", 1839 + ] 1840 + 1841 + [[package]] 1842 + name = "jose-jwa" 1843 + version = "0.1.2" 1844 + source = "registry+https://github.com/rust-lang/crates.io-index" 1845 + checksum = "9ab78e053fe886a351d67cf0d194c000f9d0dcb92906eb34d853d7e758a4b3a7" 1846 + dependencies = [ 1847 + "serde", 1848 + ] 1849 + 1850 + [[package]] 1851 + name = "jose-jwk" 1852 + version = "0.1.2" 1853 + source = "registry+https://github.com/rust-lang/crates.io-index" 1854 + checksum = "280fa263807fe0782ecb6f2baadc28dffc04e00558a58e33bfdb801d11fd58e7" 1855 + dependencies = [ 1856 + "jose-b64", 1857 + "jose-jwa", 1858 + "p256", 1859 + "p384", 1860 + "rsa", 1861 + "serde", 1862 + "zeroize", 1863 + ] 1864 + 1865 + [[package]] 1866 + name = "js-sys" 1867 + version = "0.3.81" 1868 + source = "registry+https://github.com/rust-lang/crates.io-index" 1869 + checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" 1870 + dependencies = [ 1871 + "once_cell", 1872 + "wasm-bindgen", 1873 + ] 1874 + 1875 + [[package]] 1876 + name = "k256" 1877 + version = "0.13.4" 1878 + source = "registry+https://github.com/rust-lang/crates.io-index" 1879 + checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" 1880 + dependencies = [ 1881 + "cfg-if", 1882 + "ecdsa", 1883 + "elliptic-curve", 1884 + "sha2", 1885 + ] 1886 + 1887 + [[package]] 1888 + name = "langtag" 1889 + version = "0.4.0" 1890 + source = "registry+https://github.com/rust-lang/crates.io-index" 1891 + checksum = "9ecb4c689a30e48ebeaa14237f34037e300dd072e6ad21a9ec72e810ff3c6600" 1892 + dependencies = [ 1893 + "serde", 1894 + "static-regular-grammar", 1895 + "thiserror 1.0.69", 1896 + ] 1897 + 1898 + [[package]] 1899 + name = "lazy_static" 1900 + version = "1.5.0" 1901 + source = "registry+https://github.com/rust-lang/crates.io-index" 1902 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1903 + dependencies = [ 1904 + "spin", 1905 + ] 1906 + 1907 + [[package]] 1908 + name = "lexicons" 1909 + version = "1.0.0" 1910 + dependencies = [ 1911 + "bon", 1912 + "bytes", 1913 + "jacquard-common", 1914 + "jacquard-derive", 1915 + "miette", 1916 + "serde", 1917 + "thiserror 2.0.17", 1918 + ] 1919 + 1920 + [[package]] 1921 + name = "libc" 1922 + version = "0.2.177" 1923 + source = "registry+https://github.com/rust-lang/crates.io-index" 1924 + checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" 1925 + 1926 + [[package]] 1927 + name = "libm" 1928 + version = "0.2.15" 1929 + source = "registry+https://github.com/rust-lang/crates.io-index" 1930 + checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" 1931 + 1932 + [[package]] 1933 + name = "libredox" 1934 + version = "0.1.10" 1935 + source = "registry+https://github.com/rust-lang/crates.io-index" 1936 + checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" 1937 + dependencies = [ 1938 + "bitflags", 1939 + "libc", 1940 + "redox_syscall", 1941 + ] 1942 + 1943 + [[package]] 1944 + name = "linked-hash-map" 1945 + version = "0.5.6" 1946 + source = "registry+https://github.com/rust-lang/crates.io-index" 1947 + checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 1948 + 1949 + [[package]] 1950 + name = "linux-raw-sys" 1951 + version = "0.11.0" 1952 + source = "registry+https://github.com/rust-lang/crates.io-index" 1953 + checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 1954 + 1955 + [[package]] 1956 + name = "litemap" 1957 + version = "0.8.0" 1958 + source = "registry+https://github.com/rust-lang/crates.io-index" 1959 + checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1960 + 1961 + [[package]] 1962 + name = "lock_api" 1963 + version = "0.4.14" 1964 + source = "registry+https://github.com/rust-lang/crates.io-index" 1965 + checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" 1966 + dependencies = [ 1967 + "scopeguard", 1968 + ] 1969 + 1970 + [[package]] 1971 + name = "log" 1972 + version = "0.4.28" 1973 + source = "registry+https://github.com/rust-lang/crates.io-index" 1974 + checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 1975 + 1976 + [[package]] 1977 + name = "lru-cache" 1978 + version = "0.1.2" 1979 + source = "registry+https://github.com/rust-lang/crates.io-index" 1980 + checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" 1981 + dependencies = [ 1982 + "linked-hash-map", 1983 + ] 1984 + 1985 + [[package]] 1986 + name = "lru-slab" 1987 + version = "0.1.2" 1988 + source = "registry+https://github.com/rust-lang/crates.io-index" 1989 + checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 1990 + 1991 + [[package]] 1992 + name = "malloc_buf" 1993 + version = "0.0.6" 1994 + source = "registry+https://github.com/rust-lang/crates.io-index" 1995 + checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 1996 + dependencies = [ 1997 + "libc", 1998 + ] 1999 + 2000 + [[package]] 2001 + name = "match-lookup" 2002 + version = "0.1.1" 2003 + source = "registry+https://github.com/rust-lang/crates.io-index" 2004 + checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" 2005 + dependencies = [ 2006 + "proc-macro2", 2007 + "quote", 2008 + "syn 1.0.109", 2009 + ] 2010 + 2011 + [[package]] 2012 + name = "memchr" 2013 + version = "2.7.6" 2014 + source = "registry+https://github.com/rust-lang/crates.io-index" 2015 + checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 2016 + 2017 + [[package]] 2018 + name = "miette" 2019 + version = "7.6.0" 2020 + source = "registry+https://github.com/rust-lang/crates.io-index" 2021 + checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" 2022 + dependencies = [ 2023 + "backtrace", 2024 + "backtrace-ext", 2025 + "cfg-if", 2026 + "miette-derive", 2027 + "owo-colors", 2028 + "supports-color", 2029 + "supports-hyperlinks", 2030 + "supports-unicode", 2031 + "terminal_size", 2032 + "textwrap", 2033 + "unicode-width 0.1.14", 2034 + ] 2035 + 2036 + [[package]] 2037 + name = "miette-derive" 2038 + version = "7.6.0" 2039 + source = "registry+https://github.com/rust-lang/crates.io-index" 2040 + checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" 2041 + dependencies = [ 2042 + "proc-macro2", 2043 + "quote", 2044 + "syn 2.0.107", 2045 + ] 2046 + 2047 + [[package]] 2048 + name = "mime" 2049 + version = "0.3.17" 2050 + source = "registry+https://github.com/rust-lang/crates.io-index" 2051 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 2052 + 2053 + [[package]] 2054 + name = "mime_guess" 2055 + version = "2.0.5" 2056 + source = "registry+https://github.com/rust-lang/crates.io-index" 2057 + checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 2058 + dependencies = [ 2059 + "mime", 2060 + "unicase", 2061 + ] 2062 + 2063 + [[package]] 2064 + name = "minimal-lexical" 2065 + version = "0.2.1" 2066 + source = "registry+https://github.com/rust-lang/crates.io-index" 2067 + checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 2068 + 2069 + [[package]] 2070 + name = "miniz_oxide" 2071 + version = "0.8.9" 2072 + source = "registry+https://github.com/rust-lang/crates.io-index" 2073 + checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 2074 + dependencies = [ 2075 + "adler2", 2076 + "simd-adler32", 2077 + ] 2078 + 2079 + [[package]] 2080 + name = "mio" 2081 + version = "1.1.0" 2082 + source = "registry+https://github.com/rust-lang/crates.io-index" 2083 + checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" 2084 + dependencies = [ 2085 + "libc", 2086 + "wasi", 2087 + "windows-sys 0.61.2", 2088 + ] 2089 + 2090 + [[package]] 2091 + name = "multibase" 2092 + version = "0.9.2" 2093 + source = "registry+https://github.com/rust-lang/crates.io-index" 2094 + checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" 2095 + dependencies = [ 2096 + "base-x", 2097 + "base256emoji", 2098 + "data-encoding", 2099 + "data-encoding-macro", 2100 + ] 2101 + 2102 + [[package]] 2103 + name = "multihash" 2104 + version = "0.19.3" 2105 + source = "registry+https://github.com/rust-lang/crates.io-index" 2106 + checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" 2107 + dependencies = [ 2108 + "core2", 2109 + "serde", 2110 + "unsigned-varint", 2111 + ] 2112 + 2113 + [[package]] 2114 + name = "multipart" 2115 + version = "0.18.0" 2116 + source = "registry+https://github.com/rust-lang/crates.io-index" 2117 + checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" 2118 + dependencies = [ 2119 + "buf_redux", 2120 + "httparse", 2121 + "log", 2122 + "mime", 2123 + "mime_guess", 2124 + "quick-error", 2125 + "rand 0.8.5", 2126 + "safemem", 2127 + "tempfile", 2128 + "twoway", 2129 + ] 2130 + 2131 + [[package]] 2132 + name = "native-tls" 2133 + version = "0.2.14" 2134 + source = "registry+https://github.com/rust-lang/crates.io-index" 2135 + checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 2136 + dependencies = [ 2137 + "libc", 2138 + "log", 2139 + "openssl", 2140 + "openssl-probe", 2141 + "openssl-sys", 2142 + "schannel", 2143 + "security-framework", 2144 + "security-framework-sys", 2145 + "tempfile", 2146 + ] 2147 + 2148 + [[package]] 2149 + name = "ndk-context" 2150 + version = "0.1.1" 2151 + source = "registry+https://github.com/rust-lang/crates.io-index" 2152 + checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 2153 + 2154 + [[package]] 2155 + name = "nom" 2156 + version = "7.1.3" 2157 + source = "registry+https://github.com/rust-lang/crates.io-index" 2158 + checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 2159 + dependencies = [ 2160 + "memchr", 2161 + "minimal-lexical", 2162 + ] 2163 + 2164 + [[package]] 2165 + name = "num-bigint-dig" 2166 + version = "0.8.4" 2167 + source = "registry+https://github.com/rust-lang/crates.io-index" 2168 + checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 2169 + dependencies = [ 2170 + "byteorder", 2171 + "lazy_static", 2172 + "libm", 2173 + "num-integer", 2174 + "num-iter", 2175 + "num-traits", 2176 + "rand 0.8.5", 2177 + "smallvec", 2178 + "zeroize", 2179 + ] 2180 + 2181 + [[package]] 2182 + name = "num-conv" 7 2183 version = "0.1.0" 2184 + source = "registry+https://github.com/rust-lang/crates.io-index" 2185 + checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 2186 + 2187 + [[package]] 2188 + name = "num-integer" 2189 + version = "0.1.46" 2190 + source = "registry+https://github.com/rust-lang/crates.io-index" 2191 + checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 2192 + dependencies = [ 2193 + "num-traits", 2194 + ] 2195 + 2196 + [[package]] 2197 + name = "num-iter" 2198 + version = "0.1.45" 2199 + source = "registry+https://github.com/rust-lang/crates.io-index" 2200 + checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 2201 + dependencies = [ 2202 + "autocfg", 2203 + "num-integer", 2204 + "num-traits", 2205 + ] 2206 + 2207 + [[package]] 2208 + name = "num-traits" 2209 + version = "0.2.19" 2210 + source = "registry+https://github.com/rust-lang/crates.io-index" 2211 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 2212 + dependencies = [ 2213 + "autocfg", 2214 + "libm", 2215 + ] 2216 + 2217 + [[package]] 2218 + name = "num_cpus" 2219 + version = "1.17.0" 2220 + source = "registry+https://github.com/rust-lang/crates.io-index" 2221 + checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" 2222 + dependencies = [ 2223 + "hermit-abi", 2224 + "libc", 2225 + ] 2226 + 2227 + [[package]] 2228 + name = "num_threads" 2229 + version = "0.1.7" 2230 + source = "registry+https://github.com/rust-lang/crates.io-index" 2231 + checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" 2232 + dependencies = [ 2233 + "libc", 2234 + ] 2235 + 2236 + [[package]] 2237 + name = "objc" 2238 + version = "0.2.7" 2239 + source = "registry+https://github.com/rust-lang/crates.io-index" 2240 + checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 2241 + dependencies = [ 2242 + "malloc_buf", 2243 + ] 2244 + 2245 + [[package]] 2246 + name = "object" 2247 + version = "0.37.3" 2248 + source = "registry+https://github.com/rust-lang/crates.io-index" 2249 + checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" 2250 + dependencies = [ 2251 + "memchr", 2252 + ] 2253 + 2254 + [[package]] 2255 + name = "once_cell" 2256 + version = "1.21.3" 2257 + source = "registry+https://github.com/rust-lang/crates.io-index" 2258 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 2259 + 2260 + [[package]] 2261 + name = "once_cell_polyfill" 2262 + version = "1.70.1" 2263 + source = "registry+https://github.com/rust-lang/crates.io-index" 2264 + checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 2265 + 2266 + [[package]] 2267 + name = "openssl" 2268 + version = "0.10.74" 2269 + source = "registry+https://github.com/rust-lang/crates.io-index" 2270 + checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" 2271 + dependencies = [ 2272 + "bitflags", 2273 + "cfg-if", 2274 + "foreign-types", 2275 + "libc", 2276 + "once_cell", 2277 + "openssl-macros", 2278 + "openssl-sys", 2279 + ] 2280 + 2281 + [[package]] 2282 + name = "openssl-macros" 2283 + version = "0.1.1" 2284 + source = "registry+https://github.com/rust-lang/crates.io-index" 2285 + checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 2286 + dependencies = [ 2287 + "proc-macro2", 2288 + "quote", 2289 + "syn 2.0.107", 2290 + ] 2291 + 2292 + [[package]] 2293 + name = "openssl-probe" 2294 + version = "0.1.6" 2295 + source = "registry+https://github.com/rust-lang/crates.io-index" 2296 + checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 2297 + 2298 + [[package]] 2299 + name = "openssl-sys" 2300 + version = "0.9.110" 2301 + source = "registry+https://github.com/rust-lang/crates.io-index" 2302 + checksum = "0a9f0075ba3c21b09f8e8b2026584b1d18d49388648f2fbbf3c97ea8deced8e2" 2303 + dependencies = [ 2304 + "cc", 2305 + "libc", 2306 + "pkg-config", 2307 + "vcpkg", 2308 + ] 2309 + 2310 + [[package]] 2311 + name = "ouroboros" 2312 + version = "0.18.5" 2313 + source = "registry+https://github.com/rust-lang/crates.io-index" 2314 + checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" 2315 + dependencies = [ 2316 + "aliasable", 2317 + "ouroboros_macro", 2318 + "static_assertions", 2319 + ] 2320 + 2321 + [[package]] 2322 + name = "ouroboros_macro" 2323 + version = "0.18.5" 2324 + source = "registry+https://github.com/rust-lang/crates.io-index" 2325 + checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" 2326 + dependencies = [ 2327 + "heck 0.4.1", 2328 + "proc-macro2", 2329 + "proc-macro2-diagnostics", 2330 + "quote", 2331 + "syn 2.0.107", 2332 + ] 2333 + 2334 + [[package]] 2335 + name = "owo-colors" 2336 + version = "4.2.3" 2337 + source = "registry+https://github.com/rust-lang/crates.io-index" 2338 + checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" 2339 + 2340 + [[package]] 2341 + name = "p256" 2342 + version = "0.13.2" 2343 + source = "registry+https://github.com/rust-lang/crates.io-index" 2344 + checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 2345 + dependencies = [ 2346 + "ecdsa", 2347 + "elliptic-curve", 2348 + "primeorder", 2349 + "sha2", 2350 + ] 2351 + 2352 + [[package]] 2353 + name = "p384" 2354 + version = "0.13.1" 2355 + source = "registry+https://github.com/rust-lang/crates.io-index" 2356 + checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" 2357 + dependencies = [ 2358 + "elliptic-curve", 2359 + "primeorder", 2360 + ] 2361 + 2362 + [[package]] 2363 + name = "parking_lot" 2364 + version = "0.12.5" 2365 + source = "registry+https://github.com/rust-lang/crates.io-index" 2366 + checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 2367 + dependencies = [ 2368 + "lock_api", 2369 + "parking_lot_core", 2370 + ] 2371 + 2372 + [[package]] 2373 + name = "parking_lot_core" 2374 + version = "0.9.12" 2375 + source = "registry+https://github.com/rust-lang/crates.io-index" 2376 + checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" 2377 + dependencies = [ 2378 + "cfg-if", 2379 + "libc", 2380 + "redox_syscall", 2381 + "smallvec", 2382 + "windows-link 0.2.1", 2383 + ] 2384 + 2385 + [[package]] 2386 + name = "pem-rfc7468" 2387 + version = "0.7.0" 2388 + source = "registry+https://github.com/rust-lang/crates.io-index" 2389 + checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 2390 + dependencies = [ 2391 + "base64ct", 2392 + ] 2393 + 2394 + [[package]] 2395 + name = "percent-encoding" 2396 + version = "2.3.2" 2397 + source = "registry+https://github.com/rust-lang/crates.io-index" 2398 + checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 2399 + 2400 + [[package]] 2401 + name = "pin-project-lite" 2402 + version = "0.2.16" 2403 + source = "registry+https://github.com/rust-lang/crates.io-index" 2404 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 2405 + 2406 + [[package]] 2407 + name = "pin-utils" 2408 + version = "0.1.0" 2409 + source = "registry+https://github.com/rust-lang/crates.io-index" 2410 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 2411 + 2412 + [[package]] 2413 + name = "pkcs1" 2414 + version = "0.7.5" 2415 + source = "registry+https://github.com/rust-lang/crates.io-index" 2416 + checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 2417 + dependencies = [ 2418 + "der", 2419 + "pkcs8", 2420 + "spki", 2421 + ] 2422 + 2423 + [[package]] 2424 + name = "pkcs8" 2425 + version = "0.10.2" 2426 + source = "registry+https://github.com/rust-lang/crates.io-index" 2427 + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 2428 + dependencies = [ 2429 + "der", 2430 + "spki", 2431 + ] 2432 + 2433 + [[package]] 2434 + name = "pkg-config" 2435 + version = "0.3.32" 2436 + source = "registry+https://github.com/rust-lang/crates.io-index" 2437 + checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 2438 + 2439 + [[package]] 2440 + name = "portable-atomic" 2441 + version = "1.11.1" 2442 + source = "registry+https://github.com/rust-lang/crates.io-index" 2443 + checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" 2444 + 2445 + [[package]] 2446 + name = "portable-atomic-util" 2447 + version = "0.2.4" 2448 + source = "registry+https://github.com/rust-lang/crates.io-index" 2449 + checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" 2450 + dependencies = [ 2451 + "portable-atomic", 2452 + ] 2453 + 2454 + [[package]] 2455 + name = "potential_utf" 2456 + version = "0.1.3" 2457 + source = "registry+https://github.com/rust-lang/crates.io-index" 2458 + checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" 2459 + dependencies = [ 2460 + "zerovec", 2461 + ] 2462 + 2463 + [[package]] 2464 + name = "powerfmt" 2465 + version = "0.2.0" 2466 + source = "registry+https://github.com/rust-lang/crates.io-index" 2467 + checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 2468 + 2469 + [[package]] 2470 + name = "ppv-lite86" 2471 + version = "0.2.21" 2472 + source = "registry+https://github.com/rust-lang/crates.io-index" 2473 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 2474 + dependencies = [ 2475 + "zerocopy", 2476 + ] 2477 + 2478 + [[package]] 2479 + name = "prettyplease" 2480 + version = "0.2.37" 2481 + source = "registry+https://github.com/rust-lang/crates.io-index" 2482 + checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" 2483 + dependencies = [ 2484 + "proc-macro2", 2485 + "syn 2.0.107", 2486 + ] 2487 + 2488 + [[package]] 2489 + name = "primeorder" 2490 + version = "0.13.6" 2491 + source = "registry+https://github.com/rust-lang/crates.io-index" 2492 + checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" 2493 + dependencies = [ 2494 + "elliptic-curve", 2495 + ] 2496 + 2497 + [[package]] 2498 + name = "proc-macro-error" 2499 + version = "0.4.12" 2500 + source = "registry+https://github.com/rust-lang/crates.io-index" 2501 + checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" 2502 + dependencies = [ 2503 + "proc-macro-error-attr 0.4.12", 2504 + "proc-macro2", 2505 + "quote", 2506 + "syn 1.0.109", 2507 + "version_check", 2508 + ] 2509 + 2510 + [[package]] 2511 + name = "proc-macro-error" 2512 + version = "1.0.4" 2513 + source = "registry+https://github.com/rust-lang/crates.io-index" 2514 + checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 2515 + dependencies = [ 2516 + "proc-macro-error-attr 1.0.4", 2517 + "proc-macro2", 2518 + "quote", 2519 + "syn 1.0.109", 2520 + "version_check", 2521 + ] 2522 + 2523 + [[package]] 2524 + name = "proc-macro-error-attr" 2525 + version = "0.4.12" 2526 + source = "registry+https://github.com/rust-lang/crates.io-index" 2527 + checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" 2528 + dependencies = [ 2529 + "proc-macro2", 2530 + "quote", 2531 + "syn 1.0.109", 2532 + "syn-mid", 2533 + "version_check", 2534 + ] 2535 + 2536 + [[package]] 2537 + name = "proc-macro-error-attr" 2538 + version = "1.0.4" 2539 + source = "registry+https://github.com/rust-lang/crates.io-index" 2540 + checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 2541 + dependencies = [ 2542 + "proc-macro2", 2543 + "quote", 2544 + "version_check", 2545 + ] 2546 + 2547 + [[package]] 2548 + name = "proc-macro-hack" 2549 + version = "0.5.20+deprecated" 2550 + source = "registry+https://github.com/rust-lang/crates.io-index" 2551 + checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" 2552 + 2553 + [[package]] 2554 + name = "proc-macro2" 2555 + version = "1.0.101" 2556 + source = "registry+https://github.com/rust-lang/crates.io-index" 2557 + checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 2558 + dependencies = [ 2559 + "unicode-ident", 2560 + ] 2561 + 2562 + [[package]] 2563 + name = "proc-macro2-diagnostics" 2564 + version = "0.10.1" 2565 + source = "registry+https://github.com/rust-lang/crates.io-index" 2566 + checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" 2567 + dependencies = [ 2568 + "proc-macro2", 2569 + "quote", 2570 + "syn 2.0.107", 2571 + "version_check", 2572 + "yansi", 2573 + ] 2574 + 2575 + [[package]] 2576 + name = "quick-error" 2577 + version = "1.2.3" 2578 + source = "registry+https://github.com/rust-lang/crates.io-index" 2579 + checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 2580 + 2581 + [[package]] 2582 + name = "quinn" 2583 + version = "0.11.9" 2584 + source = "registry+https://github.com/rust-lang/crates.io-index" 2585 + checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" 2586 + dependencies = [ 2587 + "bytes", 2588 + "cfg_aliases", 2589 + "pin-project-lite", 2590 + "quinn-proto", 2591 + "quinn-udp", 2592 + "rustc-hash", 2593 + "rustls", 2594 + "socket2 0.6.1", 2595 + "thiserror 2.0.17", 2596 + "tokio", 2597 + "tracing", 2598 + "web-time", 2599 + ] 2600 + 2601 + [[package]] 2602 + name = "quinn-proto" 2603 + version = "0.11.13" 2604 + source = "registry+https://github.com/rust-lang/crates.io-index" 2605 + checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" 2606 + dependencies = [ 2607 + "bytes", 2608 + "getrandom 0.3.4", 2609 + "lru-slab", 2610 + "rand 0.9.2", 2611 + "ring", 2612 + "rustc-hash", 2613 + "rustls", 2614 + "rustls-pki-types", 2615 + "slab", 2616 + "thiserror 2.0.17", 2617 + "tinyvec", 2618 + "tracing", 2619 + "web-time", 2620 + ] 2621 + 2622 + [[package]] 2623 + name = "quinn-udp" 2624 + version = "0.5.14" 2625 + source = "registry+https://github.com/rust-lang/crates.io-index" 2626 + checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" 2627 + dependencies = [ 2628 + "cfg_aliases", 2629 + "libc", 2630 + "once_cell", 2631 + "socket2 0.6.1", 2632 + "tracing", 2633 + "windows-sys 0.60.2", 2634 + ] 2635 + 2636 + [[package]] 2637 + name = "quote" 2638 + version = "1.0.41" 2639 + source = "registry+https://github.com/rust-lang/crates.io-index" 2640 + checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" 2641 + dependencies = [ 2642 + "proc-macro2", 2643 + ] 2644 + 2645 + [[package]] 2646 + name = "r-efi" 2647 + version = "5.3.0" 2648 + source = "registry+https://github.com/rust-lang/crates.io-index" 2649 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 2650 + 2651 + [[package]] 2652 + name = "rand" 2653 + version = "0.8.5" 2654 + source = "registry+https://github.com/rust-lang/crates.io-index" 2655 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2656 + dependencies = [ 2657 + "libc", 2658 + "rand_chacha 0.3.1", 2659 + "rand_core 0.6.4", 2660 + ] 2661 + 2662 + [[package]] 2663 + name = "rand" 2664 + version = "0.9.2" 2665 + source = "registry+https://github.com/rust-lang/crates.io-index" 2666 + checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" 2667 + dependencies = [ 2668 + "rand_chacha 0.9.0", 2669 + "rand_core 0.9.3", 2670 + ] 2671 + 2672 + [[package]] 2673 + name = "rand_chacha" 2674 + version = "0.3.1" 2675 + source = "registry+https://github.com/rust-lang/crates.io-index" 2676 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 2677 + dependencies = [ 2678 + "ppv-lite86", 2679 + "rand_core 0.6.4", 2680 + ] 2681 + 2682 + [[package]] 2683 + name = "rand_chacha" 2684 + version = "0.9.0" 2685 + source = "registry+https://github.com/rust-lang/crates.io-index" 2686 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 2687 + dependencies = [ 2688 + "ppv-lite86", 2689 + "rand_core 0.9.3", 2690 + ] 2691 + 2692 + [[package]] 2693 + name = "rand_core" 2694 + version = "0.6.4" 2695 + source = "registry+https://github.com/rust-lang/crates.io-index" 2696 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2697 + dependencies = [ 2698 + "getrandom 0.2.16", 2699 + ] 2700 + 2701 + [[package]] 2702 + name = "rand_core" 2703 + version = "0.9.3" 2704 + source = "registry+https://github.com/rust-lang/crates.io-index" 2705 + checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 2706 + dependencies = [ 2707 + "getrandom 0.3.4", 2708 + ] 2709 + 2710 + [[package]] 2711 + name = "range-traits" 2712 + version = "0.3.2" 2713 + source = "registry+https://github.com/rust-lang/crates.io-index" 2714 + checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab" 2715 + 2716 + [[package]] 2717 + name = "raw-window-handle" 2718 + version = "0.5.2" 2719 + source = "registry+https://github.com/rust-lang/crates.io-index" 2720 + checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" 2721 + 2722 + [[package]] 2723 + name = "redox_syscall" 2724 + version = "0.5.18" 2725 + source = "registry+https://github.com/rust-lang/crates.io-index" 2726 + checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 2727 + dependencies = [ 2728 + "bitflags", 2729 + ] 2730 + 2731 + [[package]] 2732 + name = "regex" 2733 + version = "1.12.2" 2734 + source = "registry+https://github.com/rust-lang/crates.io-index" 2735 + checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" 2736 + dependencies = [ 2737 + "aho-corasick", 2738 + "memchr", 2739 + "regex-automata", 2740 + "regex-syntax", 2741 + ] 2742 + 2743 + [[package]] 2744 + name = "regex-automata" 2745 + version = "0.4.13" 2746 + source = "registry+https://github.com/rust-lang/crates.io-index" 2747 + checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" 2748 + dependencies = [ 2749 + "aho-corasick", 2750 + "memchr", 2751 + "regex-syntax", 2752 + ] 2753 + 2754 + [[package]] 2755 + name = "regex-syntax" 2756 + version = "0.8.8" 2757 + source = "registry+https://github.com/rust-lang/crates.io-index" 2758 + checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" 2759 + 2760 + [[package]] 2761 + name = "reqwest" 2762 + version = "0.12.24" 2763 + source = "registry+https://github.com/rust-lang/crates.io-index" 2764 + checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" 2765 + dependencies = [ 2766 + "async-compression", 2767 + "base64 0.22.1", 2768 + "bytes", 2769 + "encoding_rs", 2770 + "futures-core", 2771 + "futures-util", 2772 + "h2", 2773 + "http", 2774 + "http-body", 2775 + "http-body-util", 2776 + "hyper", 2777 + "hyper-rustls", 2778 + "hyper-tls", 2779 + "hyper-util", 2780 + "js-sys", 2781 + "log", 2782 + "mime", 2783 + "native-tls", 2784 + "percent-encoding", 2785 + "pin-project-lite", 2786 + "quinn", 2787 + "rustls", 2788 + "rustls-pki-types", 2789 + "serde", 2790 + "serde_json", 2791 + "serde_urlencoded", 2792 + "sync_wrapper", 2793 + "tokio", 2794 + "tokio-native-tls", 2795 + "tokio-rustls", 2796 + "tokio-util", 2797 + "tower", 2798 + "tower-http", 2799 + "tower-service", 2800 + "url", 2801 + "wasm-bindgen", 2802 + "wasm-bindgen-futures", 2803 + "wasm-streams", 2804 + "web-sys", 2805 + "webpki-roots", 2806 + ] 2807 + 2808 + [[package]] 2809 + name = "resolv-conf" 2810 + version = "0.7.5" 2811 + source = "registry+https://github.com/rust-lang/crates.io-index" 2812 + checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799" 2813 + 2814 + [[package]] 2815 + name = "rfc6979" 2816 + version = "0.4.0" 2817 + source = "registry+https://github.com/rust-lang/crates.io-index" 2818 + checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 2819 + dependencies = [ 2820 + "hmac", 2821 + "subtle", 2822 + ] 2823 + 2824 + [[package]] 2825 + name = "ring" 2826 + version = "0.17.14" 2827 + source = "registry+https://github.com/rust-lang/crates.io-index" 2828 + checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 2829 + dependencies = [ 2830 + "cc", 2831 + "cfg-if", 2832 + "getrandom 0.2.16", 2833 + "libc", 2834 + "untrusted", 2835 + "windows-sys 0.52.0", 2836 + ] 2837 + 2838 + [[package]] 2839 + name = "rouille" 2840 + version = "3.6.2" 2841 + source = "registry+https://github.com/rust-lang/crates.io-index" 2842 + checksum = "3716fbf57fc1084d7a706adf4e445298d123e4a44294c4e8213caf1b85fcc921" 2843 + dependencies = [ 2844 + "base64 0.13.1", 2845 + "brotli", 2846 + "chrono", 2847 + "deflate", 2848 + "filetime", 2849 + "multipart", 2850 + "percent-encoding", 2851 + "rand 0.8.5", 2852 + "serde", 2853 + "serde_derive", 2854 + "serde_json", 2855 + "sha1_smol", 2856 + "threadpool", 2857 + "time", 2858 + "tiny_http", 2859 + "url", 2860 + ] 2861 + 2862 + [[package]] 2863 + name = "rsa" 2864 + version = "0.9.8" 2865 + source = "registry+https://github.com/rust-lang/crates.io-index" 2866 + checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" 2867 + dependencies = [ 2868 + "const-oid", 2869 + "digest", 2870 + "num-bigint-dig", 2871 + "num-integer", 2872 + "num-traits", 2873 + "pkcs1", 2874 + "pkcs8", 2875 + "rand_core 0.6.4", 2876 + "signature", 2877 + "spki", 2878 + "subtle", 2879 + "zeroize", 2880 + ] 2881 + 2882 + [[package]] 2883 + name = "rustc-demangle" 2884 + version = "0.1.26" 2885 + source = "registry+https://github.com/rust-lang/crates.io-index" 2886 + checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" 2887 + 2888 + [[package]] 2889 + name = "rustc-hash" 2890 + version = "2.1.1" 2891 + source = "registry+https://github.com/rust-lang/crates.io-index" 2892 + checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 2893 + 2894 + [[package]] 2895 + name = "rustix" 2896 + version = "1.1.2" 2897 + source = "registry+https://github.com/rust-lang/crates.io-index" 2898 + checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" 2899 + dependencies = [ 2900 + "bitflags", 2901 + "errno", 2902 + "libc", 2903 + "linux-raw-sys", 2904 + "windows-sys 0.61.2", 2905 + ] 2906 + 2907 + [[package]] 2908 + name = "rustls" 2909 + version = "0.23.33" 2910 + source = "registry+https://github.com/rust-lang/crates.io-index" 2911 + checksum = "751e04a496ca00bb97a5e043158d23d66b5aabf2e1d5aa2a0aaebb1aafe6f82c" 2912 + dependencies = [ 2913 + "once_cell", 2914 + "ring", 2915 + "rustls-pki-types", 2916 + "rustls-webpki", 2917 + "subtle", 2918 + "zeroize", 2919 + ] 2920 + 2921 + [[package]] 2922 + name = "rustls-pki-types" 2923 + version = "1.12.0" 2924 + source = "registry+https://github.com/rust-lang/crates.io-index" 2925 + checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 2926 + dependencies = [ 2927 + "web-time", 2928 + "zeroize", 2929 + ] 2930 + 2931 + [[package]] 2932 + name = "rustls-webpki" 2933 + version = "0.103.7" 2934 + source = "registry+https://github.com/rust-lang/crates.io-index" 2935 + checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" 2936 + dependencies = [ 2937 + "ring", 2938 + "rustls-pki-types", 2939 + "untrusted", 2940 + ] 2941 + 2942 + [[package]] 2943 + name = "rustversion" 2944 + version = "1.0.22" 2945 + source = "registry+https://github.com/rust-lang/crates.io-index" 2946 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 2947 + 2948 + [[package]] 2949 + name = "ryu" 2950 + version = "1.0.20" 2951 + source = "registry+https://github.com/rust-lang/crates.io-index" 2952 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 2953 + 2954 + [[package]] 2955 + name = "safemem" 2956 + version = "0.3.3" 2957 + source = "registry+https://github.com/rust-lang/crates.io-index" 2958 + checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" 2959 + 2960 + [[package]] 2961 + name = "same-file" 2962 + version = "1.0.6" 2963 + source = "registry+https://github.com/rust-lang/crates.io-index" 2964 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2965 + dependencies = [ 2966 + "winapi-util", 2967 + ] 2968 + 2969 + [[package]] 2970 + name = "schannel" 2971 + version = "0.1.28" 2972 + source = "registry+https://github.com/rust-lang/crates.io-index" 2973 + checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" 2974 + dependencies = [ 2975 + "windows-sys 0.61.2", 2976 + ] 2977 + 2978 + [[package]] 2979 + name = "scopeguard" 2980 + version = "1.2.0" 2981 + source = "registry+https://github.com/rust-lang/crates.io-index" 2982 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2983 + 2984 + [[package]] 2985 + name = "sec1" 2986 + version = "0.7.3" 2987 + source = "registry+https://github.com/rust-lang/crates.io-index" 2988 + checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 2989 + dependencies = [ 2990 + "base16ct", 2991 + "der", 2992 + "generic-array", 2993 + "pkcs8", 2994 + "subtle", 2995 + "zeroize", 2996 + ] 2997 + 2998 + [[package]] 2999 + name = "security-framework" 3000 + version = "2.11.1" 3001 + source = "registry+https://github.com/rust-lang/crates.io-index" 3002 + checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 3003 + dependencies = [ 3004 + "bitflags", 3005 + "core-foundation", 3006 + "core-foundation-sys", 3007 + "libc", 3008 + "security-framework-sys", 3009 + ] 3010 + 3011 + [[package]] 3012 + name = "security-framework-sys" 3013 + version = "2.15.0" 3014 + source = "registry+https://github.com/rust-lang/crates.io-index" 3015 + checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" 3016 + dependencies = [ 3017 + "core-foundation-sys", 3018 + "libc", 3019 + ] 3020 + 3021 + [[package]] 3022 + name = "serde" 3023 + version = "1.0.228" 3024 + source = "registry+https://github.com/rust-lang/crates.io-index" 3025 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 3026 + dependencies = [ 3027 + "serde_core", 3028 + "serde_derive", 3029 + ] 3030 + 3031 + [[package]] 3032 + name = "serde_bytes" 3033 + version = "0.11.19" 3034 + source = "registry+https://github.com/rust-lang/crates.io-index" 3035 + checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" 3036 + dependencies = [ 3037 + "serde", 3038 + "serde_core", 3039 + ] 3040 + 3041 + [[package]] 3042 + name = "serde_core" 3043 + version = "1.0.228" 3044 + source = "registry+https://github.com/rust-lang/crates.io-index" 3045 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 3046 + dependencies = [ 3047 + "serde_derive", 3048 + ] 3049 + 3050 + [[package]] 3051 + name = "serde_derive" 3052 + version = "1.0.228" 3053 + source = "registry+https://github.com/rust-lang/crates.io-index" 3054 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 3055 + dependencies = [ 3056 + "proc-macro2", 3057 + "quote", 3058 + "syn 2.0.107", 3059 + ] 3060 + 3061 + [[package]] 3062 + name = "serde_html_form" 3063 + version = "0.2.8" 3064 + source = "registry+https://github.com/rust-lang/crates.io-index" 3065 + checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" 3066 + dependencies = [ 3067 + "form_urlencoded", 3068 + "indexmap", 3069 + "itoa", 3070 + "ryu", 3071 + "serde_core", 3072 + ] 3073 + 3074 + [[package]] 3075 + name = "serde_ipld_dagcbor" 3076 + version = "0.6.4" 3077 + source = "registry+https://github.com/rust-lang/crates.io-index" 3078 + checksum = "46182f4f08349a02b45c998ba3215d3f9de826246ba02bb9dddfe9a2a2100778" 3079 + dependencies = [ 3080 + "cbor4ii", 3081 + "ipld-core", 3082 + "scopeguard", 3083 + "serde", 3084 + ] 3085 + 3086 + [[package]] 3087 + name = "serde_json" 3088 + version = "1.0.145" 3089 + source = "registry+https://github.com/rust-lang/crates.io-index" 3090 + checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" 3091 + dependencies = [ 3092 + "itoa", 3093 + "memchr", 3094 + "ryu", 3095 + "serde", 3096 + "serde_core", 3097 + ] 3098 + 3099 + [[package]] 3100 + name = "serde_urlencoded" 3101 + version = "0.7.1" 3102 + source = "registry+https://github.com/rust-lang/crates.io-index" 3103 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 3104 + dependencies = [ 3105 + "form_urlencoded", 3106 + "itoa", 3107 + "ryu", 3108 + "serde", 3109 + ] 3110 + 3111 + [[package]] 3112 + name = "sha1_smol" 3113 + version = "1.0.1" 3114 + source = "registry+https://github.com/rust-lang/crates.io-index" 3115 + checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" 3116 + 3117 + [[package]] 3118 + name = "sha2" 3119 + version = "0.10.9" 3120 + source = "registry+https://github.com/rust-lang/crates.io-index" 3121 + checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 3122 + dependencies = [ 3123 + "cfg-if", 3124 + "cpufeatures", 3125 + "digest", 3126 + ] 3127 + 3128 + [[package]] 3129 + name = "shlex" 3130 + version = "1.3.0" 3131 + source = "registry+https://github.com/rust-lang/crates.io-index" 3132 + checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 3133 + 3134 + [[package]] 3135 + name = "signature" 3136 + version = "2.2.0" 3137 + source = "registry+https://github.com/rust-lang/crates.io-index" 3138 + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 3139 + dependencies = [ 3140 + "digest", 3141 + "rand_core 0.6.4", 3142 + ] 3143 + 3144 + [[package]] 3145 + name = "simd-adler32" 3146 + version = "0.3.7" 3147 + source = "registry+https://github.com/rust-lang/crates.io-index" 3148 + checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 3149 + 3150 + [[package]] 3151 + name = "slab" 3152 + version = "0.4.11" 3153 + source = "registry+https://github.com/rust-lang/crates.io-index" 3154 + checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" 3155 + 3156 + [[package]] 3157 + name = "smallvec" 3158 + version = "1.15.1" 3159 + source = "registry+https://github.com/rust-lang/crates.io-index" 3160 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 3161 + 3162 + [[package]] 3163 + name = "smol_str" 3164 + version = "0.3.2" 3165 + source = "registry+https://github.com/rust-lang/crates.io-index" 3166 + checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" 3167 + dependencies = [ 3168 + "borsh", 3169 + "serde", 3170 + ] 3171 + 3172 + [[package]] 3173 + name = "socket2" 3174 + version = "0.5.10" 3175 + source = "registry+https://github.com/rust-lang/crates.io-index" 3176 + checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 3177 + dependencies = [ 3178 + "libc", 3179 + "windows-sys 0.52.0", 3180 + ] 3181 + 3182 + [[package]] 3183 + name = "socket2" 3184 + version = "0.6.1" 3185 + source = "registry+https://github.com/rust-lang/crates.io-index" 3186 + checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" 3187 + dependencies = [ 3188 + "libc", 3189 + "windows-sys 0.60.2", 3190 + ] 3191 + 3192 + [[package]] 3193 + name = "spin" 3194 + version = "0.9.8" 3195 + source = "registry+https://github.com/rust-lang/crates.io-index" 3196 + checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 3197 + 3198 + [[package]] 3199 + name = "spki" 3200 + version = "0.7.3" 3201 + source = "registry+https://github.com/rust-lang/crates.io-index" 3202 + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 3203 + dependencies = [ 3204 + "base64ct", 3205 + "der", 3206 + ] 3207 + 3208 + [[package]] 3209 + name = "stable_deref_trait" 3210 + version = "1.2.1" 3211 + source = "registry+https://github.com/rust-lang/crates.io-index" 3212 + checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 3213 + 3214 + [[package]] 3215 + name = "static-regular-grammar" 3216 + version = "2.0.2" 3217 + source = "registry+https://github.com/rust-lang/crates.io-index" 3218 + checksum = "4f4a6c40247579acfbb138c3cd7de3dab113ab4ac6227f1b7de7d626ee667957" 3219 + dependencies = [ 3220 + "abnf", 3221 + "btree-range-map", 3222 + "ciborium", 3223 + "hex_fmt", 3224 + "indoc", 3225 + "proc-macro-error 1.0.4", 3226 + "proc-macro2", 3227 + "quote", 3228 + "serde", 3229 + "sha2", 3230 + "syn 2.0.107", 3231 + "thiserror 1.0.69", 3232 + ] 3233 + 3234 + [[package]] 3235 + name = "static_assertions" 3236 + version = "1.1.0" 3237 + source = "registry+https://github.com/rust-lang/crates.io-index" 3238 + checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 3239 + 3240 + [[package]] 3241 + name = "strsim" 3242 + version = "0.11.1" 3243 + source = "registry+https://github.com/rust-lang/crates.io-index" 3244 + checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 3245 + 3246 + [[package]] 3247 + name = "subtle" 3248 + version = "2.6.1" 3249 + source = "registry+https://github.com/rust-lang/crates.io-index" 3250 + checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 3251 + 3252 + [[package]] 3253 + name = "supports-color" 3254 + version = "3.0.2" 3255 + source = "registry+https://github.com/rust-lang/crates.io-index" 3256 + checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" 3257 + dependencies = [ 3258 + "is_ci", 3259 + ] 3260 + 3261 + [[package]] 3262 + name = "supports-hyperlinks" 3263 + version = "3.1.0" 3264 + source = "registry+https://github.com/rust-lang/crates.io-index" 3265 + checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" 3266 + 3267 + [[package]] 3268 + name = "supports-unicode" 3269 + version = "3.0.0" 3270 + source = "registry+https://github.com/rust-lang/crates.io-index" 3271 + checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" 3272 + 3273 + [[package]] 3274 + name = "syn" 3275 + version = "1.0.109" 3276 + source = "registry+https://github.com/rust-lang/crates.io-index" 3277 + checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 3278 + dependencies = [ 3279 + "proc-macro2", 3280 + "quote", 3281 + "unicode-ident", 3282 + ] 3283 + 3284 + [[package]] 3285 + name = "syn" 3286 + version = "2.0.107" 3287 + source = "registry+https://github.com/rust-lang/crates.io-index" 3288 + checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" 3289 + dependencies = [ 3290 + "proc-macro2", 3291 + "quote", 3292 + "unicode-ident", 3293 + ] 3294 + 3295 + [[package]] 3296 + name = "syn-mid" 3297 + version = "0.5.4" 3298 + source = "registry+https://github.com/rust-lang/crates.io-index" 3299 + checksum = "fea305d57546cc8cd04feb14b62ec84bf17f50e3f7b12560d7bfa9265f39d9ed" 3300 + dependencies = [ 3301 + "proc-macro2", 3302 + "quote", 3303 + "syn 1.0.109", 3304 + ] 3305 + 3306 + [[package]] 3307 + name = "sync_wrapper" 3308 + version = "1.0.2" 3309 + source = "registry+https://github.com/rust-lang/crates.io-index" 3310 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 3311 + dependencies = [ 3312 + "futures-core", 3313 + ] 3314 + 3315 + [[package]] 3316 + name = "synstructure" 3317 + version = "0.13.2" 3318 + source = "registry+https://github.com/rust-lang/crates.io-index" 3319 + checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 3320 + dependencies = [ 3321 + "proc-macro2", 3322 + "quote", 3323 + "syn 2.0.107", 3324 + ] 3325 + 3326 + [[package]] 3327 + name = "system-configuration" 3328 + version = "0.6.1" 3329 + source = "registry+https://github.com/rust-lang/crates.io-index" 3330 + checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 3331 + dependencies = [ 3332 + "bitflags", 3333 + "core-foundation", 3334 + "system-configuration-sys", 3335 + ] 3336 + 3337 + [[package]] 3338 + name = "system-configuration-sys" 3339 + version = "0.6.0" 3340 + source = "registry+https://github.com/rust-lang/crates.io-index" 3341 + checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 3342 + dependencies = [ 3343 + "core-foundation-sys", 3344 + "libc", 3345 + ] 3346 + 3347 + [[package]] 3348 + name = "tempfile" 3349 + version = "3.23.0" 3350 + source = "registry+https://github.com/rust-lang/crates.io-index" 3351 + checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" 3352 + dependencies = [ 3353 + "fastrand", 3354 + "getrandom 0.3.4", 3355 + "once_cell", 3356 + "rustix", 3357 + "windows-sys 0.61.2", 3358 + ] 3359 + 3360 + [[package]] 3361 + name = "terminal_size" 3362 + version = "0.4.3" 3363 + source = "registry+https://github.com/rust-lang/crates.io-index" 3364 + checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" 3365 + dependencies = [ 3366 + "rustix", 3367 + "windows-sys 0.60.2", 3368 + ] 3369 + 3370 + [[package]] 3371 + name = "textwrap" 3372 + version = "0.16.2" 3373 + source = "registry+https://github.com/rust-lang/crates.io-index" 3374 + checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" 3375 + dependencies = [ 3376 + "unicode-linebreak", 3377 + "unicode-width 0.2.2", 3378 + ] 3379 + 3380 + [[package]] 3381 + name = "thiserror" 3382 + version = "1.0.69" 3383 + source = "registry+https://github.com/rust-lang/crates.io-index" 3384 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 3385 + dependencies = [ 3386 + "thiserror-impl 1.0.69", 3387 + ] 3388 + 3389 + [[package]] 3390 + name = "thiserror" 3391 + version = "2.0.17" 3392 + source = "registry+https://github.com/rust-lang/crates.io-index" 3393 + checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" 3394 + dependencies = [ 3395 + "thiserror-impl 2.0.17", 3396 + ] 3397 + 3398 + [[package]] 3399 + name = "thiserror-impl" 3400 + version = "1.0.69" 3401 + source = "registry+https://github.com/rust-lang/crates.io-index" 3402 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 3403 + dependencies = [ 3404 + "proc-macro2", 3405 + "quote", 3406 + "syn 2.0.107", 3407 + ] 3408 + 3409 + [[package]] 3410 + name = "thiserror-impl" 3411 + version = "2.0.17" 3412 + source = "registry+https://github.com/rust-lang/crates.io-index" 3413 + checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" 3414 + dependencies = [ 3415 + "proc-macro2", 3416 + "quote", 3417 + "syn 2.0.107", 3418 + ] 3419 + 3420 + [[package]] 3421 + name = "threadpool" 3422 + version = "1.8.1" 3423 + source = "registry+https://github.com/rust-lang/crates.io-index" 3424 + checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" 3425 + dependencies = [ 3426 + "num_cpus", 3427 + ] 3428 + 3429 + [[package]] 3430 + name = "time" 3431 + version = "0.3.44" 3432 + source = "registry+https://github.com/rust-lang/crates.io-index" 3433 + checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" 3434 + dependencies = [ 3435 + "deranged", 3436 + "libc", 3437 + "num-conv", 3438 + "num_threads", 3439 + "powerfmt", 3440 + "serde", 3441 + "time-core", 3442 + ] 3443 + 3444 + [[package]] 3445 + name = "time-core" 3446 + version = "0.1.6" 3447 + source = "registry+https://github.com/rust-lang/crates.io-index" 3448 + checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" 3449 + 3450 + [[package]] 3451 + name = "tiny_http" 3452 + version = "0.12.0" 3453 + source = "registry+https://github.com/rust-lang/crates.io-index" 3454 + checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" 3455 + dependencies = [ 3456 + "ascii", 3457 + "chunked_transfer", 3458 + "httpdate", 3459 + "log", 3460 + ] 3461 + 3462 + [[package]] 3463 + name = "tinystr" 3464 + version = "0.8.1" 3465 + source = "registry+https://github.com/rust-lang/crates.io-index" 3466 + checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 3467 + dependencies = [ 3468 + "displaydoc", 3469 + "zerovec", 3470 + ] 3471 + 3472 + [[package]] 3473 + name = "tinyvec" 3474 + version = "1.10.0" 3475 + source = "registry+https://github.com/rust-lang/crates.io-index" 3476 + checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" 3477 + dependencies = [ 3478 + "tinyvec_macros", 3479 + ] 3480 + 3481 + [[package]] 3482 + name = "tinyvec_macros" 3483 + version = "0.1.1" 3484 + source = "registry+https://github.com/rust-lang/crates.io-index" 3485 + checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 3486 + 3487 + [[package]] 3488 + name = "tokio" 3489 + version = "1.48.0" 3490 + source = "registry+https://github.com/rust-lang/crates.io-index" 3491 + checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" 3492 + dependencies = [ 3493 + "bytes", 3494 + "libc", 3495 + "mio", 3496 + "pin-project-lite", 3497 + "socket2 0.6.1", 3498 + "tokio-macros", 3499 + "windows-sys 0.61.2", 3500 + ] 3501 + 3502 + [[package]] 3503 + name = "tokio-macros" 3504 + version = "2.6.0" 3505 + source = "registry+https://github.com/rust-lang/crates.io-index" 3506 + checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" 3507 + dependencies = [ 3508 + "proc-macro2", 3509 + "quote", 3510 + "syn 2.0.107", 3511 + ] 3512 + 3513 + [[package]] 3514 + name = "tokio-native-tls" 3515 + version = "0.3.1" 3516 + source = "registry+https://github.com/rust-lang/crates.io-index" 3517 + checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 3518 + dependencies = [ 3519 + "native-tls", 3520 + "tokio", 3521 + ] 3522 + 3523 + [[package]] 3524 + name = "tokio-rustls" 3525 + version = "0.26.4" 3526 + source = "registry+https://github.com/rust-lang/crates.io-index" 3527 + checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 3528 + dependencies = [ 3529 + "rustls", 3530 + "tokio", 3531 + ] 3532 + 3533 + [[package]] 3534 + name = "tokio-util" 3535 + version = "0.7.16" 3536 + source = "registry+https://github.com/rust-lang/crates.io-index" 3537 + checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" 3538 + dependencies = [ 3539 + "bytes", 3540 + "futures-core", 3541 + "futures-sink", 3542 + "pin-project-lite", 3543 + "tokio", 3544 + ] 3545 + 3546 + [[package]] 3547 + name = "tower" 3548 + version = "0.5.2" 3549 + source = "registry+https://github.com/rust-lang/crates.io-index" 3550 + checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 3551 + dependencies = [ 3552 + "futures-core", 3553 + "futures-util", 3554 + "pin-project-lite", 3555 + "sync_wrapper", 3556 + "tokio", 3557 + "tower-layer", 3558 + "tower-service", 3559 + ] 3560 + 3561 + [[package]] 3562 + name = "tower-http" 3563 + version = "0.6.6" 3564 + source = "registry+https://github.com/rust-lang/crates.io-index" 3565 + checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 3566 + dependencies = [ 3567 + "bitflags", 3568 + "bytes", 3569 + "futures-util", 3570 + "http", 3571 + "http-body", 3572 + "iri-string", 3573 + "pin-project-lite", 3574 + "tower", 3575 + "tower-layer", 3576 + "tower-service", 3577 + ] 3578 + 3579 + [[package]] 3580 + name = "tower-layer" 3581 + version = "0.3.3" 3582 + source = "registry+https://github.com/rust-lang/crates.io-index" 3583 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 3584 + 3585 + [[package]] 3586 + name = "tower-service" 3587 + version = "0.3.3" 3588 + source = "registry+https://github.com/rust-lang/crates.io-index" 3589 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 3590 + 3591 + [[package]] 3592 + name = "tracing" 3593 + version = "0.1.41" 3594 + source = "registry+https://github.com/rust-lang/crates.io-index" 3595 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 3596 + dependencies = [ 3597 + "pin-project-lite", 3598 + "tracing-attributes", 3599 + "tracing-core", 3600 + ] 3601 + 3602 + [[package]] 3603 + name = "tracing-attributes" 3604 + version = "0.1.30" 3605 + source = "registry+https://github.com/rust-lang/crates.io-index" 3606 + checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 3607 + dependencies = [ 3608 + "proc-macro2", 3609 + "quote", 3610 + "syn 2.0.107", 3611 + ] 3612 + 3613 + [[package]] 3614 + name = "tracing-core" 3615 + version = "0.1.34" 3616 + source = "registry+https://github.com/rust-lang/crates.io-index" 3617 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 3618 + dependencies = [ 3619 + "once_cell", 3620 + ] 3621 + 3622 + [[package]] 3623 + name = "trait-variant" 3624 + version = "0.1.2" 3625 + source = "registry+https://github.com/rust-lang/crates.io-index" 3626 + checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" 3627 + dependencies = [ 3628 + "proc-macro2", 3629 + "quote", 3630 + "syn 2.0.107", 3631 + ] 3632 + 3633 + [[package]] 3634 + name = "try-lock" 3635 + version = "0.2.5" 3636 + source = "registry+https://github.com/rust-lang/crates.io-index" 3637 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 3638 + 3639 + [[package]] 3640 + name = "twoway" 3641 + version = "0.1.8" 3642 + source = "registry+https://github.com/rust-lang/crates.io-index" 3643 + checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" 3644 + dependencies = [ 3645 + "memchr", 3646 + ] 3647 + 3648 + [[package]] 3649 + name = "typenum" 3650 + version = "1.19.0" 3651 + source = "registry+https://github.com/rust-lang/crates.io-index" 3652 + checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" 3653 + 3654 + [[package]] 3655 + name = "unicase" 3656 + version = "2.8.1" 3657 + source = "registry+https://github.com/rust-lang/crates.io-index" 3658 + checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" 3659 + 3660 + [[package]] 3661 + name = "unicode-ident" 3662 + version = "1.0.19" 3663 + source = "registry+https://github.com/rust-lang/crates.io-index" 3664 + checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 3665 + 3666 + [[package]] 3667 + name = "unicode-linebreak" 3668 + version = "0.1.5" 3669 + source = "registry+https://github.com/rust-lang/crates.io-index" 3670 + checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" 3671 + 3672 + [[package]] 3673 + name = "unicode-width" 3674 + version = "0.1.14" 3675 + source = "registry+https://github.com/rust-lang/crates.io-index" 3676 + checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" 3677 + 3678 + [[package]] 3679 + name = "unicode-width" 3680 + version = "0.2.2" 3681 + source = "registry+https://github.com/rust-lang/crates.io-index" 3682 + checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" 3683 + 3684 + [[package]] 3685 + name = "unsigned-varint" 3686 + version = "0.8.0" 3687 + source = "registry+https://github.com/rust-lang/crates.io-index" 3688 + checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" 3689 + 3690 + [[package]] 3691 + name = "untrusted" 3692 + version = "0.9.0" 3693 + source = "registry+https://github.com/rust-lang/crates.io-index" 3694 + checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3695 + 3696 + [[package]] 3697 + name = "url" 3698 + version = "2.5.7" 3699 + source = "registry+https://github.com/rust-lang/crates.io-index" 3700 + checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" 3701 + dependencies = [ 3702 + "form_urlencoded", 3703 + "idna", 3704 + "percent-encoding", 3705 + "serde", 3706 + ] 3707 + 3708 + [[package]] 3709 + name = "urlencoding" 3710 + version = "2.1.3" 3711 + source = "registry+https://github.com/rust-lang/crates.io-index" 3712 + checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 3713 + 3714 + [[package]] 3715 + name = "utf8_iter" 3716 + version = "1.0.4" 3717 + source = "registry+https://github.com/rust-lang/crates.io-index" 3718 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 3719 + 3720 + [[package]] 3721 + name = "utf8parse" 3722 + version = "0.2.2" 3723 + source = "registry+https://github.com/rust-lang/crates.io-index" 3724 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 3725 + 3726 + [[package]] 3727 + name = "vcpkg" 3728 + version = "0.2.15" 3729 + source = "registry+https://github.com/rust-lang/crates.io-index" 3730 + checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 3731 + 3732 + [[package]] 3733 + name = "version_check" 3734 + version = "0.9.5" 3735 + source = "registry+https://github.com/rust-lang/crates.io-index" 3736 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3737 + 3738 + [[package]] 3739 + name = "walkdir" 3740 + version = "2.5.0" 3741 + source = "registry+https://github.com/rust-lang/crates.io-index" 3742 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 3743 + dependencies = [ 3744 + "same-file", 3745 + "winapi-util", 3746 + ] 3747 + 3748 + [[package]] 3749 + name = "want" 3750 + version = "0.3.1" 3751 + source = "registry+https://github.com/rust-lang/crates.io-index" 3752 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 3753 + dependencies = [ 3754 + "try-lock", 3755 + ] 3756 + 3757 + [[package]] 3758 + name = "wasi" 3759 + version = "0.11.1+wasi-snapshot-preview1" 3760 + source = "registry+https://github.com/rust-lang/crates.io-index" 3761 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 3762 + 3763 + [[package]] 3764 + name = "wasip2" 3765 + version = "1.0.1+wasi-0.2.4" 3766 + source = "registry+https://github.com/rust-lang/crates.io-index" 3767 + checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" 3768 + dependencies = [ 3769 + "wit-bindgen", 3770 + ] 3771 + 3772 + [[package]] 3773 + name = "wasm-bindgen" 3774 + version = "0.2.104" 3775 + source = "registry+https://github.com/rust-lang/crates.io-index" 3776 + checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" 3777 + dependencies = [ 3778 + "cfg-if", 3779 + "once_cell", 3780 + "rustversion", 3781 + "wasm-bindgen-macro", 3782 + "wasm-bindgen-shared", 3783 + ] 3784 + 3785 + [[package]] 3786 + name = "wasm-bindgen-backend" 3787 + version = "0.2.104" 3788 + source = "registry+https://github.com/rust-lang/crates.io-index" 3789 + checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" 3790 + dependencies = [ 3791 + "bumpalo", 3792 + "log", 3793 + "proc-macro2", 3794 + "quote", 3795 + "syn 2.0.107", 3796 + "wasm-bindgen-shared", 3797 + ] 3798 + 3799 + [[package]] 3800 + name = "wasm-bindgen-futures" 3801 + version = "0.4.54" 3802 + source = "registry+https://github.com/rust-lang/crates.io-index" 3803 + checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" 3804 + dependencies = [ 3805 + "cfg-if", 3806 + "js-sys", 3807 + "once_cell", 3808 + "wasm-bindgen", 3809 + "web-sys", 3810 + ] 3811 + 3812 + [[package]] 3813 + name = "wasm-bindgen-macro" 3814 + version = "0.2.104" 3815 + source = "registry+https://github.com/rust-lang/crates.io-index" 3816 + checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" 3817 + dependencies = [ 3818 + "quote", 3819 + "wasm-bindgen-macro-support", 3820 + ] 3821 + 3822 + [[package]] 3823 + name = "wasm-bindgen-macro-support" 3824 + version = "0.2.104" 3825 + source = "registry+https://github.com/rust-lang/crates.io-index" 3826 + checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" 3827 + dependencies = [ 3828 + "proc-macro2", 3829 + "quote", 3830 + "syn 2.0.107", 3831 + "wasm-bindgen-backend", 3832 + "wasm-bindgen-shared", 3833 + ] 3834 + 3835 + [[package]] 3836 + name = "wasm-bindgen-shared" 3837 + version = "0.2.104" 3838 + source = "registry+https://github.com/rust-lang/crates.io-index" 3839 + checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" 3840 + dependencies = [ 3841 + "unicode-ident", 3842 + ] 3843 + 3844 + [[package]] 3845 + name = "wasm-streams" 3846 + version = "0.4.2" 3847 + source = "registry+https://github.com/rust-lang/crates.io-index" 3848 + checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" 3849 + dependencies = [ 3850 + "futures-util", 3851 + "js-sys", 3852 + "wasm-bindgen", 3853 + "wasm-bindgen-futures", 3854 + "web-sys", 3855 + ] 3856 + 3857 + [[package]] 3858 + name = "web-sys" 3859 + version = "0.3.81" 3860 + source = "registry+https://github.com/rust-lang/crates.io-index" 3861 + checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" 3862 + dependencies = [ 3863 + "js-sys", 3864 + "wasm-bindgen", 3865 + ] 3866 + 3867 + [[package]] 3868 + name = "web-time" 3869 + version = "1.1.0" 3870 + source = "registry+https://github.com/rust-lang/crates.io-index" 3871 + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 3872 + dependencies = [ 3873 + "js-sys", 3874 + "wasm-bindgen", 3875 + ] 3876 + 3877 + [[package]] 3878 + name = "webbrowser" 3879 + version = "0.8.15" 3880 + source = "registry+https://github.com/rust-lang/crates.io-index" 3881 + checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" 3882 + dependencies = [ 3883 + "core-foundation", 3884 + "home", 3885 + "jni", 3886 + "log", 3887 + "ndk-context", 3888 + "objc", 3889 + "raw-window-handle", 3890 + "url", 3891 + "web-sys", 3892 + ] 3893 + 3894 + [[package]] 3895 + name = "webpki-roots" 3896 + version = "1.0.3" 3897 + source = "registry+https://github.com/rust-lang/crates.io-index" 3898 + checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" 3899 + dependencies = [ 3900 + "rustls-pki-types", 3901 + ] 3902 + 3903 + [[package]] 3904 + name = "widestring" 3905 + version = "1.2.1" 3906 + source = "registry+https://github.com/rust-lang/crates.io-index" 3907 + checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" 3908 + 3909 + [[package]] 3910 + name = "winapi-util" 3911 + version = "0.1.11" 3912 + source = "registry+https://github.com/rust-lang/crates.io-index" 3913 + checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 3914 + dependencies = [ 3915 + "windows-sys 0.61.2", 3916 + ] 3917 + 3918 + [[package]] 3919 + name = "windows-core" 3920 + version = "0.62.2" 3921 + source = "registry+https://github.com/rust-lang/crates.io-index" 3922 + checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" 3923 + dependencies = [ 3924 + "windows-implement", 3925 + "windows-interface", 3926 + "windows-link 0.2.1", 3927 + "windows-result 0.4.1", 3928 + "windows-strings 0.5.1", 3929 + ] 3930 + 3931 + [[package]] 3932 + name = "windows-implement" 3933 + version = "0.60.2" 3934 + source = "registry+https://github.com/rust-lang/crates.io-index" 3935 + checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" 3936 + dependencies = [ 3937 + "proc-macro2", 3938 + "quote", 3939 + "syn 2.0.107", 3940 + ] 3941 + 3942 + [[package]] 3943 + name = "windows-interface" 3944 + version = "0.59.3" 3945 + source = "registry+https://github.com/rust-lang/crates.io-index" 3946 + checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" 3947 + dependencies = [ 3948 + "proc-macro2", 3949 + "quote", 3950 + "syn 2.0.107", 3951 + ] 3952 + 3953 + [[package]] 3954 + name = "windows-link" 3955 + version = "0.1.3" 3956 + source = "registry+https://github.com/rust-lang/crates.io-index" 3957 + checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 3958 + 3959 + [[package]] 3960 + name = "windows-link" 3961 + version = "0.2.1" 3962 + source = "registry+https://github.com/rust-lang/crates.io-index" 3963 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 3964 + 3965 + [[package]] 3966 + name = "windows-registry" 3967 + version = "0.5.3" 3968 + source = "registry+https://github.com/rust-lang/crates.io-index" 3969 + checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" 3970 + dependencies = [ 3971 + "windows-link 0.1.3", 3972 + "windows-result 0.3.4", 3973 + "windows-strings 0.4.2", 3974 + ] 3975 + 3976 + [[package]] 3977 + name = "windows-result" 3978 + version = "0.3.4" 3979 + source = "registry+https://github.com/rust-lang/crates.io-index" 3980 + checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" 3981 + dependencies = [ 3982 + "windows-link 0.1.3", 3983 + ] 3984 + 3985 + [[package]] 3986 + name = "windows-result" 3987 + version = "0.4.1" 3988 + source = "registry+https://github.com/rust-lang/crates.io-index" 3989 + checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" 3990 + dependencies = [ 3991 + "windows-link 0.2.1", 3992 + ] 3993 + 3994 + [[package]] 3995 + name = "windows-strings" 3996 + version = "0.4.2" 3997 + source = "registry+https://github.com/rust-lang/crates.io-index" 3998 + checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" 3999 + dependencies = [ 4000 + "windows-link 0.1.3", 4001 + ] 4002 + 4003 + [[package]] 4004 + name = "windows-strings" 4005 + version = "0.5.1" 4006 + source = "registry+https://github.com/rust-lang/crates.io-index" 4007 + checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" 4008 + dependencies = [ 4009 + "windows-link 0.2.1", 4010 + ] 4011 + 4012 + [[package]] 4013 + name = "windows-sys" 4014 + version = "0.45.0" 4015 + source = "registry+https://github.com/rust-lang/crates.io-index" 4016 + checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 4017 + dependencies = [ 4018 + "windows-targets 0.42.2", 4019 + ] 4020 + 4021 + [[package]] 4022 + name = "windows-sys" 4023 + version = "0.48.0" 4024 + source = "registry+https://github.com/rust-lang/crates.io-index" 4025 + checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 4026 + dependencies = [ 4027 + "windows-targets 0.48.5", 4028 + ] 4029 + 4030 + [[package]] 4031 + name = "windows-sys" 4032 + version = "0.52.0" 4033 + source = "registry+https://github.com/rust-lang/crates.io-index" 4034 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 4035 + dependencies = [ 4036 + "windows-targets 0.52.6", 4037 + ] 4038 + 4039 + [[package]] 4040 + name = "windows-sys" 4041 + version = "0.59.0" 4042 + source = "registry+https://github.com/rust-lang/crates.io-index" 4043 + checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 4044 + dependencies = [ 4045 + "windows-targets 0.52.6", 4046 + ] 4047 + 4048 + [[package]] 4049 + name = "windows-sys" 4050 + version = "0.60.2" 4051 + source = "registry+https://github.com/rust-lang/crates.io-index" 4052 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 4053 + dependencies = [ 4054 + "windows-targets 0.53.5", 4055 + ] 4056 + 4057 + [[package]] 4058 + name = "windows-sys" 4059 + version = "0.61.2" 4060 + source = "registry+https://github.com/rust-lang/crates.io-index" 4061 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 4062 + dependencies = [ 4063 + "windows-link 0.2.1", 4064 + ] 4065 + 4066 + [[package]] 4067 + name = "windows-targets" 4068 + version = "0.42.2" 4069 + source = "registry+https://github.com/rust-lang/crates.io-index" 4070 + checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 4071 + dependencies = [ 4072 + "windows_aarch64_gnullvm 0.42.2", 4073 + "windows_aarch64_msvc 0.42.2", 4074 + "windows_i686_gnu 0.42.2", 4075 + "windows_i686_msvc 0.42.2", 4076 + "windows_x86_64_gnu 0.42.2", 4077 + "windows_x86_64_gnullvm 0.42.2", 4078 + "windows_x86_64_msvc 0.42.2", 4079 + ] 4080 + 4081 + [[package]] 4082 + name = "windows-targets" 4083 + version = "0.48.5" 4084 + source = "registry+https://github.com/rust-lang/crates.io-index" 4085 + checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 4086 + dependencies = [ 4087 + "windows_aarch64_gnullvm 0.48.5", 4088 + "windows_aarch64_msvc 0.48.5", 4089 + "windows_i686_gnu 0.48.5", 4090 + "windows_i686_msvc 0.48.5", 4091 + "windows_x86_64_gnu 0.48.5", 4092 + "windows_x86_64_gnullvm 0.48.5", 4093 + "windows_x86_64_msvc 0.48.5", 4094 + ] 4095 + 4096 + [[package]] 4097 + name = "windows-targets" 4098 + version = "0.52.6" 4099 + source = "registry+https://github.com/rust-lang/crates.io-index" 4100 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 4101 + dependencies = [ 4102 + "windows_aarch64_gnullvm 0.52.6", 4103 + "windows_aarch64_msvc 0.52.6", 4104 + "windows_i686_gnu 0.52.6", 4105 + "windows_i686_gnullvm 0.52.6", 4106 + "windows_i686_msvc 0.52.6", 4107 + "windows_x86_64_gnu 0.52.6", 4108 + "windows_x86_64_gnullvm 0.52.6", 4109 + "windows_x86_64_msvc 0.52.6", 4110 + ] 4111 + 4112 + [[package]] 4113 + name = "windows-targets" 4114 + version = "0.53.5" 4115 + source = "registry+https://github.com/rust-lang/crates.io-index" 4116 + checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 4117 + dependencies = [ 4118 + "windows-link 0.2.1", 4119 + "windows_aarch64_gnullvm 0.53.1", 4120 + "windows_aarch64_msvc 0.53.1", 4121 + "windows_i686_gnu 0.53.1", 4122 + "windows_i686_gnullvm 0.53.1", 4123 + "windows_i686_msvc 0.53.1", 4124 + "windows_x86_64_gnu 0.53.1", 4125 + "windows_x86_64_gnullvm 0.53.1", 4126 + "windows_x86_64_msvc 0.53.1", 4127 + ] 4128 + 4129 + [[package]] 4130 + name = "windows_aarch64_gnullvm" 4131 + version = "0.42.2" 4132 + source = "registry+https://github.com/rust-lang/crates.io-index" 4133 + checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 4134 + 4135 + [[package]] 4136 + name = "windows_aarch64_gnullvm" 4137 + version = "0.48.5" 4138 + source = "registry+https://github.com/rust-lang/crates.io-index" 4139 + checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 4140 + 4141 + [[package]] 4142 + name = "windows_aarch64_gnullvm" 4143 + version = "0.52.6" 4144 + source = "registry+https://github.com/rust-lang/crates.io-index" 4145 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 4146 + 4147 + [[package]] 4148 + name = "windows_aarch64_gnullvm" 4149 + version = "0.53.1" 4150 + source = "registry+https://github.com/rust-lang/crates.io-index" 4151 + checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 4152 + 4153 + [[package]] 4154 + name = "windows_aarch64_msvc" 4155 + version = "0.42.2" 4156 + source = "registry+https://github.com/rust-lang/crates.io-index" 4157 + checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 4158 + 4159 + [[package]] 4160 + name = "windows_aarch64_msvc" 4161 + version = "0.48.5" 4162 + source = "registry+https://github.com/rust-lang/crates.io-index" 4163 + checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 4164 + 4165 + [[package]] 4166 + name = "windows_aarch64_msvc" 4167 + version = "0.52.6" 4168 + source = "registry+https://github.com/rust-lang/crates.io-index" 4169 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 4170 + 4171 + [[package]] 4172 + name = "windows_aarch64_msvc" 4173 + version = "0.53.1" 4174 + source = "registry+https://github.com/rust-lang/crates.io-index" 4175 + checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 4176 + 4177 + [[package]] 4178 + name = "windows_i686_gnu" 4179 + version = "0.42.2" 4180 + source = "registry+https://github.com/rust-lang/crates.io-index" 4181 + checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 4182 + 4183 + [[package]] 4184 + name = "windows_i686_gnu" 4185 + version = "0.48.5" 4186 + source = "registry+https://github.com/rust-lang/crates.io-index" 4187 + checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 4188 + 4189 + [[package]] 4190 + name = "windows_i686_gnu" 4191 + version = "0.52.6" 4192 + source = "registry+https://github.com/rust-lang/crates.io-index" 4193 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 4194 + 4195 + [[package]] 4196 + name = "windows_i686_gnu" 4197 + version = "0.53.1" 4198 + source = "registry+https://github.com/rust-lang/crates.io-index" 4199 + checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 4200 + 4201 + [[package]] 4202 + name = "windows_i686_gnullvm" 4203 + version = "0.52.6" 4204 + source = "registry+https://github.com/rust-lang/crates.io-index" 4205 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 4206 + 4207 + [[package]] 4208 + name = "windows_i686_gnullvm" 4209 + version = "0.53.1" 4210 + source = "registry+https://github.com/rust-lang/crates.io-index" 4211 + checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 4212 + 4213 + [[package]] 4214 + name = "windows_i686_msvc" 4215 + version = "0.42.2" 4216 + source = "registry+https://github.com/rust-lang/crates.io-index" 4217 + checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 4218 + 4219 + [[package]] 4220 + name = "windows_i686_msvc" 4221 + version = "0.48.5" 4222 + source = "registry+https://github.com/rust-lang/crates.io-index" 4223 + checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 4224 + 4225 + [[package]] 4226 + name = "windows_i686_msvc" 4227 + version = "0.52.6" 4228 + source = "registry+https://github.com/rust-lang/crates.io-index" 4229 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 4230 + 4231 + [[package]] 4232 + name = "windows_i686_msvc" 4233 + version = "0.53.1" 4234 + source = "registry+https://github.com/rust-lang/crates.io-index" 4235 + checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 4236 + 4237 + [[package]] 4238 + name = "windows_x86_64_gnu" 4239 + version = "0.42.2" 4240 + source = "registry+https://github.com/rust-lang/crates.io-index" 4241 + checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 4242 + 4243 + [[package]] 4244 + name = "windows_x86_64_gnu" 4245 + version = "0.48.5" 4246 + source = "registry+https://github.com/rust-lang/crates.io-index" 4247 + checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 4248 + 4249 + [[package]] 4250 + name = "windows_x86_64_gnu" 4251 + version = "0.52.6" 4252 + source = "registry+https://github.com/rust-lang/crates.io-index" 4253 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 4254 + 4255 + [[package]] 4256 + name = "windows_x86_64_gnu" 4257 + version = "0.53.1" 4258 + source = "registry+https://github.com/rust-lang/crates.io-index" 4259 + checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 4260 + 4261 + [[package]] 4262 + name = "windows_x86_64_gnullvm" 4263 + version = "0.42.2" 4264 + source = "registry+https://github.com/rust-lang/crates.io-index" 4265 + checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 4266 + 4267 + [[package]] 4268 + name = "windows_x86_64_gnullvm" 4269 + version = "0.48.5" 4270 + source = "registry+https://github.com/rust-lang/crates.io-index" 4271 + checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 4272 + 4273 + [[package]] 4274 + name = "windows_x86_64_gnullvm" 4275 + version = "0.52.6" 4276 + source = "registry+https://github.com/rust-lang/crates.io-index" 4277 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 4278 + 4279 + [[package]] 4280 + name = "windows_x86_64_gnullvm" 4281 + version = "0.53.1" 4282 + source = "registry+https://github.com/rust-lang/crates.io-index" 4283 + checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 4284 + 4285 + [[package]] 4286 + name = "windows_x86_64_msvc" 4287 + version = "0.42.2" 4288 + source = "registry+https://github.com/rust-lang/crates.io-index" 4289 + checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 4290 + 4291 + [[package]] 4292 + name = "windows_x86_64_msvc" 4293 + version = "0.48.5" 4294 + source = "registry+https://github.com/rust-lang/crates.io-index" 4295 + checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 4296 + 4297 + [[package]] 4298 + name = "windows_x86_64_msvc" 4299 + version = "0.52.6" 4300 + source = "registry+https://github.com/rust-lang/crates.io-index" 4301 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 4302 + 4303 + [[package]] 4304 + name = "windows_x86_64_msvc" 4305 + version = "0.53.1" 4306 + source = "registry+https://github.com/rust-lang/crates.io-index" 4307 + checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" 4308 + 4309 + [[package]] 4310 + name = "winreg" 4311 + version = "0.50.0" 4312 + source = "registry+https://github.com/rust-lang/crates.io-index" 4313 + checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 4314 + dependencies = [ 4315 + "cfg-if", 4316 + "windows-sys 0.48.0", 4317 + ] 4318 + 4319 + [[package]] 4320 + name = "wit-bindgen" 4321 + version = "0.46.0" 4322 + source = "registry+https://github.com/rust-lang/crates.io-index" 4323 + checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 4324 + 4325 + [[package]] 4326 + name = "writeable" 4327 + version = "0.6.1" 4328 + source = "registry+https://github.com/rust-lang/crates.io-index" 4329 + checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 4330 + 4331 + [[package]] 4332 + name = "yansi" 4333 + version = "1.0.1" 4334 + source = "registry+https://github.com/rust-lang/crates.io-index" 4335 + checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" 4336 + 4337 + [[package]] 4338 + name = "yoke" 4339 + version = "0.8.0" 4340 + source = "registry+https://github.com/rust-lang/crates.io-index" 4341 + checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 4342 + dependencies = [ 4343 + "serde", 4344 + "stable_deref_trait", 4345 + "yoke-derive", 4346 + "zerofrom", 4347 + ] 4348 + 4349 + [[package]] 4350 + name = "yoke-derive" 4351 + version = "0.8.0" 4352 + source = "registry+https://github.com/rust-lang/crates.io-index" 4353 + checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 4354 + dependencies = [ 4355 + "proc-macro2", 4356 + "quote", 4357 + "syn 2.0.107", 4358 + "synstructure", 4359 + ] 4360 + 4361 + [[package]] 4362 + name = "zerocopy" 4363 + version = "0.8.27" 4364 + source = "registry+https://github.com/rust-lang/crates.io-index" 4365 + checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" 4366 + dependencies = [ 4367 + "zerocopy-derive", 4368 + ] 4369 + 4370 + [[package]] 4371 + name = "zerocopy-derive" 4372 + version = "0.8.27" 4373 + source = "registry+https://github.com/rust-lang/crates.io-index" 4374 + checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" 4375 + dependencies = [ 4376 + "proc-macro2", 4377 + "quote", 4378 + "syn 2.0.107", 4379 + ] 4380 + 4381 + [[package]] 4382 + name = "zerofrom" 4383 + version = "0.1.6" 4384 + source = "registry+https://github.com/rust-lang/crates.io-index" 4385 + checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 4386 + dependencies = [ 4387 + "zerofrom-derive", 4388 + ] 4389 + 4390 + [[package]] 4391 + name = "zerofrom-derive" 4392 + version = "0.1.6" 4393 + source = "registry+https://github.com/rust-lang/crates.io-index" 4394 + checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 4395 + dependencies = [ 4396 + "proc-macro2", 4397 + "quote", 4398 + "syn 2.0.107", 4399 + "synstructure", 4400 + ] 4401 + 4402 + [[package]] 4403 + name = "zeroize" 4404 + version = "1.8.2" 4405 + source = "registry+https://github.com/rust-lang/crates.io-index" 4406 + checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" 4407 + dependencies = [ 4408 + "serde", 4409 + ] 4410 + 4411 + [[package]] 4412 + name = "zerotrie" 4413 + version = "0.2.2" 4414 + source = "registry+https://github.com/rust-lang/crates.io-index" 4415 + checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 4416 + dependencies = [ 4417 + "displaydoc", 4418 + "yoke", 4419 + "zerofrom", 4420 + ] 4421 + 4422 + [[package]] 4423 + name = "zerovec" 4424 + version = "0.11.4" 4425 + source = "registry+https://github.com/rust-lang/crates.io-index" 4426 + checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" 4427 + dependencies = [ 4428 + "yoke", 4429 + "zerofrom", 4430 + "zerovec-derive", 4431 + ] 4432 + 4433 + [[package]] 4434 + name = "zerovec-derive" 4435 + version = "0.11.1" 4436 + source = "registry+https://github.com/rust-lang/crates.io-index" 4437 + checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 4438 + dependencies = [ 4439 + "proc-macro2", 4440 + "quote", 4441 + "syn 2.0.107", 4442 + ]
+16 -1
upload/Cargo.toml
··· 1 + [workspace] 2 + resolver = "3" 3 + members = ["lexicons"] 4 + 1 5 [package] 2 6 name = "atcities-upload" 3 - version = "0.1.0" 7 + version = "1.0.1" 4 8 edition = "2024" 5 9 6 10 [dependencies] 11 + lexicons = { path = "./lexicons" } 12 + clap = { version = "4.5.49", features = ["derive"] } 13 + ignore = "0.4.23" 14 + regex = "1.12.2" 15 + mime_guess = "2.0.5" 16 + tokio = { version = "1.48.0", features = [] } 17 + jacquard = "0.6.0" 18 + reqwest = "0.12.24" 19 + env_logger = "0.11.8" 20 + miette = { version = "7.6.0", features = ["derive", "fancy"] } 21 + thiserror = "2.0.17"
+17
upload/lexicons/Cargo.toml
··· 1 + [package] 2 + name = "lexicons" 3 + version = "1.0.0" 4 + edition = "2024" 5 + 6 + [features] 7 + default = ["dev_atcities"] 8 + dev_atcities = [] 9 + 10 + [dependencies] 11 + bon = "3.8.1" 12 + bytes = { version = "1.10.1", features = ["serde"] } 13 + miette = "7.6.0" 14 + serde = "1.0.228" 15 + thiserror = "2.0.17" 16 + jacquard-common = "0.6.0" 17 + jacquard-derive = "0.6.0"
+77
upload/lexicons/src/dev_atcities/route.rs
··· 1 + // @generated by jacquard-lexicon. DO NOT EDIT. 2 + // 3 + // Lexicon: dev.atcities.route 4 + // 5 + // This file was automatically generated from Lexicon schemas. 6 + // Any manual changes will be overwritten on the next regeneration. 7 + 8 + #[jacquard_derive::lexicon] 9 + #[derive( 10 + serde::Serialize, 11 + serde::Deserialize, 12 + Debug, 13 + Clone, 14 + PartialEq, 15 + Eq, 16 + jacquard_derive::IntoStatic, 17 + bon::Builder, 18 + )] 19 + #[serde(rename_all = "camelCase")] 20 + pub struct Blob<'a> { 21 + #[serde(borrow)] 22 + pub blob: jacquard_common::types::blob::Blob<'a>, 23 + } 24 + 25 + /// Page URL maps directly to a record key 26 + #[jacquard_derive::lexicon] 27 + #[derive( 28 + serde::Serialize, 29 + serde::Deserialize, 30 + Debug, 31 + Clone, 32 + PartialEq, 33 + Eq, 34 + jacquard_derive::IntoStatic, 35 + bon::Builder, 36 + )] 37 + #[serde(rename_all = "camelCase")] 38 + pub struct Route<'a> { 39 + #[serde(borrow)] 40 + pub page: crate::dev_atcities::route::Blob<'a>, 41 + } 42 + 43 + /// Typed wrapper for GetRecord response with this collection's record type. 44 + #[derive( 45 + serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic, 46 + )] 47 + #[serde(rename_all = "camelCase")] 48 + pub struct RouteGetRecordOutput<'a> { 49 + #[serde(skip_serializing_if = "std::option::Option::is_none")] 50 + #[serde(borrow)] 51 + pub cid: std::option::Option<jacquard_common::types::string::Cid<'a>>, 52 + #[serde(borrow)] 53 + pub uri: jacquard_common::types::string::AtUri<'a>, 54 + #[serde(borrow)] 55 + pub value: Route<'a>, 56 + } 57 + 58 + /// Marker type for deserializing records from this collection. 59 + pub struct RouteRecord; 60 + impl jacquard_common::xrpc::XrpcResp for RouteRecord { 61 + const NSID: &'static str = "dev.atcities.route"; 62 + const ENCODING: &'static str = "application/json"; 63 + type Output<'de> = RouteGetRecordOutput<'de>; 64 + type Err<'de> = jacquard_common::types::collection::RecordError<'de>; 65 + } 66 + 67 + impl jacquard_common::types::collection::Collection for Route<'_> { 68 + const NSID: &'static str = "dev.atcities.route"; 69 + type Record = RouteRecord; 70 + } 71 + 72 + impl From<RouteGetRecordOutput<'_>> for Route<'_> { 73 + fn from(output: RouteGetRecordOutput<'_>) -> Self { 74 + use jacquard_common::IntoStatic; 75 + output.value.into_static() 76 + } 77 + }
+6
upload/lexicons/src/dev_atcities.rs
··· 1 + // @generated by jacquard-lexicon. DO NOT EDIT. 2 + // 3 + // This file was automatically generated from Lexicon schemas. 4 + // Any manual changes will be overwritten on the next regeneration. 5 + 6 + pub mod route;
+7
upload/lexicons/src/lib.rs
··· 1 + // @generated by jacquard-lexicon. DO NOT EDIT. 2 + // 3 + // This file was automatically generated from Lexicon schemas. 4 + // Any manual changes will be overwritten on the next regeneration. 5 + 6 + #[cfg(feature = "dev_atcities")] 7 + pub mod dev_atcities;
-81
upload/src/config.rs
··· 1 - pub struct Config { 2 - pub user: String, 3 - pub pword: String, 4 - pub dir: String, 5 - } 6 - 7 - pub enum ConfigErr { 8 - TooManyDirectories, 9 - NotEnoughArgs(String), 10 - UnknownArg(String), 11 - NotADirectory, 12 - } 13 - 14 - pub fn extract() -> Result<Config, ConfigErr> { 15 - let mut user: Option<String> = None; 16 - let mut pword: Option<String> = None; 17 - let mut dir: Option<String> = None; 18 - 19 - let mut args = std::env::args().into_iter(); 20 - // skip first arg 21 - args.next(); 22 - while let Some(arg) = args.next() { 23 - match arg.as_str() { 24 - "--user" => user = args.next(), 25 - "--password" => pword = args.next(), 26 - _ => { 27 - if arg.starts_with("--") { 28 - return Err(ConfigErr::UnknownArg(arg)); 29 - } 30 - if dir.is_some() { 31 - return Err(ConfigErr::TooManyDirectories); 32 - } 33 - dir = Some(arg); 34 - } 35 - } 36 - } 37 - 38 - if let Some(user) = user.clone() 39 - && let Some(pword) = pword.clone() 40 - && let Some(dir) = dir.clone() 41 - { 42 - return Ok(Config { 43 - user, 44 - pword, 45 - dir: dir.to_owned(), 46 - }); 47 - } 48 - 49 - return Err(ConfigErr::NotEnoughArgs(String::from( 50 - // xxx 51 - if user.is_none() && pword.is_none() && dir.is_none() { 52 - "--user, --password, and <dir>" 53 - } 54 - // yxx 55 - else if user.is_some() && pword.is_none() && dir.is_none() { 56 - "--password and <dir>" 57 - } 58 - // xyx 59 - else if user.is_none() && pword.is_some() && dir.is_none() { 60 - "--user and <dir>" 61 - } 62 - // yyx 63 - else if user.is_some() && pword.is_some() && dir.is_none() { 64 - "<dir>" 65 - } 66 - // xxy 67 - else if user.is_none() && pword.is_none() && dir.is_some() { 68 - "--user and --password" 69 - } 70 - // yxy 71 - else if user.is_some() && pword.is_none() && dir.is_some() { 72 - "--password" 73 - } 74 - // xyy 75 - else if user.is_none() && pword.is_some() && dir.is_some() { 76 - "--user" 77 - } else { 78 - "Invalid State, as all values are provided here" 79 - }, 80 - ))); 81 - }
+318 -10
upload/src/main.rs
··· 1 - mod config; 1 + use clap::{ArgAction, Parser}; 2 + use jacquard::api::com_atproto::repo::apply_writes::{ 3 + self, ApplyWrites, ApplyWritesOutput, ApplyWritesWritesItem, 4 + }; 5 + use jacquard::client::AgentSessionExt; 6 + use jacquard::client::MemorySessionStore; 7 + use jacquard::oauth::loopback::LoopbackConfig; 8 + use jacquard::oauth::types::AuthorizeOptions; 9 + use jacquard::types::string::{AtStrError, RecordKey, Rkey}; 10 + use jacquard::{AuthorizationToken, CowStr, atproto, oauth}; 11 + use jacquard::{ 12 + Data, 13 + api::com_atproto::{self, repo::list_records::ListRecords}, 14 + client::{Agent, credential_session::CredentialSession}, 15 + cowstr::ToCowStr, 16 + identity::JacquardResolver, 17 + types::{ident::AtIdentifier, nsid::Nsid, string::AtprotoStr, uri::Uri}, 18 + xrpc::XrpcExt, 19 + }; 20 + use miette::{Context, IntoDiagnostic, Result}; 21 + use std::io::Write; 22 + use std::{collections::HashMap, fs, path::PathBuf}; 2 23 3 - fn main() -> Result<(), ()> { 4 - let config = config::extract(); 5 - if let Err(err) = config { 6 - match err { 7 - config::ConfigErr::TooManyDirectories => println!("Too many directories"), 8 - config::ConfigErr::NotEnoughArgs(args) => println!("Missing {}", args), 9 - config::ConfigErr::UnknownArg(arg) => println!("Unknown arg {}", arg), 10 - config::ConfigErr::NotADirectory => println!("Not a directory"), 24 + use crate::sitemap::{BlobRef, Sitemap, SitemapNode}; 25 + 26 + mod sitemap; 27 + mod utils; 28 + 29 + #[derive(Parser, Debug, Clone)] 30 + #[command(version, about, long_about = None)] 31 + struct Config { 32 + /// Handle or DID to authenticate 33 + #[arg(verbatim_doc_comment)] 34 + user: String, 35 + 36 + /// App password to authenticate the client 37 + /// Normal passwords also work but are not advised 38 + /// If ommited, oauth will be used instead 39 + /// Oauth is reccomended where possible. 40 + #[arg(verbatim_doc_comment, short = 'p', long = "password")] 41 + password: Option<String>, 42 + 43 + /// Include dotfiles in upload 44 + /// Default: false 45 + #[arg(verbatim_doc_comment, short = 'a', long = "all")] 46 + all_files: bool, 47 + 48 + /// Respect gitignore files 49 + /// Note: gitignore files are not uploaded unless --all is set 50 + /// Default: true 51 + #[arg(verbatim_doc_comment, short = 'g', long = "no-gitignore", action = ArgAction::SetFalse, )] 52 + git_ignore: bool, 53 + 54 + /// Directory to upload 55 + #[arg(verbatim_doc_comment)] 56 + dir: PathBuf, 57 + } 58 + 59 + async fn live_records(agent: &impl AgentSessionExt, config: Config) -> Result<Vec<String>> { 60 + // find live site records 61 + let mut cursor = None; 62 + let mut remote_records = Vec::new(); 63 + let user = config.user.clone(); 64 + let user = if user.contains(":") { 65 + AtIdentifier::Did(user.into()) 66 + } else { 67 + AtIdentifier::Handle(user.into()) 68 + }; 69 + loop { 70 + let req = com_atproto::repo::list_records::ListRecords::new() 71 + .collection( 72 + Nsid::new("dev.atcities.route").expect("failed to generate dev.atcities.route nsid"), 73 + ) 74 + .repo(user.clone()) 75 + .limit(100) 76 + .maybe_cursor(cursor) 77 + .build(); 78 + 79 + let res = agent 80 + .xrpc(agent.endpoint().await) 81 + .send::<ListRecords>(&req) 82 + .await? 83 + .into_output()?; 84 + 85 + for record in res.records { 86 + match record { 87 + Data::Object(obj) => { 88 + let obj = obj.0.clone(); 89 + let uri = obj.get_key_value("uri").and_then(|x| match x.1 { 90 + Data::String(str) => Some(str), 91 + _ => None, 92 + }); 93 + 94 + if let Some(uri) = uri 95 + && let AtprotoStr::Uri(uri) = uri 96 + && let Uri::At(uri) = uri 97 + && let Some(rkey) = uri.rkey() 98 + { 99 + let rkey = rkey.0.to_cowstr().to_string(); 100 + remote_records.push(rkey); 101 + } else { 102 + panic!("Warning: pds returned invalid data.") 103 + } 104 + } 105 + _ => { 106 + panic!("Warning: pds returned invalid data.") 107 + } 108 + } 11 109 } 12 - return Err(()); 110 + 111 + cursor = res.cursor; 112 + if cursor.is_none() { 113 + break; 114 + } 13 115 } 116 + Ok(remote_records) 117 + } 118 + 119 + async fn upload_site_blobs( 120 + agent: &impl AgentSessionExt, 121 + _config: Config, 122 + local_sitemap: Sitemap, 123 + ) -> Result<Sitemap> { 124 + // upload local site blobs 125 + let mut new_sitemap: Sitemap = HashMap::new(); 126 + for (k, v) in local_sitemap { 127 + print!("Uploading {k}... "); 128 + let _ = std::io::stdout().flush(); 129 + let blob = match v.blob { 130 + BlobRef::Local(path) => path, 131 + BlobRef::Remote(_) => { 132 + panic!("Impossible state") 133 + } 134 + }; 135 + let blob = fs::read(blob).into_diagnostic()?; 136 + 137 + let req = com_atproto::repo::upload_blob::UploadBlob::new() 138 + .body(blob.into()) 139 + .build(); 140 + let res = agent.send(req).await?.into_output()?; 141 + 142 + new_sitemap.insert( 143 + k, 144 + SitemapNode { 145 + mime_type: v.mime_type, 146 + blob: BlobRef::Remote(res.blob.into()), 147 + }, 148 + ); 149 + 150 + println!("Done!"); 151 + } 152 + 153 + Ok(new_sitemap) 154 + } 155 + 156 + async fn update_remote_site( 157 + agent: &impl AgentSessionExt, 158 + config: Config, 159 + auth: AuthorizationToken<'_>, 160 + remote_records: Vec<String>, 161 + new_sitemap: Sitemap, 162 + ) -> Result<ApplyWritesOutput<'static>> { 163 + // batch delete/upload records 164 + let mut writes = Vec::new(); 165 + let mut delete_records = remote_records 166 + .into_iter() 167 + .map(|x| { 168 + let rkey = RecordKey(Rkey::new_owned(x)?); 169 + Ok(ApplyWritesWritesItem::Delete(Box::new( 170 + apply_writes::Delete::builder() 171 + .collection(Nsid::raw("dev.atcities.route")) 172 + .rkey(rkey) 173 + .build(), 174 + ))) 175 + }) 176 + .collect::<Result<Vec<ApplyWritesWritesItem<'_>>, AtStrError>>() 177 + .into_diagnostic()?; 178 + 179 + let mut create_records = new_sitemap 180 + .into_iter() 181 + .map(|(k, v)| { 182 + let k = match k.as_str() { 183 + "404.html" => String::from("404"), 184 + "index.html" => String::from("/"), 185 + _ => match k.strip_suffix("/index.html") { 186 + Some(k) => format!("/{k}/"), 187 + None => format!("/{k}"), 188 + } 189 + }; 190 + let rkey = 191 + utils::url_to_rkey(k).wrap_err("Invalid file path. Could not be converted to rkey")?; 192 + let rkey = RecordKey(Rkey::new_owned(rkey).into_diagnostic()?); 193 + let blob = match v.blob { 194 + BlobRef::Local(_) => panic!("Illegal local blob"), 195 + BlobRef::Remote(cid) => cid, 196 + }; 197 + let data = atproto!({ 198 + "page": { 199 + "$type": "dev.atcities.route#blob", 200 + "blob": { 201 + "$type": "blob", 202 + "ref": { 203 + "$link": blob.r#ref.as_str() 204 + }, 205 + "mimeType": blob.mime_type.0.as_str(), 206 + "size": blob.size 207 + } 208 + } 209 + }); 210 + Ok(ApplyWritesWritesItem::Create(Box::new( 211 + apply_writes::Create::builder() 212 + .collection(Nsid::raw("dev.atcities.route")) 213 + .rkey(rkey) 214 + .value(data) 215 + .build(), 216 + ))) 217 + }) 218 + .collect::<Result<Vec<ApplyWritesWritesItem<'_>>, miette::Error>>()?; 219 + 220 + writes.append(&mut delete_records); 221 + writes.append(&mut create_records); 222 + 223 + let repo = if config.user.contains(":") { 224 + AtIdentifier::Did(config.user.into()) 225 + } else { 226 + AtIdentifier::Handle(config.user.into()) 227 + }; 228 + 229 + let req = com_atproto::repo::apply_writes::ApplyWrites::new() 230 + .repo(repo) 231 + .writes(writes) 232 + .build(); 233 + 234 + let res = agent 235 + .xrpc(agent.endpoint().await) 236 + .auth(auth) 237 + .send::<ApplyWrites>(&req) 238 + .await? 239 + .into_output()?; 240 + 241 + Ok(res) 242 + } 243 + 244 + #[tokio::main] 245 + async fn main() -> Result<(), miette::Error> { 246 + env_logger::init(); 247 + // get config items 248 + let config = Config::parse(); 249 + 250 + // get local site info 251 + let local_sitemap = 252 + sitemap::local_sitemap(config.dir.clone(), config.all_files, config.git_ignore)?; 253 + 254 + // create session 255 + if let Some(password) = config.password.clone() { 256 + let password = password.into(); 257 + let client = JacquardResolver::default(); 258 + let store = MemorySessionStore::default(); 259 + let session = CredentialSession::new(store.into(), client.into()); 260 + 261 + let auth = session 262 + .login(config.user.clone().into(), password, None, None, None) 263 + .await?; 264 + 265 + let agent = Agent::from(session); 266 + 267 + let remote_sitemap = live_records(&agent, config.clone()).await?; 268 + let new_sitemap = upload_site_blobs(&agent, config.clone(), local_sitemap).await?; 269 + let _ = update_remote_site( 270 + &agent, 271 + config.clone(), 272 + AuthorizationToken::Bearer(auth.access_jwt), 273 + remote_sitemap, 274 + new_sitemap, 275 + ) 276 + .await?; 277 + 278 + println!( 279 + "Site is now updated. Live at {}", 280 + utils::site_handle(config.user) 281 + ); 282 + } else { 283 + let oauth = oauth::client::OAuthClient::with_memory_store(); 284 + let session = oauth 285 + .login_with_local_server( 286 + config.user.clone(), 287 + AuthorizeOptions::default(), 288 + LoopbackConfig::default(), 289 + ) 290 + .await?; 291 + 292 + // sick and twisted reference mangling BUT it works So 293 + // tldr: the cowstr is a borrowed cowstr iiuc, 294 + // so it needs to be turned into an owned cowstr 295 + // to break reference to session which gets moved 296 + let auth = session.access_token().await; 297 + let auth = match auth { 298 + AuthorizationToken::Bearer(cow_str) => CowStr::copy_from_str(cow_str.as_str()), 299 + AuthorizationToken::Dpop(cow_str) => CowStr::copy_from_str(cow_str.as_str()), 300 + }; 301 + 302 + println!("{}", auth); 303 + 304 + let agent = Agent::from(session); 305 + 306 + let remote_sitemap = live_records(&agent, config.clone()).await?; 307 + let new_sitemap = upload_site_blobs(&agent, config.clone(), local_sitemap).await?; 308 + let _ = update_remote_site( 309 + &agent, 310 + config.clone(), 311 + AuthorizationToken::Dpop(auth), 312 + remote_sitemap, 313 + new_sitemap, 314 + ) 315 + .await?; 316 + 317 + println!( 318 + "Site is now updated. Live at {}", 319 + utils::site_handle(config.user) 320 + ); 321 + }; 14 322 15 323 Ok(()) 16 324 }
+80
upload/src/sitemap.rs
··· 1 + use ignore::WalkBuilder; 2 + use jacquard::types::blob::Blob; 3 + use miette::Diagnostic; 4 + use mime_guess::mime; 5 + use std::{collections::HashMap, path::PathBuf}; 6 + use thiserror::Error; 7 + 8 + pub type Sitemap = HashMap<String, SitemapNode>; 9 + 10 + #[derive(Debug)] 11 + pub struct SitemapNode { 12 + pub mime_type: String, 13 + pub blob: BlobRef, 14 + } 15 + 16 + #[derive(Debug)] 17 + pub enum BlobRef { 18 + Local(PathBuf), 19 + Remote(Blob<'static>), 20 + } 21 + 22 + #[derive(Debug, Error, Diagnostic)] 23 + pub enum SitemapErr { 24 + #[error("IO error: {}", .0)] 25 + IoErr(#[from] std::io::Error), 26 + #[error("Error finding files: {}", .0)] 27 + IgnoreErr(#[from] ignore::Error), 28 + #[error("Error normalising file paths: {}", .0)] 29 + StripPrefixErr(#[from] std::path::StripPrefixError), 30 + #[error("Found non UTF-8 path")] 31 + NotUTF8Path, 32 + } 33 + 34 + pub fn local_sitemap( 35 + dir: PathBuf, 36 + include_dotfiles: bool, 37 + use_gitignore: bool, 38 + ) -> miette::Result<Sitemap, SitemapErr> { 39 + let prefix = dir.canonicalize()?; 40 + 41 + let mut res = HashMap::new(); 42 + for file in WalkBuilder::new(dir) 43 + .hidden(!include_dotfiles) 44 + .git_ignore(use_gitignore) 45 + .git_exclude(use_gitignore) 46 + .git_global(use_gitignore) 47 + .follow_links(true) 48 + .build() 49 + { 50 + let file = file?; 51 + 52 + let metadata = file.metadata()?; 53 + 54 + if !metadata.is_file() { 55 + continue; 56 + }; 57 + 58 + // find the path of the files relative to the source directory 59 + // source dir `./dist`: 60 + // ./dist/index.html => index.html 61 + // ./dist/assets/cat.jpg => cat.jpg 62 + // etc 63 + let key = file.path().canonicalize()?; 64 + let key = key.strip_prefix(&prefix)?; 65 + let key = String::from(key.to_str().ok_or(SitemapErr::NotUTF8Path)?); 66 + 67 + let mime = mime_guess::from_path(&key); 68 + let mime = mime.first().unwrap_or(mime::APPLICATION_OCTET_STREAM); 69 + let mime = mime.essence_str(); 70 + 71 + res.insert( 72 + key, 73 + SitemapNode { 74 + mime_type: String::from(mime), 75 + blob: BlobRef::Local(file.path().to_owned()), 76 + }, 77 + ); 78 + } 79 + Ok(res) 80 + }
+76
upload/src/utils.rs
··· 1 + use regex::Regex; 2 + 3 + #[allow(dead_code)] 4 + pub fn rkey_to_url(rkey: String) -> Option<String> { 5 + let regex = Regex::new( 6 + // symbols A-Za-z0-9 -._~: are all valid rkey characters 7 + // however we use a subset of record keys where : is an escape character 8 + // allow any rkey character except colons 9 + // or any of the valid escape sequences 10 + // from start of string to end between 0 and unlimited times 11 + r"^(?:[A-Za-z0-9.\-_~]|(?:::)|(?::~)|(?::21)|(?::24)|(?::26)|(?::27)|(?::28)|(?::29)|(?::2A)|(?::2B)|(?::2C)|(?::3A)|(?::3B)|(?::3D)|(?::40))*$", 12 + ) 13 + .expect("Regex failed to generate"); 14 + 15 + if !regex.is_match(&rkey) { 16 + return None; 17 + }; 18 + 19 + let res = rkey 20 + .replace("::", "/") 21 + .replace(":~", "%") 22 + .replace(":21", "!") 23 + .replace(":24", "$") 24 + .replace(":26", "&") 25 + .replace(":27", "'") 26 + .replace(":28", "(") 27 + .replace(":29", ")") 28 + .replace(":2A", "*") 29 + .replace(":2B", "+") 30 + .replace(":2C", ",") 31 + .replace(":3A", ":") 32 + .replace(":3B", ";") 33 + .replace(":3D", "=") 34 + .replace(":40", "@"); 35 + 36 + Some(res) 37 + } 38 + 39 + pub fn url_to_rkey(url: String) -> Option<String> { 40 + let regex = Regex::new(r"^(?:[a-zA-Z0-9/\-._~!$&'()*+,;=:@]|(?:%[0-9a-fA-F]{2}))*$") 41 + .expect("Regex failed to generate"); 42 + if !regex.is_match(&url) { 43 + return None; 44 + } 45 + 46 + let res = url 47 + // : replace is hoisted so it doesnt replace colons from elsewhere 48 + .replace(":", ":3A") 49 + .replace("/", "::") 50 + .replace("%", ":~") 51 + .replace("!", ":21") 52 + .replace("$", ":24") 53 + .replace("&", ":26") 54 + .replace("'", ":27") 55 + .replace("(", ":28") 56 + .replace(")", ":29") 57 + .replace("*", ":2A") 58 + .replace("+", ":2B") 59 + .replace(",", ":2C") 60 + .replace(";", ":3B") 61 + .replace("=", ":3D") 62 + .replace("@", ":40"); 63 + 64 + Some(res) 65 + } 66 + 67 + pub fn site_handle(user: String) -> String { 68 + if user.contains(":") { 69 + let user = user.split(":").collect::<Vec<_>>(); 70 + let method = user[1]; 71 + let did = user[2]; 72 + format!("https://{did}.did-{method}.atcities.dev/") 73 + } else { 74 + format!("https://{user}.atcities.dev/") 75 + } 76 + }