├── .dockerignore ├── .env ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── client.Dockerfile ├── out ├── package-lock.json ├── package.json ├── ready-docker ├── server.Dockerfile ├── src ├── cli.ts ├── client.rs ├── data-writer.ts ├── logger.ts ├── main.rs ├── room │ └── set-room.ts ├── server.ts ├── set-chat.ts └── types.ts └── tsconfig.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | target 3 | build 4 | dist 5 | .git 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PARALLEL=100 2 | COUNT=20000 3 | ROOMS_TO_JOIN=1 4 | ROOM_COUNT=20 5 | TIME_BETWEEN_MESSAGES=5 6 | TIME_BETWEEN_CONNECTIONS=5 7 | MESSAGES_TO_SEND=100 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | 5 | 6 | # Added by cargo 7 | 8 | /target 9 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "anstream" 22 | version = "0.5.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" 25 | dependencies = [ 26 | "anstyle", 27 | "anstyle-parse", 28 | "anstyle-query", 29 | "anstyle-wincon", 30 | "colorchoice", 31 | "utf8parse", 32 | ] 33 | 34 | [[package]] 35 | name = "anstyle" 36 | version = "1.0.3" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" 39 | 40 | [[package]] 41 | name = "anstyle-parse" 42 | version = "0.2.1" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" 45 | dependencies = [ 46 | "utf8parse", 47 | ] 48 | 49 | [[package]] 50 | name = "anstyle-query" 51 | version = "1.0.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 54 | dependencies = [ 55 | "windows-sys", 56 | ] 57 | 58 | [[package]] 59 | name = "anstyle-wincon" 60 | version = "2.1.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" 63 | dependencies = [ 64 | "anstyle", 65 | "windows-sys", 66 | ] 67 | 68 | [[package]] 69 | name = "anyhow" 70 | version = "1.0.75" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" 73 | 74 | [[package]] 75 | name = "autocfg" 76 | version = "1.1.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 79 | 80 | [[package]] 81 | name = "backtrace" 82 | version = "0.3.69" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 85 | dependencies = [ 86 | "addr2line", 87 | "cc", 88 | "cfg-if", 89 | "libc", 90 | "miniz_oxide", 91 | "object", 92 | "rustc-demangle", 93 | ] 94 | 95 | [[package]] 96 | name = "base64" 97 | version = "0.21.4" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" 100 | 101 | [[package]] 102 | name = "bitflags" 103 | version = "1.3.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 106 | 107 | [[package]] 108 | name = "bitflags" 109 | version = "2.4.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" 112 | 113 | [[package]] 114 | name = "block-buffer" 115 | version = "0.10.4" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 118 | dependencies = [ 119 | "generic-array", 120 | ] 121 | 122 | [[package]] 123 | name = "bumpalo" 124 | version = "3.14.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" 127 | 128 | [[package]] 129 | name = "byteorder" 130 | version = "1.4.3" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 133 | 134 | [[package]] 135 | name = "bytes" 136 | version = "1.5.0" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 139 | 140 | [[package]] 141 | name = "cc" 142 | version = "1.0.83" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 145 | dependencies = [ 146 | "libc", 147 | ] 148 | 149 | [[package]] 150 | name = "cfg-if" 151 | version = "1.0.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 154 | 155 | [[package]] 156 | name = "chat-js" 157 | version = "0.1.0" 158 | dependencies = [ 159 | "anyhow", 160 | "clap", 161 | "dotenv", 162 | "futures", 163 | "futures-util", 164 | "reqwest", 165 | "serde", 166 | "serde_json", 167 | "tokio", 168 | "tokio-tungstenite", 169 | "url", 170 | ] 171 | 172 | [[package]] 173 | name = "clap" 174 | version = "4.4.3" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" 177 | dependencies = [ 178 | "clap_builder", 179 | "clap_derive", 180 | ] 181 | 182 | [[package]] 183 | name = "clap_builder" 184 | version = "4.4.2" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" 187 | dependencies = [ 188 | "anstream", 189 | "anstyle", 190 | "clap_lex", 191 | "strsim", 192 | ] 193 | 194 | [[package]] 195 | name = "clap_derive" 196 | version = "4.4.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" 199 | dependencies = [ 200 | "heck", 201 | "proc-macro2", 202 | "quote", 203 | "syn", 204 | ] 205 | 206 | [[package]] 207 | name = "clap_lex" 208 | version = "0.5.1" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" 211 | 212 | [[package]] 213 | name = "colorchoice" 214 | version = "1.0.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 217 | 218 | [[package]] 219 | name = "core-foundation" 220 | version = "0.9.3" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 223 | dependencies = [ 224 | "core-foundation-sys", 225 | "libc", 226 | ] 227 | 228 | [[package]] 229 | name = "core-foundation-sys" 230 | version = "0.8.4" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 233 | 234 | [[package]] 235 | name = "cpufeatures" 236 | version = "0.2.9" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" 239 | dependencies = [ 240 | "libc", 241 | ] 242 | 243 | [[package]] 244 | name = "crypto-common" 245 | version = "0.1.6" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 248 | dependencies = [ 249 | "generic-array", 250 | "typenum", 251 | ] 252 | 253 | [[package]] 254 | name = "data-encoding" 255 | version = "2.4.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" 258 | 259 | [[package]] 260 | name = "digest" 261 | version = "0.10.7" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 264 | dependencies = [ 265 | "block-buffer", 266 | "crypto-common", 267 | ] 268 | 269 | [[package]] 270 | name = "dotenv" 271 | version = "0.15.0" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 274 | 275 | [[package]] 276 | name = "encoding_rs" 277 | version = "0.8.33" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" 280 | dependencies = [ 281 | "cfg-if", 282 | ] 283 | 284 | [[package]] 285 | name = "errno" 286 | version = "0.3.3" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" 289 | dependencies = [ 290 | "errno-dragonfly", 291 | "libc", 292 | "windows-sys", 293 | ] 294 | 295 | [[package]] 296 | name = "errno-dragonfly" 297 | version = "0.1.2" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 300 | dependencies = [ 301 | "cc", 302 | "libc", 303 | ] 304 | 305 | [[package]] 306 | name = "fastrand" 307 | version = "2.0.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" 310 | 311 | [[package]] 312 | name = "fnv" 313 | version = "1.0.7" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 316 | 317 | [[package]] 318 | name = "foreign-types" 319 | version = "0.3.2" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 322 | dependencies = [ 323 | "foreign-types-shared", 324 | ] 325 | 326 | [[package]] 327 | name = "foreign-types-shared" 328 | version = "0.1.1" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 331 | 332 | [[package]] 333 | name = "form_urlencoded" 334 | version = "1.2.0" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" 337 | dependencies = [ 338 | "percent-encoding", 339 | ] 340 | 341 | [[package]] 342 | name = "futures" 343 | version = "0.3.28" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" 346 | dependencies = [ 347 | "futures-channel", 348 | "futures-core", 349 | "futures-executor", 350 | "futures-io", 351 | "futures-sink", 352 | "futures-task", 353 | "futures-util", 354 | ] 355 | 356 | [[package]] 357 | name = "futures-channel" 358 | version = "0.3.28" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 361 | dependencies = [ 362 | "futures-core", 363 | "futures-sink", 364 | ] 365 | 366 | [[package]] 367 | name = "futures-core" 368 | version = "0.3.28" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 371 | 372 | [[package]] 373 | name = "futures-executor" 374 | version = "0.3.28" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" 377 | dependencies = [ 378 | "futures-core", 379 | "futures-task", 380 | "futures-util", 381 | ] 382 | 383 | [[package]] 384 | name = "futures-io" 385 | version = "0.3.28" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 388 | 389 | [[package]] 390 | name = "futures-macro" 391 | version = "0.3.28" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" 394 | dependencies = [ 395 | "proc-macro2", 396 | "quote", 397 | "syn", 398 | ] 399 | 400 | [[package]] 401 | name = "futures-sink" 402 | version = "0.3.28" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 405 | 406 | [[package]] 407 | name = "futures-task" 408 | version = "0.3.28" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 411 | 412 | [[package]] 413 | name = "futures-util" 414 | version = "0.3.28" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 417 | dependencies = [ 418 | "futures-channel", 419 | "futures-core", 420 | "futures-io", 421 | "futures-macro", 422 | "futures-sink", 423 | "futures-task", 424 | "memchr", 425 | "pin-project-lite", 426 | "pin-utils", 427 | "slab", 428 | ] 429 | 430 | [[package]] 431 | name = "generic-array" 432 | version = "0.14.7" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 435 | dependencies = [ 436 | "typenum", 437 | "version_check", 438 | ] 439 | 440 | [[package]] 441 | name = "getrandom" 442 | version = "0.2.10" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 445 | dependencies = [ 446 | "cfg-if", 447 | "libc", 448 | "wasi", 449 | ] 450 | 451 | [[package]] 452 | name = "gimli" 453 | version = "0.28.0" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" 456 | 457 | [[package]] 458 | name = "h2" 459 | version = "0.3.21" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" 462 | dependencies = [ 463 | "bytes", 464 | "fnv", 465 | "futures-core", 466 | "futures-sink", 467 | "futures-util", 468 | "http", 469 | "indexmap", 470 | "slab", 471 | "tokio", 472 | "tokio-util", 473 | "tracing", 474 | ] 475 | 476 | [[package]] 477 | name = "hashbrown" 478 | version = "0.12.3" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 481 | 482 | [[package]] 483 | name = "heck" 484 | version = "0.4.1" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 487 | 488 | [[package]] 489 | name = "hermit-abi" 490 | version = "0.3.2" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 493 | 494 | [[package]] 495 | name = "http" 496 | version = "0.2.9" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" 499 | dependencies = [ 500 | "bytes", 501 | "fnv", 502 | "itoa", 503 | ] 504 | 505 | [[package]] 506 | name = "http-body" 507 | version = "0.4.5" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 510 | dependencies = [ 511 | "bytes", 512 | "http", 513 | "pin-project-lite", 514 | ] 515 | 516 | [[package]] 517 | name = "httparse" 518 | version = "1.8.0" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 521 | 522 | [[package]] 523 | name = "httpdate" 524 | version = "1.0.3" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 527 | 528 | [[package]] 529 | name = "hyper" 530 | version = "0.14.27" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" 533 | dependencies = [ 534 | "bytes", 535 | "futures-channel", 536 | "futures-core", 537 | "futures-util", 538 | "h2", 539 | "http", 540 | "http-body", 541 | "httparse", 542 | "httpdate", 543 | "itoa", 544 | "pin-project-lite", 545 | "socket2 0.4.9", 546 | "tokio", 547 | "tower-service", 548 | "tracing", 549 | "want", 550 | ] 551 | 552 | [[package]] 553 | name = "hyper-tls" 554 | version = "0.5.0" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 557 | dependencies = [ 558 | "bytes", 559 | "hyper", 560 | "native-tls", 561 | "tokio", 562 | "tokio-native-tls", 563 | ] 564 | 565 | [[package]] 566 | name = "idna" 567 | version = "0.4.0" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" 570 | dependencies = [ 571 | "unicode-bidi", 572 | "unicode-normalization", 573 | ] 574 | 575 | [[package]] 576 | name = "indexmap" 577 | version = "1.9.3" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 580 | dependencies = [ 581 | "autocfg", 582 | "hashbrown", 583 | ] 584 | 585 | [[package]] 586 | name = "ipnet" 587 | version = "2.8.0" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" 590 | 591 | [[package]] 592 | name = "itoa" 593 | version = "1.0.9" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" 596 | 597 | [[package]] 598 | name = "js-sys" 599 | version = "0.3.64" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 602 | dependencies = [ 603 | "wasm-bindgen", 604 | ] 605 | 606 | [[package]] 607 | name = "lazy_static" 608 | version = "1.4.0" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 611 | 612 | [[package]] 613 | name = "libc" 614 | version = "0.2.147" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 617 | 618 | [[package]] 619 | name = "linux-raw-sys" 620 | version = "0.4.7" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" 623 | 624 | [[package]] 625 | name = "lock_api" 626 | version = "0.4.10" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 629 | dependencies = [ 630 | "autocfg", 631 | "scopeguard", 632 | ] 633 | 634 | [[package]] 635 | name = "log" 636 | version = "0.4.20" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 639 | 640 | [[package]] 641 | name = "memchr" 642 | version = "2.6.3" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" 645 | 646 | [[package]] 647 | name = "mime" 648 | version = "0.3.17" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 651 | 652 | [[package]] 653 | name = "miniz_oxide" 654 | version = "0.7.1" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 657 | dependencies = [ 658 | "adler", 659 | ] 660 | 661 | [[package]] 662 | name = "mio" 663 | version = "0.8.8" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 666 | dependencies = [ 667 | "libc", 668 | "wasi", 669 | "windows-sys", 670 | ] 671 | 672 | [[package]] 673 | name = "native-tls" 674 | version = "0.2.11" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 677 | dependencies = [ 678 | "lazy_static", 679 | "libc", 680 | "log", 681 | "openssl", 682 | "openssl-probe", 683 | "openssl-sys", 684 | "schannel", 685 | "security-framework", 686 | "security-framework-sys", 687 | "tempfile", 688 | ] 689 | 690 | [[package]] 691 | name = "num_cpus" 692 | version = "1.16.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 695 | dependencies = [ 696 | "hermit-abi", 697 | "libc", 698 | ] 699 | 700 | [[package]] 701 | name = "object" 702 | version = "0.32.1" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" 705 | dependencies = [ 706 | "memchr", 707 | ] 708 | 709 | [[package]] 710 | name = "once_cell" 711 | version = "1.18.0" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 714 | 715 | [[package]] 716 | name = "openssl" 717 | version = "0.10.57" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" 720 | dependencies = [ 721 | "bitflags 2.4.0", 722 | "cfg-if", 723 | "foreign-types", 724 | "libc", 725 | "once_cell", 726 | "openssl-macros", 727 | "openssl-sys", 728 | ] 729 | 730 | [[package]] 731 | name = "openssl-macros" 732 | version = "0.1.1" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 735 | dependencies = [ 736 | "proc-macro2", 737 | "quote", 738 | "syn", 739 | ] 740 | 741 | [[package]] 742 | name = "openssl-probe" 743 | version = "0.1.5" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 746 | 747 | [[package]] 748 | name = "openssl-sys" 749 | version = "0.9.93" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" 752 | dependencies = [ 753 | "cc", 754 | "libc", 755 | "pkg-config", 756 | "vcpkg", 757 | ] 758 | 759 | [[package]] 760 | name = "parking_lot" 761 | version = "0.12.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 764 | dependencies = [ 765 | "lock_api", 766 | "parking_lot_core", 767 | ] 768 | 769 | [[package]] 770 | name = "parking_lot_core" 771 | version = "0.9.8" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 774 | dependencies = [ 775 | "cfg-if", 776 | "libc", 777 | "redox_syscall", 778 | "smallvec", 779 | "windows-targets", 780 | ] 781 | 782 | [[package]] 783 | name = "percent-encoding" 784 | version = "2.3.0" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" 787 | 788 | [[package]] 789 | name = "pin-project-lite" 790 | version = "0.2.13" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 793 | 794 | [[package]] 795 | name = "pin-utils" 796 | version = "0.1.0" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 799 | 800 | [[package]] 801 | name = "pkg-config" 802 | version = "0.3.27" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 805 | 806 | [[package]] 807 | name = "ppv-lite86" 808 | version = "0.2.17" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 811 | 812 | [[package]] 813 | name = "proc-macro2" 814 | version = "1.0.66" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 817 | dependencies = [ 818 | "unicode-ident", 819 | ] 820 | 821 | [[package]] 822 | name = "quote" 823 | version = "1.0.33" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 826 | dependencies = [ 827 | "proc-macro2", 828 | ] 829 | 830 | [[package]] 831 | name = "rand" 832 | version = "0.8.5" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 835 | dependencies = [ 836 | "libc", 837 | "rand_chacha", 838 | "rand_core", 839 | ] 840 | 841 | [[package]] 842 | name = "rand_chacha" 843 | version = "0.3.1" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 846 | dependencies = [ 847 | "ppv-lite86", 848 | "rand_core", 849 | ] 850 | 851 | [[package]] 852 | name = "rand_core" 853 | version = "0.6.4" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 856 | dependencies = [ 857 | "getrandom", 858 | ] 859 | 860 | [[package]] 861 | name = "redox_syscall" 862 | version = "0.3.5" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 865 | dependencies = [ 866 | "bitflags 1.3.2", 867 | ] 868 | 869 | [[package]] 870 | name = "reqwest" 871 | version = "0.11.20" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" 874 | dependencies = [ 875 | "base64", 876 | "bytes", 877 | "encoding_rs", 878 | "futures-core", 879 | "futures-util", 880 | "h2", 881 | "http", 882 | "http-body", 883 | "hyper", 884 | "hyper-tls", 885 | "ipnet", 886 | "js-sys", 887 | "log", 888 | "mime", 889 | "native-tls", 890 | "once_cell", 891 | "percent-encoding", 892 | "pin-project-lite", 893 | "serde", 894 | "serde_json", 895 | "serde_urlencoded", 896 | "tokio", 897 | "tokio-native-tls", 898 | "tower-service", 899 | "url", 900 | "wasm-bindgen", 901 | "wasm-bindgen-futures", 902 | "web-sys", 903 | "winreg", 904 | ] 905 | 906 | [[package]] 907 | name = "rustc-demangle" 908 | version = "0.1.23" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 911 | 912 | [[package]] 913 | name = "rustix" 914 | version = "0.38.13" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" 917 | dependencies = [ 918 | "bitflags 2.4.0", 919 | "errno", 920 | "libc", 921 | "linux-raw-sys", 922 | "windows-sys", 923 | ] 924 | 925 | [[package]] 926 | name = "ryu" 927 | version = "1.0.15" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" 930 | 931 | [[package]] 932 | name = "schannel" 933 | version = "0.1.22" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" 936 | dependencies = [ 937 | "windows-sys", 938 | ] 939 | 940 | [[package]] 941 | name = "scopeguard" 942 | version = "1.2.0" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 945 | 946 | [[package]] 947 | name = "security-framework" 948 | version = "2.9.2" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" 951 | dependencies = [ 952 | "bitflags 1.3.2", 953 | "core-foundation", 954 | "core-foundation-sys", 955 | "libc", 956 | "security-framework-sys", 957 | ] 958 | 959 | [[package]] 960 | name = "security-framework-sys" 961 | version = "2.9.1" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" 964 | dependencies = [ 965 | "core-foundation-sys", 966 | "libc", 967 | ] 968 | 969 | [[package]] 970 | name = "serde" 971 | version = "1.0.188" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" 974 | dependencies = [ 975 | "serde_derive", 976 | ] 977 | 978 | [[package]] 979 | name = "serde_derive" 980 | version = "1.0.188" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" 983 | dependencies = [ 984 | "proc-macro2", 985 | "quote", 986 | "syn", 987 | ] 988 | 989 | [[package]] 990 | name = "serde_json" 991 | version = "1.0.106" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2" 994 | dependencies = [ 995 | "itoa", 996 | "ryu", 997 | "serde", 998 | ] 999 | 1000 | [[package]] 1001 | name = "serde_urlencoded" 1002 | version = "0.7.1" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1005 | dependencies = [ 1006 | "form_urlencoded", 1007 | "itoa", 1008 | "ryu", 1009 | "serde", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "sha1" 1014 | version = "0.10.5" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1017 | dependencies = [ 1018 | "cfg-if", 1019 | "cpufeatures", 1020 | "digest", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "signal-hook-registry" 1025 | version = "1.4.1" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 1028 | dependencies = [ 1029 | "libc", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "slab" 1034 | version = "0.4.9" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1037 | dependencies = [ 1038 | "autocfg", 1039 | ] 1040 | 1041 | [[package]] 1042 | name = "smallvec" 1043 | version = "1.11.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 1046 | 1047 | [[package]] 1048 | name = "socket2" 1049 | version = "0.4.9" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 1052 | dependencies = [ 1053 | "libc", 1054 | "winapi", 1055 | ] 1056 | 1057 | [[package]] 1058 | name = "socket2" 1059 | version = "0.5.4" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" 1062 | dependencies = [ 1063 | "libc", 1064 | "windows-sys", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "strsim" 1069 | version = "0.10.0" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1072 | 1073 | [[package]] 1074 | name = "syn" 1075 | version = "2.0.32" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" 1078 | dependencies = [ 1079 | "proc-macro2", 1080 | "quote", 1081 | "unicode-ident", 1082 | ] 1083 | 1084 | [[package]] 1085 | name = "tempfile" 1086 | version = "3.8.0" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" 1089 | dependencies = [ 1090 | "cfg-if", 1091 | "fastrand", 1092 | "redox_syscall", 1093 | "rustix", 1094 | "windows-sys", 1095 | ] 1096 | 1097 | [[package]] 1098 | name = "thiserror" 1099 | version = "1.0.48" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" 1102 | dependencies = [ 1103 | "thiserror-impl", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "thiserror-impl" 1108 | version = "1.0.48" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" 1111 | dependencies = [ 1112 | "proc-macro2", 1113 | "quote", 1114 | "syn", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "tinyvec" 1119 | version = "1.6.0" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1122 | dependencies = [ 1123 | "tinyvec_macros", 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "tinyvec_macros" 1128 | version = "0.1.1" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1131 | 1132 | [[package]] 1133 | name = "tokio" 1134 | version = "1.32.0" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" 1137 | dependencies = [ 1138 | "backtrace", 1139 | "bytes", 1140 | "libc", 1141 | "mio", 1142 | "num_cpus", 1143 | "parking_lot", 1144 | "pin-project-lite", 1145 | "signal-hook-registry", 1146 | "socket2 0.5.4", 1147 | "tokio-macros", 1148 | "windows-sys", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "tokio-macros" 1153 | version = "2.1.0" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" 1156 | dependencies = [ 1157 | "proc-macro2", 1158 | "quote", 1159 | "syn", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "tokio-native-tls" 1164 | version = "0.3.1" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1167 | dependencies = [ 1168 | "native-tls", 1169 | "tokio", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "tokio-tungstenite" 1174 | version = "0.20.0" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2" 1177 | dependencies = [ 1178 | "futures-util", 1179 | "log", 1180 | "tokio", 1181 | "tungstenite", 1182 | ] 1183 | 1184 | [[package]] 1185 | name = "tokio-util" 1186 | version = "0.7.9" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" 1189 | dependencies = [ 1190 | "bytes", 1191 | "futures-core", 1192 | "futures-sink", 1193 | "pin-project-lite", 1194 | "tokio", 1195 | "tracing", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "tower-service" 1200 | version = "0.3.2" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1203 | 1204 | [[package]] 1205 | name = "tracing" 1206 | version = "0.1.37" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1209 | dependencies = [ 1210 | "cfg-if", 1211 | "pin-project-lite", 1212 | "tracing-core", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "tracing-core" 1217 | version = "0.1.31" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 1220 | dependencies = [ 1221 | "once_cell", 1222 | ] 1223 | 1224 | [[package]] 1225 | name = "try-lock" 1226 | version = "0.2.4" 1227 | source = "registry+https://github.com/rust-lang/crates.io-index" 1228 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 1229 | 1230 | [[package]] 1231 | name = "tungstenite" 1232 | version = "0.20.0" 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" 1234 | checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649" 1235 | dependencies = [ 1236 | "byteorder", 1237 | "bytes", 1238 | "data-encoding", 1239 | "http", 1240 | "httparse", 1241 | "log", 1242 | "rand", 1243 | "sha1", 1244 | "thiserror", 1245 | "url", 1246 | "utf-8", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "typenum" 1251 | version = "1.16.0" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1254 | 1255 | [[package]] 1256 | name = "unicode-bidi" 1257 | version = "0.3.13" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 1260 | 1261 | [[package]] 1262 | name = "unicode-ident" 1263 | version = "1.0.11" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 1266 | 1267 | [[package]] 1268 | name = "unicode-normalization" 1269 | version = "0.1.22" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1272 | dependencies = [ 1273 | "tinyvec", 1274 | ] 1275 | 1276 | [[package]] 1277 | name = "url" 1278 | version = "2.4.1" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" 1281 | dependencies = [ 1282 | "form_urlencoded", 1283 | "idna", 1284 | "percent-encoding", 1285 | ] 1286 | 1287 | [[package]] 1288 | name = "utf-8" 1289 | version = "0.7.6" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1292 | 1293 | [[package]] 1294 | name = "utf8parse" 1295 | version = "0.2.1" 1296 | source = "registry+https://github.com/rust-lang/crates.io-index" 1297 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1298 | 1299 | [[package]] 1300 | name = "vcpkg" 1301 | version = "0.2.15" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1304 | 1305 | [[package]] 1306 | name = "version_check" 1307 | version = "0.9.4" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1310 | 1311 | [[package]] 1312 | name = "want" 1313 | version = "0.3.1" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1316 | dependencies = [ 1317 | "try-lock", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "wasi" 1322 | version = "0.11.0+wasi-snapshot-preview1" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1325 | 1326 | [[package]] 1327 | name = "wasm-bindgen" 1328 | version = "0.2.87" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 1331 | dependencies = [ 1332 | "cfg-if", 1333 | "wasm-bindgen-macro", 1334 | ] 1335 | 1336 | [[package]] 1337 | name = "wasm-bindgen-backend" 1338 | version = "0.2.87" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 1341 | dependencies = [ 1342 | "bumpalo", 1343 | "log", 1344 | "once_cell", 1345 | "proc-macro2", 1346 | "quote", 1347 | "syn", 1348 | "wasm-bindgen-shared", 1349 | ] 1350 | 1351 | [[package]] 1352 | name = "wasm-bindgen-futures" 1353 | version = "0.4.37" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" 1356 | dependencies = [ 1357 | "cfg-if", 1358 | "js-sys", 1359 | "wasm-bindgen", 1360 | "web-sys", 1361 | ] 1362 | 1363 | [[package]] 1364 | name = "wasm-bindgen-macro" 1365 | version = "0.2.87" 1366 | source = "registry+https://github.com/rust-lang/crates.io-index" 1367 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 1368 | dependencies = [ 1369 | "quote", 1370 | "wasm-bindgen-macro-support", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "wasm-bindgen-macro-support" 1375 | version = "0.2.87" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 1378 | dependencies = [ 1379 | "proc-macro2", 1380 | "quote", 1381 | "syn", 1382 | "wasm-bindgen-backend", 1383 | "wasm-bindgen-shared", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "wasm-bindgen-shared" 1388 | version = "0.2.87" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 1391 | 1392 | [[package]] 1393 | name = "web-sys" 1394 | version = "0.3.64" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 1397 | dependencies = [ 1398 | "js-sys", 1399 | "wasm-bindgen", 1400 | ] 1401 | 1402 | [[package]] 1403 | name = "winapi" 1404 | version = "0.3.9" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1407 | dependencies = [ 1408 | "winapi-i686-pc-windows-gnu", 1409 | "winapi-x86_64-pc-windows-gnu", 1410 | ] 1411 | 1412 | [[package]] 1413 | name = "winapi-i686-pc-windows-gnu" 1414 | version = "0.4.0" 1415 | source = "registry+https://github.com/rust-lang/crates.io-index" 1416 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1417 | 1418 | [[package]] 1419 | name = "winapi-x86_64-pc-windows-gnu" 1420 | version = "0.4.0" 1421 | source = "registry+https://github.com/rust-lang/crates.io-index" 1422 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1423 | 1424 | [[package]] 1425 | name = "windows-sys" 1426 | version = "0.48.0" 1427 | source = "registry+https://github.com/rust-lang/crates.io-index" 1428 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1429 | dependencies = [ 1430 | "windows-targets", 1431 | ] 1432 | 1433 | [[package]] 1434 | name = "windows-targets" 1435 | version = "0.48.5" 1436 | source = "registry+https://github.com/rust-lang/crates.io-index" 1437 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1438 | dependencies = [ 1439 | "windows_aarch64_gnullvm", 1440 | "windows_aarch64_msvc", 1441 | "windows_i686_gnu", 1442 | "windows_i686_msvc", 1443 | "windows_x86_64_gnu", 1444 | "windows_x86_64_gnullvm", 1445 | "windows_x86_64_msvc", 1446 | ] 1447 | 1448 | [[package]] 1449 | name = "windows_aarch64_gnullvm" 1450 | version = "0.48.5" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1453 | 1454 | [[package]] 1455 | name = "windows_aarch64_msvc" 1456 | version = "0.48.5" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1459 | 1460 | [[package]] 1461 | name = "windows_i686_gnu" 1462 | version = "0.48.5" 1463 | source = "registry+https://github.com/rust-lang/crates.io-index" 1464 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1465 | 1466 | [[package]] 1467 | name = "windows_i686_msvc" 1468 | version = "0.48.5" 1469 | source = "registry+https://github.com/rust-lang/crates.io-index" 1470 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1471 | 1472 | [[package]] 1473 | name = "windows_x86_64_gnu" 1474 | version = "0.48.5" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1477 | 1478 | [[package]] 1479 | name = "windows_x86_64_gnullvm" 1480 | version = "0.48.5" 1481 | source = "registry+https://github.com/rust-lang/crates.io-index" 1482 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1483 | 1484 | [[package]] 1485 | name = "windows_x86_64_msvc" 1486 | version = "0.48.5" 1487 | source = "registry+https://github.com/rust-lang/crates.io-index" 1488 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1489 | 1490 | [[package]] 1491 | name = "winreg" 1492 | version = "0.50.0" 1493 | source = "registry+https://github.com/rust-lang/crates.io-index" 1494 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 1495 | dependencies = [ 1496 | "cfg-if", 1497 | "windows-sys", 1498 | ] 1499 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "chat-js" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.75" 10 | clap = { version = "4.4.3", features = ["derive", "env"] } 11 | dotenv = "0.15.0" 12 | futures = "0.3.28" 13 | futures-util = "0.3.28" 14 | reqwest = "0.11.20" 15 | serde = "1.0.188" 16 | serde_json = "1.0.106" 17 | tokio = { version = "1.32.0", features = ["full"] } 18 | tokio-tungstenite = "0.20.0" 19 | url = "2.4.1" 20 | -------------------------------------------------------------------------------- /client.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1.72 2 | 3 | WORKDIR /app 4 | COPY Cargo.toml /app/Cargo.toml 5 | COPY Cargo.lock /app/Cargo.lock 6 | COPY src/main.rs /app/src/main.rs 7 | COPY src/client.rs /app/src/client.rs 8 | RUN cargo build --release 9 | 10 | CMD ["./target/release/chat-js"] 11 | -------------------------------------------------------------------------------- /out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThePrimeagen/chat-js/fd5807d274bf9d3033c85de6897c3e087005f492/out -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chat-js", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "@types/command-line-args": "^5.2.1", 9 | "@types/node": "^20.5.9", 10 | "@types/ws": "^8.5.5", 11 | "command-line-args": "^5.2.1", 12 | "express": "^4.18.2", 13 | "pino": "^8.15.1", 14 | "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.31.0", 15 | "ws": "^8.14.1" 16 | }, 17 | "devDependencies": { 18 | "@types/express": "^4.17.17", 19 | "typescript": "^5.2.2" 20 | } 21 | }, 22 | "node_modules/@types/body-parser": { 23 | "version": "1.19.3", 24 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", 25 | "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", 26 | "dev": true, 27 | "dependencies": { 28 | "@types/connect": "*", 29 | "@types/node": "*" 30 | } 31 | }, 32 | "node_modules/@types/command-line-args": { 33 | "version": "5.2.1", 34 | "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.1.tgz", 35 | "integrity": "sha512-U2OcmS2tj36Yceu+mRuPyUV0ILfau/h5onStcSCzqTENsq0sBiAp2TmaXu1k8fY4McLcPKSYl9FRzn2hx5bI+w==" 36 | }, 37 | "node_modules/@types/connect": { 38 | "version": "3.4.36", 39 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", 40 | "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", 41 | "dev": true, 42 | "dependencies": { 43 | "@types/node": "*" 44 | } 45 | }, 46 | "node_modules/@types/express": { 47 | "version": "4.17.17", 48 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", 49 | "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", 50 | "dev": true, 51 | "dependencies": { 52 | "@types/body-parser": "*", 53 | "@types/express-serve-static-core": "^4.17.33", 54 | "@types/qs": "*", 55 | "@types/serve-static": "*" 56 | } 57 | }, 58 | "node_modules/@types/express-serve-static-core": { 59 | "version": "4.17.36", 60 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", 61 | "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", 62 | "dev": true, 63 | "dependencies": { 64 | "@types/node": "*", 65 | "@types/qs": "*", 66 | "@types/range-parser": "*", 67 | "@types/send": "*" 68 | } 69 | }, 70 | "node_modules/@types/http-errors": { 71 | "version": "2.0.2", 72 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", 73 | "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", 74 | "dev": true 75 | }, 76 | "node_modules/@types/mime": { 77 | "version": "1.3.2", 78 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", 79 | "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", 80 | "dev": true 81 | }, 82 | "node_modules/@types/node": { 83 | "version": "20.5.9", 84 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", 85 | "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" 86 | }, 87 | "node_modules/@types/qs": { 88 | "version": "6.9.8", 89 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", 90 | "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", 91 | "dev": true 92 | }, 93 | "node_modules/@types/range-parser": { 94 | "version": "1.2.4", 95 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", 96 | "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", 97 | "dev": true 98 | }, 99 | "node_modules/@types/send": { 100 | "version": "0.17.1", 101 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", 102 | "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", 103 | "dev": true, 104 | "dependencies": { 105 | "@types/mime": "^1", 106 | "@types/node": "*" 107 | } 108 | }, 109 | "node_modules/@types/serve-static": { 110 | "version": "1.15.2", 111 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", 112 | "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", 113 | "dev": true, 114 | "dependencies": { 115 | "@types/http-errors": "*", 116 | "@types/mime": "*", 117 | "@types/node": "*" 118 | } 119 | }, 120 | "node_modules/@types/ws": { 121 | "version": "8.5.5", 122 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", 123 | "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", 124 | "dependencies": { 125 | "@types/node": "*" 126 | } 127 | }, 128 | "node_modules/abort-controller": { 129 | "version": "3.0.0", 130 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 131 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 132 | "dependencies": { 133 | "event-target-shim": "^5.0.0" 134 | }, 135 | "engines": { 136 | "node": ">=6.5" 137 | } 138 | }, 139 | "node_modules/accepts": { 140 | "version": "1.3.8", 141 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 142 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 143 | "dependencies": { 144 | "mime-types": "~2.1.34", 145 | "negotiator": "0.6.3" 146 | }, 147 | "engines": { 148 | "node": ">= 0.6" 149 | } 150 | }, 151 | "node_modules/array-back": { 152 | "version": "3.1.0", 153 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", 154 | "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", 155 | "engines": { 156 | "node": ">=6" 157 | } 158 | }, 159 | "node_modules/array-flatten": { 160 | "version": "1.1.1", 161 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 162 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 163 | }, 164 | "node_modules/atomic-sleep": { 165 | "version": "1.0.0", 166 | "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", 167 | "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", 168 | "engines": { 169 | "node": ">=8.0.0" 170 | } 171 | }, 172 | "node_modules/base64-js": { 173 | "version": "1.5.1", 174 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 175 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 176 | "funding": [ 177 | { 178 | "type": "github", 179 | "url": "https://github.com/sponsors/feross" 180 | }, 181 | { 182 | "type": "patreon", 183 | "url": "https://www.patreon.com/feross" 184 | }, 185 | { 186 | "type": "consulting", 187 | "url": "https://feross.org/support" 188 | } 189 | ] 190 | }, 191 | "node_modules/body-parser": { 192 | "version": "1.20.1", 193 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 194 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 195 | "dependencies": { 196 | "bytes": "3.1.2", 197 | "content-type": "~1.0.4", 198 | "debug": "2.6.9", 199 | "depd": "2.0.0", 200 | "destroy": "1.2.0", 201 | "http-errors": "2.0.0", 202 | "iconv-lite": "0.4.24", 203 | "on-finished": "2.4.1", 204 | "qs": "6.11.0", 205 | "raw-body": "2.5.1", 206 | "type-is": "~1.6.18", 207 | "unpipe": "1.0.0" 208 | }, 209 | "engines": { 210 | "node": ">= 0.8", 211 | "npm": "1.2.8000 || >= 1.4.16" 212 | } 213 | }, 214 | "node_modules/buffer": { 215 | "version": "6.0.3", 216 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 217 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 218 | "funding": [ 219 | { 220 | "type": "github", 221 | "url": "https://github.com/sponsors/feross" 222 | }, 223 | { 224 | "type": "patreon", 225 | "url": "https://www.patreon.com/feross" 226 | }, 227 | { 228 | "type": "consulting", 229 | "url": "https://feross.org/support" 230 | } 231 | ], 232 | "dependencies": { 233 | "base64-js": "^1.3.1", 234 | "ieee754": "^1.2.1" 235 | } 236 | }, 237 | "node_modules/bytes": { 238 | "version": "3.1.2", 239 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 240 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 241 | "engines": { 242 | "node": ">= 0.8" 243 | } 244 | }, 245 | "node_modules/call-bind": { 246 | "version": "1.0.2", 247 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 248 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 249 | "dependencies": { 250 | "function-bind": "^1.1.1", 251 | "get-intrinsic": "^1.0.2" 252 | }, 253 | "funding": { 254 | "url": "https://github.com/sponsors/ljharb" 255 | } 256 | }, 257 | "node_modules/command-line-args": { 258 | "version": "5.2.1", 259 | "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", 260 | "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", 261 | "dependencies": { 262 | "array-back": "^3.1.0", 263 | "find-replace": "^3.0.0", 264 | "lodash.camelcase": "^4.3.0", 265 | "typical": "^4.0.0" 266 | }, 267 | "engines": { 268 | "node": ">=4.0.0" 269 | } 270 | }, 271 | "node_modules/content-disposition": { 272 | "version": "0.5.4", 273 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 274 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 275 | "dependencies": { 276 | "safe-buffer": "5.2.1" 277 | }, 278 | "engines": { 279 | "node": ">= 0.6" 280 | } 281 | }, 282 | "node_modules/content-type": { 283 | "version": "1.0.5", 284 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 285 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 286 | "engines": { 287 | "node": ">= 0.6" 288 | } 289 | }, 290 | "node_modules/cookie": { 291 | "version": "0.5.0", 292 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 293 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 294 | "engines": { 295 | "node": ">= 0.6" 296 | } 297 | }, 298 | "node_modules/cookie-signature": { 299 | "version": "1.0.6", 300 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 301 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 302 | }, 303 | "node_modules/debug": { 304 | "version": "2.6.9", 305 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 306 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 307 | "dependencies": { 308 | "ms": "2.0.0" 309 | } 310 | }, 311 | "node_modules/depd": { 312 | "version": "2.0.0", 313 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 314 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 315 | "engines": { 316 | "node": ">= 0.8" 317 | } 318 | }, 319 | "node_modules/destroy": { 320 | "version": "1.2.0", 321 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 322 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 323 | "engines": { 324 | "node": ">= 0.8", 325 | "npm": "1.2.8000 || >= 1.4.16" 326 | } 327 | }, 328 | "node_modules/ee-first": { 329 | "version": "1.1.1", 330 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 331 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 332 | }, 333 | "node_modules/encodeurl": { 334 | "version": "1.0.2", 335 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 336 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 337 | "engines": { 338 | "node": ">= 0.8" 339 | } 340 | }, 341 | "node_modules/escape-html": { 342 | "version": "1.0.3", 343 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 344 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 345 | }, 346 | "node_modules/etag": { 347 | "version": "1.8.1", 348 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 349 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 350 | "engines": { 351 | "node": ">= 0.6" 352 | } 353 | }, 354 | "node_modules/event-target-shim": { 355 | "version": "5.0.1", 356 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 357 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 358 | "engines": { 359 | "node": ">=6" 360 | } 361 | }, 362 | "node_modules/events": { 363 | "version": "3.3.0", 364 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 365 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 366 | "engines": { 367 | "node": ">=0.8.x" 368 | } 369 | }, 370 | "node_modules/express": { 371 | "version": "4.18.2", 372 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 373 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 374 | "dependencies": { 375 | "accepts": "~1.3.8", 376 | "array-flatten": "1.1.1", 377 | "body-parser": "1.20.1", 378 | "content-disposition": "0.5.4", 379 | "content-type": "~1.0.4", 380 | "cookie": "0.5.0", 381 | "cookie-signature": "1.0.6", 382 | "debug": "2.6.9", 383 | "depd": "2.0.0", 384 | "encodeurl": "~1.0.2", 385 | "escape-html": "~1.0.3", 386 | "etag": "~1.8.1", 387 | "finalhandler": "1.2.0", 388 | "fresh": "0.5.2", 389 | "http-errors": "2.0.0", 390 | "merge-descriptors": "1.0.1", 391 | "methods": "~1.1.2", 392 | "on-finished": "2.4.1", 393 | "parseurl": "~1.3.3", 394 | "path-to-regexp": "0.1.7", 395 | "proxy-addr": "~2.0.7", 396 | "qs": "6.11.0", 397 | "range-parser": "~1.2.1", 398 | "safe-buffer": "5.2.1", 399 | "send": "0.18.0", 400 | "serve-static": "1.15.0", 401 | "setprototypeof": "1.2.0", 402 | "statuses": "2.0.1", 403 | "type-is": "~1.6.18", 404 | "utils-merge": "1.0.1", 405 | "vary": "~1.1.2" 406 | }, 407 | "engines": { 408 | "node": ">= 0.10.0" 409 | } 410 | }, 411 | "node_modules/fast-redact": { 412 | "version": "3.3.0", 413 | "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", 414 | "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", 415 | "engines": { 416 | "node": ">=6" 417 | } 418 | }, 419 | "node_modules/finalhandler": { 420 | "version": "1.2.0", 421 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 422 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 423 | "dependencies": { 424 | "debug": "2.6.9", 425 | "encodeurl": "~1.0.2", 426 | "escape-html": "~1.0.3", 427 | "on-finished": "2.4.1", 428 | "parseurl": "~1.3.3", 429 | "statuses": "2.0.1", 430 | "unpipe": "~1.0.0" 431 | }, 432 | "engines": { 433 | "node": ">= 0.8" 434 | } 435 | }, 436 | "node_modules/find-replace": { 437 | "version": "3.0.0", 438 | "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", 439 | "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", 440 | "dependencies": { 441 | "array-back": "^3.0.1" 442 | }, 443 | "engines": { 444 | "node": ">=4.0.0" 445 | } 446 | }, 447 | "node_modules/forwarded": { 448 | "version": "0.2.0", 449 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 450 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 451 | "engines": { 452 | "node": ">= 0.6" 453 | } 454 | }, 455 | "node_modules/fresh": { 456 | "version": "0.5.2", 457 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 458 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 459 | "engines": { 460 | "node": ">= 0.6" 461 | } 462 | }, 463 | "node_modules/function-bind": { 464 | "version": "1.1.1", 465 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 466 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 467 | }, 468 | "node_modules/get-intrinsic": { 469 | "version": "1.2.1", 470 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", 471 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", 472 | "dependencies": { 473 | "function-bind": "^1.1.1", 474 | "has": "^1.0.3", 475 | "has-proto": "^1.0.1", 476 | "has-symbols": "^1.0.3" 477 | }, 478 | "funding": { 479 | "url": "https://github.com/sponsors/ljharb" 480 | } 481 | }, 482 | "node_modules/has": { 483 | "version": "1.0.3", 484 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 485 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 486 | "dependencies": { 487 | "function-bind": "^1.1.1" 488 | }, 489 | "engines": { 490 | "node": ">= 0.4.0" 491 | } 492 | }, 493 | "node_modules/has-proto": { 494 | "version": "1.0.1", 495 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 496 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 497 | "engines": { 498 | "node": ">= 0.4" 499 | }, 500 | "funding": { 501 | "url": "https://github.com/sponsors/ljharb" 502 | } 503 | }, 504 | "node_modules/has-symbols": { 505 | "version": "1.0.3", 506 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 507 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 508 | "engines": { 509 | "node": ">= 0.4" 510 | }, 511 | "funding": { 512 | "url": "https://github.com/sponsors/ljharb" 513 | } 514 | }, 515 | "node_modules/http-errors": { 516 | "version": "2.0.0", 517 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 518 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 519 | "dependencies": { 520 | "depd": "2.0.0", 521 | "inherits": "2.0.4", 522 | "setprototypeof": "1.2.0", 523 | "statuses": "2.0.1", 524 | "toidentifier": "1.0.1" 525 | }, 526 | "engines": { 527 | "node": ">= 0.8" 528 | } 529 | }, 530 | "node_modules/iconv-lite": { 531 | "version": "0.4.24", 532 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 533 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 534 | "dependencies": { 535 | "safer-buffer": ">= 2.1.2 < 3" 536 | }, 537 | "engines": { 538 | "node": ">=0.10.0" 539 | } 540 | }, 541 | "node_modules/ieee754": { 542 | "version": "1.2.1", 543 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 544 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 545 | "funding": [ 546 | { 547 | "type": "github", 548 | "url": "https://github.com/sponsors/feross" 549 | }, 550 | { 551 | "type": "patreon", 552 | "url": "https://www.patreon.com/feross" 553 | }, 554 | { 555 | "type": "consulting", 556 | "url": "https://feross.org/support" 557 | } 558 | ] 559 | }, 560 | "node_modules/inherits": { 561 | "version": "2.0.4", 562 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 563 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 564 | }, 565 | "node_modules/ipaddr.js": { 566 | "version": "1.9.1", 567 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 568 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 569 | "engines": { 570 | "node": ">= 0.10" 571 | } 572 | }, 573 | "node_modules/lodash.camelcase": { 574 | "version": "4.3.0", 575 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 576 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" 577 | }, 578 | "node_modules/media-typer": { 579 | "version": "0.3.0", 580 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 581 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 582 | "engines": { 583 | "node": ">= 0.6" 584 | } 585 | }, 586 | "node_modules/merge-descriptors": { 587 | "version": "1.0.1", 588 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 589 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 590 | }, 591 | "node_modules/methods": { 592 | "version": "1.1.2", 593 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 594 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 595 | "engines": { 596 | "node": ">= 0.6" 597 | } 598 | }, 599 | "node_modules/mime": { 600 | "version": "1.6.0", 601 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 602 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 603 | "bin": { 604 | "mime": "cli.js" 605 | }, 606 | "engines": { 607 | "node": ">=4" 608 | } 609 | }, 610 | "node_modules/mime-db": { 611 | "version": "1.52.0", 612 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 613 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 614 | "engines": { 615 | "node": ">= 0.6" 616 | } 617 | }, 618 | "node_modules/mime-types": { 619 | "version": "2.1.35", 620 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 621 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 622 | "dependencies": { 623 | "mime-db": "1.52.0" 624 | }, 625 | "engines": { 626 | "node": ">= 0.6" 627 | } 628 | }, 629 | "node_modules/ms": { 630 | "version": "2.0.0", 631 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 632 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 633 | }, 634 | "node_modules/negotiator": { 635 | "version": "0.6.3", 636 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 637 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 638 | "engines": { 639 | "node": ">= 0.6" 640 | } 641 | }, 642 | "node_modules/object-inspect": { 643 | "version": "1.12.3", 644 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 645 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 646 | "funding": { 647 | "url": "https://github.com/sponsors/ljharb" 648 | } 649 | }, 650 | "node_modules/on-exit-leak-free": { 651 | "version": "2.1.0", 652 | "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", 653 | "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" 654 | }, 655 | "node_modules/on-finished": { 656 | "version": "2.4.1", 657 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 658 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 659 | "dependencies": { 660 | "ee-first": "1.1.1" 661 | }, 662 | "engines": { 663 | "node": ">= 0.8" 664 | } 665 | }, 666 | "node_modules/parseurl": { 667 | "version": "1.3.3", 668 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 669 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 670 | "engines": { 671 | "node": ">= 0.8" 672 | } 673 | }, 674 | "node_modules/path-to-regexp": { 675 | "version": "0.1.7", 676 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 677 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 678 | }, 679 | "node_modules/pino": { 680 | "version": "8.15.1", 681 | "resolved": "https://registry.npmjs.org/pino/-/pino-8.15.1.tgz", 682 | "integrity": "sha512-Cp4QzUQrvWCRJaQ8Lzv0mJzXVk4z2jlq8JNKMGaixC2Pz5L4l2p95TkuRvYbrEbe85NQsDKrAd4zalf7Ml6WiA==", 683 | "dependencies": { 684 | "atomic-sleep": "^1.0.0", 685 | "fast-redact": "^3.1.1", 686 | "on-exit-leak-free": "^2.1.0", 687 | "pino-abstract-transport": "v1.1.0", 688 | "pino-std-serializers": "^6.0.0", 689 | "process-warning": "^2.0.0", 690 | "quick-format-unescaped": "^4.0.3", 691 | "real-require": "^0.2.0", 692 | "safe-stable-stringify": "^2.3.1", 693 | "sonic-boom": "^3.1.0", 694 | "thread-stream": "^2.0.0" 695 | }, 696 | "bin": { 697 | "pino": "bin.js" 698 | } 699 | }, 700 | "node_modules/pino-abstract-transport": { 701 | "version": "1.1.0", 702 | "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", 703 | "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", 704 | "dependencies": { 705 | "readable-stream": "^4.0.0", 706 | "split2": "^4.0.0" 707 | } 708 | }, 709 | "node_modules/pino-std-serializers": { 710 | "version": "6.2.2", 711 | "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", 712 | "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" 713 | }, 714 | "node_modules/process": { 715 | "version": "0.11.10", 716 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 717 | "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", 718 | "engines": { 719 | "node": ">= 0.6.0" 720 | } 721 | }, 722 | "node_modules/process-warning": { 723 | "version": "2.2.0", 724 | "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", 725 | "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" 726 | }, 727 | "node_modules/proxy-addr": { 728 | "version": "2.0.7", 729 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 730 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 731 | "dependencies": { 732 | "forwarded": "0.2.0", 733 | "ipaddr.js": "1.9.1" 734 | }, 735 | "engines": { 736 | "node": ">= 0.10" 737 | } 738 | }, 739 | "node_modules/qs": { 740 | "version": "6.11.0", 741 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 742 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 743 | "dependencies": { 744 | "side-channel": "^1.0.4" 745 | }, 746 | "engines": { 747 | "node": ">=0.6" 748 | }, 749 | "funding": { 750 | "url": "https://github.com/sponsors/ljharb" 751 | } 752 | }, 753 | "node_modules/quick-format-unescaped": { 754 | "version": "4.0.4", 755 | "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", 756 | "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" 757 | }, 758 | "node_modules/range-parser": { 759 | "version": "1.2.1", 760 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 761 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 762 | "engines": { 763 | "node": ">= 0.6" 764 | } 765 | }, 766 | "node_modules/raw-body": { 767 | "version": "2.5.1", 768 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 769 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 770 | "dependencies": { 771 | "bytes": "3.1.2", 772 | "http-errors": "2.0.0", 773 | "iconv-lite": "0.4.24", 774 | "unpipe": "1.0.0" 775 | }, 776 | "engines": { 777 | "node": ">= 0.8" 778 | } 779 | }, 780 | "node_modules/readable-stream": { 781 | "version": "4.4.2", 782 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", 783 | "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", 784 | "dependencies": { 785 | "abort-controller": "^3.0.0", 786 | "buffer": "^6.0.3", 787 | "events": "^3.3.0", 788 | "process": "^0.11.10", 789 | "string_decoder": "^1.3.0" 790 | }, 791 | "engines": { 792 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 793 | } 794 | }, 795 | "node_modules/real-require": { 796 | "version": "0.2.0", 797 | "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", 798 | "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", 799 | "engines": { 800 | "node": ">= 12.13.0" 801 | } 802 | }, 803 | "node_modules/safe-buffer": { 804 | "version": "5.2.1", 805 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 806 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 807 | "funding": [ 808 | { 809 | "type": "github", 810 | "url": "https://github.com/sponsors/feross" 811 | }, 812 | { 813 | "type": "patreon", 814 | "url": "https://www.patreon.com/feross" 815 | }, 816 | { 817 | "type": "consulting", 818 | "url": "https://feross.org/support" 819 | } 820 | ] 821 | }, 822 | "node_modules/safe-stable-stringify": { 823 | "version": "2.4.3", 824 | "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", 825 | "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", 826 | "engines": { 827 | "node": ">=10" 828 | } 829 | }, 830 | "node_modules/safer-buffer": { 831 | "version": "2.1.2", 832 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 833 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 834 | }, 835 | "node_modules/send": { 836 | "version": "0.18.0", 837 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 838 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 839 | "dependencies": { 840 | "debug": "2.6.9", 841 | "depd": "2.0.0", 842 | "destroy": "1.2.0", 843 | "encodeurl": "~1.0.2", 844 | "escape-html": "~1.0.3", 845 | "etag": "~1.8.1", 846 | "fresh": "0.5.2", 847 | "http-errors": "2.0.0", 848 | "mime": "1.6.0", 849 | "ms": "2.1.3", 850 | "on-finished": "2.4.1", 851 | "range-parser": "~1.2.1", 852 | "statuses": "2.0.1" 853 | }, 854 | "engines": { 855 | "node": ">= 0.8.0" 856 | } 857 | }, 858 | "node_modules/send/node_modules/ms": { 859 | "version": "2.1.3", 860 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 861 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 862 | }, 863 | "node_modules/serve-static": { 864 | "version": "1.15.0", 865 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 866 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 867 | "dependencies": { 868 | "encodeurl": "~1.0.2", 869 | "escape-html": "~1.0.3", 870 | "parseurl": "~1.3.3", 871 | "send": "0.18.0" 872 | }, 873 | "engines": { 874 | "node": ">= 0.8.0" 875 | } 876 | }, 877 | "node_modules/setprototypeof": { 878 | "version": "1.2.0", 879 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 880 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 881 | }, 882 | "node_modules/side-channel": { 883 | "version": "1.0.4", 884 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 885 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 886 | "dependencies": { 887 | "call-bind": "^1.0.0", 888 | "get-intrinsic": "^1.0.2", 889 | "object-inspect": "^1.9.0" 890 | }, 891 | "funding": { 892 | "url": "https://github.com/sponsors/ljharb" 893 | } 894 | }, 895 | "node_modules/sonic-boom": { 896 | "version": "3.3.0", 897 | "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", 898 | "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", 899 | "dependencies": { 900 | "atomic-sleep": "^1.0.0" 901 | } 902 | }, 903 | "node_modules/split2": { 904 | "version": "4.2.0", 905 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", 906 | "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", 907 | "engines": { 908 | "node": ">= 10.x" 909 | } 910 | }, 911 | "node_modules/statuses": { 912 | "version": "2.0.1", 913 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 914 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 915 | "engines": { 916 | "node": ">= 0.8" 917 | } 918 | }, 919 | "node_modules/string_decoder": { 920 | "version": "1.3.0", 921 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 922 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 923 | "dependencies": { 924 | "safe-buffer": "~5.2.0" 925 | } 926 | }, 927 | "node_modules/thread-stream": { 928 | "version": "2.4.0", 929 | "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.0.tgz", 930 | "integrity": "sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw==", 931 | "dependencies": { 932 | "real-require": "^0.2.0" 933 | } 934 | }, 935 | "node_modules/toidentifier": { 936 | "version": "1.0.1", 937 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 938 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 939 | "engines": { 940 | "node": ">=0.6" 941 | } 942 | }, 943 | "node_modules/type-is": { 944 | "version": "1.6.18", 945 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 946 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 947 | "dependencies": { 948 | "media-typer": "0.3.0", 949 | "mime-types": "~2.1.24" 950 | }, 951 | "engines": { 952 | "node": ">= 0.6" 953 | } 954 | }, 955 | "node_modules/typescript": { 956 | "version": "5.2.2", 957 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 958 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 959 | "dev": true, 960 | "bin": { 961 | "tsc": "bin/tsc", 962 | "tsserver": "bin/tsserver" 963 | }, 964 | "engines": { 965 | "node": ">=14.17" 966 | } 967 | }, 968 | "node_modules/typical": { 969 | "version": "4.0.0", 970 | "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", 971 | "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", 972 | "engines": { 973 | "node": ">=8" 974 | } 975 | }, 976 | "node_modules/unpipe": { 977 | "version": "1.0.0", 978 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 979 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 980 | "engines": { 981 | "node": ">= 0.8" 982 | } 983 | }, 984 | "node_modules/utils-merge": { 985 | "version": "1.0.1", 986 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 987 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 988 | "engines": { 989 | "node": ">= 0.4.0" 990 | } 991 | }, 992 | "node_modules/uWebSockets.js": { 993 | "version": "20.31.0", 994 | "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#809b99d2d7d12e2cbf89b7135041e9b41ff84084" 995 | }, 996 | "node_modules/vary": { 997 | "version": "1.1.2", 998 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 999 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1000 | "engines": { 1001 | "node": ">= 0.8" 1002 | } 1003 | }, 1004 | "node_modules/ws": { 1005 | "version": "8.14.1", 1006 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", 1007 | "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", 1008 | "engines": { 1009 | "node": ">=10.0.0" 1010 | }, 1011 | "peerDependencies": { 1012 | "bufferutil": "^4.0.1", 1013 | "utf-8-validate": ">=5.0.2" 1014 | }, 1015 | "peerDependenciesMeta": { 1016 | "bufferutil": { 1017 | "optional": true 1018 | }, 1019 | "utf-8-validate": { 1020 | "optional": true 1021 | } 1022 | } 1023 | } 1024 | } 1025 | } 1026 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "tsc", 4 | "server": "tsc && node ./dist/server.js", 5 | "inspect": "tsc && node --inspect ./dist/server.js", 6 | "trace": "tsc && node --trace-gc ./dist/server.js", 7 | "trace-inspect": "tsc && node --trace-gc ./dist/server.js", 8 | "client": "cargo run --release" 9 | }, 10 | "dependencies": { 11 | "@types/command-line-args": "^5.2.1", 12 | "@types/node": "^20.5.9", 13 | "@types/ws": "^8.5.5", 14 | "command-line-args": "^5.2.1", 15 | "express": "^4.18.2", 16 | "pino": "^8.15.1", 17 | "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.31.0", 18 | "ws": "^8.14.1" 19 | }, 20 | "devDependencies": { 21 | "@types/express": "^4.17.17", 22 | "typescript": "^5.2.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ready-docker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #network=$(docker network ls | grep perfnet) 4 | #if [ -z "$network" ]; then 5 | # echo "creating perfnet" 6 | # docker network create perfnet 7 | #fi 8 | 9 | echo "docker build -t perf-server -f server.Dockerfile ." 10 | docker build -t perf-server -f server.Dockerfile . > /dev/null 11 | echo "docker build -t perf-client -f client.Dockerfile ." 12 | docker build -t perf-client -f client.Dockerfile . > /dev/null 13 | -------------------------------------------------------------------------------- /server.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine3.17 2 | 3 | WORKDIR /app 4 | COPY package.json /app/package.json 5 | COPY package-lock.json /app/package-lock.json 6 | RUN npm install 7 | 8 | COPY tsconfig.json /app/tsconfig.json 9 | COPY src /app/src 10 | RUN npm run build 11 | 12 | CMD ["node", "dist/server.js"] 13 | 14 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | import cli from "command-line-args"; 2 | 3 | export type Config = { 4 | port: number; 5 | logPath: string; 6 | logLevel: string; 7 | reportInterval: number; 8 | } 9 | 10 | const args = [{ 11 | name: "port", 12 | alias: "p", 13 | type: Number, 14 | defaultValue: 42069, 15 | }, { 16 | name: "logLevel", 17 | alias: "x", 18 | type: String, 19 | defaultValue: "info", 20 | }, { 21 | name: "reportInterval", 22 | alias: "r", 23 | type: Number, 24 | defaultValue: 5000, 25 | }, { 26 | name: "logPath", 27 | alias: "l", 28 | type: String, 29 | defaultValue: undefined, 30 | }]; 31 | 32 | export function initConfig(): Config { 33 | return cli(args) as Config; 34 | } 35 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use dotenv::dotenv; 3 | use futures_util::{SinkExt, StreamExt}; 4 | use std::sync::{ 5 | atomic::{AtomicBool, AtomicUsize}, 6 | Arc, 7 | }; 8 | 9 | use clap::Parser; 10 | 11 | #[derive(Debug, Parser)] 12 | struct Config { 13 | #[clap(env, short, long, env, default_value = "42069")] 14 | port: usize, 15 | 16 | #[clap(env, long, env, default_value = "1337")] 17 | stop_port: usize, 18 | 19 | #[clap(long, default_value = "0.0.0.0")] 20 | host: String, 21 | 22 | #[clap(env, short = 'q', long, default_value_t = 1)] 23 | parallel: usize, 24 | 25 | #[clap(env, short, long, default_value_t = 1)] 26 | count: usize, 27 | 28 | #[clap(env, short, long, default_value_t = "/tmp/rooms.csv")] 29 | file: PathBuf, 30 | 31 | #[clap(env, short, long, default_value_t = 2)] 32 | rooms_to_join: usize, 33 | 34 | #[clap(env, short = 'x', long, default_value_t = 20)] 35 | room_count: usize, 36 | 37 | #[clap(env, short, long, default_value_t = 10)] 38 | time_between_messages: u64, 39 | 40 | #[clap(env, long, default_value_t = 10)] 41 | time_between_connections: u64, 42 | 43 | #[clap(env, short, long, default_value_t = 1)] 44 | messages_to_send: usize, 45 | } 46 | 47 | async fn run_client( 48 | url: &'static url::Url, 49 | rooms: &'static Vec, 50 | idx: usize, 51 | config: &'static Config, 52 | ) -> Result<(usize, usize, bool)> { 53 | let idx = idx + 1; 54 | let (stream, _) = tokio_tungstenite::connect_async(url).await?; 55 | let (mut write, mut read) = stream.split(); 56 | let msg_count = Arc::new(AtomicUsize::new(0)); 57 | let timeout = Arc::new(AtomicBool::new(false)); 58 | let now = std::time::Instant::now(); 59 | 60 | let inner_msg_count = msg_count.clone(); 61 | let inner_timeout = timeout.clone(); 62 | let reader = tokio::spawn(async move { 63 | let msg_count = inner_msg_count; 64 | let timeout = inner_timeout; 65 | let mut my_message_count = config.messages_to_send; 66 | let now = std::time::Instant::now(); 67 | 68 | loop { 69 | let time_between = std::cmp::max(1, config.time_between_messages); 70 | let time_left = config.messages_to_send * time_between as usize * 3; 71 | let time_left = 72 | (std::cmp::max(1000, time_left)).saturating_sub(now.elapsed().as_millis() as usize); 73 | 74 | tokio::select! { 75 | _ = tokio::time::sleep(tokio::time::Duration::from_millis(time_left as u64)) => { 76 | timeout.store(true, std::sync::atomic::Ordering::Relaxed); 77 | break; 78 | } 79 | Some(Ok(msg)) = read.next() => { 80 | msg_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed); 81 | 82 | let (id, _) = msg.to_text().unwrap().split_once(":").unwrap(); 83 | let id = id.split(" ").last().unwrap(); 84 | let id = id.parse::().unwrap(); 85 | if id == idx { 86 | my_message_count = my_message_count.saturating_sub(1); 87 | if my_message_count == 0 { 88 | break; 89 | } 90 | } 91 | } 92 | }; 93 | } 94 | }); 95 | 96 | let mut my_rooms = vec![]; 97 | for i in 0..config.rooms_to_join { 98 | let duration = tokio::time::Duration::from_millis(config.time_between_messages); 99 | tokio::time::sleep(duration).await; 100 | 101 | let idx = (idx + i) % rooms.len(); 102 | let room = &rooms[idx]; 103 | my_rooms.push(room); 104 | 105 | let msg = format!("JOIN {}", room); 106 | write 107 | .send(tokio_tungstenite::tungstenite::Message::Text(msg)) 108 | .await?; 109 | } 110 | 111 | for i in 0..config.messages_to_send { 112 | let duration = tokio::time::Duration::from_millis(config.time_between_messages); 113 | tokio::time::sleep(duration).await; 114 | 115 | let room = my_rooms[(idx + i) % my_rooms.len()]; 116 | let msg = format!("MSG {} {}: hello {}", room, idx, room); 117 | write 118 | .send(tokio_tungstenite::tungstenite::Message::Text(msg)) 119 | .await?; 120 | } 121 | 122 | reader.await?; 123 | write.close().await?; 124 | 125 | let time_taken = now.elapsed().as_millis(); 126 | 127 | return Ok(( 128 | time_taken as usize, 129 | msg_count.load(std::sync::atomic::Ordering::Relaxed), 130 | timeout.load(std::sync::atomic::Ordering::Relaxed), 131 | )); 132 | } 133 | 134 | enum Run { 135 | Error, 136 | Timeout, 137 | Success(usize, usize), 138 | } 139 | 140 | pub async fn client() -> Result<()> { 141 | dotenv().ok(); 142 | 143 | let config: &'static Config = Box::leak(Box::new(Config::parse())); 144 | println!("config: {:?}", config); 145 | 146 | let semaphore = Arc::new(tokio::sync::Semaphore::new(config.parallel)); 147 | let url: &'static url::Url = Box::leak(Box::new(url::Url::parse(&format!( 148 | "ws://{}:{}", 149 | config.host, config.port 150 | ))?)); 151 | let rooms = (0..config.room_count) 152 | .map(|x| format!("room-{}", x)) 153 | .collect::>(); 154 | let rooms: &'static Vec = Box::leak(Box::new(rooms)); 155 | 156 | let (tx, mut rx) = tokio::sync::mpsc::channel::>(config.parallel); 157 | 158 | let rx_handle = tokio::spawn(async move { 159 | let mut results = vec![]; 160 | let mut timeouts = 0; 161 | let mut errors = 0; 162 | while let Some(run) = rx.recv().await { 163 | match run { 164 | Some(Run::Error) => { 165 | errors += 1; 166 | } 167 | Some(Run::Timeout) => { 168 | timeouts += 1; 169 | } 170 | Some(Run::Success(time_taken, count)) => { 171 | results.push((time_taken, count)); 172 | } 173 | None => { 174 | break; 175 | } 176 | } 177 | } 178 | 179 | println!("time_taken, count"); 180 | for (time_taken, count) in results { 181 | println!("{}, {}", time_taken, count); 182 | } 183 | println!("{} clients timed out", timeouts); 184 | println!("{} clients errored", errors); 185 | }); 186 | 187 | let mut handles = vec![]; 188 | for i in 0..config.count { 189 | if i < config.parallel { 190 | tokio::time::sleep(tokio::time::Duration::from_millis(config.time_between_connections)) 191 | .await; 192 | } 193 | 194 | let permit = semaphore.clone().acquire_owned().await; 195 | let tx = tx.clone(); 196 | 197 | if (i + 1) % 1000 == 0 { 198 | println!("{} clients spawned", i + 1); 199 | } 200 | 201 | let handle = tokio::spawn(async move { 202 | match run_client(url, rooms, i, config).await { 203 | Ok((time_taken, count, timedout)) => { 204 | if timedout { 205 | _ = tx.send(Some(Run::Timeout)).await; 206 | } else { 207 | _ = tx.send(Some(Run::Success(time_taken, count))).await; 208 | } 209 | } 210 | Err(_) => { 211 | _ = tx.send(Some(Run::Error)).await; 212 | } 213 | }; 214 | 215 | drop(permit); 216 | }); 217 | 218 | if handles.len() < config.parallel { 219 | handles.push(handle); 220 | } else { 221 | handles[i % config.parallel] = handle; 222 | } 223 | } 224 | 225 | futures_util::future::join_all(handles).await; 226 | _ = tx.send(None).await; 227 | rx_handle.await?; 228 | 229 | match reqwest::get(&format!("http://{}:{}/stop", config.host, config.stop_port)).await { 230 | Ok(_) => {} 231 | Err(e) => { 232 | eprintln!("Failed to stop server: {:?}", e); 233 | } 234 | } 235 | 236 | return Ok(()); 237 | } 238 | -------------------------------------------------------------------------------- /src/data-writer.ts: -------------------------------------------------------------------------------- 1 | import { Config } from "./cli"; 2 | import { getLogger } from "./logger"; 3 | 4 | export class Writer { 5 | private data: Map>; 6 | private counters: Map; 7 | private lastTime: number; 8 | 9 | constructor(private reportIntervalMS: number = 1000) { 10 | this.data = new Map(); 11 | this.counters = new Map(); 12 | this.lastTime = 0; 13 | } 14 | 15 | count(title: string) { 16 | let count = this.counters.get(title); 17 | if (!count) { 18 | count = 0; 19 | this.counters.set(title, count); 20 | } 21 | this.counters.set(title, count + 1); 22 | this.flush(); 23 | } 24 | 25 | write(title: string, data: number) { 26 | let pointSet = this.data.get(title); 27 | if (!pointSet) { 28 | pointSet = new Map(); 29 | this.data.set(title, pointSet); 30 | } 31 | 32 | pointSet.set(data, (pointSet.get(data) ?? 0) + 1); 33 | 34 | this.flush(); 35 | } 36 | 37 | private async flush() { 38 | 39 | if (this.lastTime === 0) { 40 | this.lastTime = Date.now(); 41 | } 42 | 43 | if (this.lastTime + this.reportIntervalMS > Date.now()) { 44 | return; 45 | } 46 | 47 | for (const [title, pointSet] of this.data.entries()) { 48 | getLogger().warn({ title, pointSet: Object.fromEntries(pointSet) }); 49 | } 50 | 51 | this.data.clear(); 52 | 53 | for (const [title, count] of this.counters.entries()) { 54 | getLogger().warn({ title, count }); 55 | } 56 | 57 | this.counters.clear(); 58 | this.lastTime = Date.now(); 59 | } 60 | 61 | } 62 | 63 | let writer: Writer | undefined = undefined; 64 | 65 | export function getWriter(args?: Config): Writer { 66 | if (args) { 67 | writer = new Writer(args.reportInterval); 68 | } 69 | 70 | if (!writer) { 71 | throw new Error("No writer"); 72 | } 73 | 74 | return writer; 75 | } 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | import pino, { Logger } from "pino"; 2 | import { Config } from "./cli"; 3 | 4 | let logger: undefined | Logger = undefined; 5 | export function getLogger(): Logger { 6 | if (!logger) { 7 | throw new Error("Logger not initialized"); 8 | } 9 | 10 | return logger; 11 | } 12 | 13 | export function initLogger(args: Config): Logger { 14 | let fileTransport: undefined | ReturnType = undefined; 15 | 16 | if (args.logPath) { 17 | fileTransport = pino.transport({ 18 | target: 'pino/file', 19 | options: { destination: args.logPath }, 20 | }); 21 | } 22 | 23 | logger = pino({ 24 | level: args.logLevel || process.env.PINO_LEVEL || "debug", 25 | }, fileTransport); 26 | 27 | return logger; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod client; 2 | 3 | #[tokio::main] 4 | async fn main() { 5 | match client::client().await { 6 | Ok(_) => println!("Success!"), 7 | Err(e) => println!("Error: {}", e), 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/room/set-room.ts: -------------------------------------------------------------------------------- 1 | import { IRoom, WS } from "../types"; 2 | 3 | let id = 0; 4 | export default class SetRoom { 5 | private users: Map; 6 | 7 | constructor(public name: string) { 8 | this.users = new Map(); 9 | } 10 | 11 | add(user: WS) { 12 | this.users.set(user, ++id); 13 | } 14 | 15 | remove(user: WS) { 16 | this.users.delete(user); 17 | } 18 | 19 | push(from: WS, message: string) { 20 | const id = this.users.get(from); 21 | if (!id) { 22 | // user hasn't joined the room yet 23 | return; 24 | } 25 | 26 | for (const sock of this.users.keys()) { 27 | sock.send(`${id} says ${message}`); 28 | } 29 | } 30 | } 31 | 32 | export function createRoom(name: string): IRoom { 33 | return new SetRoom(name); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { Chat, string } from "./set-chat"; 3 | import { createRoom } from "./room/set-room"; 4 | import { initConfig } from "./cli"; 5 | import { initLogger } from "./logger"; 6 | 7 | import ws from "uWebSockets.js"; 8 | import { WS } from "./types"; 9 | 10 | const config = initConfig(); 11 | initLogger(config); 12 | console.log("port", config.port); 13 | const chat = new Chat(createRoom); 14 | 15 | const wss = ws.App(); 16 | wss.ws("/*", { 17 | message: (ws: WS, message: any) => { 18 | chat.msg(ws, message); 19 | }, 20 | 21 | close: (ws) => { 22 | chat.close(ws); 23 | }, 24 | }); 25 | 26 | wss.listen(config.port, (token) => { 27 | if (token) { 28 | console.log("Listening to port " + config.port); 29 | } else { 30 | console.log("Failed to listen to port " + config.port); 31 | } 32 | }); 33 | 34 | const app = express(); 35 | app.get("/healthcheck", (_, res) => { 36 | res.status(200).end(); 37 | }); 38 | app.get("/stop", (_, res) => { 39 | console.log("stopping"); 40 | setTimeout(function() { 41 | process.exit(0); 42 | }, 100); 43 | res.status(200).end(); 44 | }); 45 | 46 | app.listen(1337, () => { console.log("health check ready") }); 47 | -------------------------------------------------------------------------------- /src/set-chat.ts: -------------------------------------------------------------------------------- 1 | import { IRoom, WS } from "./types"; 2 | import { getLogger } from "./logger"; 3 | 4 | export function string(item: string | Buffer | ArrayBuffer) { 5 | if (typeof item === "string") { 6 | return item; 7 | } else if (item instanceof Buffer) { 8 | return item.toString(); 9 | } 10 | 11 | return Buffer.from(item).toString(); 12 | } 13 | 14 | type MSG = { 15 | command: "MSG"; 16 | room: string; 17 | message: string; 18 | } 19 | 20 | type JOIN = { 21 | command: "JOIN"; 22 | room: string; 23 | } 24 | 25 | type LEAVE = { 26 | command: "LEAVE"; 27 | room: string; 28 | } 29 | 30 | type Command = MSG | JOIN | LEAVE; 31 | 32 | function isCommand(msg: string): boolean { 33 | return msg === "MSG" || msg === "JOIN" || msg === "LEAVE"; 34 | } 35 | 36 | function getMessage(message: string | Buffer): Command | undefined { 37 | if (typeof message === "object") { 38 | message = string(message); 39 | } 40 | 41 | const [command, ...rest] = message.split(" "); 42 | if (!isCommand(command)) { 43 | return undefined; 44 | } 45 | 46 | if (command === "MSG") { 47 | return { 48 | command: "MSG", 49 | room: rest[0], 50 | message: rest.slice(1).join(" "), 51 | }; 52 | } else if (command === "JOIN") { 53 | return { 54 | command: "JOIN", 55 | room: rest[0], 56 | }; 57 | } 58 | return { 59 | command: "LEAVE", 60 | room: rest[0], 61 | }; 62 | } 63 | 64 | 65 | export class Chat { 66 | private rooms: Map; 67 | 68 | constructor(private createRoom: (name: string) => IRoom) { 69 | this.rooms = new Map(); 70 | } 71 | 72 | msg(user: WS, msg: string | Buffer) { 73 | const message = getMessage(msg); 74 | if (!message) { 75 | return; 76 | } 77 | 78 | if (message.command === "JOIN") { 79 | this.getRoom(message.room).add(user); 80 | } else if (message.command === "MSG") { 81 | this.getRoom(message.room).push(user, message.message); 82 | } else { 83 | this.getRoom(message.room).remove(user); 84 | } 85 | } 86 | 87 | close(user: WS) { 88 | this.rooms.forEach((room) => { 89 | room.remove(user); 90 | }); 91 | } 92 | 93 | private getRoom(roomName: string): IRoom { 94 | let room = this.rooms.get(roomName); 95 | 96 | if (!room) { 97 | room = this.createRoom(roomName); 98 | this.rooms.set(roomName, room); 99 | } 100 | 101 | return room 102 | } 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { WebSocket } from "uWebSockets.js"; 2 | 3 | export type WS = WebSocket; 4 | 5 | export interface IRoom { 6 | name: string; 7 | 8 | add(user: WS): void; 9 | push(from: WS, message: string): void; 10 | remove(user: WS): void; 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | --------------------------------------------------------------------------------